mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-11-05 20:31:54 +00:00
feat: add scheduler pause configuration
Co-authored-by: PR0M3TH3AN <[email protected]>
This commit is contained in:
1 parent
31074099a1
commit
27c30f769a
6 files changed
+39
-2
No files matched your search
@@ -26,6 +26,7 @@ Create a `torch-config.json` file in your project root (or set `TORCH_CONFIG_PAT
|
|||||||
- `dashboard.defaultCadenceView` (`daily`, `weekly`, or `all`)
|
- `dashboard.defaultCadenceView` (`daily`, `weekly`, or `all`)
|
||||||
- `dashboard.defaultStatusView` (`active` or `all`)
|
- `dashboard.defaultStatusView` (`active` or `all`)
|
||||||
- `scheduler.firstPromptByCadence.daily` / `.weekly`
|
- `scheduler.firstPromptByCadence.daily` / `.weekly`
|
||||||
|
- `scheduler.paused.daily` / `.weekly` (array of agent names to pause locally)
|
||||||
|
|
||||||
Weekly alignment maintenance is available via `src/prompts/weekly/repo-fit-agent.md`, which is designed to keep TORCH defaults and docs tuned to the host repository over time.
|
Weekly alignment maintenance is available via `src/prompts/weekly/repo-fit-agent.md`, which is designed to keep TORCH defaults and docs tuned to the host repository over time.
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ Common settings:
|
|||||||
- `dashboard.defaultCadenceView` — default dashboard view (`daily`, `weekly`, `all`).
|
- `dashboard.defaultCadenceView` — default dashboard view (`daily`, `weekly`, `all`).
|
||||||
- `dashboard.defaultStatusView` — default dashboard status filter (`active`, `all`).
|
- `dashboard.defaultStatusView` — default dashboard status filter (`active`, `all`).
|
||||||
- `scheduler.firstPromptByCadence.daily` / `.weekly` — first-run scheduler starting agent.
|
- `scheduler.firstPromptByCadence.daily` / `.weekly` — first-run scheduler starting agent.
|
||||||
|
- `scheduler.paused.daily` / `.weekly` — array of agent names to exclude from scheduler rotation.
|
||||||
|
|
||||||
Default first-run daily scheduler prompt is `scheduler-update-agent`.
|
Default first-run daily scheduler prompt is `scheduler-update-agent`.
|
||||||
|
|
||||||
|
|||||||
+10
-1
@@ -259,15 +259,22 @@ async function cmdCheck(cadence) {
|
|||||||
const relays = getRelays();
|
const relays = getRelays();
|
||||||
const namespace = getNamespace();
|
const namespace = getNamespace();
|
||||||
const dateStr = todayDateStr();
|
const dateStr = todayDateStr();
|
||||||
|
const config = loadTorchConfig();
|
||||||
|
const pausedAgents = (cadence === 'daily' ? config.scheduler.paused.daily : config.scheduler.paused.weekly) || [];
|
||||||
|
|
||||||
console.error(`Checking locks: namespace=${namespace}, cadence=${cadence}, date=${dateStr}`);
|
console.error(`Checking locks: namespace=${namespace}, cadence=${cadence}, date=${dateStr}`);
|
||||||
console.error(`Relays: ${relays.join(', ')}`);
|
console.error(`Relays: ${relays.join(', ')}`);
|
||||||
|
if (pausedAgents.length > 0) {
|
||||||
|
console.error(`Paused agents: ${pausedAgents.join(', ')}`);
|
||||||
|
}
|
||||||
|
|
||||||
const locks = await queryLocks(relays, cadence, dateStr, namespace);
|
const locks = await queryLocks(relays, cadence, dateStr, namespace);
|
||||||
const lockedAgents = [...new Set(locks.map((l) => l.agent).filter(Boolean))];
|
const lockedAgents = [...new Set(locks.map((l) => l.agent).filter(Boolean))];
|
||||||
const roster = getRoster(cadence);
|
const roster = getRoster(cadence);
|
||||||
|
|
||||||
|
const excludedAgents = [...new Set([...lockedAgents, ...pausedAgents])];
|
||||||
const unknownLockedAgents = lockedAgents.filter((agent) => !roster.includes(agent));
|
const unknownLockedAgents = lockedAgents.filter((agent) => !roster.includes(agent));
|
||||||
const available = roster.filter((a) => !lockedAgents.includes(a));
|
const available = roster.filter((a) => !excludedAgents.includes(a));
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
@@ -276,6 +283,8 @@ async function cmdCheck(cadence) {
|
|||||||
cadence,
|
cadence,
|
||||||
date: dateStr,
|
date: dateStr,
|
||||||
locked: lockedAgents.sort(),
|
locked: lockedAgents.sort(),
|
||||||
|
paused: pausedAgents.sort(),
|
||||||
|
excluded: excludedAgents.sort(),
|
||||||
available: available.sort(),
|
available: available.sort(),
|
||||||
lockCount: locks.length,
|
lockCount: locks.length,
|
||||||
unknownLockedAgents: unknownLockedAgents.sort(),
|
unknownLockedAgents: unknownLockedAgents.sort(),
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ Use this document for all scheduler runs.
|
|||||||
Selection algorithm (MUST be followed exactly):
|
Selection algorithm (MUST be followed exactly):
|
||||||
|
|
||||||
- Roster source: `src/prompts/roster.json` and the key matching `<cadence>`.
|
- Roster source: `src/prompts/roster.json` and the key matching `<cadence>`.
|
||||||
- Let `roster` be that ordered array and `excluded` be the locked set from step 2.
|
- Let `roster` be that ordered array and `excluded` be the `excluded` set (including paused and locked agents) from the JSON output of step 2.
|
||||||
- Let `latest_file` be the lexicographically last filename in `<log_dir>`.
|
- Let `latest_file` be the lexicographically last filename in `<log_dir>`.
|
||||||
- Determine `previous_agent` from `latest_file` using this precedence:
|
- Determine `previous_agent` from `latest_file` using this precedence:
|
||||||
1. Parse YAML frontmatter from `<log_dir>/<latest_file>` and use key `agent` when present and non-empty.
|
1. Parse YAML frontmatter from `<log_dir>/<latest_file>` and use key `agent` when present and non-empty.
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ export function loadTorchConfig() {
|
|||||||
const dashboard = raw.dashboard || {};
|
const dashboard = raw.dashboard || {};
|
||||||
const scheduler = raw.scheduler || {};
|
const scheduler = raw.scheduler || {};
|
||||||
const firstPromptByCadence = scheduler.firstPromptByCadence || {};
|
const firstPromptByCadence = scheduler.firstPromptByCadence || {};
|
||||||
|
const paused = scheduler.paused || {};
|
||||||
|
|
||||||
cachedConfig = {
|
cachedConfig = {
|
||||||
configPath,
|
configPath,
|
||||||
@@ -77,6 +78,10 @@ export function loadTorchConfig() {
|
|||||||
daily: typeof firstPromptByCadence.daily === 'string' ? firstPromptByCadence.daily.trim() : null,
|
daily: typeof firstPromptByCadence.daily === 'string' ? firstPromptByCadence.daily.trim() : null,
|
||||||
weekly: typeof firstPromptByCadence.weekly === 'string' ? firstPromptByCadence.weekly.trim() : null,
|
weekly: typeof firstPromptByCadence.weekly === 'string' ? firstPromptByCadence.weekly.trim() : null,
|
||||||
},
|
},
|
||||||
|
paused: {
|
||||||
|
daily: parseRoster(paused.daily) || [],
|
||||||
|
weekly: parseRoster(paused.weekly) || [],
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { test, describe, it } from 'node:test';
|
import { test, describe, it } from 'node:test';
|
||||||
import assert from 'node:assert';
|
import assert from 'node:assert';
|
||||||
import { spawnSync } from 'node:child_process';
|
import { spawnSync } from 'node:child_process';
|
||||||
|
import fs from 'node:fs';
|
||||||
|
|
||||||
describe('CLI Smoke Test', () => {
|
describe('CLI Smoke Test', () => {
|
||||||
it('should print usage when no args provided', () => {
|
it('should print usage when no args provided', () => {
|
||||||
@@ -14,4 +15,24 @@ describe('CLI Smoke Test', () => {
|
|||||||
assert.strictEqual(result.status, 1);
|
assert.strictEqual(result.status, 1);
|
||||||
assert.match(result.stderr.toString(), /--cadence <daily|weekly> is required/);
|
assert.match(result.stderr.toString(), /--cadence <daily|weekly> is required/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should include paused agents in check output', () => {
|
||||||
|
const configPath = 'test-torch-config.json';
|
||||||
|
fs.writeFileSync(configPath, JSON.stringify({
|
||||||
|
scheduler: { paused: { daily: ['paused-agent'] } }
|
||||||
|
}));
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = spawnSync('node', ['src/nostr-lock.mjs', 'check', '--cadence', 'daily'], {
|
||||||
|
env: { ...process.env, TORCH_CONFIG_PATH: configPath }
|
||||||
|
});
|
||||||
|
const output = JSON.parse(result.stdout.toString());
|
||||||
|
assert.deepStrictEqual(output.paused, ['paused-agent']);
|
||||||
|
assert.ok(output.excluded.includes('paused-agent'));
|
||||||
|
} finally {
|
||||||
|
if (fs.existsSync(configPath)) {
|
||||||
|
fs.unlinkSync(configPath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
Reference in new issue
Block a user