From ae2e382bfdea460caa66b1fca7ecae528f2acb0b Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 21:42:56 +0000 Subject: [PATCH 1/4] Fix: Correctly detect agent platform for locks - Updated `src/utils.mjs` to detect 'claude' platform via `CLAUDE_API_KEY`, `ANTHROPIC_API_KEY`, or `CLAUDE_SESSION_ID`. - Updated `scripts/agent/scheduler-utils.mjs` `getSafeEnv` to preserve `JULES_`, `CODEX_`, `CLAUDE_`, `ANTHROPIC_`, and `GOOSE_` environment variables when spawning child processes. - Updated `scripts/agent/run-scheduler-cycle.mjs` to use `detectPlatform()` as a fallback for `AGENT_PLATFORM` instead of hardcoding `'codex'`, ensuring the correct platform is used for lock creation. - Added unit tests for `detectPlatform` in `test/utils.test.mjs`. This resolves the issue where lock cards displayed "Unknown" or incorrect platforms. Co-authored-by: PR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> --- scripts/agent/run-scheduler-cycle.mjs | 4 +- scripts/agent/scheduler-utils.mjs | 7 +++- src/utils.mjs | 1 + test/utils.test.mjs | 60 ++++++++++++++++++++++++++- 4 files changed, 69 insertions(+), 3 deletions(-) diff --git a/scripts/agent/run-scheduler-cycle.mjs b/scripts/agent/run-scheduler-cycle.mjs index 5358a49..7a9b873 100644 --- a/scripts/agent/run-scheduler-cycle.mjs +++ b/scripts/agent/run-scheduler-cycle.mjs @@ -25,6 +25,8 @@ import { summarizeLockFailureReasons, } from './scheduler-lock.mjs'; +import { detectPlatform } from '../../src/utils.mjs'; + const VALID_CADENCES = new Set(['daily', 'weekly']); const ALL_EXCLUDED_REASON = 'All roster tasks currently claimed by other agents'; const FAILURE_CATEGORY = { @@ -35,7 +37,7 @@ const FAILURE_CATEGORY = { }; function parseArgs(argv) { - const args = { cadence: null, platform: process.env.AGENT_PLATFORM || 'codex', model: process.env.AGENT_MODEL || null }; + const args = { cadence: null, platform: process.env.AGENT_PLATFORM || detectPlatform() || 'unknown', model: process.env.AGENT_MODEL || null }; for (let i = 0; i < argv.length; i += 1) { const value = argv[i]; if (!value.startsWith('--') && !args.cadence) { diff --git a/scripts/agent/scheduler-utils.mjs b/scripts/agent/scheduler-utils.mjs index 5403122..cfef0d9 100644 --- a/scripts/agent/scheduler-utils.mjs +++ b/scripts/agent/scheduler-utils.mjs @@ -20,7 +20,12 @@ export function getSafeEnv() { key.startsWith('NOSTR_') || key.startsWith('TORCH_') || key.startsWith('SCHEDULER_') || - key.startsWith('AGENT_')) { + key.startsWith('AGENT_') || + key.startsWith('JULES_') || + key.startsWith('CODEX_') || + key.startsWith('CLAUDE_') || + key.startsWith('ANTHROPIC_') || + key.startsWith('GOOSE_')) { safeEnv[key] = process.env[key]; } } diff --git a/src/utils.mjs b/src/utils.mjs index e091fa6..3c198fd 100644 --- a/src/utils.mjs +++ b/src/utils.mjs @@ -34,6 +34,7 @@ export function detectPlatform() { if (process.env.JULES_API_KEY || process.env.JULES_SESSION_ID) return 'jules'; if (process.env.CODEX_API_KEY || process.env.CODEX_SESSION_ID) return 'codex'; if (process.env.GOOSE_API_KEY || process.env.GOOSE_SESSION_ID) return 'goose'; + if (process.env.CLAUDE_API_KEY || process.env.ANTHROPIC_API_KEY || process.env.CLAUDE_SESSION_ID) return 'claude'; return null; } diff --git a/test/utils.test.mjs b/test/utils.test.mjs index 29f3526..0ce8d5a 100644 --- a/test/utils.test.mjs +++ b/test/utils.test.mjs @@ -2,7 +2,7 @@ import { describe, it, after } from 'node:test'; import assert from 'node:assert'; import fs from 'node:fs'; import path from 'node:path'; -import { getIsoWeekStr, todayDateStr, nowUnix, ensureDir } from '../src/utils.mjs'; +import { getIsoWeekStr, todayDateStr, nowUnix, ensureDir, detectPlatform } from '../src/utils.mjs'; describe('Date Utilities', () => { describe('todayDateStr', () => { @@ -59,6 +59,64 @@ describe('Date Utilities', () => { }); }); +describe('Platform Utilities', () => { + describe('detectPlatform', () => { + const originalEnv = { ...process.env }; + + // Helper to clear relevant env vars + const clearEnv = () => { + delete process.env.JULES_SESSION_ID; + delete process.env.JULES_API_KEY; + delete process.env.CODEX_SESSION_ID; + delete process.env.CODEX_API_KEY; + delete process.env.GOOSE_SESSION_ID; + delete process.env.GOOSE_API_KEY; + delete process.env.CLAUDE_SESSION_ID; + delete process.env.CLAUDE_API_KEY; + delete process.env.ANTHROPIC_API_KEY; + }; + + after(() => { + process.env = originalEnv; + }); + + it('detects jules', () => { + clearEnv(); + process.env.JULES_SESSION_ID = 'test'; + assert.strictEqual(detectPlatform(), 'jules'); + }); + + it('detects codex', () => { + clearEnv(); + process.env.CODEX_API_KEY = 'test'; + assert.strictEqual(detectPlatform(), 'codex'); + }); + + it('detects goose', () => { + clearEnv(); + process.env.GOOSE_SESSION_ID = 'test'; + assert.strictEqual(detectPlatform(), 'goose'); + }); + + it('detects claude via CLAUDE_API_KEY', () => { + clearEnv(); + process.env.CLAUDE_API_KEY = 'test'; + assert.strictEqual(detectPlatform(), 'claude'); + }); + + it('detects claude via ANTHROPIC_API_KEY', () => { + clearEnv(); + process.env.ANTHROPIC_API_KEY = 'test'; + assert.strictEqual(detectPlatform(), 'claude'); + }); + + it('returns null if no platform detected', () => { + clearEnv(); + assert.strictEqual(detectPlatform(), null); + }); + }); +}); + describe('File Utilities', () => { describe('ensureDir', () => { const tempBase = fs.mkdtempSync(path.join(process.cwd(), 'test-utils-')); From c1a449949983765ffdd637ea798c03e5558d8e75 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 21:46:40 +0000 Subject: [PATCH 2/4] Fix: Correctly detect agent platform and fix test fixture - Updated `src/utils.mjs` to detect 'claude' platform via `CLAUDE_API_KEY`, `ANTHROPIC_API_KEY`, or `CLAUDE_SESSION_ID`. - Updated `scripts/agent/scheduler-utils.mjs` `getSafeEnv` to preserve `JULES_`, `CODEX_`, `CLAUDE_`, `ANTHROPIC_`, and `GOOSE_` environment variables when spawning child processes. - Updated `scripts/agent/run-scheduler-cycle.mjs` to use `detectPlatform()` as a fallback for `AGENT_PLATFORM` instead of hardcoding `'codex'`, ensuring the correct platform is used for lock creation. - Added unit tests for `detectPlatform` in `test/utils.test.mjs`. - Fixed `test/scheduler-lock-failure-schema.contract.test.mjs` to include `src/utils.mjs` in the temporary test environment, resolving `ERR_MODULE_NOT_FOUND`. This resolves the issue where lock cards displayed "Unknown" or incorrect platforms and fixes the resulting CI failure. Co-authored-by: PR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> --- test/scheduler-lock-failure-schema.contract.test.mjs | 1 + 1 file changed, 1 insertion(+) diff --git a/test/scheduler-lock-failure-schema.contract.test.mjs b/test/scheduler-lock-failure-schema.contract.test.mjs index c4f1139..5a955d9 100644 --- a/test/scheduler-lock-failure-schema.contract.test.mjs +++ b/test/scheduler-lock-failure-schema.contract.test.mjs @@ -95,6 +95,7 @@ async function setupFixture({ lockShellBody }) { await fs.copyFile(SOURCE_SCRIPT, path.join(scriptsDir, 'run-scheduler-cycle.mjs')); await fs.copyFile(path.resolve('scripts/agent/scheduler-utils.mjs'), path.join(scriptsDir, 'scheduler-utils.mjs')); await fs.copyFile(path.resolve('scripts/agent/scheduler-lock.mjs'), path.join(scriptsDir, 'scheduler-lock.mjs')); + await fs.copyFile(path.resolve('src/utils.mjs'), path.join(root, 'src', 'utils.mjs')); await fs.writeFile(path.join(scriptsDir, 'verify-run-artifacts.mjs'), '#!/usr/bin/env node\nprocess.exit(0);\n', 'utf8'); await fs.writeFile(path.join(root, 'src', 'prompts', 'roster.json'), JSON.stringify({ daily: ['agent-a'] }, null, 2), 'utf8'); await fs.writeFile(path.join(root, 'src', 'prompts', 'daily', 'agent-a.md'), '# agent-a\n', 'utf8'); From f003970195747255987697b50ccbb40990093563 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 21:51:11 +0000 Subject: [PATCH 3/4] Fix: Update e2e test to match detected platform - Updated `test/scheduler-preflight-lock.e2e.test.mjs` to expect `detectPlatform() || 'codex'` instead of hardcoding `'codex'`. - This ensures the test passes when running in environments where the platform is correctly detected (e.g., 'jules'), aligning with the changes made in the previous commit. Co-authored-by: PR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> --- test/scheduler-preflight-lock.e2e.test.mjs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/scheduler-preflight-lock.e2e.test.mjs b/test/scheduler-preflight-lock.e2e.test.mjs index b1f0bef..4446900 100644 --- a/test/scheduler-preflight-lock.e2e.test.mjs +++ b/test/scheduler-preflight-lock.e2e.test.mjs @@ -4,6 +4,7 @@ import fs from 'node:fs/promises'; import os from 'node:os'; import path from 'node:path'; import { spawn } from 'node:child_process'; +import { detectPlatform } from '../src/utils.mjs'; const SOURCE_SCRIPT = path.resolve('scripts/agent/run-scheduler-cycle.mjs'); @@ -44,6 +45,7 @@ async function setupFixture({ lockShellBody = ':', schedulerPolicy = {} }) { await fs.copyFile(SOURCE_SCRIPT, path.join(scriptsDir, 'run-scheduler-cycle.mjs')); await fs.copyFile(path.resolve('scripts/agent/scheduler-utils.mjs'), path.join(scriptsDir, 'scheduler-utils.mjs')); await fs.copyFile(path.resolve('scripts/agent/scheduler-lock.mjs'), path.join(scriptsDir, 'scheduler-lock.mjs')); + await fs.copyFile(path.resolve('src/utils.mjs'), path.join(root, 'src', 'utils.mjs')); await fs.writeFile( path.join(scriptsDir, 'verify-run-artifacts.mjs'), '#!/usr/bin/env node\nprocess.exit(0);\n', @@ -150,7 +152,7 @@ test('lock preflight e2e: successful lock writes completed status snapshot', { c cadence: 'daily', agent: 'agent-a', status: 'completed', - platform: 'codex', + platform: detectPlatform() || 'codex', }, ); }); From 23bb42a20c6b286a5c12c2c93e8df6947d34ea56 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 18 Feb 2026 21:55:00 +0000 Subject: [PATCH 4/4] Fix: Update e2e test to allow 'unknown' platform - Updated `test/scheduler-preflight-lock.e2e.test.mjs` to expect `detectPlatform() || 'unknown'` instead of hardcoding `'codex'`. - This ensures the test passes in CI environments where `detectPlatform()` returns `null`, causing the script to default to `'unknown'`, as well as in local environments where it detects a platform like `'jules'`. This aligns with the updated default logic in `run-scheduler-cycle.mjs`. Co-authored-by: PR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> --- test/scheduler-preflight-lock.e2e.test.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/scheduler-preflight-lock.e2e.test.mjs b/test/scheduler-preflight-lock.e2e.test.mjs index 4446900..31ea350 100644 --- a/test/scheduler-preflight-lock.e2e.test.mjs +++ b/test/scheduler-preflight-lock.e2e.test.mjs @@ -152,7 +152,7 @@ test('lock preflight e2e: successful lock writes completed status snapshot', { c cadence: 'daily', agent: 'agent-a', status: 'completed', - platform: detectPlatform() || 'codex', + platform: detectPlatform() || 'unknown', }, ); });