mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-10-27 07:51:52 +00:00
update
This commit is contained in:
1 parent
03b6725cfc
commit
2b8a0c3d0d
25 files changed
+1126
-5
No files matched your search
@@ -158,12 +158,20 @@ Configuration options:
|
||||
- `nostrLock.relays` (array of relay URLs)
|
||||
- `nostrLock.ttlSeconds` (lock duration in seconds)
|
||||
- `nostrLock.queryTimeoutMs` (timeout for relay queries)
|
||||
- `nostrLock.publishTimeoutMs` (per-relay publish timeout in ms)
|
||||
- `nostrLock.minSuccessfulRelayPublishes` (minimum successful publishes before lock continues, default: `1`)
|
||||
- `nostrLock.relayFallbacks` (optional fallback relay URLs used when primary relays fail quorum)
|
||||
- `nostrLock.minActiveRelayPool` (minimum relays kept active even when others are quarantined, default: `1`)
|
||||
- `nostrLock.dailyRoster` / `nostrLock.weeklyRoster` (explicit rosters)
|
||||
- `dashboard.defaultCadenceView` (`daily`, `weekly`, or `all`)
|
||||
- `dashboard.defaultStatusView` (`active` or `all`)
|
||||
- `dashboard.hashtag` (custom hashtag for lock events)
|
||||
- `scheduler.firstPromptByCadence.daily` / `.weekly` (first prompt to run)
|
||||
- `scheduler.handoffCommandByCadence.daily` / `.weekly` (shell command run after lock acquisition; must use `SCHEDULER_AGENT`, `SCHEDULER_CADENCE`, `SCHEDULER_PROMPT_PATH` env vars)
|
||||
- `scheduler.paused.daily` / `.weekly` (array of agent names to pause locally)
|
||||
- `scheduler.strict_lock` (lock backend policy; when `false`, defers backend-unavailable failures before failing, default: `true`)
|
||||
- `scheduler.degraded_lock_retry_window` (ms window for non-strict deferral of backend failures)
|
||||
- `scheduler.max_deferrals` (max non-strict lock deferrals before recording a hard failure)
|
||||
|
||||
### Dashboard
|
||||
|
||||
@@ -201,6 +209,10 @@ You can override configuration using environment variables:
|
||||
- `NOSTR_LOCK_RELAYS` (comma-separated)
|
||||
- `NOSTR_LOCK_TTL`
|
||||
- `NOSTR_LOCK_QUERY_TIMEOUT_MS`
|
||||
- `NOSTR_LOCK_PUBLISH_TIMEOUT_MS`
|
||||
- `NOSTR_LOCK_MIN_SUCCESSFUL_PUBLISHES`
|
||||
- `NOSTR_LOCK_RELAY_FALLBACKS` (comma-separated fallback relay URLs)
|
||||
- `NOSTR_LOCK_MIN_ACTIVE_RELAY_POOL`
|
||||
- `NOSTR_LOCK_DAILY_ROSTER` (comma-separated list of agents)
|
||||
- `NOSTR_LOCK_WEEKLY_ROSTER` (comma-separated list of agents)
|
||||
- `TORCH_CONFIG_PATH` (path to config file)
|
||||
|
||||
@@ -7,7 +7,7 @@ This document identifies areas of the TORCH repository that lack specific agent
|
||||
| Gap | Evidence | Proposed Agent |
|
||||
| :--- | :--- | :--- |
|
||||
| **Database Migrations** | `migrations/` directory and SQL files present. | `migration-agent` |
|
||||
| **E2E Testing** | `playwright` dependency and `test/` integration files. | `e2e-agent` |
|
||||
| **E2E Testing** | `test/` integration/e2e files (Node.js `--test`). | `e2e-agent` |
|
||||
| **Memory Subsystem** | `scripts/memory/`, `.scheduler-memory/` exist. | `memory-health-agent` |
|
||||
| **Relay Stability** | `src/relay-health.mjs` and known relay flakiness. | `relay-health-agent` |
|
||||
| **Skills Management** | `skills/` directory and `torch-basics.md`. | `skills-agent` |
|
||||
@@ -24,8 +24,8 @@ This document identifies areas of the TORCH repository that lack specific agent
|
||||
- **Priority**: Medium
|
||||
|
||||
### 2. `e2e-agent`
|
||||
- **Gap**: `playwright` is used for dashboard and integration testing, but no agent is dedicated to scenario maintenance.
|
||||
- **Mission**: Maintain Playwright E2E scenarios, fix flaky tests, and ensure the dashboard remains functional across protocol changes.
|
||||
- **Gap**: E2E/integration tests exist (e.g., `test/scheduler-preflight-lock.e2e.test.mjs` via Node.js `--test`), but no agent is dedicated to scenario maintenance.
|
||||
- **Mission**: Maintain E2E scenarios, fix flaky tests, and ensure the dashboard and scheduler flow remain functional across protocol changes.
|
||||
- **Priority**: High (given the "Scenario-First" mandate in `AGENTS.md`)
|
||||
|
||||
### 3. `memory-health-agent`
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
# Docs Agent: README/TORCH.md Synchronization Pattern
|
||||
|
||||
- **Context:** docs-agent run 2026-02-20. Audited README.md, CONTRIBUTING.md, AGENTS.md against package.json, src/, and TORCH.md.
|
||||
- **Observation:** `TORCH.md` is the authoritative configuration and env-var reference. `README.md` had drifted and was missing 4 env vars and 8 `torch-config.json` keys present in TORCH.md and verified in `src/torch-config.mjs`.
|
||||
- **Action taken:** Added missing items to README.md's "Environment variables" and "Configuration" sections. No changes to CONTRIBUTING.md or AGENTS.md — both were accurate.
|
||||
- **Validation performed:** Grep confirmed all 4 missing env vars are used in `src/torch-config.mjs`. All referenced file paths verified to exist via Glob.
|
||||
- **Recommendation for next agents:**
|
||||
1. When updating env vars or torch-config keys in TORCH.md or `src/torch-config.mjs`, also update README.md's matching sections.
|
||||
2. CONTRIBUTING.md is minimal and accurate — only update if new scripts are added to package.json.
|
||||
3. AGENTS.md is a policy-only file — do not edit it for accuracy; open an issue if policy appears wrong.
|
||||
4. The 4 env vars most often missed in README: `NOSTR_LOCK_PUBLISH_TIMEOUT_MS`, `NOSTR_LOCK_MIN_SUCCESSFUL_PUBLISHES`, `NOSTR_LOCK_RELAY_FALLBACKS`, `NOSTR_LOCK_MIN_ACTIVE_RELAY_POOL`.
|
||||
@@ -0,0 +1,15 @@
|
||||
# Docs Alignment Agent: Claims Tracing Pattern
|
||||
|
||||
- **Context:** docs-alignment-agent run 2026-02-20. Daily pass auditing docs/lib-overview.md, docs/lock-ops-overview.md, docs/memory-index-overview.md, docs/removal.md, docs/architecture/system-overview.md, docs/AGENT_COVERAGE_GAPS.md, src/constants.mjs USAGE_TEXT.
|
||||
- **Observation:** Four confirmed doc/code divergences found and fixed:
|
||||
1. `docs/lib-overview.md` claimed RACE_CHECK_DELAY_MS = 2000ms; actual is 1500ms (src/constants.mjs:2).
|
||||
2. `src/constants.mjs` USAGE_TEXT said `NOSTR_LOCK_QUERY_TIMEOUT_MS` default is 15000; actual default is 30000 (`DEFAULT_QUERY_TIMEOUT_MS`). The 15000 value matches `DEFAULT_PUBLISH_TIMEOUT_MS` — likely copy-paste confusion between the two timeouts.
|
||||
3. `docs/removal.md` env var cleanup list was missing 4 vars: `NOSTR_LOCK_PUBLISH_TIMEOUT_MS`, `NOSTR_LOCK_MIN_SUCCESSFUL_PUBLISHES`, `NOSTR_LOCK_RELAY_FALLBACKS`, `NOSTR_LOCK_MIN_ACTIVE_RELAY_POOL`.
|
||||
4. `docs/AGENT_COVERAGE_GAPS.md` claimed "playwright dependency" — Playwright is not in package.json; E2E tests use Node.js built-in `--test` runner.
|
||||
- **Action taken:** Fixed all four issues with minimal, targeted edits.
|
||||
- **Validation performed:** Grep confirmed exact corrected values in all edited files post-edit.
|
||||
- **Recommendation for next agents:**
|
||||
1. When auditing docs, always trace numeric constants (timeouts, delays, counts) to `src/constants.mjs` — these drift most often.
|
||||
2. The USAGE_TEXT in `src/constants.mjs` is the CLI `--help` string — verify its defaults match the exported constants above it.
|
||||
3. `docs/removal.md` env var list must stay in sync with `src/torch-config.mjs` — the four new relay-reliability vars are the most commonly missed.
|
||||
4. When AGENT_COVERAGE_GAPS.md mentions technology dependencies, verify against `package.json` before trusting the claim.
|
||||
@@ -0,0 +1,11 @@
|
||||
# Learning: Scheduler Cycle File Documentation Patterns
|
||||
|
||||
- **Context:** docs-code-investigator run 2026-02-20. Documented `scripts/agent/run-scheduler-cycle.mjs` (926 lines) with JSDoc, inline comments, and `docs/scheduler-cycle-overview.md`.
|
||||
- **Observation:** The file's logic precisely mirrors the 19 numbered steps in `src/prompts/scheduler-flow.md`. The top-of-file comment already referenced scheduler-flow.md but didn't enumerate the steps — adding them makes the code immediately navigable.
|
||||
- **Action taken:** Added module-level JSDoc with 19-step flow, JSDoc to 15 internal functions, targeted inline comments, and a full overview doc.
|
||||
- **Validation performed:** Static read of full 926-line file. Call graph traced to scheduler-utils.mjs, scheduler-lock.mjs, src/utils.mjs, roster.json, and test files.
|
||||
- **Recommendation for next agents:**
|
||||
1. When documenting scheduler-related files, always cross-reference `src/prompts/scheduler-flow.md` — it is the spec; the code implements it.
|
||||
2. The most non-obvious invariant: lock:complete is called ONLY after all validation gates pass. Document this explicitly when touching the scheduler.
|
||||
3. Three test files cover scheduler behavior: run-scheduler-cycle-memory-policy.test.mjs, scheduler-time-window.test.mjs, scheduler-preflight-lock.e2e.test.mjs. Run all three when changing scheduler logic.
|
||||
4. `task-logs/<cadence>/.scheduler-run-state.json` is day-scoped (resets at midnight UTC). Do not treat it as persistent cross-day storage.
|
||||
@@ -40,7 +40,7 @@ Displays a CLI-friendly table of active locks.
|
||||
- Content: JSON payload with metadata.
|
||||
4. **Publish**: Send to all configured relays.
|
||||
5. **Race Check**:
|
||||
- Wait `RACE_CHECK_DELAY_MS` (default 2000ms).
|
||||
- Wait `RACE_CHECK_DELAY_MS` (default 1500ms).
|
||||
- Query relays again.
|
||||
- If another valid event exists with an *earlier* `created_at`: **Abort** (Race lost).
|
||||
- Otherwise: **Success**.
|
||||
|
||||
@@ -106,6 +106,10 @@ If you configured TORCH environment variables in your shell profile, CI, or `.en
|
||||
- `NOSTR_LOCK_RELAYS`
|
||||
- `NOSTR_LOCK_TTL`
|
||||
- `NOSTR_LOCK_QUERY_TIMEOUT_MS`
|
||||
- `NOSTR_LOCK_PUBLISH_TIMEOUT_MS`
|
||||
- `NOSTR_LOCK_MIN_SUCCESSFUL_PUBLISHES`
|
||||
- `NOSTR_LOCK_RELAY_FALLBACKS`
|
||||
- `NOSTR_LOCK_MIN_ACTIVE_RELAY_POOL`
|
||||
- `NOSTR_LOCK_DAILY_ROSTER`
|
||||
- `NOSTR_LOCK_WEEKLY_ROSTER`
|
||||
- `TORCH_CONFIG_PATH`
|
||||
|
||||
@@ -0,0 +1,262 @@
|
||||
# Scheduler Cycle Overview (`scripts/agent/run-scheduler-cycle.mjs`)
|
||||
|
||||
## What this module does
|
||||
|
||||
`run-scheduler-cycle.mjs` is the main scheduler entry point. Given a cadence
|
||||
(`daily` or `weekly`), it selects the next eligible agent from the roster,
|
||||
acquires a distributed Nostr lock to prevent duplicate execution across agents,
|
||||
runs the selected agent's prompt via a configured handoff command, verifies that
|
||||
required run artifacts and memory evidence were produced, then publishes task
|
||||
completion.
|
||||
|
||||
This script owns the full agent lifecycle for one slot per invocation:
|
||||
lock acquisition → prompt execution → artifact/memory verification → lock:complete.
|
||||
Spawned agents must **not** call `lock:complete` themselves — the scheduler does it
|
||||
after all validation passes.
|
||||
|
||||
## Where it fits
|
||||
|
||||
```
|
||||
npm run scheduler:daily
|
||||
└─ scripts/agent/run-scheduler-cycle.mjs daily
|
||||
├─ src/prompts/roster.json (agent list)
|
||||
├─ torch-config.json (handoff command, memory policy, etc.)
|
||||
├─ scripts/agent/scheduler-utils.mjs
|
||||
├─ scripts/agent/scheduler-lock.mjs
|
||||
├─ npm run lock:check:daily (relay query)
|
||||
├─ npm run lock:lock (relay publish)
|
||||
├─ <handoffCommand> (spawns the agent)
|
||||
├─ scripts/agent/verify-run-artifacts.mjs
|
||||
└─ npm run lock:complete (relay publish, permanent)
|
||||
```
|
||||
|
||||
## Typical call flow
|
||||
|
||||
```
|
||||
1. Parse args → cadence='daily', platform='codex', model=null
|
||||
|
||||
2. Load roster from src/prompts/roster.json → ['audit-agent', 'docs-agent', ...]
|
||||
|
||||
3. Read AGENTS.md → print to stdout (best-effort; non-fatal if missing)
|
||||
|
||||
4. [LOOP] Read run-state → { run_date: '2026-02-20', lock_deferral: null }
|
||||
|
||||
5. [LOOP] Lock health preflight (if enabled):
|
||||
npm run lock:health -- --cadence daily
|
||||
→ non-zero: write _deferred.md or _failed.md, exit
|
||||
|
||||
6. [LOOP] npm run lock:check:daily -- --json --quiet
|
||||
→ exclusion set: { locked: ['ci-health-agent'], paused: [], completed: [] }
|
||||
|
||||
7. [LOOP] Time-window guard: exclude agents that ran within 24h window
|
||||
|
||||
8. [LOOP] Round-robin select:
|
||||
roster = ['audit-agent', 'ci-health-agent', 'docs-agent', ...]
|
||||
previous = 'ci-health-agent' (from latest log)
|
||||
excluded = { 'ci-health-agent' }
|
||||
→ selected = 'docs-agent'
|
||||
|
||||
9. [LOOP] npm run lock:lock -- --agent docs-agent --cadence daily
|
||||
→ exit 0: lock acquired (continue)
|
||||
→ exit 3: race lost (restart loop at step 4)
|
||||
→ exit 2: backend error → defer (non-strict) or fail (strict)
|
||||
|
||||
10. [LOOP] Validate src/prompts/daily/docs-agent.md
|
||||
→ not readable → _failed.md (prompt_parse_error), exit 1
|
||||
→ bad first line → _failed.md (prompt_schema_error), exit 1
|
||||
|
||||
11. [LOOP] Clear deferral state. Run memory retrieve command (if configured).
|
||||
|
||||
12. [LOOP] Run handoff command (e.g. `claude --prompt "$SCHEDULER_PROMPT_PATH"`)
|
||||
→ non-zero → _failed.md (execution_error), exit non-zero
|
||||
→ missing → _failed.md, exit 1
|
||||
|
||||
13. [LOOP] Run memory store command (if configured).
|
||||
|
||||
14. [LOOP] Verify memory evidence (markers/artifacts):
|
||||
→ mode='required' + missing → _failed.md, exit 1
|
||||
→ mode='optional' + missing → console.warn, continue
|
||||
|
||||
15. [LOOP] node scripts/agent/verify-run-artifacts.mjs --since <runStart>
|
||||
→ non-zero → _failed.md (prompt_schema_error), exit non-zero
|
||||
|
||||
16. [LOOP] npm run lint (or configured validationCommands)
|
||||
→ non-zero → _failed.md (execution_error), exit non-zero
|
||||
|
||||
17. [LOOP] npm run lock:complete -- --agent docs-agent --cadence daily
|
||||
→ non-zero → _failed.md, exit non-zero
|
||||
|
||||
18. [LOOP] Write _completed.md task log. Print run summary. Exit 0.
|
||||
```
|
||||
|
||||
## Public API summary
|
||||
|
||||
This is a CLI script — it has no exported functions. The entry point is:
|
||||
|
||||
```bash
|
||||
node scripts/agent/run-scheduler-cycle.mjs <daily|weekly> [--platform <p>] [--model <m>]
|
||||
# or via npm:
|
||||
npm run scheduler:daily
|
||||
npm run scheduler:weekly
|
||||
```
|
||||
|
||||
**Environment variables:**
|
||||
|
||||
| Variable | Source | Purpose |
|
||||
|----------|--------|---------|
|
||||
| `AGENT_PLATFORM` | env | Platform identifier (codex, claude, linux) |
|
||||
| `AGENT_MODEL` | env | Model identifier forwarded to lock events |
|
||||
| `SCHEDULER_LOCK_MAX_RETRIES` | env | Override lock:lock retry count (default: 2) |
|
||||
| `SCHEDULER_LOCK_BACKOFF_MS` | env | Override base backoff ms (default: 250) |
|
||||
| `SCHEDULER_LOCK_JITTER_MS` | env | Override jitter ms (default: 75) |
|
||||
| `SCHEDULER_LOCK_HEALTH_PREFLIGHT` | env | Enable/disable relay health preflight |
|
||||
| `SCHEDULER_SKIP_LOCK_HEALTH_PREFLIGHT` | env | Skip preflight even if enabled |
|
||||
| `SCHEDULER_STRICT_LOCK` | env | Override strict_lock policy |
|
||||
| `SCHEDULER_DEGRADED_LOCK_RETRY_WINDOW_MS` | env | Override deferral window ms |
|
||||
| `SCHEDULER_MAX_DEFERRALS` | env | Override max deferral count |
|
||||
|
||||
**Variables injected into child processes:**
|
||||
|
||||
| Variable | Value | Purpose |
|
||||
|----------|-------|---------|
|
||||
| `SCHEDULER_AGENT` | selected agent name | Used by handoff/memory commands |
|
||||
| `SCHEDULER_CADENCE` | `daily`\|`weekly` | Used by handoff/memory commands |
|
||||
| `SCHEDULER_PROMPT_PATH` | absolute path | Path to prompt file |
|
||||
| `SCHEDULER_MEMORY_FILE` | absolute path | Agent writes learnings here |
|
||||
|
||||
## Key internal functions
|
||||
|
||||
| Function | Purpose |
|
||||
|----------|---------|
|
||||
| `parseArgs(argv)` | Parses cadence, platform, model from CLI args |
|
||||
| `getSchedulerConfig(cadence, opts)` | Merges torch-config.json + env overrides |
|
||||
| `readRunState(cadence)` / `writeRunState(path, state)` | Deferral state persistence (day-scoped) |
|
||||
| `getLatestFile(logDir)` | Finds most recent valid task log for previous-agent detection |
|
||||
| `selectNextAgent({roster, excludedSet, previousAgent, firstPrompt})` | Round-robin with exclusion |
|
||||
| `validatePromptFile(promptPath)` | Reads and validates prompt format |
|
||||
| `verifyMemoryStep({name, markers, artifacts, outputText, sinceMs})` | Evidence check |
|
||||
| `writeLog({cadence, agent, status, ...})` | Writes YAML-frontmatter task log file |
|
||||
| `exitWithSummary(code, data)` | Prints summary + calls process.exit |
|
||||
|
||||
## Key invariants
|
||||
|
||||
1. **lock:complete gate**: `npm run lock:complete` is called only after memory
|
||||
verification (step 14), artifact verification (step 15), and all validation
|
||||
commands (step 16) pass. If any gate fails, the run ends without publishing
|
||||
completion.
|
||||
|
||||
2. **Completed log gate**: `_completed.md` task log is written only after
|
||||
lock:complete exits 0 (step 17). Earlier failures always write `_failed.md`
|
||||
or `_deferred.md`.
|
||||
|
||||
3. **Race resolution**: Lock exit code 3 (race lost) causes the scheduler to
|
||||
restart the loop at step 4, re-checking what agents are available. This is
|
||||
the normal race resolution path — not an error.
|
||||
|
||||
4. **Time-window guard**: Agents that appear in a recent local log (within 24h
|
||||
for daily, 7d for weekly) are added to the exclusion set regardless of relay
|
||||
state. This handles the cross-midnight edge case where the relay date-scope
|
||||
has rolled over.
|
||||
|
||||
5. **Cycle saturation**: When all roster agents are in the time-window exclusion
|
||||
set, the scheduler exits 0 with a "cycle complete" reason — not treated as
|
||||
an error by cron/CI.
|
||||
|
||||
6. **Deferral state is day-scoped**: `task-logs/<cadence>/.scheduler-run-state.json`
|
||||
is reset whenever `run_date` changes, so deferral budgets do not carry across days.
|
||||
|
||||
## Edge cases & error paths
|
||||
|
||||
| Scenario | Behavior |
|
||||
|----------|----------|
|
||||
| No roster entries | `process.exit(1)` before loop |
|
||||
| Roster fully excluded (not cycle-saturated) | `_failed.md` + exit 1 |
|
||||
| All relays unhealthy (preflight) | `_deferred.md` + exit 0 |
|
||||
| Lock backend error (strict mode) | `_failed.md` + exit 2 |
|
||||
| Lock backend error (non-strict, within window/budget) | `_deferred.md` + exit 0; deferral state persisted |
|
||||
| Lock backend error (non-strict, budget exhausted) | `_failed.md` + exit 2 |
|
||||
| Prompt file missing or unreadable | `_failed.md (prompt_parse_error)` + exit 1 |
|
||||
| Prompt first line not `#` or `>` | `_failed.md (prompt_schema_error)` + exit 1 |
|
||||
| handoffCommand missing (non-interactive mode) | `_failed.md (execution_error)` + exit 1 |
|
||||
| handoffCommand exits non-zero | `_failed.md (execution_error)` + exit non-zero |
|
||||
| Memory evidence missing (required mode) | `_failed.md (prompt_schema_error)` + exit 1 |
|
||||
| Memory evidence missing (optional mode) | console.warn, continue |
|
||||
| Artifact verification fails | `_failed.md (prompt_schema_error)` + exit non-zero |
|
||||
| Validation command exits non-zero | `_failed.md (execution_error)` + exit non-zero |
|
||||
| lock:complete exits non-zero | `_failed.md` + exit non-zero |
|
||||
|
||||
## Security considerations
|
||||
|
||||
- ⚠️ Environment variables injected into child processes (`SCHEDULER_AGENT`,
|
||||
`SCHEDULER_CADENCE`, `SCHEDULER_PROMPT_PATH`, `SCHEDULER_MEMORY_FILE`) are derived
|
||||
from the roster and config — not from user input. No sanitization issue here, but
|
||||
ensure `torch-config.json` is not writable by untrusted parties.
|
||||
- The handoff command is executed via `bash -lc` with a login shell. The command
|
||||
string comes from `torch-config.json`. Do not allow untrusted config sources.
|
||||
- No cryptographic or signing logic in this file.
|
||||
|
||||
## Performance & concurrency
|
||||
|
||||
- The loop is single-threaded and sequential; no parallel lock attempts.
|
||||
- Each iteration makes several network calls (lock:check, lock:lock, lock:complete)
|
||||
that may take seconds each. Total wall-clock time per cycle depends heavily on
|
||||
relay latency and handoff command duration.
|
||||
- `getLatestFile()` reads all log filenames and file contents synchronously in
|
||||
memory — acceptable for typical log counts (< 1000 files) but worth monitoring
|
||||
if logs accumulate without rotation.
|
||||
|
||||
## Related files and call graph
|
||||
|
||||
| File | Relationship |
|
||||
|------|-------------|
|
||||
| `scripts/agent/scheduler-utils.mjs` | Utility functions (runCommand, readJson, parsers, etc.) |
|
||||
| `scripts/agent/scheduler-lock.mjs` | Lock acquisition, error classification, preflight |
|
||||
| `scripts/agent/verify-run-artifacts.mjs` | Run artifact validation (called as subprocess) |
|
||||
| `scripts/agent/scheduler-utils.mjs:buildRecentlyRunExclusionSet` | Time-window guard |
|
||||
| `src/utils.mjs:detectPlatform` | Auto-detects agent platform |
|
||||
| `src/prompts/roster.json` | Agent roster (read at startup) |
|
||||
| `src/prompts/scheduler-flow.md` | Authoritative numbered steps (implemented by this script) |
|
||||
| `torch-config.json` | Handoff command, memory policy, lock policy |
|
||||
| `task-logs/<cadence>/` | Task logs written and read here |
|
||||
| `task-logs/<cadence>/.scheduler-run-state.json` | Deferral state (day-scoped) |
|
||||
| `memory-updates/` | Memory update files (written path injected as env var) |
|
||||
|
||||
## Why it works this way
|
||||
|
||||
- **Infinite loop with restart on race loss**: Distributed lock systems inherently
|
||||
have races; the loop lets the scheduler immediately try the next available agent
|
||||
without requiring the caller to re-invoke the script.
|
||||
- **Day-scoped run-state**: Deferral tracking needs to persist across multiple rapid
|
||||
scheduler invocations on the same day (e.g., cron every 5 minutes) but should
|
||||
reset daily so a failed relay doesn't block the next day's run.
|
||||
- **lock:complete gated behind all validation**: Ensures a completion event on the
|
||||
relay (which prevents future agents from re-running the same slot) is only
|
||||
published after the run is genuinely finished and verified. This prevents
|
||||
"green-but-worthless" completions.
|
||||
- **Subprocess model for handoff**: Agents run in their own process with
|
||||
environment variables injected by the scheduler. This isolates agent crashes
|
||||
and allows the scheduler to check exit codes cleanly.
|
||||
|
||||
## When to change
|
||||
|
||||
- **New validation gate**: Add a step between artifact check and lock:complete.
|
||||
Maintain the gate ordering: memory evidence → artifact check → validation → lock:complete.
|
||||
- **New failure category**: Add to the `FAILURE_CATEGORY` constant and document
|
||||
in `src/prompts/scheduler-flow.md`.
|
||||
- **New config option**: Add parsing in `getSchedulerConfig()` with an env var
|
||||
override following the existing pattern.
|
||||
- **Log format change**: Update `writeLog()` — also update `verify-run-artifacts.mjs`
|
||||
and `scheduler-utils.mjs:parseFrontmatterAgent` to match.
|
||||
|
||||
## Tests that validate behavior
|
||||
|
||||
- `test/run-scheduler-cycle-memory-policy.test.mjs` — memory policy enforcement
|
||||
- `test/scheduler-time-window.test.mjs` — time-window guard behavior
|
||||
- `test/scheduler-preflight-lock.e2e.test.mjs` — preflight + lock flow
|
||||
|
||||
```bash
|
||||
# Run all scheduler tests:
|
||||
node --test test/run-scheduler-cycle-memory-policy.test.mjs test/scheduler-time-window.test.mjs
|
||||
# Or full suite (may be slow in sandbox):
|
||||
npm test
|
||||
```
|
||||
@@ -0,0 +1,18 @@
|
||||
# Memory Update — docs-agent — 2026-02-20
|
||||
|
||||
## Key findings
|
||||
|
||||
- `TORCH.md` is the authoritative env-var and torch-config.json reference; README.md is consumer-facing and drifts from TORCH.md when new config keys are added.
|
||||
- `CONTRIBUTING.md` is accurate; all commands verified against `package.json` (no `npm run format` script exists in this project — only `npm run lint`).
|
||||
- `AGENTS.md` is a policy document only; do not edit it for accuracy.
|
||||
|
||||
## Patterns / reusable knowledge
|
||||
|
||||
- When auditing docs: diff README.md "Environment variables" and "Configuration" sections against TORCH.md as the ground truth; also grep `src/torch-config.mjs` to confirm env var usage.
|
||||
- Run artifact YAML frontmatter must include `agent:`, `cadence:`, and `run-start:` — missing any of these causes `verify-run-artifacts.mjs` to fail.
|
||||
- Glob is the right tool for path existence checks; Grep confirms env var/config key usage in source.
|
||||
|
||||
## Warnings / gotchas
|
||||
|
||||
- Claude Code sandbox blocks outbound WebSockets — cannot run lock commands or relay health checks; document this limitation in test logs.
|
||||
- All 4 missing env vars that were added to README.md: `NOSTR_LOCK_PUBLISH_TIMEOUT_MS`, `NOSTR_LOCK_MIN_SUCCESSFUL_PUBLISHES`, `NOSTR_LOCK_RELAY_FALLBACKS`, `NOSTR_LOCK_MIN_ACTIVE_RELAY_POOL`.
|
||||
@@ -0,0 +1,18 @@
|
||||
# Memory Update — docs-alignment-agent — 2026-02-20
|
||||
|
||||
## Key findings
|
||||
|
||||
- `src/constants.mjs` is the single source of truth for numeric defaults (RACE_CHECK_DELAY_MS=1500, DEFAULT_QUERY_TIMEOUT_MS=30000, DEFAULT_PUBLISH_TIMEOUT_MS=15000). Docs frequently show stale values — always re-verify these numbers.
|
||||
- USAGE_TEXT in `src/constants.mjs` (displayed by `torch-lock --help`) had a wrong default for `NOSTR_LOCK_QUERY_TIMEOUT_MS`: said 15000 but constant is 30000. This was likely copy-paste of the publish timeout value.
|
||||
- `docs/AGENT_COVERAGE_GAPS.md` tech claims can be stale — verify against `package.json` (Playwright was not present despite being claimed as a dependency).
|
||||
|
||||
## Patterns / reusable knowledge
|
||||
|
||||
- **Claims tracing sequence:** Read doc → extract numeric/behavioral claim → Grep `src/constants.mjs` for actual constant → compare. Repeat for every timeout/delay/count.
|
||||
- **Four env vars most likely to be missing from lists:** `NOSTR_LOCK_PUBLISH_TIMEOUT_MS`, `NOSTR_LOCK_MIN_SUCCESSFUL_PUBLISHES`, `NOSTR_LOCK_RELAY_FALLBACKS`, `NOSTR_LOCK_MIN_ACTIVE_RELAY_POOL`. Check `docs/removal.md`, README.md, and any other env-var reference lists.
|
||||
- Architecture file paths in `docs/architecture/system-overview.md` are accurate and do not need re-verification unless new files are added.
|
||||
|
||||
## Warnings / gotchas
|
||||
|
||||
- Claude Code sandbox: outbound WebSocket/EPERM restrictions prevent `npm run lint` and `npm test` — document this in test_logs but do not treat it as a failure for docs-only changes.
|
||||
- The 2000ms RACE_CHECK_DELAY_MS value may appear in other agents' memory or notes — it is wrong; actual value is 1500ms.
|
||||
@@ -0,0 +1,18 @@
|
||||
# Memory Update — docs-code-investigator — 2026-02-20
|
||||
|
||||
## Key findings
|
||||
|
||||
- `scripts/agent/run-scheduler-cycle.mjs` (926 lines) is now documented with a 19-step module JSDoc + JSDoc on all 15 internal functions + `docs/scheduler-cycle-overview.md`. Do not re-document this file on next run.
|
||||
- The scheduler's key invariant: lock:complete is called ONLY after memory evidence check, artifact check, and all validation commands pass. This ordering is critical and must be preserved in any scheduler modification.
|
||||
- `src/prompts/scheduler-flow.md` is the spec; `run-scheduler-cycle.mjs` implements it. Step numbers in scheduler-flow.md map directly to code sections.
|
||||
|
||||
## Patterns / reusable knowledge
|
||||
|
||||
- **File selection heuristic:** run `git ls-files '*.js' '*.mjs' | xargs -n1 wc -l | sort -rn | head -20`, then subtract files already covered by `docs/*-overview.md`. Next best undocumented large files: `src/ops.mjs` (795 lines), `scripts/agent/scheduler-utils.mjs` (321 lines).
|
||||
- **JSDoc insertion:** Use Edit tool with targeted old_string/new_string to insert JSDoc above each function. Do not use Write to rewrite the whole file — too risky for a 926-line file.
|
||||
- **Docs style:** Match existing overview docs (`docs/lib-overview.md`, `docs/lock-ops-overview.md`) — sections: What it does / Where it fits / Typical call flow / Public API / Key invariants / Edge cases / Security / Related files / Why / When to change / Tests.
|
||||
|
||||
## Warnings / gotchas
|
||||
|
||||
- `npm run lint` and `npm test` not runnable in Claude Code sandbox. For documentation-only changes this is acceptable — document it in TEST_LOG but don't treat as blocking.
|
||||
- `CONTEXT_20260220T041302Z.md` already exists in src/context/ (owned by prompt-maintenance-agent). Use a different timestamp for docs-code-investigator artifacts.
|
||||
@@ -1,4 +1,43 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* run-scheduler-cycle.mjs — TORCH Agent Scheduler
|
||||
*
|
||||
* Orchestrates one full scheduling cycle for a given cadence (daily|weekly).
|
||||
* Selects the next eligible agent from the roster, acquires a distributed Nostr
|
||||
* lock, executes the agent's prompt via a configured handoff command, verifies
|
||||
* required artifacts and memory evidence, then publishes completion.
|
||||
*
|
||||
* This script owns the full lifecycle for a single agent slot per invocation:
|
||||
* lock acquisition → prompt execution → artifact verification → lock:complete.
|
||||
* Spawned agents MUST NOT call lock:complete themselves.
|
||||
*
|
||||
* Main flow (mirrors src/prompts/scheduler-flow.md numbered MUST steps):
|
||||
* 1. Parse cadence (daily|weekly), platform, and model from CLI args.
|
||||
* 2. Load roster from src/prompts/roster.json.
|
||||
* 3. Read AGENTS.md policy file (best-effort, non-fatal if missing).
|
||||
* 4. [loop] Read cadence run-state (deferral tracking for the current UTC day).
|
||||
* 5. [loop] Optional lock health preflight — fail/defer if all relays unhealthy.
|
||||
* 6. [loop] Run lock:check to build the exclusion set (locked + paused + completed).
|
||||
* 7. [loop] Apply local time-window guard (24 h daily / 7 d weekly) to exclusion set.
|
||||
* 8. [loop] Round-robin select next eligible agent from roster minus exclusion set.
|
||||
* 9. [loop] If no agent eligible → exit (cycle-saturated or all-excluded).
|
||||
* 10. [loop] Acquire lock with retry. exit 3 → back to step 4; exit 2 → defer or fail.
|
||||
* 11. [loop] Validate prompt file (readable, correct format).
|
||||
* 12. [loop] Clear deferral state. Run memory retrieve command (if configured).
|
||||
* 13. [loop] Run handoff command — hard fail if missing or exits non-zero.
|
||||
* 14. [loop] Run memory store command (if configured).
|
||||
* 15. [loop] Verify memory evidence (markers/artifact files).
|
||||
* 16. [loop] Verify run artifacts via verify-run-artifacts.mjs.
|
||||
* 17. [loop] Run validation commands (default: npm run lint).
|
||||
* 18. [loop] Publish lock:complete — hard fail if relay error.
|
||||
* 19. [loop] Write completed task log and print run summary. Exit 0.
|
||||
*
|
||||
* Key invariants:
|
||||
* - lock:complete is called ONLY after all validation gates pass (step 18 is last gate).
|
||||
* - Completed task log is written ONLY after lock:complete succeeds.
|
||||
* - Lock exit code 3 (race lost) causes a loop restart to pick the next agent.
|
||||
* - Memory mode 'required' turns missing evidence into a hard failure.
|
||||
*/
|
||||
// Source of truth: numbered MUST steps 2 and 4-16 in src/prompts/scheduler-flow.md are
|
||||
// implemented by this script; step 3 (policy-file read) is best-effort and non-fatal.
|
||||
import fs from 'node:fs/promises';
|
||||
@@ -43,6 +82,14 @@ const FAILURE_CATEGORY = {
|
||||
EXECUTION: 'execution_error',
|
||||
};
|
||||
|
||||
/**
|
||||
* Parses CLI arguments into a structured options object.
|
||||
* Supports both positional cadence (`daily`|`weekly`) and named flags.
|
||||
* Falls back to AGENT_PLATFORM env var or auto-detected platform for platform.
|
||||
*
|
||||
* @param {string[]} argv - process.argv slice (args after the script name)
|
||||
* @returns {{ cadence: string|null, platform: string, model: string|null }}
|
||||
*/
|
||||
function parseArgs(argv) {
|
||||
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) {
|
||||
@@ -68,10 +115,25 @@ function parseArgs(argv) {
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an ISO 8601 timestamp string safe for use as a filename component.
|
||||
* Colons are replaced with dashes and milliseconds are stripped.
|
||||
* Example output: `2026-02-20T07-00-00Z`
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
function ts() {
|
||||
return new Date().toISOString().replace(/\.\d{3}Z$/, 'Z').replace(/:/g, '-');
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a metadata object that includes a standardized `failure_category` field.
|
||||
* Used by writeLog() to attach structured failure classification to task logs.
|
||||
*
|
||||
* @param {string} failureCategory - One of FAILURE_CATEGORY values (e.g. 'lock_backend_error').
|
||||
* @param {Object} [extraMetadata={}] - Additional key/value pairs to merge.
|
||||
* @returns {Object}
|
||||
*/
|
||||
function categorizeFailureMetadata(failureCategory, extraMetadata = {}) {
|
||||
return {
|
||||
failure_category: failureCategory,
|
||||
@@ -79,6 +141,16 @@ function categorizeFailureMetadata(failureCategory, extraMetadata = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a prompt file is readable and contains a valid markdown heading
|
||||
* or blockquote as its first non-empty line.
|
||||
*
|
||||
* This is a lightweight schema check — it does not parse frontmatter or validate
|
||||
* the full prompt contract (that is handled by validate-prompt-contract.mjs).
|
||||
*
|
||||
* @param {string} promptPath - Absolute path to the prompt markdown file.
|
||||
* @returns {Promise<{ok: true}|{ok: false, category: string, reason: string, detail: string}>}
|
||||
*/
|
||||
async function validatePromptFile(promptPath) {
|
||||
let content;
|
||||
try {
|
||||
@@ -106,6 +178,14 @@ async function validatePromptFile(promptPath) {
|
||||
return { ok: true };
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether a file exists and was modified at or after `sinceMs`.
|
||||
* Used to verify that memory evidence artifacts were produced during the current run.
|
||||
*
|
||||
* @param {string|null} filePath - Relative or absolute path to check.
|
||||
* @param {number} sinceMs - Epoch milliseconds threshold (run start time).
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
async function artifactExistsSince(filePath, sinceMs) {
|
||||
if (!filePath) return false;
|
||||
const resolved = path.isAbsolute(filePath)
|
||||
@@ -119,6 +199,19 @@ async function artifactExistsSince(filePath, sinceMs) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a memory pipeline step (retrieve or store) produced observable evidence.
|
||||
* Evidence can be either a deterministic output marker string OR a qualifying artifact file.
|
||||
* A step is considered complete when either form of evidence is present.
|
||||
*
|
||||
* @param {Object} params
|
||||
* @param {string} params.name - Step name ('retrieve'|'store') for logging.
|
||||
* @param {string[]} params.markers - Substrings to search for in combined command output.
|
||||
* @param {string[]} params.artifacts - Relative paths of artifact files to check.
|
||||
* @param {string} params.outputText - Combined stdout+stderr from all commands this run.
|
||||
* @param {number} params.sinceMs - Run start epoch ms; artifact files must be newer.
|
||||
* @returns {Promise<{name: string, markerMatched: boolean, artifactMatched: boolean, complete: boolean}>}
|
||||
*/
|
||||
async function verifyMemoryStep({ name, markers, artifacts, outputText, sinceMs }) {
|
||||
const markerMatched = markers.some((marker) => outputText.includes(marker));
|
||||
const artifactResults = await Promise.all(artifacts.map((artifact) => artifactExistsSince(artifact, sinceMs)));
|
||||
@@ -133,6 +226,17 @@ async function verifyMemoryStep({ name, markers, artifacts, outputText, sinceMs
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds the most recent valid scheduler task log file in `logDir`.
|
||||
* "Valid" means the filename passes isStrictSchedulerLogFilename() AND the file
|
||||
* contains a parseable timestamp (from frontmatter created_at or the filename itself).
|
||||
*
|
||||
* Files with unparseable timestamps are skipped with a console warning.
|
||||
* The effective timestamp for sorting is derived from frontmatter first, then filename.
|
||||
*
|
||||
* @param {string} logDir - Absolute path to the cadence log directory (e.g. task-logs/daily/).
|
||||
* @returns {Promise<string|null>} Filename (not path) of the latest log, or null if none.
|
||||
*/
|
||||
async function getLatestFile(logDir) {
|
||||
await fs.mkdir(logDir, { recursive: true });
|
||||
const entries = await fs.readdir(logDir, { withFileTypes: true });
|
||||
@@ -170,6 +274,22 @@ async function getLatestFile(logDir) {
|
||||
return latest?.filename || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Selects the next eligible agent from the roster using round-robin scheduling.
|
||||
*
|
||||
* Selection algorithm:
|
||||
* - If `previousAgent` is in the roster, start scanning from the next index (wrap-around).
|
||||
* - Otherwise, start from `firstPrompt` index (if configured) or index 0.
|
||||
* - Returns the first candidate not present in `excludedSet`.
|
||||
* - Returns null if every roster agent is excluded.
|
||||
*
|
||||
* @param {Object} params
|
||||
* @param {string[]} params.roster - Ordered array of agent names for this cadence.
|
||||
* @param {Set<string>} params.excludedSet - Agents to skip (locked, paused, completed, time-excluded).
|
||||
* @param {string|null} params.previousAgent - Agent that ran most recently (from latest log).
|
||||
* @param {string|null} params.firstPrompt - Configured first-run starting agent name.
|
||||
* @returns {string|null} Selected agent name, or null if roster is fully excluded.
|
||||
*/
|
||||
function selectNextAgent({ roster, excludedSet, previousAgent, firstPrompt }) {
|
||||
const previousIndex = roster.indexOf(previousAgent);
|
||||
const firstIndex = roster.indexOf(firstPrompt);
|
||||
@@ -186,6 +306,27 @@ function selectNextAgent({ roster, excludedSet, previousAgent, firstPrompt }) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads and normalizes scheduler configuration for the given cadence.
|
||||
* Merges torch-config.json settings with environment variable overrides.
|
||||
*
|
||||
* Configuration covers:
|
||||
* - handoffCommand: shell command to execute the selected agent's prompt.
|
||||
* - validationCommands: commands that must pass before lock:complete (default: npm run lint).
|
||||
* - lockRetry: maxRetries, backoffMs, jitterMs for lock acquisition retries.
|
||||
* - lockHealthPreflight: whether to probe relay health before lock acquisition.
|
||||
* - lockFailurePolicy: strictLock, degradedLockRetryWindowMs, maxDeferrals.
|
||||
* - memoryPolicy: mode (required|optional), retrieve/store commands, markers, artifacts.
|
||||
*
|
||||
* Environment variable overrides (all optional):
|
||||
* SCHEDULER_LOCK_MAX_RETRIES, SCHEDULER_LOCK_BACKOFF_MS, SCHEDULER_LOCK_JITTER_MS,
|
||||
* SCHEDULER_LOCK_HEALTH_PREFLIGHT, SCHEDULER_SKIP_LOCK_HEALTH_PREFLIGHT,
|
||||
* SCHEDULER_STRICT_LOCK, SCHEDULER_DEGRADED_LOCK_RETRY_WINDOW_MS, SCHEDULER_MAX_DEFERRALS
|
||||
*
|
||||
* @param {string} cadence - 'daily'|'weekly'
|
||||
* @param {{ isInteractive: boolean }} options
|
||||
* @returns {Promise<Object>} Normalized scheduler config object.
|
||||
*/
|
||||
async function getSchedulerConfig(cadence, { isInteractive }) {
|
||||
const cfg = await readJson(path.resolve(process.cwd(), 'torch-config.json'), {});
|
||||
const scheduler = cfg.scheduler || {};
|
||||
@@ -262,6 +403,17 @@ async function getSchedulerConfig(cadence, { isInteractive }) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads persisted scheduler run-state for the current UTC day.
|
||||
* Run-state is used to track lock deferral metadata across multiple invocations
|
||||
* within the same day (e.g., retry window tracking for non-strict lock failures).
|
||||
*
|
||||
* If the state file is missing, unreadable, or belongs to a previous day, returns
|
||||
* a fresh default state. State is keyed by `run_date` (YYYY-MM-DD UTC).
|
||||
*
|
||||
* @param {string} cadence - 'daily'|'weekly'
|
||||
* @returns {Promise<{ statePath: string, state: { run_date: string, lock_deferral: Object|null } }>}
|
||||
*/
|
||||
async function readRunState(cadence) {
|
||||
const statePath = path.resolve(process.cwd(), 'task-logs', cadence, '.scheduler-run-state.json');
|
||||
const fallback = { run_date: getRunDateKey(), lock_deferral: null };
|
||||
@@ -283,15 +435,45 @@ async function readRunState(cadence) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Persists scheduler run-state to disk (JSON file).
|
||||
* Creates parent directories if they do not exist.
|
||||
*
|
||||
* @param {string} statePath - Absolute path to the state file.
|
||||
* @param {Object} state - State object to serialize.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function writeRunState(statePath, state) {
|
||||
await fs.mkdir(path.dirname(statePath), { recursive: true });
|
||||
await fs.writeFile(statePath, `${JSON.stringify(state, null, 2)}\n`, 'utf8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a unique idempotency key for a deferred lock attempt.
|
||||
* The key is stable across retries for the same agent/cadence/date combination
|
||||
* by being stored in run-state and reused on subsequent invocations.
|
||||
*
|
||||
* @param {{ cadence: string, selectedAgent: string, runDate: string }} params
|
||||
* @returns {string}
|
||||
*/
|
||||
function createIdempotencyKey({ cadence, selectedAgent, runDate }) {
|
||||
return `${cadence}:${selectedAgent}:${runDate}:${randomUUID()}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a task log file to `task-logs/<cadence>/` with YAML frontmatter.
|
||||
* File naming: `<ts>__<agent>__<status>.md`
|
||||
*
|
||||
* The frontmatter includes cadence, agent, status, reason, created_at, platform,
|
||||
* and any additional metadata fields. The file body repeats key fields as bullets
|
||||
* for human readability.
|
||||
*
|
||||
* These files are read by getLatestFile(), cmdCheck(), and the dashboard.
|
||||
*
|
||||
* @param {{ cadence: string, agent: string, status: string, reason: string,
|
||||
* detail?: string, platform?: string, metadata?: Object }} params
|
||||
* @returns {Promise<string>} The filename (not full path) of the written log.
|
||||
*/
|
||||
async function writeLog({ cadence, agent, status, reason, detail, platform, metadata = {} }) {
|
||||
const logDir = path.resolve(process.cwd(), 'task-logs', cadence);
|
||||
await fs.mkdir(logDir, { recursive: true });
|
||||
@@ -328,6 +510,15 @@ async function writeLog({ cadence, agent, status, reason, detail, platform, meta
|
||||
return file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints a human-readable run summary to stdout.
|
||||
* Includes status, agent, prompt path, platform, reason, and the contents of
|
||||
* the memory update file (up to 2000 characters, truncated if longer).
|
||||
*
|
||||
* @param {{ status: string, agent: string, promptPath: string|null, reason: string,
|
||||
* detail?: string, memoryFile?: string, platform: string }} params
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async function printRunSummary({ status, agent, promptPath, reason, detail, memoryFile, platform }) {
|
||||
let learnings = 'No learnings recorded.';
|
||||
if (memoryFile) {
|
||||
@@ -360,6 +551,15 @@ async function printRunSummary({ status, agent, promptPath, reason, detail, memo
|
||||
process.stdout.write('================================================================================\n\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the run summary then terminates the process with the given exit code.
|
||||
* All normal and failure exit paths in main() go through this function to ensure
|
||||
* a summary is always printed before exit.
|
||||
*
|
||||
* @param {number} code - Exit code (0 = success, 1 = general failure, 2 = backend error).
|
||||
* @param {Object|null} summaryData - Data passed to printRunSummary, or null to skip.
|
||||
* @returns {Promise<never>}
|
||||
*/
|
||||
async function exitWithSummary(code, summaryData) {
|
||||
if (summaryData) {
|
||||
await printRunSummary(summaryData);
|
||||
@@ -433,6 +633,8 @@ async function main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Step 6: Build exclusion set from relay state. Prefer the top-level `excluded`
|
||||
// field (computed by cmdCheck), falling back to the union of locked/paused/completed.
|
||||
const checkResult = await runCommand('npm', ['run', `lock:check:${cadence}`, '--', '--json', '--quiet']);
|
||||
const checkPayload = parseJsonFromOutput(`${checkResult.stdout}\n${checkResult.stderr}`) || {};
|
||||
const excluded = Array.isArray(checkPayload.excluded)
|
||||
@@ -523,6 +725,8 @@ async function main() {
|
||||
});
|
||||
const lockResult = lockAttempt.result;
|
||||
|
||||
// Lock exit 3: race lost — another agent claimed this slot between our check
|
||||
// and our publish. Restart the loop to pick the next available agent.
|
||||
if (lockResult.code === 3) {
|
||||
continue;
|
||||
}
|
||||
@@ -664,6 +868,8 @@ async function main() {
|
||||
const runStartMs = Date.parse(runArtifactSince);
|
||||
const outputChunks = [];
|
||||
|
||||
// Pre-create the memory update file path and inject it as SCHEDULER_MEMORY_FILE
|
||||
// so the spawned agent can write learnings without computing the path itself.
|
||||
const memoryDir = path.resolve(process.cwd(), 'memory-updates');
|
||||
await fs.mkdir(memoryDir, { recursive: true });
|
||||
const memoryFile = path.join(memoryDir, `${ts()}__${selectedAgent}.md`);
|
||||
@@ -795,6 +1001,7 @@ async function main() {
|
||||
sinceMs: runStartMs,
|
||||
});
|
||||
|
||||
// mode='required' → missing evidence is a hard failure; mode='optional' → warning only.
|
||||
const missingSteps = [retrieveCheck, storeCheck].filter((step) => !step.complete).map((step) => step.name);
|
||||
if (missingSteps.length && schedulerConfig.memoryPolicy.mode === 'required') {
|
||||
await writeLog({
|
||||
|
||||
+1
-1
@@ -69,7 +69,7 @@ Environment:
|
||||
NOSTR_LOCK_NAMESPACE Namespace prefix for lock tags (default: torch)
|
||||
NOSTR_LOCK_RELAYS Comma-separated relay WSS URLs
|
||||
NOSTR_LOCK_TTL Lock TTL in seconds (default: 7200)
|
||||
NOSTR_LOCK_QUERY_TIMEOUT_MS Relay query timeout in milliseconds (default: 15000)
|
||||
NOSTR_LOCK_QUERY_TIMEOUT_MS Relay query timeout in milliseconds (default: 30000)
|
||||
NOSTR_LOCK_DAILY_ROSTER Comma-separated daily roster (optional)
|
||||
NOSTR_LOCK_WEEKLY_ROSTER Comma-separated weekly roster (optional)
|
||||
TORCH_CONFIG_PATH Optional path to torch-config.json (default: ./torch-config.json)
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
agent: docs-agent
|
||||
cadence: daily
|
||||
run-start: "2026-02-20T05:00:00Z"
|
||||
prompt: src/prompts/daily/docs-agent.md
|
||||
---
|
||||
|
||||
# Context — docs-agent — 2026-02-20
|
||||
|
||||
## Goal
|
||||
|
||||
Audit key documentation files (`README.md`, `AGENTS.md`) for accuracy relative to the codebase and fix any inaccuracies found.
|
||||
|
||||
## Scope
|
||||
|
||||
- Baseline reads: `AGENTS.md`, `CLAUDE.md`, `KNOWN_ISSUES.md`, `docs/agent-handoffs/README.md`
|
||||
- Audit targets: `README.md`, `AGENTS.md`, `CONTRIBUTING.md`
|
||||
- Verify all scripts/commands against `package.json`
|
||||
- Fix P1 inaccuracies (missing env vars, missing config keys)
|
||||
- Write run artifacts in canonical paths
|
||||
|
||||
## Constraints
|
||||
|
||||
- Do not invent commands or APIs not verified in code
|
||||
- Minimal edits — prefer targeted fixes over wholesale rewrites
|
||||
- Do not change test behavior or policy intent in AGENTS.md/CLAUDE.md
|
||||
|
||||
## Open questions
|
||||
|
||||
- None. All referenced files found and verified.
|
||||
|
||||
## Findings
|
||||
|
||||
1. `README.md` environment variables section is missing 4 env vars present in `TORCH.md` and used in `src/torch-config.mjs`: `NOSTR_LOCK_PUBLISH_TIMEOUT_MS`, `NOSTR_LOCK_MIN_SUCCESSFUL_PUBLISHES`, `NOSTR_LOCK_RELAY_FALLBACKS`, `NOSTR_LOCK_MIN_ACTIVE_RELAY_POOL`.
|
||||
2. `README.md` `torch-config.json` section is missing 8 config keys fully documented in `TORCH.md`: `publishTimeoutMs`, `minSuccessfulRelayPublishes`, `relayFallbacks`, `minActiveRelayPool`, `handoffCommandByCadence`, `strict_lock`, `degraded_lock_retry_window`, `max_deferrals`.
|
||||
3. `CONTRIBUTING.md` — accurate; all commands verified against `package.json`. No issues found.
|
||||
4. `AGENTS.md` — accurate; no broken paths or incorrect commands.
|
||||
5. `.env.example`, `torch-config.example.json`, `docs/lib-overview.md`, `docs/lock-ops-overview.md`, `skills/`, `dashboard/` — all exist ✓
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
agent: docs-alignment-agent
|
||||
cadence: daily
|
||||
run-start: "2026-02-20T06:00:00Z"
|
||||
prompt: src/prompts/daily/docs-alignment-agent.md
|
||||
---
|
||||
|
||||
# Context — docs-alignment-agent — 2026-02-20
|
||||
|
||||
## Goal
|
||||
|
||||
Verify, correct, and validate that development documentation matches codebase reality (daily diff-driven pass). Trace concrete doc claims to code and fix confirmed mismatches.
|
||||
|
||||
## Scope
|
||||
|
||||
- Audit targets: `docs/lib-overview.md`, `docs/lock-ops-overview.md`, `docs/memory-index-overview.md`, `docs/removal.md`, `docs/architecture/system-overview.md`, `docs/AGENT_COVERAGE_GAPS.md`, `src/constants.mjs` (USAGE_TEXT)
|
||||
- Verify each claim by tracing to `src/` code
|
||||
- Fix P1 (incorrect) and P2 (incomplete) issues in targeted docs
|
||||
- Write claims map, diagnosis, and validation notes
|
||||
|
||||
## Constraints
|
||||
|
||||
- No inventing behavior — trace every claim to code
|
||||
- Minimal edits only
|
||||
- Constants USAGE_TEXT fix is a doc string in source code — small, safe, and a clear correctness fix
|
||||
|
||||
## Open questions
|
||||
|
||||
- None. All relevant source files found and inspected.
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
agent: docs-code-investigator
|
||||
cadence: daily
|
||||
run-start: "2026-02-20T07:00:00Z"
|
||||
prompt: src/prompts/daily/docs-code-investigator.md
|
||||
---
|
||||
|
||||
# Context — docs-code-investigator — 2026-02-20
|
||||
|
||||
## Selected target file
|
||||
|
||||
- **File:** `scripts/agent/run-scheduler-cycle.mjs`
|
||||
- **Line count:** 926 lines
|
||||
- **Reason for selection:**
|
||||
- Largest undocumented source file in the repo (existing overview docs cover only `src/lib.mjs`, `src/lock-ops.mjs`, `src/services/memory/index.js`).
|
||||
- Central orchestrator for all agent scheduling — highest maintenance risk.
|
||||
- Recent active commits with no corresponding documentation.
|
||||
- No `TODO/FIXME/XXX` but function-level complexity warrants JSDoc and a flow overview.
|
||||
- **Last significant commits:**
|
||||
- `a5f08ff` feat(scheduler): add local time-window guard (recent)
|
||||
- `9278dad` Print final run summary in scheduler cycle
|
||||
- `ae2e382` Fix: Correctly detect agent platform for locks
|
||||
|
||||
## Plan
|
||||
|
||||
1. Add top-of-file flow comment (16-step outline per `src/prompts/scheduler-flow.md`).
|
||||
2. Add JSDoc to all internal helper functions.
|
||||
3. Add targeted inline comments where intent is non-obvious.
|
||||
4. Produce `docs/scheduler-cycle-overview.md`.
|
||||
5. Write run artifacts.
|
||||
|
||||
## Constraints
|
||||
|
||||
- Documentation only — no behavioral changes.
|
||||
- No crypto code in this file; no security issue to open.
|
||||
- Single file scope: only `scripts/agent/run-scheduler-cycle.mjs` modified.
|
||||
- `npm run lint` and `npm test` not runnable in Claude Code sandbox (KNOWN-ISSUE-sandbox-eprem-tests).
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
agent: docs-agent
|
||||
cadence: daily
|
||||
run-start: "2026-02-20T05:00:00Z"
|
||||
prompt: src/prompts/daily/docs-agent.md
|
||||
---
|
||||
|
||||
# Decisions — docs-agent — 2026-02-20
|
||||
|
||||
## Decision 1: Add missing env vars to README.md
|
||||
|
||||
**Decision:** Add the 4 missing environment variables to the README.md "Environment variables" section.
|
||||
|
||||
**Alternatives considered:**
|
||||
- Open an issue instead of fixing — rejected; the change is small, safe, and well-supported by TORCH.md as authoritative source.
|
||||
- Add to TORCH.md only — rejected; README.md is the consumer-facing entry point and should be complete.
|
||||
|
||||
**Rationale:** `TORCH.md` lists all env vars and is synchronized with `src/torch-config.mjs`. README.md was missing `NOSTR_LOCK_PUBLISH_TIMEOUT_MS`, `NOSTR_LOCK_MIN_SUCCESSFUL_PUBLISHES`, `NOSTR_LOCK_RELAY_FALLBACKS`, and `NOSTR_LOCK_MIN_ACTIVE_RELAY_POOL`. These affect production lock reliability and users configuring these env vars would not find them in README.md.
|
||||
|
||||
**Consequences/follow-ups:** Keep README.md env var list synchronized with TORCH.md on future changes.
|
||||
|
||||
---
|
||||
|
||||
## Decision 2: Add missing torch-config.json options to README.md
|
||||
|
||||
**Decision:** Add 8 missing configuration keys to README.md's `torch-config.json` section.
|
||||
|
||||
**Alternatives considered:**
|
||||
- Open an issue instead of fixing — rejected; all keys are verified in TORCH.md and code.
|
||||
- Only add the most user-facing ones — rejected; all 8 keys are production-relevant and documented in TORCH.md.
|
||||
|
||||
**Rationale:** `TORCH.md` is the authoritative configuration reference. The README.md configuration section was a subset, omitting scheduler behavior keys (`handoffCommandByCadence`, `strict_lock`, `degraded_lock_retry_window`, `max_deferrals`) and lock reliability keys (`publishTimeoutMs`, `minSuccessfulRelayPublishes`, `relayFallbacks`, `minActiveRelayPool`) that users configuring production deployments need.
|
||||
|
||||
**Consequences/follow-ups:** Keep README.md config section synchronized with TORCH.md on future changes.
|
||||
|
||||
---
|
||||
|
||||
## Decision 3: No changes to CONTRIBUTING.md
|
||||
|
||||
**Decision:** No changes made to CONTRIBUTING.md.
|
||||
|
||||
**Rationale:** All commands verified against package.json. Node.js >=22 requirement, npm install, npm run build, npm test, npm run lint, npm run test:unit:lock-backend, npm run test:extended-main, npm run validate:scheduler — all exist. Referenced docs (docs/lib-overview.md, docs/lock-ops-overview.md) exist.
|
||||
|
||||
---
|
||||
|
||||
## Decision 4: No changes to AGENTS.md
|
||||
|
||||
**Decision:** No changes made to AGENTS.md.
|
||||
|
||||
**Rationale:** AGENTS.md is the test integrity policy document. It is accurate and consistent with CLAUDE.md. No broken paths or incorrect commands found.
|
||||
@@ -0,0 +1,50 @@
|
||||
---
|
||||
agent: docs-alignment-agent
|
||||
cadence: daily
|
||||
run-start: "2026-02-20T06:00:00Z"
|
||||
prompt: src/prompts/daily/docs-alignment-agent.md
|
||||
---
|
||||
|
||||
# Decisions — docs-alignment-agent — 2026-02-20
|
||||
|
||||
## Decision 1: Fix RACE_CHECK_DELAY_MS in docs/lib-overview.md (2000→1500ms)
|
||||
|
||||
**Decision:** Update the docs to reflect the actual value.
|
||||
|
||||
**Evidence:** `src/constants.mjs` line 2: `export const RACE_CHECK_DELAY_MS = 1500;`
|
||||
|
||||
**Rationale:** docs/lib-overview.md stated "Wait `RACE_CHECK_DELAY_MS` (default 2000ms)" — that value is wrong. The constant is 1500. This is a P1 incorrect doc claim.
|
||||
|
||||
**Alternatives considered:** Open an issue instead — rejected; the fix is a single-word change with unambiguous ground truth in code.
|
||||
|
||||
---
|
||||
|
||||
## Decision 2: Fix USAGE_TEXT query timeout default in src/constants.mjs (15000→30000)
|
||||
|
||||
**Decision:** Update the `--help` display string to reflect the actual default.
|
||||
|
||||
**Evidence:** `DEFAULT_QUERY_TIMEOUT_MS = 30_000` in `src/constants.mjs` line 10. The USAGE_TEXT on line 72 said `(default: 15000)` which matches `DEFAULT_PUBLISH_TIMEOUT_MS` (15_000), not the query timeout.
|
||||
|
||||
**Rationale:** The USAGE_TEXT is a documentation string displayed in CLI `--help` output. Showing an incorrect default misleads users configuring `NOSTR_LOCK_QUERY_TIMEOUT_MS`. The fix is a one-character change with clear code evidence. Permitted as a small, safe correctness fix.
|
||||
|
||||
**Alternatives considered:** Open an issue only — rejected; code change is trivial and unambiguous.
|
||||
|
||||
---
|
||||
|
||||
## Decision 3: Add 4 missing env vars to docs/removal.md cleanup list
|
||||
|
||||
**Decision:** Add `NOSTR_LOCK_PUBLISH_TIMEOUT_MS`, `NOSTR_LOCK_MIN_SUCCESSFUL_PUBLISHES`, `NOSTR_LOCK_RELAY_FALLBACKS`, `NOSTR_LOCK_MIN_ACTIVE_RELAY_POOL` to the manual cleanup list.
|
||||
|
||||
**Evidence:** These vars are used in `src/torch-config.mjs` and were already added to README.md in the prior docs-agent run. The removal guide's env var list was incomplete.
|
||||
|
||||
**Rationale:** Users following the manual removal guide would leave these env vars set in their shell profile / CI / .env files. Completing the list is a P2 completeness fix.
|
||||
|
||||
---
|
||||
|
||||
## Decision 4: Fix Playwright claim in docs/AGENT_COVERAGE_GAPS.md
|
||||
|
||||
**Decision:** Replace "playwright dependency and test/ integration files" with "test/ integration/e2e files (Node.js --test)".
|
||||
|
||||
**Evidence:** `package.json` has no playwright in dependencies or devDependencies. The `test/scheduler-preflight-lock.e2e.test.mjs` file uses the Node.js built-in `--test` runner, not Playwright.
|
||||
|
||||
**Rationale:** The Playwright claim is factually wrong. Leaving it misleads any agent/developer who reads this doc to look for Playwright configuration that does not exist.
|
||||
@@ -0,0 +1,77 @@
|
||||
---
|
||||
agent: docs-code-investigator
|
||||
cadence: daily
|
||||
run-start: "2026-02-20T07:00:00Z"
|
||||
prompt: src/prompts/daily/docs-code-investigator.md
|
||||
---
|
||||
|
||||
# Decisions — docs-code-investigator — 2026-02-20
|
||||
|
||||
## Decision 1: Target file = scripts/agent/run-scheduler-cycle.mjs
|
||||
|
||||
**Decision:** Document `scripts/agent/run-scheduler-cycle.mjs` (926 lines).
|
||||
|
||||
**Rationale:**
|
||||
- Largest undocumented source file in the repo.
|
||||
- Central orchestrator for all agent scheduling — highest maintenance risk and value.
|
||||
- `src/lib.mjs`, `src/lock-ops.mjs`, `src/services/memory/index.js` already have overview docs.
|
||||
- Recent active commits (time-window guard, summary printing, platform detection) without documentation.
|
||||
|
||||
**Alternatives considered:**
|
||||
- `src/ops.mjs` (795 lines) — also undocumented, but less critical than the scheduler.
|
||||
- `dashboard/app.js` (822 lines) — frontend UI, lower maintenance priority.
|
||||
|
||||
---
|
||||
|
||||
## Decision 2: Add top-of-file module JSDoc block with 19-step flow comment
|
||||
|
||||
**Decision:** Add a multi-line JSDoc comment before the imports that describes the
|
||||
module's purpose, role, and numbered main flow steps.
|
||||
|
||||
**Rationale:** The file has a comment stub ("Source of truth: numbered MUST steps…")
|
||||
but no description of what the module does or the complete execution flow. The
|
||||
19-step flow directly mirrors `src/prompts/scheduler-flow.md` and is the clearest
|
||||
way to help future maintainers understand the script.
|
||||
|
||||
**Constraints:** Documentation only — no behavioral changes.
|
||||
|
||||
---
|
||||
|
||||
## Decision 3: Add JSDoc to all internal helper functions
|
||||
|
||||
**Decision:** Add JSDoc (description, @param, @returns, @throws where applicable) to:
|
||||
parseArgs, ts, categorizeFailureMetadata, validatePromptFile, artifactExistsSince,
|
||||
verifyMemoryStep, getLatestFile, selectNextAgent, getSchedulerConfig, readRunState,
|
||||
writeRunState, createIdempotencyKey, writeLog, printRunSummary, exitWithSummary.
|
||||
|
||||
**Rationale:** These functions are the building blocks of the scheduler loop.
|
||||
Without docs, their contracts, side effects, and error modes are unclear to
|
||||
contributors who did not write them.
|
||||
|
||||
**Constraints:** Documentation only — no changes to function signatures or behavior.
|
||||
|
||||
---
|
||||
|
||||
## Decision 4: Add targeted inline comments for non-obvious logic
|
||||
|
||||
**Decision:** Add inline comments at:
|
||||
- Lock exit 3 handling (loop restart vs. error)
|
||||
- Exclusion set fallback construction (why the union of locked/paused/completed)
|
||||
- Memory file path pre-creation (why SCHEDULER_MEMORY_FILE is injected)
|
||||
- Memory mode check (required vs. optional semantics)
|
||||
|
||||
**Rationale:** These are the spots most likely to confuse contributors doing
|
||||
bug investigation or adding new validation gates.
|
||||
|
||||
---
|
||||
|
||||
## Decision 5: Create docs/scheduler-cycle-overview.md
|
||||
|
||||
**Decision:** Create a full overview document mirroring the style of docs/lib-overview.md.
|
||||
|
||||
**Rationale:** The scheduler cycle is the most complex operational entry point in TORCH.
|
||||
An overview doc provides a call-flow diagram, API reference, invariant documentation,
|
||||
and error path table — material that does not fit cleanly in inline comments.
|
||||
|
||||
**No issues opened:** No correctness problems, security issues, or design concerns found
|
||||
that require maintainer decision.
|
||||
@@ -0,0 +1,74 @@
|
||||
---
|
||||
agent: docs-agent
|
||||
cadence: daily
|
||||
run-start: "2026-02-20T05:00:00Z"
|
||||
prompt: src/prompts/daily/docs-agent.md
|
||||
---
|
||||
|
||||
# Test Log — docs-agent — 2026-02-20
|
||||
|
||||
## Verification: package.json scripts
|
||||
|
||||
**Method:** Read `package.json` and compared against commands in `README.md` and `CONTRIBUTING.md`.
|
||||
|
||||
**Result:** PASS
|
||||
|
||||
Verified scripts exist:
|
||||
- `npm test` ✓
|
||||
- `npm run build` ✓
|
||||
- `npm run lint` ✓
|
||||
- `npm run test:unit:lock-backend` ✓
|
||||
- `npm run test:extended-main` ✓
|
||||
- `npm run validate:scheduler` ✓
|
||||
- `npm run lock:check:daily` ✓
|
||||
- `npm run lock:check:weekly` ✓
|
||||
- `npm run lock:list` ✓
|
||||
- `npm run lock:health` ✓
|
||||
- `npm run lock:complete` ✓
|
||||
- `npm run scheduler:daily` ✓
|
||||
- `npm run scheduler:weekly` ✓
|
||||
- `npm run report:lock-reliability` ✓
|
||||
- `npm run dashboard:serve` ✓
|
||||
|
||||
No `npm run format` script exists — CONTRIBUTING.md does not reference it (only `npm run lint`). No discrepancy.
|
||||
|
||||
## Verification: referenced paths
|
||||
|
||||
**Method:** Used Glob to check file existence for all paths referenced in README.md and CONTRIBUTING.md.
|
||||
|
||||
**Result:** PASS
|
||||
|
||||
- `.env.example` ✓
|
||||
- `torch-config.example.json` ✓
|
||||
- `TORCH.md` ✓
|
||||
- `docs/prompt-versioning.md` ✓
|
||||
- `docs/removal.md` ✓
|
||||
- `docs/lib-overview.md` ✓
|
||||
- `docs/lock-ops-overview.md` ✓
|
||||
- `src/lib.mjs` (referenced as main export in package.json) ✓
|
||||
- `src/prompts/` ✓
|
||||
- `skills/` ✓
|
||||
- `dashboard/` ✓
|
||||
- `src/prompts/roster.json` ✓
|
||||
- `bin/torch-lock.mjs` (referenced as CLI bin) ✓
|
||||
|
||||
## Verification: env vars in codebase
|
||||
|
||||
**Method:** Used Grep on `src/torch-config.mjs` to verify the 4 env vars missing from README.md.
|
||||
|
||||
**Result:** PASS — all 4 confirmed used in `src/torch-config.mjs`:
|
||||
- `NOSTR_LOCK_PUBLISH_TIMEOUT_MS` ✓
|
||||
- `NOSTR_LOCK_MIN_SUCCESSFUL_PUBLISHES` ✓
|
||||
- `NOSTR_LOCK_RELAY_FALLBACKS` ✓
|
||||
- `NOSTR_LOCK_MIN_ACTIVE_RELAY_POOL` ✓
|
||||
|
||||
## Verification: README.md changes
|
||||
|
||||
**Method:** Inspected README.md after edits to confirm additions are accurate.
|
||||
|
||||
**Result:** PASS — all added content matches TORCH.md and src/torch-config.mjs.
|
||||
|
||||
## Environmental limitations
|
||||
|
||||
- `npm run lint` not executed (outbound WebSocket restricted in Claude Code environment — see KNOWN_ISSUES.md). Documentation-only changes; lint would verify JS syntax only, not markdown content.
|
||||
- `npm test` not executed (sandbox restrictions — see KNOWN_ISSUES.md: `KNOWN-ISSUE-sandbox-eprem-tests`). No test changes made this run.
|
||||
@@ -0,0 +1,41 @@
|
||||
---
|
||||
agent: docs-alignment-agent
|
||||
cadence: daily
|
||||
run-start: "2026-02-20T06:00:00Z"
|
||||
prompt: src/prompts/daily/docs-alignment-agent.md
|
||||
---
|
||||
|
||||
# Test Log — docs-alignment-agent — 2026-02-20
|
||||
|
||||
## Claims Map
|
||||
|
||||
| Claim | Doc Location | Code Location | Status |
|
||||
|-------|-------------|---------------|--------|
|
||||
| `cmdCheck`, `cmdLock`, `cmdComplete`, `cmdList` exist | docs/lib-overview.md | src/lib.mjs:66,167,344,431 | ✅ matches |
|
||||
| `cmdLock` returns `{ status: 'ok', eventId }` | docs/lib-overview.md | src/lib.mjs:333 | ✅ matches |
|
||||
| RACE_CHECK_DELAY_MS default 2000ms | docs/lib-overview.md | src/constants.mjs:2 | ⚠️ WRONG — was 2000, actual 1500 |
|
||||
| RelayHealthManager, LockPublisher architecture | docs/lock-ops-overview.md | src/relay-health-manager.mjs, src/lock-publisher.mjs | ✅ matches |
|
||||
| `publishLock`, `queryLocks`, `parseLockEvent` API | docs/lock-ops-overview.md | src/lock-ops.mjs | ✅ matches |
|
||||
| Memory import at src/lib.mjs:28 | docs/memory-index-overview.md | src/lib.mjs:28-35 | ✅ matches (imports start at 28) |
|
||||
| scripts/memory/retrieve.mjs:1, store.mjs:1 | docs/memory-index-overview.md | scripts/memory/ | ✅ both files exist |
|
||||
| Memory public API (ingestEvents, getRelevantMemories, etc.) | docs/memory-index-overview.md | src/services/memory/index.js | ✅ matches |
|
||||
| USAGE_TEXT NOSTR_LOCK_QUERY_TIMEOUT_MS default 15000 | src/constants.mjs:72 | src/constants.mjs:10 | ⚠️ WRONG — was 15000, actual DEFAULT_QUERY_TIMEOUT_MS = 30000 |
|
||||
| proposal stored in src/proposals/<ts>_<agent>/ | docs/prompt-versioning.md | src/cmd-proposal.mjs | ✅ matches |
|
||||
| TORCH_HOST_SCRIPTS list matches docs/removal.md | docs/removal.md | src/constants.mjs:30-37 | ✅ matches |
|
||||
| docs/removal.md env var list complete | docs/removal.md | src/torch-config.mjs | ⚠️ INCOMPLETE — missing 4 vars |
|
||||
| playwright dependency | docs/AGENT_COVERAGE_GAPS.md | package.json | ⚠️ WRONG — not in package.json |
|
||||
| landing/ and migrations/ directories exist | docs/AGENT_COVERAGE_GAPS.md | filesystem | ✅ both exist |
|
||||
| system-overview.md file paths (bin/, src/, dashboard/, etc.) | docs/architecture/system-overview.md | filesystem | ✅ all exist |
|
||||
| DEFAULT_DASHBOARD_PORT = 4173 | (inferred from dashboard command examples) | src/constants.mjs:1 | ✅ matches |
|
||||
|
||||
## Changes verified post-edit
|
||||
|
||||
- `docs/lib-overview.md:43` — "1500ms" confirmed ✅
|
||||
- `src/constants.mjs:72` — "(default: 30000)" confirmed ✅
|
||||
- `docs/removal.md:109-112` — 4 new env vars present ✅
|
||||
- `docs/AGENT_COVERAGE_GAPS.md` — "playwright" no longer present ✅
|
||||
|
||||
## Environmental limitations
|
||||
|
||||
- `npm run lint` not run (Claude Code sandbox — WebSocket/EPERM restrictions per KNOWN_ISSUES.md). Changed files: one doc string in constants.mjs + pure markdown. ESLint not expected to flag these.
|
||||
- `npm test` not run (same sandbox restrictions).
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
agent: docs-code-investigator
|
||||
cadence: daily
|
||||
run-start: "2026-02-20T07:00:00Z"
|
||||
prompt: src/prompts/daily/docs-code-investigator.md
|
||||
---
|
||||
|
||||
# Test Log — docs-code-investigator — 2026-02-20
|
||||
|
||||
## Static analysis verification
|
||||
|
||||
### All 926 lines read
|
||||
|
||||
Read the complete file across multiple passes. No missed sections.
|
||||
|
||||
### Call graph verified
|
||||
|
||||
- `scripts/agent/scheduler-utils.mjs` — all imported symbols confirmed used (runCommand, parseJsonFromOutput, readJson, normalizeStringList, parseNonNegativeInt, parseBooleanFlag, excerptText, getRunDateKey, toYamlScalar, buildRecentlyRunExclusionSet, parseDateValue, parseFrontmatterCreatedAt, parseFrontmatterAgent, parseTimestampFromFilename, isStrictSchedulerLogFilename, parseAgentFromFilename).
|
||||
- `scripts/agent/scheduler-lock.mjs` — all 5 imported symbols confirmed used: classifyLockBackendError, buildLockBackendRemediation, runLockHealthPreflight, acquireLockWithRetry, summarizeLockFailureReasons.
|
||||
- `src/utils.mjs:detectPlatform` — confirmed used at line 35.
|
||||
- `src/prompts/roster.json` — confirmed read at main() startup.
|
||||
|
||||
### Related test files confirmed
|
||||
|
||||
- `test/run-scheduler-cycle-memory-policy.test.mjs` — 613 lines, tests memory policy enforcement.
|
||||
- `test/scheduler-time-window.test.mjs` — 310 lines, tests time-window guard.
|
||||
- `test/scheduler-preflight-lock.e2e.test.mjs` — present in test/.
|
||||
|
||||
### No crypto or signing logic found
|
||||
|
||||
The file contains no cryptographic operations. No `requires-security-review` issue needed.
|
||||
|
||||
### No TODO/FIXME/XXX found
|
||||
|
||||
Confirmed by git grep (only 2 hits in repo, both in non-target files).
|
||||
|
||||
### JSDoc additions verified
|
||||
|
||||
Read the modified file to confirm all 15 helper functions now have JSDoc blocks.
|
||||
No behavioral changes made — only documentation insertions.
|
||||
|
||||
## Commands not run (environmental limitations)
|
||||
|
||||
- `npm run lint` — not run (Claude Code sandbox: outbound WebSocket/EPERM restrictions per KNOWN_ISSUES.md: KNOWN-ISSUE-sandbox-eprem-tests).
|
||||
- `npm test` — not run (same sandbox restrictions).
|
||||
|
||||
**Assessment:** Changes are documentation-only (JSDoc blocks, inline comments).
|
||||
ESLint will not flag JSDoc content — only syntax. No code logic was altered.
|
||||
Risk of lint failure from these changes: negligible.
|
||||
|
||||
## Git diff summary
|
||||
|
||||
```
|
||||
scripts/agent/run-scheduler-cycle.mjs | +~130 lines (JSDoc + flow comment + inline comments)
|
||||
docs/scheduler-cycle-overview.md | +254 lines (new overview document)
|
||||
```
|
||||
@@ -0,0 +1,31 @@
|
||||
---
|
||||
agent: docs-agent
|
||||
cadence: daily
|
||||
run-start: "2026-02-20T05:00:00Z"
|
||||
prompt: src/prompts/daily/docs-agent.md
|
||||
---
|
||||
|
||||
# Todo — docs-agent — 2026-02-20
|
||||
|
||||
## Pending tasks
|
||||
|
||||
(none remaining)
|
||||
|
||||
## Completed tasks
|
||||
|
||||
- [x] Read AGENTS.md, CLAUDE.md, KNOWN_ISSUES.md, docs/agent-handoffs/README.md (baseline reads)
|
||||
- [x] Read latest memory files (.scheduler-memory/latest/daily/memories.md)
|
||||
- [x] Audit README.md for accuracy against package.json and src/
|
||||
- [x] Audit CONTRIBUTING.md for accuracy
|
||||
- [x] Audit AGENTS.md for accuracy
|
||||
- [x] Verify all referenced paths and files exist
|
||||
- [x] Verify env vars used in src/torch-config.mjs
|
||||
- [x] Update README.md — add missing env vars and torch-config.json keys
|
||||
- [x] Write context artifact
|
||||
- [x] Write decisions artifact
|
||||
- [x] Write test_log artifact
|
||||
- [x] Write learning note in docs/agent-handoffs/learnings/
|
||||
|
||||
## Blocked tasks
|
||||
|
||||
(none)
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
agent: docs-alignment-agent
|
||||
cadence: daily
|
||||
run-start: "2026-02-20T06:00:00Z"
|
||||
prompt: src/prompts/daily/docs-alignment-agent.md
|
||||
---
|
||||
|
||||
# Todo — docs-alignment-agent — 2026-02-20
|
||||
|
||||
## Completed tasks
|
||||
|
||||
- [x] Baseline reads: AGENTS.md, CLAUDE.md, KNOWN_ISSUES.md, docs/agent-handoffs/README.md
|
||||
- [x] Read memory files (.scheduler-memory/latest/daily/memories.md)
|
||||
- [x] Audit docs/lib-overview.md — RACE_CHECK_DELAY_MS value
|
||||
- [x] Audit docs/lock-ops-overview.md — architecture claims
|
||||
- [x] Audit docs/memory-index-overview.md — line references, API surface
|
||||
- [x] Audit docs/removal.md — env var list completeness
|
||||
- [x] Audit docs/AGENT_COVERAGE_GAPS.md — technology claims
|
||||
- [x] Audit src/constants.mjs USAGE_TEXT — query timeout default
|
||||
- [x] Audit docs/architecture/system-overview.md — file paths, architecture
|
||||
- [x] Trace RACE_CHECK_DELAY_MS to src/constants.mjs → confirmed 1500ms
|
||||
- [x] Trace DEFAULT_QUERY_TIMEOUT_MS to src/constants.mjs → confirmed 30000
|
||||
- [x] Trace TORCH_HOST_SCRIPTS to confirm removal.md script list accuracy
|
||||
- [x] Fix docs/lib-overview.md: 2000ms → 1500ms
|
||||
- [x] Fix src/constants.mjs USAGE_TEXT: default 15000 → 30000
|
||||
- [x] Fix docs/removal.md: add 4 missing env vars
|
||||
- [x] Fix docs/AGENT_COVERAGE_GAPS.md: remove false Playwright claim
|
||||
- [x] Write context, todo, decisions, test_logs artifacts
|
||||
- [x] Write learning note
|
||||
|
||||
## Pending
|
||||
|
||||
(none)
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
agent: docs-code-investigator
|
||||
cadence: daily
|
||||
run-start: "2026-02-20T07:00:00Z"
|
||||
prompt: src/prompts/daily/docs-code-investigator.md
|
||||
---
|
||||
|
||||
# Todo — docs-code-investigator — 2026-02-20
|
||||
|
||||
## Completed tasks
|
||||
|
||||
- [x] Baseline reads: AGENTS.md, CLAUDE.md, KNOWN_ISSUES.md, docs/agent-handoffs/README.md
|
||||
- [x] Reviewed memory files
|
||||
- [x] Ran file discovery: git ls-files | xargs wc -l | sort -rn; git grep TODO/FIXME/XXX
|
||||
- [x] Selected target: scripts/agent/run-scheduler-cycle.mjs (926 lines, no existing docs)
|
||||
- [x] Read entire file (all 926 lines across multiple reads)
|
||||
- [x] Read scheduler-lock.mjs (173 lines) for call graph
|
||||
- [x] Checked existing docs coverage (lib-overview, lock-ops-overview, memory-index-overview)
|
||||
- [x] Wrote CONTEXT artifact
|
||||
- [x] Added top-of-file JSDoc + 19-step flow comment
|
||||
- [x] Added JSDoc to all 10 internal helper functions
|
||||
- [x] Added targeted inline comments for non-obvious logic
|
||||
- [x] Created docs/scheduler-cycle-overview.md (full overview)
|
||||
- [x] Wrote TODO, DECISIONS, TEST_LOG artifacts
|
||||
- [x] Wrote learning note
|
||||
|
||||
## Pending
|
||||
|
||||
(none)
|
||||
Reference in new issue
Block a user