mirror of
https://github.com/PR0M3TH3AN/SeedPass.git
synced 2026-10-27 16:02:05 +00:00
294 lines
17 KiB
Markdown
294 lines
17 KiB
Markdown
# Scheduler Flow (Single Source of Truth)
|
|
|
|
Use this document for all scheduler runs.
|
|
|
|
|
|
## Canonical artifact paths
|
|
|
|
All daily/weekly prompt files must reference run artifacts using these canonical directories:
|
|
|
|
- `src/context/CONTEXT_<timestamp>.md`
|
|
- `src/todo/TODO_<timestamp>.md`
|
|
- `src/decisions/DECISIONS_<timestamp>.md`
|
|
- `src/test_logs/TEST_LOG_<timestamp>.md`
|
|
|
|
Prompt authors: do not use legacy unprefixed paths (`context/`, `todo/`, `decisions/`, `test_logs/`).
|
|
|
|
|
|
## Shared Agent Run Contract (Required for All Spawned Agents)
|
|
|
|
Every agent prompt invoked by the schedulers (daily/weekly) MUST enforce this contract:
|
|
|
|
1. **Read baseline policy files before implementation**:
|
|
- `torch/TORCH.md`
|
|
- `KNOWN_ISSUES.md`
|
|
- Canonical path note: active issues are tracked in root `KNOWN_ISSUES.md` (not `docs/KNOWN_ISSUES.md`)
|
|
- `docs/agent-handoffs/README.md`
|
|
- Recent notes in `docs/agent-handoffs/learnings/` and `docs/agent-handoffs/incidents/`
|
|
2. **Update run artifacts** in `src/context/`, `src/todo/`, `src/decisions/`, and `src/test_logs/` during the run, or explicitly document why each artifact update is not needed for that run.
|
|
- When creating filenames with `<timestamp>`, use the scheduler-provided `SCHEDULER_RUN_TIMESTAMP` value when available.
|
|
- Required filename-safe format: `YYYY-MM-DDTHH-MM-SSZ` (for example `2026-02-15T01-03-31Z`); never use `:` in filenames.
|
|
3. **Capture reusable failures and unresolved issues**:
|
|
- Record reusable failures in `docs/agent-handoffs/incidents/`
|
|
- Record active unresolved reproducible items in `KNOWN_ISSUES.md`
|
|
4. **Execute memory retrieval before implementation begins**:
|
|
- Run configured memory retrieval workflow before prompt execution (for example via `scheduler.memoryPolicyByCadence.<cadence>.retrieveCommand`)
|
|
- Retrieval command MUST call real memory services (`src/services/memory/index.js#getRelevantMemories` with `ingestEvents` seeding) and MUST emit deterministic marker `MEMORY_RETRIEVED`.
|
|
- Retrieval command MUST write cadence-scoped evidence artifacts:
|
|
- `.scheduler-memory/retrieve-<cadence>.ok`
|
|
- `.scheduler-memory/retrieve-<cadence>.json` containing operation inputs/outputs (`agentId`, `query`, seeded event count, ingested count, retrieved count).
|
|
- **Agent Action**: Review `.scheduler-memory/latest/<cadence>/memories.md` for relevant context.
|
|
|
|
5. **Store memory after implementation and before completion publish**:
|
|
- **Agent Action**: Write any new insights, learnings, or patterns to the file specified by `$SCHEDULER_MEMORY_FILE`. The scheduler sets this env var to `memory-updates/<timestamp>__<agent>.md` automatically — do not compute a path yourself.
|
|
- **What to write** — use this template (keep each bullet to 1-2 lines; omit sections with nothing to say):
|
|
```markdown
|
|
# Memory Update — <agent-name> — <YYYY-MM-DD>
|
|
|
|
## Key findings
|
|
- <concrete fact discovered this run, e.g. "ESLint v9 requires flat config">
|
|
|
|
## Patterns / reusable knowledge
|
|
- <technique or pattern that will help this agent on its next run>
|
|
|
|
## Warnings / gotchas
|
|
- <env quirk, test failure, or constraint to watch for>
|
|
```
|
|
- Write only facts that will help the **same agent** on its **next run**. Skip meta-commentary about the task structure.
|
|
- Run configured memory storage workflow after prompt execution (for example via `scheduler.memoryPolicyByCadence.<cadence>.storeCommand`)
|
|
- Storage command MUST call real memory services (`src/services/memory/index.js#ingestEvents`, which uses ingestor/summarizer pipeline) and MUST emit deterministic marker `MEMORY_STORED`.
|
|
- Storage command MUST ingest content from the file at `$SCHEDULER_MEMORY_FILE` (or fallback to `memory-update.md` if present).
|
|
- Storage command MUST write cadence-scoped evidence artifacts:
|
|
- `.scheduler-memory/store-<cadence>.ok`
|
|
- `.scheduler-memory/store-<cadence>.json` containing operation inputs/outputs (`agentId`, input event count, stored count, generated summaries).
|
|
6. **Scheduler-owned completion/logging is mandatory**:
|
|
- Spawned agents MUST NOT run `lock:complete`.
|
|
- Spawned agents MUST NOT write final `task-logs/<cadence>/<timestamp>__<agent-name>__completed.md` or `__failed.md` files.
|
|
- Scheduler performs completion publish and writes final success/failure task logs after its own validation gates.
|
|
|
|
## Numbered MUST Procedure
|
|
|
|
0. Normalize execution context before any command:
|
|
- If `torch/scheduler-flow.md` exists in the current working directory:
|
|
- `script_prefix = npm run`
|
|
- `path_prefix = ` (empty)
|
|
- Else if `torch/torch/scheduler-flow.md` exists:
|
|
- `script_prefix = npm run --prefix torch`
|
|
- `path_prefix = torch/`
|
|
- Else stop with: `Unable to locate TORCH scheduler files (checked src/prompts and torch/src/prompts).`
|
|
- Ensure dependencies are installed:
|
|
- If `<path_prefix>node_modules` does not exist, run `npm install` (applying `<path_prefix>` if needed, e.g. `npm install --prefix torch`).
|
|
- Apply `script_prefix` to all `lock:*` invocations and apply `path_prefix` to scheduler paths.
|
|
|
|
1. Set cadence variables before any command:
|
|
- `cadence` = `daily` or `weekly`
|
|
- `log_dir` = `<path_prefix>task-logs/<cadence>/`
|
|
- `prompt_dir` = `<path_prefix>src/prompts/<cadence>/`
|
|
|
|
Note: branch naming (for example `agents/<cadence>/`) is orchestration-level behavior and is not used by `run-scheduler-cycle.mjs`.
|
|
|
|
2. Run preflight to build the exclusion set:
|
|
|
|
```bash
|
|
if daily: `<script_prefix> lock:check:daily -- --json --quiet`; if weekly: `<script_prefix> lock:check:weekly -- --json --quiet`
|
|
```
|
|
|
|
Canonical exclusion rule:
|
|
- Use `excluded` from the `<script_prefix> lock:check:<cadence>` JSON output.
|
|
- If `excluded` is unavailable, fallback to the union of `locked`, `paused`, and `completed` from that same JSON payload.
|
|
|
|
Goose Desktop note: `<script_prefix> lock:check:<cadence>` can emit large hermit wrapper logs. Use `--json --quiet` (as documented above). If the command still fails due to Goose hermit issues, apply the PATH workaround in `KNOWN_ISSUES.md` before rerunning.
|
|
|
|
3. Read policy file(s) once before the run loop. This step is conditional: if `torch/TORCH.md` is missing, continue without failing.
|
|
|
|
```bash
|
|
test -f <path_prefix>torch/TORCH.md && cat <path_prefix>torch/TORCH.md || echo "No torch/TORCH.md found; continuing"
|
|
```
|
|
|
|
4. Bootstrap log directories before listing files:
|
|
|
|
```bash
|
|
mkdir -p <log_dir>
|
|
```
|
|
|
|
5. When lock health preflight is enabled (`scheduler.lockHealthPreflight: true` or env `SCHEDULER_LOCK_HEALTH_PREFLIGHT=1`), verify relay/query health before selecting an agent or calling `lock:lock`:
|
|
|
|
```bash
|
|
<script_prefix> lock:health -- --cadence <cadence>
|
|
```
|
|
|
|
- Escape hatch: set `SCHEDULER_SKIP_LOCK_HEALTH_PREFLIGHT=1` to skip this check for local/offline workflows.
|
|
- If preflight exits non-zero because every relay is unhealthy, write `_deferred.md` with reason `All relays unhealthy preflight`, include `incident_signal_id`, set `failure_category: lock_backend_error`, state `prompt not executed`, and stop before lock acquisition.
|
|
- For other non-zero preflight failures, write `_failed.md` with reason `Lock backend unavailable preflight`, set `failure_category: lock_backend_error`, state `prompt not executed`, and include:
|
|
- `relay_list`
|
|
- `preflight_failure_category`
|
|
- `preflight_stderr_excerpt`
|
|
- `preflight_stdout_excerpt`
|
|
- Always include any preflight alert payload (`preflight_alerts`) in the scheduler metadata for operational triage.
|
|
|
|
6. Find latest cadence log file, derive the previous agent, then choose the next roster agent not in exclusion set:
|
|
|
|
```bash
|
|
ls -1 <log_dir> | sort | tail -n 1
|
|
```
|
|
|
|
Selection algorithm (MUST be followed exactly):
|
|
|
|
- Roster source: `torch/roster.json` and the key matching `<cadence>`.
|
|
- Resolve that source path as `<path_prefix>torch/roster.json`.
|
|
- Let `roster` be that ordered array and `excluded` be the set from step 2's canonical exclusion rule.
|
|
- Let `latest_file` be the lexicographically last filename in `<log_dir>`.
|
|
- 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.
|
|
2. Otherwise parse filename convention `<timestamp>__<agent-name>__<status>.md` and take `<agent-name>`.
|
|
- If no valid `latest_file` exists, or parsing fails, or `previous_agent` is not in `roster`, treat as first run fallback.
|
|
- First run fallback:
|
|
- Read `scheduler.firstPromptByCadence.<cadence>` from repository-root `torch-config.json` if present.
|
|
- If that agent exists in `roster`, set `start_index = index(configured_agent)`.
|
|
- Otherwise set `start_index = 0`.
|
|
- Otherwise: `start_index = (index(previous_agent in roster) + 1) mod len(roster)`.
|
|
- Round-robin scan:
|
|
- Iterate offsets `0..len(roster)-1`.
|
|
- Candidate index: `(start_index + offset) mod len(roster)` (wrap-around required).
|
|
- Choose the first candidate whose agent is **not** in `excluded`.
|
|
- If no candidate is eligible, execute step 7.
|
|
|
|
Worked examples:
|
|
|
|
- **Daily example**
|
|
- `roster.daily = [audit-agent, ci-health-agent, const-refactor-agent, ...]`
|
|
- `latest_file = 2026-02-13T00-10-00Z__ci-health-agent__completed.md`
|
|
- `excluded = {const-refactor-agent, docs-agent}`
|
|
- `previous_agent = ci-health-agent`, so `start_index` points to `const-refactor-agent`.
|
|
- `const-refactor-agent` is excluded; skip to `content-audit-agent`.
|
|
- **Selection result: `content-audit-agent`.**
|
|
|
|
- **Weekly example**
|
|
- `roster.weekly = [bug-reproducer-agent, changelog-agent, ..., weekly-synthesis-agent]`
|
|
- `latest_file = 2026-02-09T00-00-00Z__weekly-synthesis-agent__completed.md`
|
|
- `excluded = {}`
|
|
- `previous_agent = weekly-synthesis-agent` (last roster entry), so `start_index = 0` by wrap-around.
|
|
- First candidate is `bug-reproducer-agent` and is eligible.
|
|
- **Selection result: `bug-reproducer-agent`.**
|
|
|
|
7. If every roster agent is excluded, write a `_failed.md` log with:
|
|
`All roster tasks currently claimed by other agents` and stop.
|
|
|
|
8. Claim selected agent:
|
|
|
|
```bash
|
|
AGENT_PLATFORM=<platform> \
|
|
<script_prefix> lock:lock -- --agent <agent-name> --cadence <cadence>
|
|
```
|
|
|
|
- Exit `0`: lock acquired, continue.
|
|
- Exit `3`: race lost/already locked, return to step 2.
|
|
- Exit `2`: lock backend error.
|
|
- If `scheduler.strict_lock` is `false`, defer the run while both budget constraints are still satisfied:
|
|
- `degraded_lock_retry_window` (ms) since first backend failure has not elapsed.
|
|
- `max_deferrals` has not been exceeded.
|
|
- Record deferral metadata in scheduler run state (`attempt_count`, `first_failure_timestamp`, `backend_category`, and preserved idempotency key).
|
|
- Otherwise write `_failed.md` with reason `Lock backend error`, and include failure metadata fields:
|
|
- `backend_category` (classified backend failure category)
|
|
- `lock_command` (raw lock command for retry)
|
|
- `lock_stderr_excerpt` (redacted stderr snippet)
|
|
- `lock_stdout_excerpt` (redacted stdout snippet)
|
|
- Include `failure_class: backend_unavailable` and `failure_category: lock_backend_error` for both deferred and failed backend-unavailable lock outcomes.
|
|
- Include recommended auto-remediation text in `detail`: retry window, `<script_prefix> lock:health -- --cadence <cadence>`, and incident runbook link.
|
|
- Keep generic reason text for compatibility, but append actionable retry guidance in `detail` using the command from `lock_command`.
|
|
|
|
9. Execute `<prompt_dir>/<prompt-file>` end-to-end via configured handoff command.
|
|
|
|
- Scheduler automation runs `scheduler.handoffCommandByCadence.<cadence>` with environment variables for cadence/agent/prompt path.
|
|
- If no handoff command is configured for the cadence, write `_failed.md` and stop.
|
|
- Prompt file read/parse failures should emit `failure_category: prompt_parse_error`.
|
|
- Prompt schema/contract failures should emit `failure_category: prompt_schema_error`.
|
|
- Command/handoff/validation runtime failures should emit `failure_category: execution_error`.
|
|
|
|
10. Confirm memory contract completion:
|
|
|
|
- Memory retrieval evidence must exist for this run (output marker and/or artifact file).
|
|
- Memory storage evidence must exist for this run (output marker and/or artifact file).
|
|
- Enforced daily/weekly commands in `torch-config.json` run `node --input-type=module` snippets that call `src/services/memory/index.js` APIs directly:
|
|
- Retrieval path: `ingestEvents(...)` seed + `getRelevantMemories(...)` retrieval.
|
|
- Storage path: `ingestEvents(...)` (ingestor + summarizer path).
|
|
- Input contract for retrieval evidence JSON:
|
|
- Required keys: `cadence`, `operation: "retrieve"`, `servicePath`, `inputs`, `outputs`, `status: "ok"`.
|
|
- `inputs` must include `agentId`, `query`, and seeded `events` count.
|
|
- `outputs` must include `ingestedCount` and `retrievedCount`.
|
|
- Input contract for storage evidence JSON:
|
|
- Required keys: `cadence`, `operation: "store"`, `servicePath`, `inputs`, `outputs`, `status: "ok"`.
|
|
- `inputs` must include `agentId` and input `events` count.
|
|
- `outputs` must include `storedCount` and generated `summaries`.
|
|
- Failure semantics for required mode:
|
|
- If retrieval/store command exits non-zero, scheduler writes `_failed.md` and stops.
|
|
- If command succeeds but markers/artifacts are missing, scheduler treats this as missing memory evidence.
|
|
- Prompt authors MUST keep any command changes aligned with configured markers/artifacts so scheduler evidence checks remain satisfiable.
|
|
- If `scheduler.memoryPolicyByCadence.<cadence>.mode = required`, missing evidence is a hard failure.
|
|
- If mode is `optional`, log warning context and continue.
|
|
|
|
11. Verify required run artifacts for the current run window.
|
|
|
|
- Scheduler runs `node scripts/agent/verify-run-artifacts.mjs --since <run-start-iso> --check-failure-notes`.
|
|
- If artifact verification exits non-zero: write `_failed.md` and stop.
|
|
|
|
12. Run repository checks (for example: `<script_prefix> lint`).
|
|
|
|
- If any validation command exits non-zero: **fail the run immediately**, write `_failed.md` with the failing command and reason, and stop.
|
|
- step 12 MUST NOT be executed (`lock:complete` is forbidden until validation passes).
|
|
- In current numbering: when step 12 fails, step 13 MUST NOT run.
|
|
|
|
13. Publish completion before writing final success log:
|
|
|
|
```bash
|
|
AGENT_PLATFORM=<platform> \
|
|
<script_prefix> lock:complete -- --agent <agent-name> --cadence <cadence>
|
|
```
|
|
|
|
(Equivalent invocation is allowed: `torch-lock complete --agent <agent-name> --cadence <cadence>`.)
|
|
|
|
- Exit `0`: completion published successfully; continue to step 14.
|
|
- Exit non-zero: **fail the run**, write `_failed.md` with a clear reason that completion publish failed and retry guidance (for example: `Retry <script_prefix> lock:complete -- --agent <agent-name> --cadence <cadence> after verifying relay connectivity`), then stop.
|
|
|
|
14. Create final task log only after step 13 succeeds (scheduler-owned):
|
|
|
|
- `_completed.md` MUST be created only after completion publish succeeds.
|
|
- `_failed.md` is required when step 11, step 12, or step 13 fails, and should include the failure reason and next retry action.
|
|
- Include `platform` in frontmatter using `AGENT_PLATFORM` (or the scheduler `--platform` value) for both `_completed.md` and `_failed.md`.
|
|
|
|
15. Commit/push behavior is delegated outside this scheduler script.
|
|
|
|
- `scripts/agent/run-scheduler-cycle.mjs` does **not** run `git commit` or `git push`.
|
|
- If commit/push is required for your workflow, perform it in the configured handoff agent command or a separate orchestration step.
|
|
|
|
16. Print a final summary message to stdout (standard output).
|
|
|
|
- The message MUST include:
|
|
- **Status**: [Success/Failure/Deferred]
|
|
- **Agent**: [Agent Name]
|
|
- **Prompt**: [Prompt Path]
|
|
- **Reason**: [Reason string]
|
|
- **Learnings**: [Content of the memory update file or "No learnings recorded"]
|
|
|
|
- If the run failed, include the failure reason.
|
|
- If the run succeeded, try to include the content of the memory update file (e.g., `memory-updates/<timestamp>__<agent>.md`) as the "Learnings".
|
|
|
|
Worked post-task example (MUST order):
|
|
|
|
1. `AGENT_PLATFORM=codex <script_prefix> lock:lock -- --agent content-audit-agent --cadence daily`
|
|
2. Execute `<path_prefix>torch/prompts/daily/content-audit-agent.md`
|
|
3. `node scripts/agent/verify-run-artifacts.mjs --since <run-start-iso> --check-failure-notes`
|
|
4. `AGENT_PLATFORM=codex <script_prefix> lock:complete -- --agent content-audit-agent --cadence daily` (complete, permanent)
|
|
5. Write `<path_prefix>task-logs/daily/2026-02-14T10-00-00Z__content-audit-agent__completed.md`
|
|
6. Print final summary (Status: Success, Learnings: <content>)
|
|
|
|
Worked validation-failure example (MUST behavior):
|
|
|
|
1. `AGENT_PLATFORM=codex <script_prefix> lock:lock -- --agent content-audit-agent --cadence daily`
|
|
2. Execute `<path_prefix>torch/prompts/daily/content-audit-agent.md`
|
|
3. `node scripts/agent/verify-run-artifacts.mjs --since <run-start-iso> --check-failure-notes` passes
|
|
4. `<script_prefix> lint` exits non-zero (or `<script_prefix> test` exits non-zero)
|
|
5. Write `<path_prefix>task-logs/daily/2026-02-14T10-00-00Z__content-audit-agent__failed.md` with the failing command and reason
|
|
6. Stop the run **without** calling `<script_prefix> lock:complete -- --agent content-audit-agent --cadence daily`
|
|
7. Print final summary (Status: Failed, Reason: <reason>)
|