Merge pull request #7 from PR0M3TH3AN/codex/align-roster-configuration-across-files

Align lock roster source with scheduler prompts
This commit is contained in:
thePR0M3TH3AN authored and GitHub committed 2026-02-13 21:52:04 -05:00
commit 3b1920ac55
6 files changed
+162 -19

No files matched your search

+13 -2
View File
@@ -9,7 +9,7 @@ From the repository root:
```bash
npm install
npm run lock:check:daily
AGENT_PLATFORM=codex npm run lock:lock -- --agent documentation-agent --cadence daily
AGENT_PLATFORM=codex npm run lock:lock -- --agent docs-agent --cadence daily
npm run lock:list
```
@@ -52,12 +52,23 @@ Declared in `package.json` and pinned:
- `NOSTR_LOCK_WEEKLY_ROSTER`
- `AGENT_PLATFORM`
## Roster precedence
The lock CLI resolves roster names in this order:
1. `NOSTR_LOCK_DAILY_ROSTER` / `NOSTR_LOCK_WEEKLY_ROSTER` (comma-separated env overrides).
2. `src/prompts/roster.json` (`daily` / `weekly` canonical scheduler roster).
3. Built-in fallback roster (used only if `src/prompts/roster.json` is unreadable).
`lock --agent` validates names against the resolved cadence roster, and `check`/`list` report lock events whose agent names do not match scheduler roster entries exactly.
## Example
```bash
NOSTR_LOCK_NAMESPACE=my-project \
AGENT_PLATFORM=codex \
node src/nostr-lock.mjs lock --agent documentation-agent --cadence daily
node src/nostr-lock.mjs lock --agent docs-agent --cadence daily
```
[Tip Jar](https://tipjar.bitvid.network/?n=npub15jnttpymeytm80hatjqcvhhqhzrhx6gxp8pq0wn93rhnu8s9h9dsha32lx)
+12 -1
View File
@@ -9,7 +9,7 @@ TORCH is a decentralized task-locking protocol for multi-agent software developm
node src/nostr-lock.mjs check --cadence daily
# Claim a task
AGENT_PLATFORM=codex node src/nostr-lock.mjs lock --agent documentation-agent --cadence daily
AGENT_PLATFORM=codex node src/nostr-lock.mjs lock --agent docs-agent --cadence daily
# List all active locks
node src/nostr-lock.mjs list
@@ -35,6 +35,17 @@ node src/nostr-lock.mjs list
- `NOSTR_LOCK_WEEKLY_ROSTER`
- `AGENT_PLATFORM`
## Roster precedence
The lock CLI resolves roster names in this order:
1. `NOSTR_LOCK_DAILY_ROSTER` / `NOSTR_LOCK_WEEKLY_ROSTER` (comma-separated env overrides).
2. `src/prompts/roster.json` (`daily` / `weekly` canonical scheduler roster).
3. Built-in fallback roster (used only if `src/prompts/roster.json` is unreadable).
`lock --agent` validates names against the resolved cadence roster, and `check`/`list` report lock events whose agent names do not match scheduler roster entries exactly.
## Exit codes
- `0`: success
+90 -16
View File
@@ -3,6 +3,9 @@
// TORCH — Task Orchestration via Relay-Coordinated Handoff
// Generic Nostr-based task locking for multi-agent development.
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { generateSecretKey, getPublicKey, finalizeEvent } from 'nostr-tools/pure';
import { SimplePool } from 'nostr-tools/pool';
import { useWebSocketImplementation } from 'nostr-tools/relay';
@@ -21,21 +24,52 @@ const DEFAULT_NAMESPACE = 'torch';
const QUERY_TIMEOUT_MS = 15_000;
const VALID_CADENCES = new Set(['daily', 'weekly']);
const DEFAULT_DAILY_ROSTER = [
'documentation-agent',
'quality-agent',
'security-agent',
'performance-agent',
'refactor-agent',
];
const ROSTER_FILE = path.resolve(path.dirname(fileURLToPath(import.meta.url)), 'prompts/roster.json');
const FALLBACK_ROSTER = {
daily: [
'audit-agent',
'ci-health-agent',
'const-refactor-agent',
'content-audit-agent',
'decompose-agent',
'deps-security-agent',
'design-system-audit-agent',
'docs-agent',
'docs-alignment-agent',
'docs-code-investigator',
'innerhtml-migration-agent',
'known-issues-agent',
'load-test-agent',
'onboarding-audit-agent',
'perf-agent',
'prompt-curator-agent',
'protocol-research-agent',
'scheduler-update-agent',
'style-agent',
'test-audit-agent',
'todo-triage-agent',
],
weekly: [
'bug-reproducer-agent',
'changelog-agent',
'dead-code-agent',
'event-schema-agent',
'frontend-console-debug-agent',
'fuzz-agent',
'interop-agent',
'perf-deepdive-agent',
'perf-optimization-agent',
'pr-review-agent',
'race-condition-agent',
'refactor-agent',
'smoke-agent',
'telemetry-agent',
'test-coverage-agent',
'weekly-synthesis-agent',
],
};
const DEFAULT_WEEKLY_ROSTER = [
'bug-reproducer-agent',
'integration-agent',
'release-agent',
'test-coverage-agent',
'weekly-synthesis-agent',
];
let cachedCanonicalRoster = null;
function getRelays() {
const envRelays = process.env.NOSTR_LOCK_RELAYS;
@@ -59,6 +93,31 @@ function getTtl() {
return DEFAULT_TTL;
}
function loadCanonicalRoster() {
if (cachedCanonicalRoster) return cachedCanonicalRoster;
try {
const parsed = JSON.parse(fs.readFileSync(ROSTER_FILE, 'utf8'));
const daily = Array.isArray(parsed.daily) ? parsed.daily.map((item) => String(item).trim()).filter(Boolean) : [];
const weekly = Array.isArray(parsed.weekly)
? parsed.weekly.map((item) => String(item).trim()).filter(Boolean)
: [];
if (daily.length > 0 && weekly.length > 0) {
cachedCanonicalRoster = { daily, weekly };
return cachedCanonicalRoster;
}
console.error(`WARNING: Roster file is missing daily/weekly entries, falling back: ${ROSTER_FILE}`);
} catch (err) {
console.error(`WARNING: Failed to read roster file (${ROSTER_FILE}): ${err.message}`);
}
cachedCanonicalRoster = FALLBACK_ROSTER;
return cachedCanonicalRoster;
}
function parseEnvRoster(value) {
if (!value) return null;
return value
@@ -70,12 +129,13 @@ function parseEnvRoster(value) {
function getRoster(cadence) {
const dailyFromEnv = parseEnvRoster(process.env.NOSTR_LOCK_DAILY_ROSTER);
const weeklyFromEnv = parseEnvRoster(process.env.NOSTR_LOCK_WEEKLY_ROSTER);
const canonical = loadCanonicalRoster();
if (cadence === 'daily') {
return dailyFromEnv && dailyFromEnv.length ? dailyFromEnv : DEFAULT_DAILY_ROSTER;
return dailyFromEnv && dailyFromEnv.length ? dailyFromEnv : canonical.daily;
}
return weeklyFromEnv && weeklyFromEnv.length ? weeklyFromEnv : DEFAULT_WEEKLY_ROSTER;
return weeklyFromEnv && weeklyFromEnv.length ? weeklyFromEnv : canonical.weekly;
}
function todayDateStr() {
@@ -178,6 +238,7 @@ async function cmdCheck(cadence) {
const locks = await queryLocks(relays, cadence, dateStr, namespace);
const lockedAgents = [...new Set(locks.map((l) => l.agent).filter(Boolean))];
const roster = getRoster(cadence);
const unknownLockedAgents = lockedAgents.filter((agent) => !roster.includes(agent));
const available = roster.filter((a) => !lockedAgents.includes(a));
console.log(
@@ -189,6 +250,7 @@ async function cmdCheck(cadence) {
locked: lockedAgents.sort(),
available: available.sort(),
lockCount: locks.length,
unknownLockedAgents: unknownLockedAgents.sort(),
locks: locks.map((l) => ({
agent: l.agent,
eventId: l.eventId,
@@ -215,6 +277,13 @@ async function cmdLock(agent, cadence, dryRun = false) {
console.error(`TTL: ${ttl}s, expires: ${new Date(expiresAt * 1000).toISOString()}`);
console.error(`Relays: ${relays.join(', ')}`);
const roster = getRoster(cadence);
if (!roster.includes(agent)) {
console.error(`ERROR: agent "${agent}" is not in the ${cadence} roster`);
console.error(`Allowed ${cadence} agents: ${roster.join(', ')}`);
process.exit(1);
}
console.error('Step 1: Checking for existing locks...');
const existingLocks = await queryLocks(relays, cadence, dateStr, namespace);
const conflicting = existingLocks.filter((l) => l.agent === agent);
@@ -341,8 +410,13 @@ async function cmdList(cadence) {
const roster = getRoster(c);
const lockedAgents = new Set(locks.map((l) => l.agent).filter(Boolean));
const unknownLockedAgents = [...lockedAgents].filter((agent) => !roster.includes(agent));
const available = roster.filter((a) => !lockedAgents.has(a));
if (unknownLockedAgents.length > 0) {
console.log(` Warning: lock events found with non-roster agent names: ${unknownLockedAgents.join(', ')}`);
}
console.log(`\n Locked: ${lockedAgents.size}/${roster.length}`);
console.log(` Available: ${available.join(', ') || '(none)'}`);
}
+2
View File
@@ -2,6 +2,8 @@
Use `src/prompts/scheduler-flow.md` as the authoritative scheduler procedure.
Canonical roster source: `src/prompts/roster.json` (`daily` key).
## Daily Cadence Configuration
- `cadence`: `daily`
+43
View File
@@ -0,0 +1,43 @@
{
"daily": [
"audit-agent",
"ci-health-agent",
"const-refactor-agent",
"content-audit-agent",
"decompose-agent",
"deps-security-agent",
"design-system-audit-agent",
"docs-agent",
"docs-alignment-agent",
"docs-code-investigator",
"innerhtml-migration-agent",
"known-issues-agent",
"load-test-agent",
"onboarding-audit-agent",
"perf-agent",
"prompt-curator-agent",
"protocol-research-agent",
"scheduler-update-agent",
"style-agent",
"test-audit-agent",
"todo-triage-agent"
],
"weekly": [
"bug-reproducer-agent",
"changelog-agent",
"dead-code-agent",
"event-schema-agent",
"frontend-console-debug-agent",
"fuzz-agent",
"interop-agent",
"perf-deepdive-agent",
"perf-optimization-agent",
"pr-review-agent",
"race-condition-agent",
"refactor-agent",
"smoke-agent",
"telemetry-agent",
"test-coverage-agent",
"weekly-synthesis-agent"
]
}
+2
View File
@@ -2,6 +2,8 @@
Use `src/prompts/scheduler-flow.md` as the authoritative scheduler procedure.
Canonical roster source: `src/prompts/roster.json` (`weekly` key).
## Weekly Cadence Configuration
- `cadence`: `weekly`