diff --git a/KNOWN_ISSUES.md b/KNOWN_ISSUES.md index 72644d5..d71fcec 100644 --- a/KNOWN_ISSUES.md +++ b/KNOWN_ISSUES.md @@ -17,15 +17,14 @@ Track only **active, reproducible, unresolved** issues. ## Active issues ### `test/scheduler-preflight-lock.e2e.test.mjs` platform mismatch (`unknown` vs `codex`) -- **Status:** Active -- **Issue-ID:** KNOWN-ISSUE-scheduler-preflight-platform +- **Status:** Resolved - **Area:** Test -- **Symptom:** The first e2e scenario fails because expected frontmatter platform resolves to `unknown` in test context while scheduler output persists `platform: codex`. -- **Trigger/Conditions:** Running `node test/scheduler-preflight-lock.e2e.test.mjs` or `node --test test/scheduler-preflight-lock.e2e.test.mjs` in this environment. -- **Workaround:** Exclude `test/scheduler-preflight-lock.e2e.test.mjs` from local sandbox triage runs until the expectation source is aligned with scheduler platform semantics. -- **Impact:** Medium — scheduler e2e bundle reports a deterministic failure unrelated to most feature changes. +- **Symptom:** Historical issue where test expected `platform: unknown` while scheduler logs used `platform: codex`. +- **Trigger/Conditions:** Previously reproed in Codex. +- **Workaround:** None needed after assertion behavior update. +- **Impact:** No longer blocking. - **Related notes:** `docs/agent-handoffs/incidents/2026-02-20-codex-test-failures-platform-and-telemetry.md` -- **Last verified:** 2026-02-21 +- **Last verified:** 2026-02-20 ### `test/memory-telemetry.test.mjs` expects child-process stdout/stderr that are empty in this environment - **Status:** Active diff --git a/TORCH.md b/TORCH.md index 7247e71..72b1357 100644 --- a/TORCH.md +++ b/TORCH.md @@ -330,9 +330,6 @@ Common settings: - `dashboard.hashtag` — custom hashtag for lock events (defaults to `-agent-lock`). - `scheduler.firstPromptByCadence.daily` / `.weekly` — first-run scheduler starting agent. - `scheduler.handoffCommandByCadence.daily` / `.weekly` — shell command run after lock acquisition; command must use `SCHEDULER_AGENT`, `SCHEDULER_CADENCE`, and `SCHEDULER_PROMPT_PATH` provided by `scripts/agent/run-scheduler-cycle.mjs`. -- `scheduler.handoffPolicyByCadence.daily` / `.weekly` — optional retry/fallback policy for handoff execution (`maxAttempts`, `retryBackoffMs`, `retryOnPatterns`, `fallbackPlatform`). -- `scheduler.runnerHealthCommandByCadence.daily` / `.weekly` — optional command run before lock acquisition to verify runner availability; non-zero exits fail the run before prompt execution. -- `scheduler.memoryPolicyByCadence..retrieveArtifacts` / `.storeArtifacts` — evidence file list; recommended canonical files include `.scheduler-memory/latest//retrieve.ok`, `.scheduler-memory/latest//retrieve.json`, `.scheduler-memory/latest//store.ok`, `.scheduler-memory/latest//store.json`. - `scheduler.paused.daily` / `.weekly` — array of agent names to exclude from scheduler rotation. - `scheduler.strict_lock` — lock backend policy switch (default: `true`); when `false`, scheduler defers backend-unavailable lock failures before converting the run to failed. - `scheduler.degraded_lock_retry_window` — non-strict deferral window in milliseconds; backend lock failures outside this window immediately consume failure budget and mark run failed. diff --git a/docs/agent-handoffs/incidents/2026-02-20-codex-test-failures-platform-and-telemetry.md b/docs/agent-handoffs/incidents/2026-02-20-codex-test-failures-platform-and-telemetry.md index b95ce41..cfafaee 100644 --- a/docs/agent-handoffs/incidents/2026-02-20-codex-test-failures-platform-and-telemetry.md +++ b/docs/agent-handoffs/incidents/2026-02-20-codex-test-failures-platform-and-telemetry.md @@ -28,30 +28,3 @@ - Treat these as environment-sensitive test failures until assertions are aligned with Codex platform semantics and child-process output behavior. - If updating tests, follow spec-correction protocol and preserve strict behavioral intent. - Keep `KNOWN_ISSUES.md` dates/status current after remediation. - -## Update 2026-02-21 - -### Context -- Agent: `test-audit-agent` -- Scope: scenario-first audit run using `scripts/test-audit/run-flaky-check.mjs` and targeted scheduler e2e verification. - -### Observation -- The scheduler platform mismatch is still reproducible: - - Expected in test assertion: `platform: unknown` (derived from test-side `detectPlatform() || 'unknown'`) - - Actual log frontmatter: `platform: codex` -- Reproduced with: - - `node test/scheduler-preflight-lock.e2e.test.mjs` - - `node --test test/scheduler-preflight-lock.e2e.test.mjs` - -### Action taken -- Reclassified the issue in `KNOWN_ISSUES.md` from Resolved back to Active (`KNOWN-ISSUE-scheduler-preflight-platform`) with updated workaround and verification date. -- Did not weaken/modify scenario expectations in the e2e test without explicit spec correction. - -### Validation performed -- `node test/scheduler-preflight-lock.e2e.test.mjs` (fails with platform mismatch) -- `node --test test/scheduler-preflight-lock.e2e.test.mjs` (fails) - -### Recommendation for next agents -- Resolve via spec correction only: - 1. Decide canonical platform source for scheduler logs in fixtures (`AGENT_PLATFORM` fallback vs runtime detector). - 2. Update assertion to match documented scheduler behavior, not incidental environment state. diff --git a/docs/proposals/plan-agent-architecture.md b/docs/proposals/plan-agent-architecture.md deleted file mode 100644 index c8dcc99..0000000 --- a/docs/proposals/plan-agent-architecture.md +++ /dev/null @@ -1,542 +0,0 @@ -# Proposal: Plan Agent Architecture — Closing the Idea-to-Implementation Gap - -## Problem Statement - -TORCH has **44 agents** generating proposals, audits, and feature ideas — but **zero agents** that evaluate those proposals, plan implementation strategies, or build approved features. The result is a growing pile of dead ends: - -### Diagnosed Dead Ends (Current State) - -| Dead End | Type | Why It's Stuck | -|----------|------|----------------| -| Node-based prompt editor | Proposal | 306-line design doc, zero implementation, no champion | -| Prompt packages system | Proposal | Concept doc only, never prioritized into work | -| Hybrid distribution (binary + dashboard) | Proposal | Architecture written, zero progress | -| `event-schema-agent` | Broken agent | References `src/lib/eventSchemas.js` which doesn't exist — failed 2x, never fixed | -| `content-audit-agent` | Scope mismatch | Audits upload/contribution features that don't exist in TORCH | -| `style-agent` | Missing tooling | Blocked on missing `npm run format` script — never added | -| 7 proposed agents in `AGENT_COVERAGE_GAPS.md` | Coverage gaps | Documented but no agent builds new agents | -| 77 scattered TODO files | Organizational debt | Created daily, never consolidated or triaged | -| 130+ dead artifacts | Audit fatigue | Reports generated continuously, never acted upon | - -### Root Cause: Missing Pipeline Stages - -The current pipeline has a structural gap. Ideas flow in but never flow through to completion: - -``` -CURRENT PIPELINE (broken feedback loop) - - feature-proposer-agent ──→ creates single file in features/ - prompt-gap-analysis-agent ──→ identifies gaps, writes report - weekly-synthesis-agent ──→ summarizes activity - governance-agent ──→ applies/rejects prompt changes - - ┌─────────────────────────────────────────────────┐ - │ MISSING: Who evaluates proposals? │ - │ MISSING: Who plans implementation strategy? │ - │ MISSING: Who builds multi-file features? │ - │ MISSING: Who retires dead-end work? │ - │ MISSING: Who closes the loop on artifacts? │ - └─────────────────────────────────────────────────┘ -``` - -The `feature-proposer-agent` creates single-file features in `features/`. It explicitly cannot modify existing files or execute multi-step implementations. The `governance-agent` handles prompt changes but not feature development. Nobody triages the 3 stalled proposals, 7 unimplemented agent gaps, or 15 failed task logs. - ---- - -## Proposed Solution: Three New Pipeline Agents - -Add three new weekly agents that close the gap between "idea" and "implementation": - -``` -PROPOSED PIPELINE (closed loop) - - IDEAS IN BUILT OUT - ───────── ───────── - feature-proposer-agent ─┐ - prompt-gap-analysis-agent ─┤ - docs/proposals/*.md ──────┤ - AGENT_COVERAGE_GAPS.md ───┤ - KNOWN_ISSUES.md ──────────┤ - artifacts/ reports ───────┘ - │ - ┌───────▼────────┐ - │ proposal- │ TRIAGE: Evaluates all pending - │ triage-agent │ proposals, dead ends, and gaps. - │ │ Produces prioritized backlog. - └───────┬────────┘ - │ - ┌───────▼────────┐ - │ plan-agent │ PLAN: Takes top-priority item - │ │ from backlog. Produces step-by-step - │ │ implementation plan with file list, - │ │ test strategy, and acceptance criteria. - └───────┬────────┘ - │ - ┌───────▼────────┐ - │ builder-agent │ BUILD: Executes approved plan. - │ │ Creates/modifies files, writes tests, - │ │ validates against acceptance criteria. - └────────────────┘ -``` - -### Why Three Agents, Not One? - -A single "do everything" agent would violate TORCH's core design principles: - -1. **Single responsibility** — Each agent has one job, one prompt, one failure mode -2. **Round-robin fairness** — Three separate agents get three separate time slots; a monolithic agent would monopolize an entire weekly slot -3. **Incremental progress** — Triage can run without planning; planning can run without building; each produces value independently -4. **Auditable handoffs** — Each stage produces artifacts that the next stage consumes, creating a reviewable paper trail -5. **Failure isolation** — If the builder fails, the plan still exists for the next cycle; if triage fails, existing plans aren't affected - ---- - -## Agent 1: `proposal-triage-agent` (Weekly) - -### Identity - -> You are: **proposal-triage-agent**, a weekly agent that evaluates pending proposals, identifies dead ends, and produces a prioritized implementation backlog. - -### Mission - -Synthesize all pending work items (proposals, coverage gaps, dead-end agents, stale artifacts) into a single prioritized backlog file that downstream agents can consume. - -### Inputs (Read) - -| Source | What to Extract | -|--------|----------------| -| `docs/proposals/*.md` | Active proposals and their implementation status | -| `docs/AGENT_COVERAGE_GAPS.md` | Proposed but unimplemented agents | -| `KNOWN_ISSUES.md` | Blocking issues that need tooling fixes | -| `task-logs/daily/` + `task-logs/weekly/` | Failed agent runs (pattern detection) | -| `artifacts/` | Reports that haven't driven action | -| `src/todo/` | Scattered TODO files needing consolidation | -| `features/` | Single-file features from `feature-proposer-agent` | -| `docs/agent-handoffs/incidents/` | Unresolved incidents | -| Previous backlog (`src/backlog/BACKLOG.md`) | Carry forward items not yet addressed | - -### Output (Write) - -**Primary artifact:** `src/backlog/BACKLOG.md` - -```markdown -# Implementation Backlog — - -## Triage Summary -- Items evaluated: -- New items added: -- Items retired (dead end): -- Items promoted to ready: - -## Priority 1: Ready to Plan - - -### BACKLOG-001: Add `npm run format` script to package.json -- **Source:** KNOWN_ISSUES.md, style-agent failures -- **Impact:** Unblocks style-agent (daily cadence) -- **Scope:** Single line in package.json -- **Status:** ready-to-plan -- **Acceptance:** `npm run format` exits 0; style-agent completes successfully - -### BACKLOG-002: Create `src/lib/eventSchemas.js` -- **Source:** event-schema-agent failures (2x) -- **Impact:** Unblocks event-schema-agent (weekly cadence) -- **Scope:** Extract event builders from `src/nostr-lock.mjs` into shared module -- **Status:** ready-to-plan -- **Acceptance:** event-schema-agent completes; `src/nostr-lock.mjs` imports from new module - -## Priority 2: Needs Scoping - - -### BACKLOG-003: Implement Phase 0 of prompt graph extraction -- **Source:** docs/proposals/node-based-prompt-editor.md -- **Impact:** Machine-readable agent metadata for all 44 prompts -- **Scope:** 4 new scripts in `scripts/prompt-graph/` -- **Status:** needs-scoping -- **Blockers:** None -- **Open Questions:** Regex patterns may not cover all prompt variations - -## Priority 3: Deferred - - -## Retired (Dead Ends) - - -### RETIRED: content-audit-agent upload/contribution scope -- **Rationale:** TORCH has no upload UI, API, or storage. Agent audits features - that don't exist. Recommend revising agent scope instead of building features. -``` - -### Triage Criteria - -Items are scored on four dimensions: - -| Dimension | Weight | Scoring | -|-----------|--------|---------| -| **Unblock** | 3x | Does this unblock a currently-broken agent or workflow? | -| **Value** | 2x | Does this deliver user-visible value or reduce failure rate? | -| **Scope** | 1x | Is the implementation scope clear and bounded? | -| **Risk** | -1x | Does this require architectural changes or new dependencies? | - -### Retirement Rules - -An item should be retired (not deferred) when: -- The feature it depends on doesn't exist and isn't planned (e.g., content-audit-agent auditing upload features) -- The proposal has been superseded by a different approach -- The cost clearly exceeds the benefit with no path to improvement -- The item has been deferred for 4+ consecutive triage cycles with no progress - -### Weekly Workflow - -1. Read all inputs listed above -2. Read previous `src/backlog/BACKLOG.md` if it exists -3. Evaluate each pending item against triage criteria -4. Score and rank items -5. Write updated `src/backlog/BACKLOG.md` -6. Write triage summary to `src/decisions/DECISIONS_.md` - ---- - -## Agent 2: `plan-agent` (Weekly) - -### Identity - -> You are: **plan-agent**, a weekly agent that creates detailed implementation plans for the highest-priority backlog item. - -### Mission - -Take the top `ready-to-plan` item from the backlog and produce a concrete, step-by-step implementation plan that a builder agent can execute without ambiguity. - -### Inputs (Read) - -| Source | What to Extract | -|--------|----------------| -| `src/backlog/BACKLOG.md` | Top `ready-to-plan` item | -| Original proposal/source doc | Full context for the item | -| Relevant codebase files | Current implementation to understand integration points | -| `KNOWN_ISSUES.md` | Active blockers that might affect the plan | -| `docs/agent-handoffs/learnings/` | Past learnings relevant to this work | -| Previous plans (`src/plans/`) | Avoid re-planning already-planned items | - -### Output (Write) - -**Primary artifact:** `src/plans/PLAN-.md` - -```markdown -# Implementation Plan: BACKLOG-001 — Add `npm run format` script - -## Backlog Reference -- **ID:** BACKLOG-001 -- **Source:** KNOWN_ISSUES.md, style-agent failures -- **Priority:** P1 (unblocks daily agent) - -## Objective -Add a working `npm run format` script to `package.json` that the -`style-agent` can invoke to auto-format code. - -## Analysis -- `style-agent` prompt references `npm run format` at line 12 -- `package.json` has `prettier` in devDependencies (v3.2.x) -- `.prettierrc` exists with project configuration -- No existing format script; only `lint` exists - -## Implementation Steps - -### Step 1: Add format script to package.json -- **File:** `package.json` -- **Change:** Add `"format": "prettier --write ."` to `scripts` object -- **Test:** `npm run format` exits 0 without errors - -### Step 2: Add format check script (CI-friendly) -- **File:** `package.json` -- **Change:** Add `"format:check": "prettier --check ."` to `scripts` object -- **Test:** `npm run format:check` exits 0 after formatting - -### Step 3: Validate style-agent can complete -- **Action:** Verify `style-agent` prompt references match available scripts -- **Test:** Dry-run style-agent workflow mentally against available npm scripts - -## Files Modified -- `package.json` (2 lines added to `scripts`) - -## Files Created -- None - -## Acceptance Criteria -1. `npm run format` exits 0 and formats `.js` / `.mjs` files per `.prettierrc` -2. `npm run format:check` exits 0 after running `npm run format` -3. `style-agent` prompt commands all resolve to valid npm scripts -4. No existing tests break - -## Test Strategy -- Run `npm run format` and verify exit code -- Run `npm run format:check` and verify exit code -- Run `npm test` to verify no regressions -- Run `npm run lint` to verify compatibility - -## Risk Assessment -- **Low risk:** Adding scripts to package.json is additive -- **No architectural changes required** -- **Rollback:** Remove the two script lines - -## Dependencies -- None — self-contained change - -## Estimated Complexity -- **Simple** (< 5 file changes, no new modules) -``` - -### Planning Rules - -1. **One plan per cycle** — Don't try to plan everything. Pick the single highest-priority `ready-to-plan` item -2. **Concrete file paths** — Every step must name the exact file(s) to create or modify -3. **Testable acceptance** — Every acceptance criterion must be verifiable by running a command -4. **No ambiguity** — A builder agent reading only this plan should be able to implement it without guessing -5. **Scope guard** — If the item is too large for a single builder cycle, break it into sub-plans and update the backlog - -### Status Updates - -After planning, update the backlog item's status: - -``` -- **Status:** ready-to-plan → planned (see src/plans/PLAN-BACKLOG-001.md) -``` - -### Weekly Workflow - -1. Read `src/backlog/BACKLOG.md` -2. Select top `ready-to-plan` item -3. If no items are `ready-to-plan`, check for `needs-scoping` items and attempt to scope them (update status to `ready-to-plan` if successful) -4. Read all referenced source documents and relevant codebase files -5. Write implementation plan to `src/plans/PLAN-.md` -6. Update backlog item status to `planned` -7. Write planning rationale to `src/decisions/DECISIONS_.md` - ---- - -## Agent 3: `builder-agent` (Weekly) - -### Identity - -> You are: **builder-agent**, a weekly agent that implements the oldest approved plan from the plans directory. - -### Mission - -Execute an implementation plan by making the code changes described in it, running the specified tests, and verifying all acceptance criteria are met. - -### Inputs (Read) - -| Source | What to Extract | -|--------|----------------| -| `src/plans/PLAN-*.md` | Oldest plan with status `planned` (not `completed` or `in-progress`) | -| All files referenced in the plan | Current state of code to be modified | -| `KNOWN_ISSUES.md` | Active blockers that might affect implementation | -| `src/backlog/BACKLOG.md` | Context for the work item | - -### Implementation Protocol - -1. **Claim the plan** — Add frontmatter `status: in-progress` and `started: ` to the plan file -2. **Execute steps sequentially** — Follow the plan's implementation steps in order -3. **Validate after each step** — Run the step's test command if specified -4. **Run acceptance criteria** — Execute every acceptance criterion command -5. **Update plan status** — Set `status: completed` with `completed: ` if all criteria pass -6. **Update backlog** — Set backlog item status to `completed` -7. **Handle failures** — If any acceptance criterion fails: - - Set plan status to `blocked` with `blocked_reason` - - Do NOT mark backlog item as completed - - Document the failure in `KNOWN_ISSUES.md` if it's a new issue - - Write incident note to `docs/agent-handoffs/incidents/` - -### Output (Write) - -- Modified/created files per the plan -- Updated plan file (status, timestamps) -- Updated backlog (item status) -- Test log in `src/test_logs/TEST_LOG_.md` - -### Builder Rules - -1. **Follow the plan exactly** — Don't improvise. If the plan says "add line X to file Y", do that -2. **Don't expand scope** — Only make changes listed in the plan. No bonus refactors, no "while I'm here" improvements -3. **Fail loudly** — If a step can't be completed, stop and document why. Don't skip steps -4. **Test everything** — Run every test command in the plan. Run `npm test` and `npm run lint` as final validation -5. **One plan per cycle** — Complete one plan fully before starting another - -### Conflict with `feature-proposer-agent` - -The existing `feature-proposer-agent` creates single-file features in `features/`. The `builder-agent` executes multi-step plans that may modify existing files. These agents have different scopes: - -| Aspect | feature-proposer-agent | builder-agent | -|--------|----------------------|---------------| -| Scope | Single new file in `features/` | Any files specified in plan | -| Input | Own analysis of codebase | Explicit plan from `plan-agent` | -| Modifications | New files only | New + existing files | -| Validation | Self-verified | Acceptance criteria from plan | -| Autonomy | High (chooses what to build) | Low (follows plan exactly) | - -Both agents should continue to exist. The `feature-proposer-agent` handles quick, self-contained additions. The `builder-agent` handles planned, multi-step implementations. - ---- - -## Integration with Existing Pipeline - -### Roster Changes - -Add to `src/prompts/roster.json` under `weekly`: - -```json -{ - "weekly": [ - "bug-reproducer-agent", - "builder-agent", - "changelog-agent", - "dead-code-agent", - "feature-proposer-agent", - "frontend-console-debug-agent", - "fuzz-agent", - "perf-deepdive-agent", - "perf-optimization-agent", - "plan-agent", - "pr-review-agent", - "prompt-fixer-agent", - "prompt-gap-analysis-agent", - "prompt-maintenance-agent", - "prompt-safety-agent", - "proposal-triage-agent", - "race-condition-agent", - "refactor-agent", - "repo-fit-agent", - "smoke-agent", - "telemetry-agent", - "test-coverage-agent", - "ui-ux-agent", - "weekly-synthesis-agent" - ] -} -``` - -### New Directories - -``` -src/backlog/ # Prioritized implementation backlog (from proposal-triage-agent) -src/plans/ # Implementation plans (from plan-agent) -``` - -### New Prompt Files - -``` -src/prompts/weekly/proposal-triage-agent.md -src/prompts/weekly/plan-agent.md -src/prompts/weekly/builder-agent.md -``` - -### Execution Order Consideration - -In the current round-robin, these agents run in alphabetical order within the weekly cadence. The ideal execution order is: - -1. `proposal-triage-agent` (produces backlog) -2. `plan-agent` (consumes backlog, produces plan) -3. `builder-agent` (consumes plan, produces implementation) - -Since round-robin is alphabetical (`builder-agent` < `plan-agent` < `proposal-triage-agent`), the builder would run *before* the planner in any given week. This is acceptable because: - -- Plans persist across weeks — a plan written in week N is built in week N+1 -- The pipeline is designed for multi-week cadence, not single-week completion -- Each agent checks for existing artifacts from previous cycles - -If same-week execution is desired in the future, the Phase 3+ custom flow configurations from the prompt editor proposal would enable DAG-based ordering. - -### Interaction with Existing Agents - -| Existing Agent | Interaction | -|---------------|-------------| -| `feature-proposer-agent` | Features it creates may be evaluated by `proposal-triage-agent` | -| `prompt-gap-analysis-agent` | Gap reports feed into `proposal-triage-agent` inputs | -| `weekly-synthesis-agent` | Summarizes triage/plan/build activity in weekly report | -| `governance-agent` | Prompt changes from builder go through normal governance | -| `prompt-maintenance-agent` | Validates new agent prompts follow contract | -| `dead-code-agent` | May identify retired items for triage to confirm | - ---- - -## Addressing the Identified Dead Ends - -Here's how the new pipeline would handle each current dead end: - -| Dead End | Agent | Action | -|----------|-------|--------| -| Missing `npm run format` | triage → plan → builder | P1: triage identifies, plan writes 2-line change, builder implements | -| Missing `eventSchemas.js` | triage → plan → builder | P1: triage identifies, plan designs extraction, builder creates module | -| content-audit-agent scope | triage | Retired: agent audits nonexistent features | -| Prompt editor Phase 0 | triage → plan | Scoped: triage breaks into sub-tasks, plan designs Phase 0 extraction | -| Prompt packages | triage → plan | Deferred or scoped depending on priority vs. other items | -| Distribution binary | triage | Deferred: requires external tooling, low relative priority | -| 7 coverage gap agents | triage → plan → builder | Each gap becomes a backlog item; plan designs prompt, builder creates it | -| 77 scattered TODOs | triage | Consolidated into backlog; triage replaces scattered TODO creation | -| 130+ dead artifacts | triage | Evaluated for actionability; non-actionable artifacts flagged for GC | - ---- - -## Success Metrics - -| Metric | Current | Target (4 weeks) | Target (8 weeks) | -|--------|---------|-------------------|-------------------| -| Stalled proposals | 3 | 2 (1 retired, 1 planned) | 0 (all planned or retired) | -| Broken agents | 3 (event-schema, style, content-audit) | 1 (content-audit retired) | 0 | -| Unimplemented coverage gaps | 7 | 5 (2 planned) | 3 (2 built, 2 planned) | -| Backlog items with clear status | 0 | 10+ | 15+ | -| Plans executed per month | 0 | 2 | 4 | - ---- - -## Implementation Plan for This Proposal - -This proposal itself should go through the pipeline it describes. Bootstrap order: - -### Step 1: Create directories -```bash -mkdir -p src/backlog src/plans -``` - -### Step 2: Create `proposal-triage-agent.md` -- Write prompt following shared agent run contract -- Add to `roster.json` weekly array - -### Step 3: Create `plan-agent.md` -- Write prompt following shared agent run contract -- Add to `roster.json` weekly array - -### Step 4: Create `builder-agent.md` -- Write prompt following shared agent run contract -- Add to `roster.json` weekly array - -### Step 5: Seed initial backlog -- Create `src/backlog/BACKLOG.md` with known dead ends pre-triaged -- This gives the plan-agent something to work with on its first run - -### Step 6: Validate -- Run `node scripts/validate-prompt-contract.mjs` -- Run `node scripts/validate-scheduler-roster.mjs` -- Run `npm run lint` -- Run `npm test` - ---- - -## Risks - -| Risk | Severity | Mitigation | -|------|----------|------------| -| Builder agent makes incorrect changes | High | Plan must have testable acceptance criteria; builder runs all tests | -| Triage agent deprioritizes important work | Medium | Triage criteria are explicit and weighted; human can override backlog | -| Plan scope creep | Medium | Planning rules enforce one plan per cycle, concrete file paths | -| Agents produce circular work (triage creates items that triage later retires) | Low | Retirement rules require 4+ deferred cycles before retirement | -| Builder conflicts with other agents modifying same files | Medium | Lock system prevents concurrent modification; plan specifies exact files | - ---- - -## Relationship to Other Proposals - -- **Prompt Editor (Phase 0):** The triage agent would evaluate this proposal and potentially break Phase 0 into backlog items. The plan agent would design the extraction scripts. The builder agent would create them. -- **Prompt Packages:** Same pipeline — triage evaluates, plan designs, builder implements. -- **Distribution Plan:** Triage would likely defer this (requires external tooling) but keep it visible in the backlog. -- **Agent Coverage Gaps:** Each gap becomes a backlog item. The builder agent is literally designed to create new agent prompts from plans. diff --git a/memory-updates/2026-02-21T19-48-22Z__test-audit-agent.md b/memory-updates/2026-02-21T19-48-22Z__test-audit-agent.md deleted file mode 100644 index c1ab2ff..0000000 --- a/memory-updates/2026-02-21T19-48-22Z__test-audit-agent.md +++ /dev/null @@ -1,13 +0,0 @@ -# Memory Update - test-audit-agent - 2026-02-21 - -## Key findings -- `scripts/test-audit/run-flaky-check.mjs` can produce false-green empty output when relying on piped child stdout in this environment. -- Writing node:test TAP output to explicit reporter destination files is stable across this sandbox and keeps flakiness evidence auditable. - -## Patterns / reusable knowledge -- For audit tooling that consumes child test output, prefer file-based reporter destinations over stdio capture. -- Add deterministic pass/fail fixtures to test audit scripts so regressions in signal extraction fail immediately. - -## Warnings / gotchas -- `test/scheduler-preflight-lock.e2e.test.mjs` remains reproducibly red on platform mismatch (`unknown` vs `codex`) and should be treated as active until spec correction. -- Running node:test from inside another node:test process may require clearing `NODE_TEST_CONTEXT` in child env for stable behavior. diff --git a/memory-updates/2026-02-21T20-08-13Z__scheduler-update-agent.md b/memory-updates/2026-02-21T20-08-13Z__scheduler-update-agent.md deleted file mode 100644 index d2cc9bc..0000000 --- a/memory-updates/2026-02-21T20-08-13Z__scheduler-update-agent.md +++ /dev/null @@ -1,13 +0,0 @@ -# Memory Update - scheduler-update-agent - 2026-02-21 - -## Key findings -- Scheduler reliability improves when handoff failures are classified and retried only for retryable network signatures. -- `lock:check --json --quiet` still needs defensive parsing; consume structured JSON events and choose the payload with exclusion keys. - -## Patterns / reusable knowledge -- For spawned-agent handoff, use bounded retries with backoff plus optional fallback platform as a last resort. -- For runner availability, run a preflight command before lock acquisition to avoid claiming work that cannot execute. - -## Warnings / gotchas -- `cmdCheck` should suppress query health/error loggers in quiet JSON mode to keep automation parsing deterministic. -- Memory evidence is easier to validate when latest cadence artifacts include both marker and JSON (`retrieve/store.ok` + `retrieve/store.json`). diff --git a/memory-updates/2026-02-21T20-22-32Z__proposal-triage-agent.md b/memory-updates/2026-02-21T20-22-32Z__proposal-triage-agent.md deleted file mode 100644 index d6ed359..0000000 --- a/memory-updates/2026-02-21T20-22-32Z__proposal-triage-agent.md +++ /dev/null @@ -1,13 +0,0 @@ -# Memory Update — proposal-triage-agent — 2026-02-21 - -## Key findings -- The highest-value unblockers remain local and deterministic: missing `npm run format`, missing `src/lib/eventSchemas.js`, and scheduler preflight platform assertion drift. -- Coverage-gap ideas should be split by urgency; low-priority agent additions dilute execution if treated as near-term work. - -## Patterns / reusable knowledge -- Keep backlog focused on `ready-to-plan` items that remove recurring scheduler/test friction before adding net-new agent surface area. -- Retire upstream-only defects from implementation backlog, but retain them in known-issues/incidents for operator visibility. - -## Warnings / gotchas -- `../scheduler-flow.md` links in weekly prompt files resolve to `src/prompts/scheduler-flow.md`; direct parent-relative lookups from repo root can appear missing during manual checks. -- Artifact-verifier failures often stem from metadata/frontmatter omissions rather than code defects; triage should classify these separately. diff --git a/reports/test-audit/flakiness-matrix.json b/reports/test-audit/flakiness-matrix.json index 828887a..5368ac2 100644 --- a/reports/test-audit/flakiness-matrix.json +++ b/reports/test-audit/flakiness-matrix.json @@ -1,14 +1,618 @@ { - "test/lock-ops-publish-retry.test.mjs": { - "pass": 5, - "fail": 0 - }, - "test/scheduler-lock-failure-schema.contract.test.mjs": { - "pass": 5, - "fail": 0 - }, - "test/scheduler-preflight-lock.e2e.test.mjs": { + "Build artifacts verification": { "pass": 0, "fail": 5 + }, + "parseArgs should parse basic command": { + "pass": 5, + "fail": 0 + }, + "parseArgs should parse agent and cadence": { + "pass": 5, + "fail": 0 + }, + "parseArgs should parse equals sign syntax": { + "pass": 5, + "fail": 0 + }, + "parseArgs should parse dry-run flag": { + "pass": 5, + "fail": 0 + }, + "parseArgs should parse port with default": { + "pass": 5, + "fail": 0 + }, + "parseArgs should parse custom port": { + "pass": 5, + "fail": 0 + }, + "parseArgs should parse ignore-logs flag": { + "pass": 5, + "fail": 0 + }, + "parseArgs should parse memory flags": { + "pass": 5, + "fail": 0 + }, + "parseArgs should parse memory flags with equals": { + "pass": 5, + "fail": 0 + }, + "cmdList": { + "pass": 5, + "fail": 0 + }, + "Dashboard Authentication": { + "pass": 5, + "fail": 0 + }, + "Dashboard Configuration Exposure Security": { + "pass": 5, + "fail": 0 + }, + "Dashboard Configuration Security": { + "pass": 5, + "fail": 0 + }, + "Dashboard Path Traversal Security Fix": { + "pass": 5, + "fail": 0 + }, + "Dashboard File Access Security": { + "pass": 5, + "fail": 0 + }, + "cmdInit should validate install directory name": { + "pass": 5, + "fail": 0 + }, + "src/lib.mjs": { + "pass": 5, + "fail": 0 + }, + "ci-resilience lock acquisition under unstable relays": { + "pass": 5, + "fail": 0 + }, + "publishLock retry behavior": { + "pass": 5, + "fail": 0 + }, + "lock-ops": { + "pass": 5, + "fail": 0 + }, + "lock-utils": { + "pass": 5, + "fail": 0 + }, + "listMemories, inspectMemory, pinMemory, and unpinMemory support admin hooks": { + "pass": 5, + "fail": 0 + }, + "triggerPruneDryRun returns candidate metadata without deleting records": { + "pass": 5, + "fail": 0 + }, + "memoryStats reports counts/rates and retrieval telemetry remains redaction-safe": { + "pass": 5, + "fail": 0 + }, + "runPruneCycle respects prune feature-flag modes": { + "pass": 5, + "fail": 0 + }, + "markMemoryMerged delegates to repository and clears cache": { + "pass": 5, + "fail": 0 + }, + "stores runtime events in signer/session namespace and clears scope": { + "pass": 5, + "fail": 0 + }, + "expires runtime events and records expiration metrics": { + "pass": 5, + "fail": 0 + }, + "enforces LRU bounds and tracks eviction metrics": { + "pass": 5, + "fail": 0 + }, + "blocks decrypted/session-sensitive data from durable promotion without sanitizer pass": { + "pass": 5, + "fail": 0 + }, + "createEmbedderAdapter selects in-memory backend and supports vector CRUD": { + "pass": 5, + "fail": 0 + }, + "createEmbedderAdapter reads backend from environment": { + "pass": 5, + "fail": 0 + }, + "memory feature flags parse defaults and canary allow-lists": { + "pass": 5, + "fail": 0 + }, + "memory prune flag supports off, dry-run, and active modes": { + "pass": 5, + "fail": 0 + }, + "estimateTokenCount returns heuristic count": { + "pass": 5, + "fail": 0 + }, + "formatMemoryBlock converts memory record to display block": { + "pass": 5, + "fail": 0 + }, + "formatMemoryBlock handles missing optional fields and default clamping": { + "pass": 5, + "fail": 0 + }, + "formatMemoryBlock respects custom clamping options": { + "pass": 5, + "fail": 0 + }, + "formatMemoryBlock handles edge cases for clamping": { + "pass": 5, + "fail": 0 + }, + "formatMemoriesForPrompt enforces token budget and k limit": { + "pass": 5, + "fail": 0 + }, + "formatMemoriesForPrompt handles aggressive budget fitting": { + "pass": 5, + "fail": 0 + }, + "renderPromptWithMemoryContext injects context when enabled": { + "pass": 5, + "fail": 0 + }, + "renderPromptWithMemoryContext returns base prompt when disabled": { + "pass": 5, + "fail": 0 + }, + "renderPromptWithMemoryContext handles missing query or service": { + "pass": 5, + "fail": 0 + }, + "renderPromptWithMemoryContext handles circular agentContext gracefully": { + "pass": 5, + "fail": 0 + }, + "renderPromptWithMemoryContext handles agentContext as array of strings": { + "pass": 5, + "fail": 0 + }, + "renderPromptWithMemoryContext handles agentContext as plain object": { + "pass": 5, + "fail": 0 + }, + "renderPromptWithMemoryContext handles agentContext as primitives": { + "pass": 5, + "fail": 0 + }, + "renderPromptWithMemoryContext calls updateMemoryUsage for retrieved memories": { + "pass": 5, + "fail": 0 + }, + "renderPromptWithMemoryContext handles empty memories gracefully": { + "pass": 5, + "fail": 0 + }, + "renderPromptWithMemoryContext handles null/undefined memories gracefully": { + "pass": 5, + "fail": 0 + }, + "renderPromptWithMemoryContext respects TORCH_MEMORY_ENABLED=false": { + "pass": 5, + "fail": 0 + }, + "renderPromptWithMemoryContext respects retrieval allowlist": { + "pass": 5, + "fail": 0 + }, + "renderPromptWithMemoryContext passes k and tokenBudget": { + "pass": 5, + "fail": 0 + }, + "getRelevantMemories uses cached results when available": { + "pass": 5, + "fail": 0 + }, + "getRelevantMemories calls ranker and updates cache on miss": { + "pass": 5, + "fail": 0 + }, + "getRelevantMemories passes correct parameters to ranker": { + "pass": 5, + "fail": 0 + }, + "getRelevantMemories triggers updateMemoryUsage on repository": { + "pass": 5, + "fail": 0 + }, + "ingestEvents": { + "pass": 5, + "fail": 0 + }, + "ingestMemoryWindow gathers sources, redacts pii, chunks, embeds, links, and emits telemetry": { + "pass": 5, + "fail": 0 + }, + "ingestMemoryWindow dedupes overlapping windows by hashed content + agent + timestamp bucket": { + "pass": 5, + "fail": 0 + }, + "pinMemory pins the memory and clears the cache": { + "pass": 5, + "fail": 0 + }, + "pinMemory returns null for non-existent ID but still clears cache": { + "pass": 5, + "fail": 0 + }, + "unpinMemory unpins the memory and clears the cache": { + "pass": 5, + "fail": 0 + }, + "unpinMemory returns null for non-existent ID but still clears cache": { + "pass": 5, + "fail": 0 + }, + "createLifecyclePlan respects delete safety constraints and logs reasons": { + "pass": 5, + "fail": 0 + }, + "createLifecyclePlan condenses near-duplicates and archives merged source records": { + "pass": 5, + "fail": 0 + }, + "applyLifecycleActions executes keep/archive/delete and merge markers": { + "pass": 5, + "fail": 0 + }, + "filterAndRankMemories applies metadata filters and composite score": { + "pass": 5, + "fail": 0 + }, + "formatMemoriesForPrompt returns prompt blocks and enforces token budget trimming": { + "pass": 5, + "fail": 0 + }, + "isMemoryRetrievalEnabled supports global toggle and agent canary list": { + "pass": 5, + "fail": 0 + }, + "renderPromptWithMemoryContext injects bounded memory block before base prompt": { + "pass": 5, + "fail": 0 + }, + "runPruneCycle respects off mode": { + "pass": 5, + "fail": 0 + }, + "runPruneCycle respects dry-run mode": { + "pass": 5, + "fail": 0 + }, + "runPruneCycle removes stale unpinned memories in active mode": { + "pass": 5, + "fail": 0 + }, + "runPruneCycle starts scheduler if requested": { + "pass": 5, + "fail": 0 + }, + "createDbAdvisoryLockProvider acquires and releases postgres advisory locks": { + "pass": 5, + "fail": 0 + }, + "startMemoryMaintenanceScheduler runs all jobs and emits metrics including retries": { + "pass": 5, + "fail": 0 + }, + "startMemoryMaintenanceScheduler skips jobs when feature flags disable memory": { + "pass": 5, + "fail": 0 + }, + "normalizeMemoryItem applies durable schema defaults and coercions": { + "pass": 5, + "fail": 0 + }, + "validateMemoryItem reports field-level errors": { + "pass": 5, + "fail": 0 + }, + "ingestEvents rejects invalid writes and logs structured validation details": { + "pass": 5, + "fail": 0 + }, + "memoryStats with empty repository returns zero counts and rates": { + "pass": 5, + "fail": 0 + }, + "memoryStats with populated repository returns correct counts and totals": { + "pass": 5, + "fail": 0 + }, + "memoryStats calculates ingest throughput based on window": { + "pass": 5, + "fail": 0 + }, + "memoryStats reflects deleted count from prune cycle": { + "pass": 5, + "fail": 0 + }, + "memoryStats handles windowMs parameter correctly": { + "pass": 5, + "fail": 0 + }, + "loadMemoryPromptTemplates loads all memory prompt templates from disk": { + "pass": 5, + "fail": 0 + }, + "summarizeEvents retries with repair prompt when first response is malformed JSON": { + "pass": 5, + "fail": 0 + }, + "summarizeEvents falls back to deterministic minimal summary with conservative importance when parsing fails twice": { + "pass": 5, + "fail": 0 + }, + "telemetry should not log to stdout or stderr by default": { + "pass": 5, + "fail": 0 + }, + "telemetry should log to stderr when NODE_DEBUG=torch-memory is set": { + "pass": 5, + "fail": 0 + }, + "schema validation covers required fields, coercion, and rejection paths": { + "pass": 5, + "fail": 0 + }, + "summarizer parser accepts valid json and recovers after malformed json response": { + "pass": 5, + "fail": 0 + }, + "ingest integration persists memory records and links embeddings from event batches": { + "pass": 5, + "fail": 0 + }, + "retrieval ranking blends semantic, importance, and recency signals": { + "pass": 5, + "fail": 0 + }, + "pruner policy protects pins, merges duplicates, and picks archive/delete outcomes": { + "pass": 5, + "fail": 0 + }, + "scheduler smoke test handles mocked clock and lock contention": { + "pass": 5, + "fail": 0 + }, + "CLI Smoke Test": { + "pass": 5, + "fail": 0 + }, + "cmdInit creates directory structure and files": { + "pass": 5, + "fail": 0 + }, + "cmdInit fails if directory exists without force": { + "pass": 5, + "fail": 0 + }, + "cmdUpdate preserves modified prompt": { + "pass": 5, + "fail": 0 + }, + "cmdUpdate overwrites prompt with force": { + "pass": 5, + "fail": 0 + }, + "cmdUpdate creates backup": { + "pass": 5, + "fail": 0 + }, + "torch-lock check respects local roster": { + "pass": 5, + "fail": 0 + }, + "cmdInit creates torch-config.json with random namespace": { + "pass": 5, + "fail": 0 + }, + "relay fanout quorum integration": { + "pass": 5, + "fail": 0 + }, + "RelayHealthManager": { + "pass": 5, + "fail": 0 + }, + "evaluateAlertThresholds": { + "pass": 5, + "fail": 0 + }, + "summarizeHistory - basic statistics calculation": { + "pass": 5, + "fail": 0 + }, + "summarizeHistory - handles empty history": { + "pass": 5, + "fail": 0 + }, + "summarizeHistory - respects time window for stats": { + "pass": 5, + "fail": 0 + }, + "summarizeHistory - allDownDurationMinutes considers outside window entries": { + "pass": 5, + "fail": 0 + }, + "summarizeHistory - allDownDurationMinutes is null if never healthy": { + "pass": 5, + "fail": 0 + }, + "summarizeHistory - allDownDurationMinutes is 0 if currently healthy": { + "pass": 5, + "fail": 0 + }, + "summarizeHistory - handles malformed entries gracefully": { + "pass": 5, + "fail": 0 + }, + "summarizeHistory - handles valid timestamp but missing summary": { + "pass": 5, + "fail": 0 + }, + "summarizeHistory - healthy entry with invalid timestamp results in NaN duration": { + "pass": 5, + "fail": 0 + }, + "Roster (Unit Tests with Dependency Injection)": { + "pass": 5, + "fail": 0 + }, + "fails required memory policy when retrieval/storage evidence is missing": { + "pass": 5, + "fail": 0 + }, + "accepts required memory policy when markers or artifacts are produced": { + "pass": 5, + "fail": 0 + }, + "records backend failure metadata when lock command exits with code 2": { + "pass": 5, + "fail": 0 + }, + "defers backend failures in non-strict mode and reuses idempotency key on successful retry": { + "pass": 5, + "fail": 0 + }, + "fails after exceeding non-strict deferral budget": { + "pass": 5, + "fail": 0 + }, + "strict lock mode fails immediately without deferral": { + "pass": 5, + "fail": 0 + }, + "skips lock health preflight by default when not enabled": { + "pass": 5, + "fail": 0 + }, + "fails scheduler with preflight metadata when lock health preflight is enabled": { + "pass": 5, + "fail": 0 + }, + "categorizes unreadable prompt files as prompt_parse_error": { + "pass": 5, + "fail": 0 + }, + "categorizes invalid prompt schema as prompt_schema_error": { + "pass": 5, + "fail": 0 + }, + "categorizes handoff runtime failures as execution_error": { + "pass": 5, + "fail": 0 + }, + "retries lock acquisition for backend error and succeeds on a later attempt": { + "pass": 5, + "fail": 0 + }, + "stops retrying after configured lock backend retries are exhausted": { + "pass": 5, + "fail": 0 + }, + "does not use backend retry flow for exit code 3 lock conflicts": { + "pass": 5, + "fail": 0 + }, + "runs selected scheduler prompt through configured runner command": { + "pass": 5, + "fail": 0 + }, + "propagates non-zero runner exit code": { + "pass": 5, + "fail": 0 + }, + "scheduler lock backend failure artifact matches required frontmatter schema": { + "pass": 5, + "fail": 0 + }, + "schema contract catches missing required lock-backend field": { + "pass": 5, + "fail": 0 + }, + "schema contract catches misnamed lock-backend key": { + "pass": 5, + "fail": 0 + }, + "lock preflight e2e: successful lock writes completed status snapshot": { + "pass": 5, + "fail": 0 + }, + "lock preflight e2e: exit code 2 quorum failure persists failed backend status and prompt-not-started marker": { + "pass": 5, + "fail": 0 + }, + "lock preflight e2e: non-lock failure exits failed without prompt parse/schema classification": { + "pass": 5, + "fail": 0 + }, + "Scheduler Ratchet Logic (Log Checking)": { + "pass": 5, + "fail": 0 + }, + "Scheduler cycle ordering guarantees": { + "pass": 5, + "fail": 0 + }, + "secureRandom": { + "pass": 5, + "fail": 0 + }, + "summarizes recent lock reliability by platform/cadence/backend/relay": { + "pass": 5, + "fail": 0 + }, + "loadTorchConfig (Unit Tests with Mocked FS)": { + "pass": 5, + "fail": 0 + }, + "torch-config": { + "pass": 5, + "fail": 0 + }, + "Date Utilities": { + "pass": 5, + "fail": 0 + }, + "Platform Utilities": { + "pass": 5, + "fail": 0 + }, + "File Utilities": { + "pass": 5, + "fail": 0 + }, + "passes when artifacts include metadata and failure IDs map to unresolved known issue entries": { + "pass": 5, + "fail": 0 + }, + "fails when required metadata is missing from artifacts": { + "pass": 5, + "fail": 0 + }, + "fails when failure identifiers are not cross-linked to known issues or incidents": { + "pass": 5, + "fail": 0 } } \ No newline at end of file diff --git a/reports/test-audit/flakiness-runs.json b/reports/test-audit/flakiness-runs.json deleted file mode 100644 index 3cde1b2..0000000 --- a/reports/test-audit/flakiness-runs.json +++ /dev/null @@ -1,32 +0,0 @@ -[ - { - "run": 1, - "code": 1, - "tapOutputPath": "reports/test-audit/flaky-run-01.tap", - "observed": 3 - }, - { - "run": 2, - "code": 1, - "tapOutputPath": "reports/test-audit/flaky-run-02.tap", - "observed": 3 - }, - { - "run": 3, - "code": 1, - "tapOutputPath": "reports/test-audit/flaky-run-03.tap", - "observed": 3 - }, - { - "run": 4, - "code": 1, - "tapOutputPath": "reports/test-audit/flaky-run-04.tap", - "observed": 3 - }, - { - "run": 5, - "code": 1, - "tapOutputPath": "reports/test-audit/flaky-run-05.tap", - "observed": 3 - } -] \ No newline at end of file diff --git a/reports/test-audit/flaky-run-01.tap b/reports/test-audit/flaky-run-01.tap deleted file mode 100644 index 06c390d..0000000 --- a/reports/test-audit/flaky-run-01.tap +++ /dev/null @@ -1,34 +0,0 @@ -TAP version 13 -# Subtest: test/lock-ops-publish-retry.test.mjs -ok 1 - test/lock-ops-publish-retry.test.mjs - --- - duration_ms: 102.263713 - type: 'test' - ... -# Subtest: test/scheduler-lock-failure-schema.contract.test.mjs -ok 2 - test/scheduler-lock-failure-schema.contract.test.mjs - --- - duration_ms: 111.249474 - type: 'test' - ... -# Subtest: test/scheduler-preflight-lock.e2e.test.mjs -not ok 3 - test/scheduler-preflight-lock.e2e.test.mjs - --- - duration_ms: 286.217684 - type: 'test' - location: '/home/user/Documents/GitHub/TORCH/test/scheduler-preflight-lock.e2e.test.mjs:1:1' - failureType: 'testCodeFailure' - exitCode: 1 - signal: ~ - error: 'test failed' - code: 'ERR_TEST_FAILURE' - ... -1..3 -# tests 3 -# suites 0 -# pass 2 -# fail 1 -# cancelled 0 -# skipped 0 -# todo 0 -# duration_ms 300.601253 diff --git a/reports/test-audit/flaky-run-02.tap b/reports/test-audit/flaky-run-02.tap deleted file mode 100644 index 38c5c10..0000000 --- a/reports/test-audit/flaky-run-02.tap +++ /dev/null @@ -1,34 +0,0 @@ -TAP version 13 -# Subtest: test/lock-ops-publish-retry.test.mjs -ok 1 - test/lock-ops-publish-retry.test.mjs - --- - duration_ms: 136.571153 - type: 'test' - ... -# Subtest: test/scheduler-lock-failure-schema.contract.test.mjs -ok 2 - test/scheduler-lock-failure-schema.contract.test.mjs - --- - duration_ms: 150.466335 - type: 'test' - ... -# Subtest: test/scheduler-preflight-lock.e2e.test.mjs -not ok 3 - test/scheduler-preflight-lock.e2e.test.mjs - --- - duration_ms: 315.710253 - type: 'test' - location: '/home/user/Documents/GitHub/TORCH/test/scheduler-preflight-lock.e2e.test.mjs:1:1' - failureType: 'testCodeFailure' - exitCode: 1 - signal: ~ - error: 'test failed' - code: 'ERR_TEST_FAILURE' - ... -1..3 -# tests 3 -# suites 0 -# pass 2 -# fail 1 -# cancelled 0 -# skipped 0 -# todo 0 -# duration_ms 333.778214 diff --git a/reports/test-audit/flaky-run-03.tap b/reports/test-audit/flaky-run-03.tap deleted file mode 100644 index 698c285..0000000 --- a/reports/test-audit/flaky-run-03.tap +++ /dev/null @@ -1,34 +0,0 @@ -TAP version 13 -# Subtest: test/lock-ops-publish-retry.test.mjs -ok 1 - test/lock-ops-publish-retry.test.mjs - --- - duration_ms: 134.112659 - type: 'test' - ... -# Subtest: test/scheduler-lock-failure-schema.contract.test.mjs -ok 2 - test/scheduler-lock-failure-schema.contract.test.mjs - --- - duration_ms: 135.921496 - type: 'test' - ... -# Subtest: test/scheduler-preflight-lock.e2e.test.mjs -not ok 3 - test/scheduler-preflight-lock.e2e.test.mjs - --- - duration_ms: 316.604483 - type: 'test' - location: '/home/user/Documents/GitHub/TORCH/test/scheduler-preflight-lock.e2e.test.mjs:1:1' - failureType: 'testCodeFailure' - exitCode: 1 - signal: ~ - error: 'test failed' - code: 'ERR_TEST_FAILURE' - ... -1..3 -# tests 3 -# suites 0 -# pass 2 -# fail 1 -# cancelled 0 -# skipped 0 -# todo 0 -# duration_ms 334.498823 diff --git a/reports/test-audit/flaky-run-04.tap b/reports/test-audit/flaky-run-04.tap deleted file mode 100644 index 20d36d6..0000000 --- a/reports/test-audit/flaky-run-04.tap +++ /dev/null @@ -1,34 +0,0 @@ -TAP version 13 -# Subtest: test/lock-ops-publish-retry.test.mjs -ok 1 - test/lock-ops-publish-retry.test.mjs - --- - duration_ms: 125.402872 - type: 'test' - ... -# Subtest: test/scheduler-lock-failure-schema.contract.test.mjs -ok 2 - test/scheduler-lock-failure-schema.contract.test.mjs - --- - duration_ms: 132.678397 - type: 'test' - ... -# Subtest: test/scheduler-preflight-lock.e2e.test.mjs -not ok 3 - test/scheduler-preflight-lock.e2e.test.mjs - --- - duration_ms: 442.786008 - type: 'test' - location: '/home/user/Documents/GitHub/TORCH/test/scheduler-preflight-lock.e2e.test.mjs:1:1' - failureType: 'testCodeFailure' - exitCode: 1 - signal: ~ - error: 'test failed' - code: 'ERR_TEST_FAILURE' - ... -1..3 -# tests 3 -# suites 0 -# pass 2 -# fail 1 -# cancelled 0 -# skipped 0 -# todo 0 -# duration_ms 460.996364 diff --git a/reports/test-audit/flaky-run-05.tap b/reports/test-audit/flaky-run-05.tap deleted file mode 100644 index 51077d3..0000000 --- a/reports/test-audit/flaky-run-05.tap +++ /dev/null @@ -1,34 +0,0 @@ -TAP version 13 -# Subtest: test/lock-ops-publish-retry.test.mjs -ok 1 - test/lock-ops-publish-retry.test.mjs - --- - duration_ms: 118.053138 - type: 'test' - ... -# Subtest: test/scheduler-lock-failure-schema.contract.test.mjs -ok 2 - test/scheduler-lock-failure-schema.contract.test.mjs - --- - duration_ms: 127.486819 - type: 'test' - ... -# Subtest: test/scheduler-preflight-lock.e2e.test.mjs -not ok 3 - test/scheduler-preflight-lock.e2e.test.mjs - --- - duration_ms: 340.626807 - type: 'test' - location: '/home/user/Documents/GitHub/TORCH/test/scheduler-preflight-lock.e2e.test.mjs:1:1' - failureType: 'testCodeFailure' - exitCode: 1 - signal: ~ - error: 'test failed' - code: 'ERR_TEST_FAILURE' - ... -1..3 -# tests 3 -# suites 0 -# pass 2 -# fail 1 -# cancelled 0 -# skipped 0 -# todo 0 -# duration_ms 357.903984 diff --git a/reports/test-audit/scheduler-preflight-direct.exitcode b/reports/test-audit/scheduler-preflight-direct.exitcode deleted file mode 100644 index d00491f..0000000 --- a/reports/test-audit/scheduler-preflight-direct.exitcode +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/reports/test-audit/scheduler-preflight.exitcode b/reports/test-audit/scheduler-preflight.exitcode deleted file mode 100644 index d00491f..0000000 --- a/reports/test-audit/scheduler-preflight.exitcode +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/reports/test-audit/suspicious-tests.json b/reports/test-audit/suspicious-tests.json index 1cf3e8a..0294568 100644 --- a/reports/test-audit/suspicious-tests.json +++ b/reports/test-audit/suspicious-tests.json @@ -6,13 +6,19 @@ ] }, { - "file": "test/relay-fanout-quorum.integration.test.mjs", + "file": "test/memory-cache.test.mjs", "issues": [ "Found setTimeout()" ] }, { - "file": "test/utils-async.test.mjs", + "file": "test/memory.test.js", + "issues": [ + "Found setTimeout()" + ] + }, + { + "file": "test/relay-fanout-quorum.integration.test.mjs", "issues": [ "Found setTimeout()" ] diff --git a/reports/test-audit/test-audit-report-2026-02-21.md b/reports/test-audit/test-audit-report-2026-02-21.md deleted file mode 100644 index f047c1b..0000000 --- a/reports/test-audit/test-audit-report-2026-02-21.md +++ /dev/null @@ -1,89 +0,0 @@ -# Test Audit Report - 2026-02-21 - -## Scope -- Agent: `test-audit-agent` -- Cadence: `daily` -- Prompt: `src/prompts/daily/test-audit-agent.md` -- Focus: scenario fidelity, determinism, and cheat-vector resistance in audit tooling/tests. - -## Discovery -- Test runner entry points: - - `npm test` -> `npm run validate:scheduler && npm run test:integration:e2e && node --test --test-timeout=30000 test/*.test.mjs test/*.test.js` - - `npm run test:integration:e2e` -> `node --test test/scheduler-preflight-lock.e2e.test.mjs` -- CI entry points: - - `.github/workflows/ci.yml` runs `npm run lint` and `npm test`. -- Audit tools used: - - `scripts/test-audit/run-static-analysis.mjs` - - `scripts/test-audit/run-flaky-check.mjs` - -## Findings -1. **High - flakiness signal could be silently false-green** - - `scripts/test-audit/run-flaky-check.mjs` parsed only piped child stdout and produced `{}` in this environment, even when tests emitted pass/fail TAP lines. - - Risk: audit report can claim "no flakes" with zero observed outcomes. -2. **Medium - unresolved scheduler e2e platform mismatch** - - `test/scheduler-preflight-lock.e2e.test.mjs` still fails on `platform` expectation (`unknown` expected vs `codex` actual). - - Treated as unresolved spec/contract mismatch; test expectation was not weakened. -3. **Low - static-analysis noise** - - `reports/test-audit/suspicious-tests.json` flags `test/fixtures/memory-fixtures.js` for assertions (fixture-only file), plus intentional `setTimeout` usages in timing-related tests. - -## Changes Applied -- Hardened `scripts/test-audit/run-flaky-check.mjs` to: - - force TAP reporter output to per-run files (`flaky-run-*.tap`), - - parse TAP files deterministically, - - emit run diagnostics (`flakiness-runs.json`), - - fail closed when zero outcomes are observed. -- Added integration regression coverage: - - `test/test-audit-run-flaky-check.test.mjs` - - fixtures: `test/fixtures/flaky-check/pass.fixture.test.mjs`, `test/fixtures/flaky-check/fail.fixture.test.mjs` - -## Scenario List (Given/When/Then) -- `SCN-flaky-check-captures-results` - - Given deterministic pass and fail fixture tests, - - When `run-flaky-check.mjs` executes 5 runs, - - Then `flakiness-matrix.json` records 5 pass counts for the pass fixture and 5 fail counts for the fail fixture. -- `SCN-flaky-check-fail-closed-on-no-signal` - - Given no observed TAP outcomes across all runs, - - When `run-flaky-check.mjs` completes, - - Then the command exits non-zero to prevent false-green flakiness reports. - -## Validation -- `node scripts/test-audit/run-static-analysis.mjs --output-dir reports/test-audit` -- `node scripts/test-audit/run-flaky-check.mjs --output-dir reports/test-audit test/scheduler-preflight-lock.e2e.test.mjs test/scheduler-lock-failure-schema.contract.test.mjs test/lock-ops-publish-retry.test.mjs` -- `node --test test/test-audit-run-flaky-check.test.mjs` -- `node test/scheduler-preflight-lock.e2e.test.mjs` (repro unresolved issue) - -## Needs Spec Clarification -- Scheduler e2e platform assertion source of truth is unclear in this environment. -- Candidate scenarios: - - Given scheduler completion log frontmatter, when runtime platform is detected/declared, then platform value should come from one canonical source (`AGENT_PLATFORM` or detector), consistently in code and tests. - -## Test Integrity Note -```yaml -test_integrity_note: - change_type: ["new_tests", "refactor_tests", "flake_fix"] - scenarios: - - id: SCN-flaky-check-captures-results - given: "A deterministic pass fixture and deterministic fail fixture" - when: "run-flaky-check executes five node:test runs" - then: "flakiness matrix records pass/fail counts per fixture across all runs" - - id: SCN-flaky-check-fail-closed-on-no-signal - given: "No TAP outcomes are captured for all runs" - when: "run-flaky-check finishes aggregation" - then: "script exits non-zero instead of emitting a false-green empty matrix" - observable_outcomes: - - "reports/test-audit/flakiness-matrix.json includes concrete pass/fail counters" - - "reports/test-audit/flakiness-runs.json includes per-run observed counts and exit codes" - - "process exit code is non-zero when observed outcome count is zero" - determinism_controls: - - "Fixture tests are deterministic and local" - - "TAP reporter output is written to explicit files instead of environment-sensitive piped stdio" - anti_cheat_rationale: - prevents: - - "hard-coded empty flakiness output" - - "false-green flake audit when no outcomes are parsed" - - "environment-dependent stdout capture masking failures" - - "retry/sleep-based flake masking" - relaxation: - did_relax_any_assertion: false - if_true_explain_spec_basis: "" -``` diff --git a/reports/test-audit/test-audit-run-flaky-check.exitcode b/reports/test-audit/test-audit-run-flaky-check.exitcode deleted file mode 100644 index 573541a..0000000 --- a/reports/test-audit/test-audit-run-flaky-check.exitcode +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/scripts/agent/run-scheduler-cycle.mjs b/scripts/agent/run-scheduler-cycle.mjs index 7dcdf3b..5c7f088 100644 --- a/scripts/agent/run-scheduler-cycle.mjs +++ b/scripts/agent/run-scheduler-cycle.mjs @@ -47,7 +47,6 @@ import { randomUUID } from 'node:crypto'; import { runCommand, parseJsonFromOutput, - parseJsonEventsFromOutput, readJson, normalizeStringList, parseNonNegativeInt, @@ -62,7 +61,6 @@ import { parseTimestampFromFilename, isStrictSchedulerLogFilename, parseAgentFromFilename, - sleep, } from './scheduler-utils.mjs'; import { @@ -84,12 +82,6 @@ const FAILURE_CATEGORY = { EXECUTION: 'execution_error', }; -const HANDOFF_FAILURE = { - NETWORK: 'network_error', - RUNNER_UNAVAILABLE: 'runner_unavailable', - UNKNOWN: 'unknown_error', -}; - /** * Parses CLI arguments into a structured options object. * Supports both positional cadence (`daily`|`weekly`) and named flags. @@ -149,23 +141,6 @@ function categorizeFailureMetadata(failureCategory, extraMetadata = {}) { }; } -function getDefaultRunnerHealthCommand({ platform, handoffCommand }) { - if (!handoffCommand || !handoffCommand.includes('run-selected-prompt.mjs')) { - return null; - } - const normalizedPlatform = String(platform || '').trim().toLowerCase(); - if (normalizedPlatform === 'codex') { - return 'command -v codex >/dev/null 2>&1'; - } - if (normalizedPlatform === 'claude') { - return 'command -v claude >/dev/null 2>&1'; - } - if (normalizedPlatform === 'linux') { - return 'command -v echo >/dev/null 2>&1'; - } - return null; -} - /** * Validates that a prompt file is readable and contains a valid markdown heading * or blockquote as its first non-empty line. @@ -250,55 +225,6 @@ async function verifyMemoryStep({ name, markers, artifacts, outputText, sinceMs }; } -function classifyHandoffFailure(text) { - const normalized = String(text || '').toLowerCase(); - if (!normalized) return HANDOFF_FAILURE.UNKNOWN; - - if ( - normalized.includes('stream disconnected') - || normalized.includes('econnreset') - || normalized.includes('enotfound') - || normalized.includes('eai_again') - || normalized.includes('timed out') - || normalized.includes('timeout') - || normalized.includes('temporarily unavailable') - || normalized.includes('connection reset') - || normalized.includes('502') - || normalized.includes('503') - || normalized.includes('504') - ) { - return HANDOFF_FAILURE.NETWORK; - } - - if ( - normalized.includes('runner command not found') - || normalized.includes('command not found') - || normalized.includes('enoent') - || normalized.includes('unsupported agent_platform') - ) { - return HANDOFF_FAILURE.RUNNER_UNAVAILABLE; - } - - return HANDOFF_FAILURE.UNKNOWN; -} - -function isRetryableHandoffFailure({ failureCategory, combinedOutput, retryOnPatterns }) { - if (failureCategory === HANDOFF_FAILURE.NETWORK) { - return true; - } - const text = String(combinedOutput || ''); - for (const pattern of retryOnPatterns || []) { - try { - if (new RegExp(pattern, 'i').test(text)) { - return true; - } - } catch { - // Invalid regex in config; ignore and continue. - } - } - return false; -} - /** * Finds the most recent valid scheduler task log file in `logDir`. @@ -407,7 +333,6 @@ async function getSchedulerConfig(cadence, { isInteractive }) { const handoffCommand = scheduler.handoffCommandByCadence?.[cadence] || null; const missingHandoffCommandForMode = !isInteractive && !handoffCommand; const memoryPolicyRaw = scheduler.memoryPolicyByCadence?.[cadence] || {}; - const handoffPolicyRaw = scheduler.handoffPolicyByCadence?.[cadence] || {}; const mode = memoryPolicyRaw.mode === 'required' ? 'required' : 'optional'; const lockRetryRaw = scheduler.lockRetry || {}; const maxRetries = parseNonNegativeInt( @@ -440,42 +365,11 @@ async function getSchedulerConfig(cadence, { isInteractive }) { process.env.SCHEDULER_MAX_DEFERRALS, parseNonNegativeInt(scheduler.max_deferrals, 3), ); - const handoffMaxAttempts = Math.max(1, parseNonNegativeInt( - process.env.SCHEDULER_HANDOFF_MAX_ATTEMPTS, - parseNonNegativeInt(handoffPolicyRaw.maxAttempts, 1), - )); - const handoffRetryBackoffMs = parseNonNegativeInt( - process.env.SCHEDULER_HANDOFF_RETRY_BACKOFF_MS, - parseNonNegativeInt(handoffPolicyRaw.retryBackoffMs, 1000), - ); - const runnerHealthCommand = (process.env.SCHEDULER_RUNNER_HEALTH_COMMAND - || scheduler.runnerHealthCommandByCadence?.[cadence] - || null); - const fallbackPlatform = (process.env.SCHEDULER_HANDOFF_FALLBACK_PLATFORM - || handoffPolicyRaw.fallbackPlatform - || null); - const retryOnPatterns = normalizeStringList(handoffPolicyRaw.retryOnPatterns, [ - 'stream disconnected', - 'timeout', - 'temporarily unavailable', - 'connection reset', - ]); return { firstPrompt: scheduler.firstPromptByCadence?.[cadence] || null, handoffCommand, - runnerHealthCommand: typeof runnerHealthCommand === 'string' && runnerHealthCommand.trim() - ? runnerHealthCommand.trim() - : null, missingHandoffCommandForMode, - handoffPolicy: { - maxAttempts: handoffMaxAttempts, - retryBackoffMs: handoffRetryBackoffMs, - retryOnPatterns, - fallbackPlatform: typeof fallbackPlatform === 'string' && fallbackPlatform.trim() - ? fallbackPlatform.trim() - : null, - }, validationCommands: Array.isArray(scheduler.validationCommandsByCadence?.[cadence]) ? scheduler.validationCommandsByCadence[cadence].filter((cmd) => typeof cmd === 'string' && cmd.trim()) : ['npm run lint'], @@ -688,8 +582,6 @@ async function main() { const isInteractive = Boolean(process.stdin.isTTY && process.stdout.isTTY); const schedulerConfig = await getSchedulerConfig(cadence, { isInteractive }); - const runnerHealthPreflightCommand = schedulerConfig.runnerHealthCommand - || getDefaultRunnerHealthCommand({ platform, handoffCommand: schedulerConfig.handoffCommand }); const logDir = path.resolve(process.cwd(), 'task-logs', cadence); const agentsPath = path.resolve(process.cwd(), 'AGENTS.md'); @@ -744,14 +636,7 @@ 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 checkCombinedOutput = `${checkResult.stdout}\n${checkResult.stderr}`; - const checkEvents = parseJsonEventsFromOutput(checkCombinedOutput); - const checkPayload = checkEvents.findLast((event) => ( - Array.isArray(event.excluded) - || Array.isArray(event.locked) - || Array.isArray(event.paused) - || Array.isArray(event.completed) - )) || parseJsonFromOutput(checkCombinedOutput) || {}; + const checkPayload = parseJsonFromOutput(`${checkResult.stdout}\n${checkResult.stderr}`) || {}; const excluded = Array.isArray(checkPayload.excluded) ? checkPayload.excluded : [...new Set([ @@ -826,43 +711,6 @@ async function main() { }); } - if (runnerHealthPreflightCommand) { - const runnerPreflightPromptPath = path.resolve(process.cwd(), 'src/prompts', cadence, `${selectedAgent}.md`); - const runnerPreflight = await runCommand('bash', ['-lc', runnerHealthPreflightCommand], { - env: { - AGENT_PLATFORM: platform, - ...(model ? { AGENT_MODEL: model } : {}), - SCHEDULER_AGENT: selectedAgent, - SCHEDULER_CADENCE: cadence, - SCHEDULER_PROMPT_PATH: runnerPreflightPromptPath, - }, - }); - if (runnerPreflight.code !== 0) { - await writeLog({ - cadence, - agent: selectedAgent, - status: 'failed', - platform, - reason: 'Runner health preflight failed', - detail: `Prompt not executed. Command failed: ${runnerHealthPreflightCommand}`, - metadata: categorizeFailureMetadata(FAILURE_CATEGORY.EXECUTION, { - failure_class: 'runner_unavailable', - runner_health_command: runnerHealthPreflightCommand, - runner_health_stdout_excerpt: excerptText(runnerPreflight.stdout) || '(empty)', - runner_health_stderr_excerpt: excerptText(runnerPreflight.stderr) || '(empty)', - }), - }); - await exitWithSummary(runnerPreflight.code, { - status: 'failed', - agent: selectedAgent, - promptPath: runnerPreflightPromptPath, - reason: 'Runner health preflight failed', - detail: runnerHealthPreflightCommand, - platform, - }); - } - } - const deferralForAgent = schedulerRunState.lock_deferral?.selected_agent === selectedAgent ? schedulerRunState.lock_deferral : null; @@ -1062,95 +910,26 @@ async function main() { } if (schedulerConfig.handoffCommand) { - const handoffAttempts = []; - const maxAttempts = schedulerConfig.handoffPolicy.maxAttempts; - let handoffSucceeded = false; - let fallbackUsed = false; - let attempt = 0; - let finalHandoff = { code: 1, stdout: '', stderr: '' }; - - while (attempt < maxAttempts) { - attempt += 1; - const handoff = await runCommand('bash', ['-lc', schedulerConfig.handoffCommand], { - env: schedulerEnv, - }); - handoffAttempts.push(handoff); - outputChunks.push(handoff.stdout, handoff.stderr); - finalHandoff = handoff; - if (handoff.code === 0) { - handoffSucceeded = true; - break; - } - const combinedOutput = `${handoff.stdout}\n${handoff.stderr}`; - const failureCategory = classifyHandoffFailure(combinedOutput); - const retryable = isRetryableHandoffFailure({ - failureCategory, - combinedOutput, - retryOnPatterns: schedulerConfig.handoffPolicy.retryOnPatterns, - }); - if (!retryable || attempt >= maxAttempts) { - break; - } - if (schedulerConfig.handoffPolicy.retryBackoffMs > 0) { - await sleep(schedulerConfig.handoffPolicy.retryBackoffMs * attempt); - } - } - - if ( - !handoffSucceeded - && schedulerConfig.handoffPolicy.fallbackPlatform - && schedulerConfig.handoffPolicy.fallbackPlatform !== platform - ) { - const fallbackPlatform = schedulerConfig.handoffPolicy.fallbackPlatform; - const fallbackResult = await runCommand('bash', ['-lc', schedulerConfig.handoffCommand], { - env: { - ...schedulerEnv, - AGENT_PLATFORM: fallbackPlatform, - }, - }); - handoffAttempts.push(fallbackResult); - outputChunks.push(fallbackResult.stdout, fallbackResult.stderr); - finalHandoff = fallbackResult; - fallbackUsed = true; - if (fallbackResult.code === 0) { - handoffSucceeded = true; - } - } - - if (!handoffSucceeded) { - const combinedOutput = `${finalHandoff.stdout}\n${finalHandoff.stderr}`; - const failureCategory = classifyHandoffFailure(combinedOutput); - const retryable = isRetryableHandoffFailure({ - failureCategory, - combinedOutput, - retryOnPatterns: schedulerConfig.handoffPolicy.retryOnPatterns, - }); - const detail = `Handoff callback failed after ${handoffAttempts.length} attempt(s)${fallbackUsed ? ` including fallback platform ${schedulerConfig.handoffPolicy.fallbackPlatform}` : ''}.`; + const handoff = await runCommand('bash', ['-lc', schedulerConfig.handoffCommand], { + env: schedulerEnv, + }); + outputChunks.push(handoff.stdout, handoff.stderr); + if (handoff.code !== 0) { await writeLog({ cadence, agent: selectedAgent, status: 'failed', platform, reason: 'Prompt/handoff execution failed', - detail, - metadata: categorizeFailureMetadata(FAILURE_CATEGORY.EXECUTION, { - failure_class: 'prompt_validation_error', - handoff_failure_category: failureCategory, - handoff_retryable: retryable, - handoff_attempts: handoffAttempts.length, - handoff_fallback_used: fallbackUsed, - handoff_fallback_platform: fallbackUsed ? schedulerConfig.handoffPolicy.fallbackPlatform : null, - handoff_last_exit_code: finalHandoff.code, - handoff_stdout_excerpt: excerptText(finalHandoff.stdout) || '(empty)', - handoff_stderr_excerpt: excerptText(finalHandoff.stderr) || '(empty)', - }), + detail: 'Handoff callback failed.', + metadata: categorizeFailureMetadata(FAILURE_CATEGORY.EXECUTION, { failure_class: 'prompt_validation_error' }), }); - await exitWithSummary(finalHandoff.code || 1, { + await exitWithSummary(handoff.code, { status: 'failed', agent: selectedAgent, promptPath, reason: 'Prompt/handoff execution failed', - detail, + detail: 'Handoff callback failed', memoryFile, platform, }); diff --git a/scripts/memory/retrieve.mjs b/scripts/memory/retrieve.mjs index 4cf1a75..4bdda00 100644 --- a/scripts/memory/retrieve.mjs +++ b/scripts/memory/retrieve.mjs @@ -84,7 +84,6 @@ try { writeFileSync(path.join(sessionDir, 'retrieve.json'), JSON.stringify(artifact, null, 2)); writeFileSync(path.join(sessionDir, 'retrieve.ok'), 'MEMORY_RETRIEVED\n'); writeFileSync(path.join(latestDir, 'retrieve.ok'), 'MEMORY_RETRIEVED\n'); - writeFileSync(path.join(latestDir, 'retrieve.json'), JSON.stringify(artifact, null, 2)); // Format retrieved memories as readable markdown sections. // Prefer m.summary (compact excerpt) over m.content (full blob) for prompt injection. const memoriesMarkdown = retrieved.length > 0 diff --git a/scripts/memory/store.mjs b/scripts/memory/store.mjs index e365e46..cf0e170 100644 --- a/scripts/memory/store.mjs +++ b/scripts/memory/store.mjs @@ -108,7 +108,6 @@ try { writeFileSync(path.join(sessionDir, 'store.json'), JSON.stringify(artifact, null, 2)); writeFileSync(path.join(sessionDir, 'store.ok'), 'MEMORY_STORED\n'); writeFileSync(path.join(latestDir, 'store.ok'), 'MEMORY_STORED\n'); - writeFileSync(path.join(latestDir, 'store.json'), JSON.stringify(artifact, null, 2)); // 4. Output success marker to stdout (for scheduler verification) console.log('MEMORY_STORED'); diff --git a/scripts/test-audit/run-flaky-check.mjs b/scripts/test-audit/run-flaky-check.mjs index e693d65..575e518 100644 --- a/scripts/test-audit/run-flaky-check.mjs +++ b/scripts/test-audit/run-flaky-check.mjs @@ -1,10 +1,9 @@ import { spawn } from 'node:child_process'; -import { writeFileSync, mkdirSync, readFileSync, existsSync } from 'node:fs'; +import { writeFileSync, mkdirSync } from 'node:fs'; import { join } from 'node:path'; const RUNS = 5; const results = {}; -const runDiagnostics = []; // Parse arguments to separate our flags from test runner args const args = process.argv.slice(2); @@ -23,65 +22,44 @@ for (let i = 0; i < args.length; i++) { async function runTests(i) { console.log(`Run ${i + 1}/${RUNS}...`); return new Promise((resolve) => { - const tapOutputPath = join(outputDir, `flaky-run-${String(i + 1).padStart(2, '0')}.tap`); - const child = spawn(process.execPath, [ - '--test', - '--test-reporter=tap', - `--test-reporter-destination=${tapOutputPath}`, - ...testArgs - ], { - stdio: ['ignore', 'ignore', 'ignore'] + // Pass strictly the test args to the child process + const child = spawn('node', ['--test', ...testArgs], { + stdio: ['ignore', 'pipe', 'pipe'] }); - child.on('close', (code) => { - let observed = 0; - const tapOutput = existsSync(tapOutputPath) ? readFileSync(tapOutputPath, 'utf8') : ''; - const lines = tapOutput.split('\n'); + let stdout = ''; + + child.stdout.on('data', (d) => stdout += d.toString()); + + child.on('close', (_code) => { + const lines = stdout.split('\n'); for (const line of lines) { if (line.startsWith('not ok ') && !line.includes('# skip') && !line.includes('# todo')) { const name = line.substring(line.indexOf('-') + 1).trim(); if (!results[name]) results[name] = { pass: 0, fail: 0 }; results[name].fail++; - observed++; } else if (line.startsWith('ok ') && !line.includes('# skip') && !line.includes('# todo')) { const name = line.substring(line.indexOf('-') + 1).trim(); if (!results[name]) results[name] = { pass: 0, fail: 0 }; results[name].pass++; - observed++; } } - runDiagnostics.push({ - run: i + 1, - code: code ?? 1, - tapOutputPath, - observed - }); resolve(); }); }); } async function main() { - // Ensure output directory exists before creating per-run TAP files - mkdirSync(outputDir, { recursive: true }); - for (let i = 0; i < RUNS; i++) { await runTests(i); } + // Ensure output directory exists + mkdirSync(outputDir, { recursive: true }); + const outputPath = join(outputDir, 'flakiness-matrix.json'); writeFileSync(outputPath, JSON.stringify(results, null, 2)); console.log(`Flakiness matrix written to ${outputPath}.`); - - const diagnosticsPath = join(outputDir, 'flakiness-runs.json'); - writeFileSync(diagnosticsPath, JSON.stringify(runDiagnostics, null, 2)); - - // Fail closed: an empty matrix means the signal is missing, not "no flakiness". - const totalObserved = runDiagnostics.reduce((sum, run) => sum + run.observed, 0); - if (totalObserved === 0) { - console.error('No TAP test outcomes were observed across runs; flakiness report is not trustworthy.'); - process.exitCode = 1; - } } main(); diff --git a/src/backlog/BACKLOG.md b/src/backlog/BACKLOG.md deleted file mode 100644 index 23b9dc9..0000000 --- a/src/backlog/BACKLOG.md +++ /dev/null @@ -1,143 +0,0 @@ -# Implementation Backlog — 2026-02-21 - -## Triage Summary -- Items evaluated: 18 -- New items added: 7 -- Items retired: 2 -- Items promoted to ready: 1 - -## Priority 1: Ready to Plan - -### BACKLOG-001: Add `npm run format` script to package.json -- **Source:** `KNOWN_ISSUES.md`, `src/todo/TODO_2026-02-18.md` -- **Impact:** Unblocks formatting workflows and prevents repeated `style-agent` no-op/failure risk. -- **Scope:** Add `format` and `format:check` scripts in `package.json`; verify they run in this repo. -- **Status:** ready-to-plan -- **Acceptance:** `npm run format -- --check` and `npm run format:check` execute successfully. - -### BACKLOG-002: Create `src/lib/eventSchemas.js` canonical event builders -- **Source:** weekly `event-schema-agent` failures; missing `src/lib/eventSchemas.js` -- **Impact:** Unblocks schema-related weekly work and removes repeated missing-file dead end. -- **Scope:** Extract/centralize lock-event schema builders into `src/lib/eventSchemas.js` and wire current call sites. -- **Status:** ready-to-plan -- **Acceptance:** `src/lib/eventSchemas.js` exists, is imported by lock/event code paths, and related tests pass. - -### BACKLOG-003: Revise `content-audit-agent` scope to TORCH-relevant surfaces -- **Source:** `docs/agent-handoffs/incidents/2026-02-20-content-audit-no-upload-surface.md` -- **Impact:** Replaces a recurring no-op daily run with actionable audits. -- **Scope:** Update the prompt to target real TORCH docs/contracts and expected outputs. -- **Status:** ready-to-plan -- **Acceptance:** Next `content-audit-agent` run produces findings against existing TORCH files/features. - -### BACKLOG-004: Implement prompt graph metadata extraction (Phase 0) -- **Source:** `docs/proposals/node-based-prompt-editor.md` -- **Impact:** Enables prompt fleet visibility, dependency mapping, and higher-quality governance analysis. -- **Scope:** Add extraction/build/validation scripts and emit graph artifact under `artifacts/prompt-graph/`. -- **Status:** ready-to-plan -- **Acceptance:** `npm run graph:build` (or equivalent script) generates a valid prompt graph including all roster agents. - -### BACKLOG-012: Align scheduler preflight platform assertion with runtime contract -- **Source:** `KNOWN_ISSUES.md` (`KNOWN-ISSUE-scheduler-preflight-platform`), `reports/test-audit/test-audit-report-2026-02-21.md` -- **Impact:** Removes a deterministic false failure in scheduler E2E validation. -- **Scope:** Define a single platform source-of-truth and update scheduler/test expectations accordingly via spec-correction protocol. -- **Status:** ready-to-plan -- **Acceptance:** `node --test test/scheduler-preflight-lock.e2e.test.mjs` passes without weakening scenario assertions. - -## Priority 2: Needs Scoping - -### BACKLOG-005: Implement `e2e-agent` for scenario-first E2E test maintenance -- **Source:** `docs/AGENT_COVERAGE_GAPS.md` -- **Impact:** Adds explicit ownership for scenario-level regressions and anti-cheat integrity. -- **Scope:** New weekly agent plus deterministic validation workflow. -- **Status:** needs-scoping - -### BACKLOG-006: Implement `memory-health-agent` for memory subsystem auditing -- **Source:** `docs/AGENT_COVERAGE_GAPS.md` -- **Impact:** Adds quality controls for retrieval relevance and memory lifecycle behavior. -- **Scope:** New weekly agent with measurable health criteria. -- **Status:** needs-scoping - -### BACKLOG-007: Implement `relay-health-agent` for relay stability operations -- **Source:** `docs/AGENT_COVERAGE_GAPS.md`, relay incidents in `KNOWN_ISSUES.md` -- **Impact:** Improves lock reliability and actionable relay operations beyond current preflight checks. -- **Scope:** Define monitor/rotation policy and integration boundaries with existing `lock:health` flows. -- **Status:** needs-scoping - -### BACKLOG-008: Implement project-type prompt packages system -- **Source:** `docs/proposals/prompt-packages.md` -- **Impact:** Improves onboarding and relevance outside TORCH’s own repo shape. -- **Scope:** `torch init` package selection, metadata schema, and package-aware prompt installation. -- **Status:** needs-scoping - -### BACKLOG-013: Stabilize `test/memory-telemetry.test.mjs` child-process signal capture -- **Source:** `KNOWN_ISSUES.md` (`KNOWN-ISSUE-memory-telemetry-stdout-stderr`) -- **Impact:** Removes recurring false negatives in memory telemetry test coverage. -- **Scope:** Investigate environment-sensitive stdio capture and replace with deterministic boundary assertions. -- **Status:** needs-scoping - -### BACKLOG-014: Enforce artifact metadata requirements at prompt/template level -- **Source:** `docs/agent-handoffs/incidents/2026-02-20-pr-review-agent-artifact-metadata-failure.md`, `task-logs/daily/2026-02-20T04-25-38Z__load-test-agent__failed.md` -- **Impact:** Reduces scheduler failures due to missing or malformed run artifacts. -- **Scope:** Add explicit metadata template/guardrails for all agent prompts and verify against `verify-run-artifacts` expectations. -- **Status:** needs-scoping - -### BACKLOG-015: Consolidate persistent TODO debt into actionable tracked items -- **Source:** `src/todo/` backlog sprawl, `artifacts/todos.txt` -- **Impact:** Prevents repeated rediscovery loops and improves planner/builder throughput. -- **Scope:** Define archival policy for stale TODO artifacts and create a maintained actionable TODO registry. -- **Status:** needs-scoping - -## Priority 3: Deferred - -### BACKLOG-009: Build standalone binary distribution (Node.js SEA or pkg) -- **Source:** `docs/architecture/distribution-plan.md` -- **Impact:** Removes Node.js runtime requirement for some users. -- **Scope:** Build/release pipeline work across platforms. -- **Status:** deferred - -### BACKLOG-010: Build hosted dashboard at `dashboard.torch.sh` -- **Source:** `docs/architecture/distribution-plan.md` -- **Impact:** Provides shareable dashboard access without local runtime. -- **Scope:** Hosting/domain/release operational work. -- **Status:** deferred - -### BACKLOG-011: Implement `migration-agent` for database migration auditing -- **Source:** `docs/AGENT_COVERAGE_GAPS.md` -- **Impact:** Adds migration-focused audit coverage. -- **Scope:** New weekly agent and migration verification checks. -- **Status:** deferred - -### BACKLOG-016: Implement `prompt-contract-agent` -- **Source:** `docs/AGENT_COVERAGE_GAPS.md` -- **Impact:** Dedicated ownership for prompt-contract drift prevention. -- **Scope:** New weekly agent; likely overlaps with existing prompt-maintenance/governance workflows. -- **Status:** deferred - -### BACKLOG-017: Implement `skills-agent` -- **Source:** `docs/AGENT_COVERAGE_GAPS.md` -- **Impact:** Ongoing maintenance for skill definitions and usage quality. -- **Scope:** New low-priority weekly agent. -- **Status:** deferred - -### BACKLOG-018: Implement `landing-page-agent` -- **Source:** `docs/AGENT_COVERAGE_GAPS.md` -- **Impact:** Dedicated ownership of landing-page updates and release messaging. -- **Scope:** New low-priority weekly agent. -- **Status:** deferred - -## Completed (Last 4 Weeks) -- No backlog-tracked items have been transitioned to `completed` yet. - -## Retired - -### RETIRED-001: `content-audit-agent` upload/contribution audit scope -- **Rationale:** TORCH has no upload/contribution product surface; replaced by `BACKLOG-003` scoped to real TORCH surfaces. -- **Retired:** 2026-02-21 - -### RETIRED-002: `plan-agent-architecture` proposal as a net-new pipeline request -- **Rationale:** Core pipeline agents (`proposal-triage-agent`, `plan-agent`, `builder-agent`) already exist in weekly roster and prompt set; remaining work is tracked as discrete backlog items. -- **Retired:** 2026-02-21 - -### RETIRED-003: Goose Desktop wrapper defects as direct repository backlog items -- **Rationale:** ETXTBSY and exit-code swallowing are upstream Goose wrapper defects outside this repo’s control; keep in `KNOWN_ISSUES.md`/incident notes until upstream remediation lands. -- **Retired:** 2026-02-21 diff --git a/src/context/CONTEXT_2026-02-21T19-48-18Z.md b/src/context/CONTEXT_2026-02-21T19-48-18Z.md deleted file mode 100644 index b592053..0000000 --- a/src/context/CONTEXT_2026-02-21T19-48-18Z.md +++ /dev/null @@ -1,17 +0,0 @@ -agent: test-audit-agent -cadence: daily -session: daily-20260221T194818Z-test-audit-agent -run-start: 2026-02-21T19:48:18Z -prompt-file: src/prompts/daily/test-audit-agent.md - -Goal -- Audit test integrity and strengthen scenario-level anti-cheat coverage. - -Scope -- Inspect test/CI entry points and run audit tools. -- Fix audit signal integrity defects. -- Add regression tests for audit tooling behavior. - -Constraints -- No test weakening. -- No scheduler completion/log publication from spawned agent. diff --git a/src/context/CONTEXT_2026-02-21T20-22-32Z.md b/src/context/CONTEXT_2026-02-21T20-22-32Z.md deleted file mode 100644 index 13df87a..0000000 --- a/src/context/CONTEXT_2026-02-21T20-22-32Z.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -agent: proposal-triage-agent -cadence: weekly -session: weekly-20260221T202232Z-proposal-triage-agent -run-start: 2026-02-21T20:22:32Z -prompt-file: src/prompts/weekly/proposal-triage-agent.md ---- - -Goal -- Re-triage pending proposals, unresolved incidents/issues, and operational dead ends into a single prioritized implementation backlog. - -Scope -- Inputs reviewed: `docs/proposals/*.md`, `docs/AGENT_COVERAGE_GAPS.md`, `KNOWN_ISSUES.md`, `task-logs/daily/`, `task-logs/weekly/`, `artifacts/`, `src/todo/`, `features/`, `docs/agent-handoffs/incidents/`, previous `src/backlog/BACKLOG.md`. - -Constraints -- No implementation planning/build execution in this run. -- Preserve existing backlog IDs and classify by triage status only. -- Keep scheduler-owned completion/logging out of scope for this spawned agent run. - -Issue handling -- No new reproducible issue was discovered during this triage pass. -- Existing unresolved issues remain tracked in `KNOWN_ISSUES.md` and corresponding incident notes; no updates were required in this run. diff --git a/src/decisions/DECISIONS_2026-02-21T19-48-18Z.md b/src/decisions/DECISIONS_2026-02-21T19-48-18Z.md deleted file mode 100644 index 2d5e2f6..0000000 --- a/src/decisions/DECISIONS_2026-02-21T19-48-18Z.md +++ /dev/null @@ -1,20 +0,0 @@ -agent: test-audit-agent -cadence: daily -session: daily-20260221T194818Z-test-audit-agent -run-start: 2026-02-21T19:48:18Z -prompt-file: src/prompts/daily/test-audit-agent.md - -Decision -- Refactor `scripts/test-audit/run-flaky-check.mjs` to parse TAP reporter files per run and fail closed when zero outcomes are observed. - -Rationale -- Piped child-process output is environment-sensitive and produced empty matrices in this run. -- A truthful flakiness audit must not report success when no evidence was captured. - -Alternatives considered -- Keep stdout parsing and parse stderr too: still vulnerable to no-output child-process environments. -- Loosen checks and allow empty matrices: rejected as anti-cheat regression. - -Consequence -- Flaky-check now exposes missing signal as a failing audit outcome. -- Added dedicated regression test with deterministic pass/fail fixtures. diff --git a/src/decisions/DECISIONS_2026-02-21T20-22-32Z.md b/src/decisions/DECISIONS_2026-02-21T20-22-32Z.md deleted file mode 100644 index be3ae00..0000000 --- a/src/decisions/DECISIONS_2026-02-21T20-22-32Z.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -agent: proposal-triage-agent -cadence: weekly -session: weekly-20260221T202232Z-proposal-triage-agent -run-start: 2026-02-21T20:22:32Z -prompt-file: src/prompts/weekly/proposal-triage-agent.md ---- - -Decision -- Reclassify the implementation backlog to prioritize direct unblockers first (format script, missing event schema module, content-audit scope correction, prompt graph extraction, scheduler platform assertion alignment), while deferring lower-impact agent additions and upstream-only external defects. - -Rationale -- Current highest-friction failures are deterministic and local to this repository (`npm run format` absent, missing `src/lib/eventSchemas.js`, scheduler preflight platform mismatch). -- Coverage-gap proposals with lower immediate operational impact (`skills-agent`, `landing-page-agent`) should remain deferred. -- Goose wrapper ETXTBSY/exit-code defects are external to this repository and should be retired from implementation backlog while remaining tracked as operational known issues. - -Scoring notes (weighted: Unblock*3 + Value*2 + Scope*1 - Risk*1) -- BACKLOG-001 `npm run format`: score 14 (high unblock, low risk) -> `ready-to-plan` -- BACKLOG-002 `src/lib/eventSchemas.js`: score 13 (high unblock, bounded scope) -> `ready-to-plan` -- BACKLOG-012 scheduler platform assertion alignment: score 12 (high validation unblock) -> `ready-to-plan` -- BACKLOG-013 memory telemetry capture stabilization: score 8 (valuable but implementation uncertain) -> `needs-scoping` -- BACKLOG-016/017/018 new low-priority agent additions: score <=5 -> `deferred` - -Alternatives considered -- Keep prior backlog unchanged: rejected because it omitted active known-issue backlog items and several coverage-gap entries. -- Promote all coverage-gap agents to `needs-scoping`: rejected to avoid priority dilution and preserve execution focus for plan/builder. - -Consequences -- Plan-agent now has a tighter set of P1 items aligned to active failures. -- Deferred queue remains visible without blocking higher-value remediation. diff --git a/src/lib.mjs b/src/lib.mjs index ddb87e1..ab7b9c3 100644 --- a/src/lib.mjs +++ b/src/lib.mjs @@ -102,13 +102,7 @@ export async function cmdCheck(cadence, deps = {}) { } } - const locks = await queryLocks( - relays, - cadence, - dateStr, - namespace, - quiet ? { errorLogger: () => {}, healthLogger: () => {} } : {}, - ); + const locks = await queryLocks(relays, cadence, dateStr, namespace); const lockedAgents = [...new Set(locks.map((l) => l.agent).filter(Boolean))]; const roster = await getRoster(cadence); const rosterSet = new Set(roster); diff --git a/src/lock-publisher.mjs b/src/lock-publisher.mjs index 0027877..b330232 100644 --- a/src/lock-publisher.mjs +++ b/src/lock-publisher.mjs @@ -1,4 +1,4 @@ -import { randomUUID, randomInt } from 'node:crypto'; +import { randomUUID } from 'node:crypto'; import { SimplePool } from 'nostr-tools/pool'; import { getPublishTimeoutMs, diff --git a/src/lock-utils.mjs b/src/lock-utils.mjs index 8e68dd2..974cc06 100644 --- a/src/lock-utils.mjs +++ b/src/lock-utils.mjs @@ -51,19 +51,14 @@ export async function getCompletedAgents(cadence, logDir, deps) { return completed; } -export function withTimeout(promise, timeoutMs, timeoutMessage = 'Operation timed out') { - let timer; +export function withTimeout(promise, timeoutMs, timeoutMessage) { + let timeoutHandle; const timeoutPromise = new Promise((_, reject) => { - timer = setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs); + timeoutHandle = setTimeout(() => reject(new Error(timeoutMessage)), timeoutMs); + }); + return Promise.race([promise, timeoutPromise]).finally(() => { + if (timeoutHandle) clearTimeout(timeoutHandle); }); - return Promise.race([ - promise.finally(() => clearTimeout(timer)), - timeoutPromise, - ]); -} - -export function mergeRelayList(primaryRelays, fallbackRelays) { - return [...new Set([...primaryRelays, ...fallbackRelays])]; } const MAX_RANDOM = 281474976710655; // 2**48 - 1 diff --git a/src/ops.mjs b/src/ops.mjs index d471aac..5c831ad 100644 --- a/src/ops.mjs +++ b/src/ops.mjs @@ -289,14 +289,8 @@ function configureTorch(cwd, paths, installDir, namespace, relays, hashtag) { mode: "required", retrieveSuccessMarkers: ["MEMORY_RETRIEVED"], storeSuccessMarkers: ["MEMORY_STORED"], - retrieveArtifacts: [ - `.scheduler-memory/latest/${cadence}/retrieve.ok`, - `.scheduler-memory/latest/${cadence}/retrieve.json`, - ], - storeArtifacts: [ - `.scheduler-memory/latest/${cadence}/store.ok`, - `.scheduler-memory/latest/${cadence}/store.json`, - ], + retrieveArtifacts: [`.scheduler-memory/latest/${cadence}/retrieve.ok`], + storeArtifacts: [`.scheduler-memory/latest/${cadence}/store.ok`] }; } @@ -304,22 +298,6 @@ function configureTorch(cwd, paths, installDir, namespace, relays, hashtag) { const policy = configData.scheduler.memoryPolicyByCadence[cadence]; policy.retrieveCommand = `node ${scriptPrefix}scripts/memory/retrieve.mjs`; policy.storeCommand = `node ${scriptPrefix}scripts/memory/store.mjs`; - const retrieveArtifacts = Array.isArray(policy.retrieveArtifacts) ? policy.retrieveArtifacts : []; - const storeArtifacts = Array.isArray(policy.storeArtifacts) ? policy.storeArtifacts : []; - if (!retrieveArtifacts.includes(`.scheduler-memory/latest/${cadence}/retrieve.ok`)) { - retrieveArtifacts.push(`.scheduler-memory/latest/${cadence}/retrieve.ok`); - } - if (!retrieveArtifacts.includes(`.scheduler-memory/latest/${cadence}/retrieve.json`)) { - retrieveArtifacts.push(`.scheduler-memory/latest/${cadence}/retrieve.json`); - } - if (!storeArtifacts.includes(`.scheduler-memory/latest/${cadence}/store.ok`)) { - storeArtifacts.push(`.scheduler-memory/latest/${cadence}/store.ok`); - } - if (!storeArtifacts.includes(`.scheduler-memory/latest/${cadence}/store.json`)) { - storeArtifacts.push(`.scheduler-memory/latest/${cadence}/store.json`); - } - policy.retrieveArtifacts = retrieveArtifacts; - policy.storeArtifacts = storeArtifacts; }); fs.writeFileSync(configPath, JSON.stringify(configData, null, 2), 'utf8'); diff --git a/src/prompts/roster.json b/src/prompts/roster.json index ef39f74..9fe4dda 100644 --- a/src/prompts/roster.json +++ b/src/prompts/roster.json @@ -26,7 +26,6 @@ ], "weekly": [ "bug-reproducer-agent", - "builder-agent", "changelog-agent", "dead-code-agent", "feature-proposer-agent", @@ -34,13 +33,11 @@ "fuzz-agent", "perf-deepdive-agent", "perf-optimization-agent", - "plan-agent", "pr-review-agent", "prompt-fixer-agent", "prompt-gap-analysis-agent", "prompt-maintenance-agent", "prompt-safety-agent", - "proposal-triage-agent", "race-condition-agent", "refactor-agent", "repo-fit-agent", diff --git a/src/prompts/weekly-scheduler.md b/src/prompts/weekly-scheduler.md index 6a3944d..983b268 100644 --- a/src/prompts/weekly-scheduler.md +++ b/src/prompts/weekly-scheduler.md @@ -25,26 +25,23 @@ Canonical roster source: `src/prompts/roster.json` (`weekly` key). | # | Agent Name | Prompt File | |---|------------|-------------| | 1 | bug-reproducer-agent | `bug-reproducer-agent.md` | -| 2 | builder-agent | `builder-agent.md` | -| 3 | changelog-agent | `changelog-agent.md` | -| 4 | dead-code-agent | `dead-code-agent.md` | -| 5 | feature-proposer-agent | `feature-proposer-agent.md` | -| 6 | frontend-console-debug-agent | `frontend-console-debug-agent.md` | -| 7 | fuzz-agent | `fuzz-agent.md` | -| 8 | perf-deepdive-agent | `perf-deepdive-agent.md` | -| 9 | perf-optimization-agent | `perf-optimization-agent.md` | -| 10 | plan-agent | `plan-agent.md` | -| 11 | pr-review-agent | `pr-review-agent.md` | -| 12 | prompt-fixer-agent | `prompt-fixer-agent.md` | -| 13 | prompt-gap-analysis-agent | `prompt-gap-analysis-agent.md` | -| 14 | prompt-maintenance-agent | `prompt-maintenance-agent.md` | -| 15 | prompt-safety-agent | `prompt-safety-agent.md` | -| 16 | proposal-triage-agent | `proposal-triage-agent.md` | -| 17 | race-condition-agent | `race-condition-agent.md` | -| 18 | refactor-agent | `refactor-agent.md` | -| 19 | repo-fit-agent | `repo-fit-agent.md` | -| 20 | smoke-agent | `smoke-agent.md` | -| 21 | telemetry-agent | `telemetry-agent.md` | -| 22 | test-coverage-agent | `test-coverage-agent.md` | -| 23 | ui-ux-agent | `ui-ux-agent.md` | -| 24 | weekly-synthesis-agent | `weekly-synthesis-agent.md` | +| 2 | changelog-agent | `changelog-agent.md` | +| 3 | dead-code-agent | `dead-code-agent.md` | +| 4 | feature-proposer-agent | `feature-proposer-agent.md` | +| 5 | frontend-console-debug-agent | `frontend-console-debug-agent.md` | +| 6 | fuzz-agent | `fuzz-agent.md` | +| 7 | perf-deepdive-agent | `perf-deepdive-agent.md` | +| 8 | perf-optimization-agent | `perf-optimization-agent.md` | +| 9 | pr-review-agent | `pr-review-agent.md` | +| 10 | prompt-fixer-agent | `prompt-fixer-agent.md` | +| 11 | prompt-gap-analysis-agent | `prompt-gap-analysis-agent.md` | +| 12 | prompt-maintenance-agent | `prompt-maintenance-agent.md` | +| 13 | prompt-safety-agent | `prompt-safety-agent.md` | +| 14 | race-condition-agent | `race-condition-agent.md` | +| 15 | refactor-agent | `refactor-agent.md` | +| 16 | repo-fit-agent | `repo-fit-agent.md` | +| 17 | smoke-agent | `smoke-agent.md` | +| 18 | telemetry-agent | `telemetry-agent.md` | +| 19 | test-coverage-agent | `test-coverage-agent.md` | +| 20 | ui-ux-agent | `ui-ux-agent.md` | +| 21 | weekly-synthesis-agent | `weekly-synthesis-agent.md` | diff --git a/src/prompts/weekly/builder-agent.md b/src/prompts/weekly/builder-agent.md deleted file mode 100644 index ceeb614..0000000 --- a/src/prompts/weekly/builder-agent.md +++ /dev/null @@ -1,119 +0,0 @@ -If no work is required, exit without making changes. - -> **Shared contract (required):** Follow [`Scheduler Flow → Shared Agent Run Contract`](../scheduler-flow.md#shared-agent-run-contract-required-for-all-spawned-agents) and [`Scheduler Flow → Canonical artifact paths`](../scheduler-flow.md#canonical-artifact-paths) before and during this run. - -## Required startup + artifacts + memory + issue capture - -- Baseline reads (required, before implementation): `AGENTS.md`, `CLAUDE.md`, `KNOWN_ISSUES.md`, and `docs/agent-handoffs/README.md`. -- Run artifacts (required): update or explicitly justify omission for `src/context/`, `src/todo/`, `src/decisions/`, and `src/test_logs/`. -- Unresolved issue handling (required): if unresolved/reproducible findings remain, update `KNOWN_ISSUES.md` and add or update an incidents note in `docs/agent-handoffs/incidents/`. -- Memory contract (required): execute configured memory retrieval before implementation and configured memory storage after implementation, preserving scheduler evidence markers/artifacts. -- Completion ownership (required): **do not** run `lock:complete` and **do not** create final `task-logs//____completed.md` or `__failed.md`; spawned agents hand results back to the scheduler, and the scheduler owns completion publishing/logging. - -You are: **builder-agent**, a weekly agent that implements the oldest approved plan from the plans directory. - -Mission: Execute an implementation plan by making the code changes described in it, running the specified tests, and verifying all acceptance criteria are met. - ---- - -## Scope - -In scope: -- Reading `src/plans/PLAN-*.md` to find the oldest plan with status `planned` -- Implementing the exact changes described in the plan -- Running all test commands specified in the plan -- Verifying all acceptance criteria -- Updating plan status (`planned` → `completed` or `blocked`) -- Updating backlog item status after completion - -Out of scope: -- Making changes not described in the plan -- Expanding scope beyond what the plan specifies -- Skipping steps or tests listed in the plan -- Creating new plans (that's `plan-agent`'s job) -- Triaging or prioritizing items (that's `proposal-triage-agent`'s job) -- Modifying agent prompts outside of what the plan specifies (use `governance-agent` for prompt changes) - ---- - -## Builder rules - -1. **Follow the plan exactly** — Do not improvise. If the plan says "add line X to file Y", do that. Do not add bonus refactors, extra comments, or "while I'm here" improvements. -2. **Don't expand scope** — Only make changes listed in the plan's implementation steps. If you discover additional work is needed, document it as a new backlog item instead of doing it. -3. **Fail loudly** — If a step cannot be completed (file doesn't exist, test fails, dependency missing), stop and document why. Do not skip steps. -4. **Test everything** — Run every test command in the plan. Run `npm test` and `npm run lint` as final validation even if not explicitly listed. -5. **One plan per cycle** — Complete one plan fully before considering another. If the plan cannot be completed, mark it `blocked` and stop. - ---- - -## Weekly workflow - -1. Read `src/plans/` directory and find the oldest plan file with `Status: planned` -2. If no `planned` plans exist, exit without changes -3. Read the full plan file -4. Read all files referenced in the plan's "Files Modified" and "Files Created" sections -5. Read `KNOWN_ISSUES.md` for any blockers that might affect implementation -6. **Claim the plan**: Update the plan file frontmatter to `Status: in-progress` and add `started: ` -7. **Execute steps sequentially**: Follow each implementation step in order -8. **Validate after each step**: Run the step's test command if one is specified -9. **Run acceptance criteria**: Execute every acceptance criterion command -10. **Final validation**: Run `npm test` and `npm run lint` -11. **Update plan status**: - - If all acceptance criteria pass: set `Status: completed`, add `completed: ` - - If any criterion fails: set `Status: blocked`, add `blocked_reason: ` -12. **Update backlog**: If completed, update the corresponding item in `src/backlog/BACKLOG.md` to `completed` - ---- - -## Handling failures - -If any implementation step or acceptance criterion fails: - -1. **Stop implementing** — Do not continue to subsequent steps -2. **Revert partial changes** if they would leave the codebase in a broken state (tests failing, lint errors) -3. **Update plan status** to `blocked` with: - ``` - Status: blocked - blocked_reason: - blocked_at_step: - blocked_timestamp: - ``` -4. **Document the failure**: - - If it's a new issue: add to `KNOWN_ISSUES.md` - - Write incident note to `docs/agent-handoffs/incidents/` -5. **Do NOT mark backlog item as completed** -6. **Do NOT attempt workarounds** that deviate from the plan - -The `proposal-triage-agent` will pick up the blocked plan in its next cycle and either re-scope the backlog item or identify a prerequisite fix. - ---- - -## Relationship to feature-proposer-agent - -The existing `feature-proposer-agent` creates single-file features in `features/`. This agent (`builder-agent`) executes multi-step plans that may modify existing files. Both agents coexist: - -| Aspect | feature-proposer-agent | builder-agent | -|--------|----------------------|---------------| -| Input | Own analysis | Explicit plan from plan-agent | -| Scope | Single new file in `features/` | Any files specified in plan | -| Modifications | New files only | New + existing files | -| Validation | Self-verified | Acceptance criteria from plan | -| Autonomy | High (chooses what to build) | Low (follows plan exactly) | - ---- - -## Output expectations - -- Code changes as specified in the implementation plan -- Updated plan file with completion status and timestamps -- Updated `src/backlog/BACKLOG.md` with item status -- Test log in `src/test_logs/TEST_LOG_.md` with all test results -- Decision artifact in `src/decisions/DECISIONS_.md` -- Context artifact in `src/context/CONTEXT_.md` - -FAILURE MODES -- If preconditions are not met, stop. -- If no plans with `Status: planned` exist, do nothing. -- If the plan references files that don't exist, mark plan as `blocked` and stop. -- If tests fail after implementation, revert changes, mark plan as `blocked`, and document the failure. -- If specific resources (files, URLs) are unavailable, log the error and mark plan as `blocked`. diff --git a/src/prompts/weekly/plan-agent.md b/src/prompts/weekly/plan-agent.md deleted file mode 100644 index 5a246ef..0000000 --- a/src/prompts/weekly/plan-agent.md +++ /dev/null @@ -1,131 +0,0 @@ -If no work is required, exit without making changes. - -> **Shared contract (required):** Follow [`Scheduler Flow → Shared Agent Run Contract`](../scheduler-flow.md#shared-agent-run-contract-required-for-all-spawned-agents) and [`Scheduler Flow → Canonical artifact paths`](../scheduler-flow.md#canonical-artifact-paths) before and during this run. - -## Required startup + artifacts + memory + issue capture - -- Baseline reads (required, before implementation): `AGENTS.md`, `CLAUDE.md`, `KNOWN_ISSUES.md`, and `docs/agent-handoffs/README.md`. -- Run artifacts (required): update or explicitly justify omission for `src/context/`, `src/todo/`, `src/decisions/`, and `src/test_logs/`. -- Unresolved issue handling (required): if unresolved/reproducible findings remain, update `KNOWN_ISSUES.md` and add or update an incidents note in `docs/agent-handoffs/incidents/`. -- Memory contract (required): execute configured memory retrieval before implementation and configured memory storage after implementation, preserving scheduler evidence markers/artifacts. -- Completion ownership (required): **do not** run `lock:complete` and **do not** create final `task-logs//____completed.md` or `__failed.md`; spawned agents hand results back to the scheduler, and the scheduler owns completion publishing/logging. - -You are: **plan-agent**, a weekly agent that creates detailed implementation plans for the highest-priority backlog item. - -Mission: Take the top `ready-to-plan` item from the backlog and produce a concrete, step-by-step implementation plan that a builder agent can execute without ambiguity. - ---- - -## Scope - -In scope: -- Reading `src/backlog/BACKLOG.md` to find the top `ready-to-plan` item -- Reading the original proposal or source document for full context -- Reading relevant codebase files to understand integration points -- Producing a single implementation plan in `src/plans/` -- Updating the backlog item status from `ready-to-plan` to `planned` -- If no `ready-to-plan` items exist, scoping a `needs-scoping` item (update its status to `ready-to-plan`) - -Out of scope: -- Implementing code changes (that's `builder-agent`'s job) -- Triaging or prioritizing items (that's `proposal-triage-agent`'s job) -- Planning more than one item per cycle -- Making changes beyond the plan file and backlog status update - ---- - -## Planning rules - -1. **One plan per cycle** — Pick the single highest-priority `ready-to-plan` item. Do not plan multiple items. -2. **Concrete file paths** — Every step must name the exact file(s) to create or modify. -3. **Testable acceptance** — Every acceptance criterion must be verifiable by running a command (e.g., `npm test`, `npm run lint`, a specific script). -4. **No ambiguity** — A builder agent reading only this plan should be able to implement it without guessing intent. -5. **Scope guard** — If the item is too large for a single builder cycle (more than ~10 file changes), break it into sub-plans and update the backlog with sub-items. - ---- - -## Weekly workflow - -1. Read `src/backlog/BACKLOG.md` -2. Select the top `ready-to-plan` item (highest priority, earliest backlog ID) -3. If no `ready-to-plan` items exist: - a. Look for `needs-scoping` items - b. Investigate scope for the highest-priority one - c. If scopable, update its status to `ready-to-plan` and continue - d. If not scopable, document why in decisions artifact and exit -4. Read all source documents referenced by the backlog item -5. Read all relevant codebase files to understand current state -6. Write implementation plan to `src/plans/PLAN-.md` -7. Update the backlog item status: `ready-to-plan` → `planned (see src/plans/PLAN-.md)` -8. Write planning rationale to `src/decisions/DECISIONS_.md` - ---- - -## Plan file format - -Write `src/plans/PLAN-.md` using this structure: - -```markdown -# Implementation Plan: — - -## Backlog Reference -- **ID:** <backlog-id> -- **Source:** <original source document or issue> -- **Priority:** <P1/P2/P3> -- **Status:** planned - -## Objective -<1-2 sentence description of what this plan achieves> - -## Analysis -<Key findings from reading the codebase — what exists today, what's missing, -what the integration points are> - -## Implementation Steps - -### Step 1: <action> -- **File:** <exact file path> -- **Change:** <what to add/modify/remove> -- **Test:** <command to verify this step> - -### Step 2: <action> -... - -## Files Modified -- <file path> (<brief description of change>) - -## Files Created -- <file path> (<brief description>) - -## Acceptance Criteria -1. <Verifiable criterion with command> -2. <Verifiable criterion with command> -... - -## Test Strategy -- <What tests to run and in what order> - -## Risk Assessment -- <Potential issues and how to handle them> - -## Dependencies -- <Other backlog items or external factors this depends on> - -## Complexity -- **Simple** (< 5 file changes) | **Medium** (5-10 changes) | **Complex** (10+ changes, may need sub-plans) -``` - ---- - -## Output expectations - -- A plan file in `src/plans/PLAN-<backlog-id>.md` -- Updated `src/backlog/BACKLOG.md` with item status changed to `planned` -- Decision artifact in `src/decisions/DECISIONS_<timestamp>.md` -- Context artifact in `src/context/CONTEXT_<timestamp>.md` - -FAILURE MODES -- If preconditions are not met, stop. -- If no changes are needed (no `ready-to-plan` or `needs-scoping` items), do nothing. -- If the backlog file doesn't exist, document this in decisions and exit. -- If specific resources (files, URLs) are unavailable, log the error and skip. diff --git a/src/prompts/weekly/proposal-triage-agent.md b/src/prompts/weekly/proposal-triage-agent.md deleted file mode 100644 index 582c04d..0000000 --- a/src/prompts/weekly/proposal-triage-agent.md +++ /dev/null @@ -1,126 +0,0 @@ -If no work is required, exit without making changes. - -> **Shared contract (required):** Follow [`Scheduler Flow → Shared Agent Run Contract`](../scheduler-flow.md#shared-agent-run-contract-required-for-all-spawned-agents) and [`Scheduler Flow → Canonical artifact paths`](../scheduler-flow.md#canonical-artifact-paths) before and during this run. - -## Required startup + artifacts + memory + issue capture - -- Baseline reads (required, before implementation): `AGENTS.md`, `CLAUDE.md`, `KNOWN_ISSUES.md`, and `docs/agent-handoffs/README.md`. -- Run artifacts (required): update or explicitly justify omission for `src/context/`, `src/todo/`, `src/decisions/`, and `src/test_logs/`. -- Unresolved issue handling (required): if unresolved/reproducible findings remain, update `KNOWN_ISSUES.md` and add or update an incidents note in `docs/agent-handoffs/incidents/`. -- Memory contract (required): execute configured memory retrieval before implementation and configured memory storage after implementation, preserving scheduler evidence markers/artifacts. -- Completion ownership (required): **do not** run `lock:complete` and **do not** create final `task-logs/<cadence>/<timestamp>__<agent-name>__completed.md` or `__failed.md`; spawned agents hand results back to the scheduler, and the scheduler owns completion publishing/logging. - -You are: **proposal-triage-agent**, a weekly agent that evaluates pending proposals, identifies dead ends, and produces a prioritized implementation backlog. - -Mission: Synthesize all pending work items — proposals, coverage gaps, dead-end agents, stale artifacts, and unresolved incidents — into a single prioritized backlog that downstream agents (`plan-agent`, `builder-agent`) can consume. - ---- - -## Scope - -In scope: -- Reading and evaluating `docs/proposals/*.md` for implementation status -- Reading `docs/AGENT_COVERAGE_GAPS.md` for unimplemented agents -- Reading `KNOWN_ISSUES.md` for blocking issues that need tooling fixes -- Scanning `task-logs/daily/` and `task-logs/weekly/` for failed agent patterns -- Scanning `artifacts/` for reports that haven't driven action -- Consolidating `src/todo/` scattered files into backlog items -- Evaluating `features/` outputs from `feature-proposer-agent` -- Reading `docs/agent-handoffs/incidents/` for unresolved incidents -- Carrying forward items from previous `src/backlog/BACKLOG.md` -- Retiring dead-end items with documented rationale - -Out of scope: -- Creating implementation plans (that's `plan-agent`'s job) -- Making code changes (that's `builder-agent`'s job) -- Modifying agent prompts (that's `governance-agent`'s job) - ---- - -## Triage criteria - -Score each item on four dimensions: - -| Dimension | Weight | Question | -|-----------|--------|----------| -| **Unblock** | 3x | Does this unblock a currently-broken agent or workflow? | -| **Value** | 2x | Does this deliver user-visible value or reduce failure rate? | -| **Scope** | 1x | Is the implementation scope clear and bounded? | -| **Risk** | -1x | Does this require architectural changes or new dependencies? | - -### Status values - -- `ready-to-plan` — Clear scope, no blockers, high value. Plan-agent should pick this up. -- `needs-scoping` — Valuable but unclear implementation. Needs investigation before planning. -- `deferred` — Has value but lower priority or blocked by dependencies. -- `planned` — Plan-agent has created an implementation plan (set by plan-agent, not triage). -- `in-progress` — Builder-agent is implementing (set by builder-agent, not triage). -- `completed` — Implemented and verified (set by builder-agent, not triage). -- `retired` — Not worth pursuing. Must include rationale. - -### Retirement rules - -Retire an item (don't just defer) when: -- The feature it depends on doesn't exist and isn't planned -- The proposal has been superseded by a different approach -- The cost clearly exceeds the benefit with no path to improvement -- The item has been deferred for 4+ consecutive triage cycles with no progress - ---- - -## Weekly workflow - -1. Read all inputs: `docs/proposals/`, `docs/AGENT_COVERAGE_GAPS.md`, `KNOWN_ISSUES.md`, `task-logs/`, `artifacts/`, `src/todo/`, `features/`, `docs/agent-handoffs/incidents/` -2. Read previous `src/backlog/BACKLOG.md` if it exists -3. Evaluate each pending item against triage criteria -4. Score and rank all items -5. Write updated `src/backlog/BACKLOG.md` with the format below -6. Write triage rationale to `src/decisions/DECISIONS_<timestamp>.md` - ---- - -## Output format - -Write `src/backlog/BACKLOG.md` using this structure: - -```markdown -# Implementation Backlog — <YYYY-MM-DD> - -## Triage Summary -- Items evaluated: <N> -- New items added: <N> -- Items retired: <N> -- Items promoted to ready: <N> - -## Priority 1: Ready to Plan - -### BACKLOG-<NNN>: <title> -- **Source:** <where this item came from> -- **Impact:** <what it unblocks or improves> -- **Scope:** <brief description of implementation size> -- **Status:** ready-to-plan -- **Acceptance:** <how to verify completion> - -## Priority 2: Needs Scoping - -## Priority 3: Deferred - -## Completed (Last 4 Weeks) - -## Retired -``` - -Preserve existing backlog IDs. Assign new sequential IDs for new items (starting after the highest existing ID). - ---- - -## Output expectations - -- Updated `src/backlog/BACKLOG.md` with all items evaluated and prioritized -- Decision artifact in `src/decisions/DECISIONS_<timestamp>.md` explaining triage rationale -- Context artifact in `src/context/CONTEXT_<timestamp>.md` - -FAILURE MODES -- If preconditions are not met, stop. -- If no changes are needed, do nothing. -- If specific resources (files, URLs) are unavailable, log the error and skip. diff --git a/src/services/governance/index.js b/src/services/governance/index.js index 87f0974..dd3290b 100644 --- a/src/services/governance/index.js +++ b/src/services/governance/index.js @@ -220,9 +220,8 @@ export async function applyProposal(id) { // Git Commit (optional) try { - // We use execFileSync for git operations to avoid command injection. - // Explicitly using the array form ensures arguments are passed directly to the spawned process - // without shell interpretation, preventing command injection attacks via 'meta.target' or 'commitMsg'. + // We use execFileSync for git operations to avoid command injection + // Ensure we are in repo root? cwd is repo root. execFileSync('git', ['add', meta.target]); const commitMsg = `feat(prompts): apply proposal ${id} by ${meta.author}`; execFileSync('git', ['commit', '-m', commitMsg]); diff --git a/src/test_logs/TEST_LOG_2026-02-21T19-48-18Z.md b/src/test_logs/TEST_LOG_2026-02-21T19-48-18Z.md deleted file mode 100644 index f0eaab9..0000000 --- a/src/test_logs/TEST_LOG_2026-02-21T19-48-18Z.md +++ /dev/null @@ -1,26 +0,0 @@ -agent: test-audit-agent -cadence: daily -session: daily-20260221T194818Z-test-audit-agent -run-start: 2026-02-21T19:48:18Z -prompt-file: src/prompts/daily/test-audit-agent.md - -Command: node scripts/memory/retrieve.mjs -Result: pass -Notes: emitted MEMORY_RETRIEVED; artifact marker at .scheduler-memory/latest/daily/retrieve.ok - -Command: node scripts/test-audit/run-static-analysis.mjs --output-dir reports/test-audit -Result: pass -Notes: wrote reports/test-audit/suspicious-tests.json - -Command: node scripts/test-audit/run-flaky-check.mjs --output-dir reports/test-audit test/scheduler-preflight-lock.e2e.test.mjs test/scheduler-lock-failure-schema.contract.test.mjs test/lock-ops-publish-retry.test.mjs -Result: pass -Notes: wrote flakiness-matrix.json + flakiness-runs.json + flaky-run-*.tap - -Command: node --test test/test-audit-run-flaky-check.test.mjs -Result: pass -Notes: regression test for deterministic flakiness signal capture - -Command: node test/scheduler-preflight-lock.e2e.test.mjs -Result: fail -Failure-ID: KNOWN-ISSUE-scheduler-preflight-platform -Notes: expected platform unknown vs actual codex; issue tracked in KNOWN_ISSUES.md and incidents note. diff --git a/src/test_logs/TEST_LOG_2026-02-21T20-22-32Z.md b/src/test_logs/TEST_LOG_2026-02-21T20-22-32Z.md deleted file mode 100644 index abd032e..0000000 --- a/src/test_logs/TEST_LOG_2026-02-21T20-22-32Z.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -agent: proposal-triage-agent -cadence: weekly -session: weekly-20260221T202232Z-proposal-triage-agent -run-start: 2026-02-21T20:22:32Z -prompt-file: src/prompts/weekly/proposal-triage-agent.md ---- - -# Test Log — proposal-triage-agent — 2026-02-21T20:22:32Z - -- Command: `SCHEDULER_CADENCE=weekly SCHEDULER_AGENT=proposal-triage-agent SCHEDULER_PROMPT_PATH=src/prompts/weekly/proposal-triage-agent.md SCHEDULER_RUN_ID=manual-proposal-triage-20260221T152500Z node scripts/memory/retrieve.mjs` - - Result: pass (`MEMORY_RETRIEVED`) - - Notes: Retrieval evidence refreshed under `.scheduler-memory/latest/weekly/`. - -- Command: `SCHEDULER_CADENCE=weekly SCHEDULER_AGENT=proposal-triage-agent SCHEDULER_PROMPT_PATH=src/prompts/weekly/proposal-triage-agent.md SCHEDULER_RUN_ID=manual-proposal-triage-20260221T152500Z SCHEDULER_MEMORY_FILE=memory-updates/2026-02-21T20-22-32Z__proposal-triage-agent.md node scripts/memory/store.mjs` - - Result: pass (`MEMORY_STORED`) - - Notes: Store evidence refreshed under `.scheduler-memory/latest/weekly/`. - -- Command: source review across triage inputs (`docs/proposals`, `docs/AGENT_COVERAGE_GAPS.md`, `KNOWN_ISSUES.md`, `task-logs`, `artifacts`, `src/todo`, `features`, `docs/agent-handoffs/incidents`, existing backlog) - - Result: pass - - Notes: Evidence collection for backlog reprioritization. - -- Command: `ls src/lib/eventSchemas.js` - - Result: fail (`MISSING src/lib/eventSchemas.js`) - - Notes: Confirms backlog blocker remains unresolved. - -- Command: `node -e "const p=require('./package.json'); ..."` and script-key check - - Result: fail (`format` / `format:check` scripts absent) - - Notes: Confirms BACKLOG-001 remains actionable. diff --git a/src/todo/TODO_2026-02-21T19-48-18Z.md b/src/todo/TODO_2026-02-21T19-48-18Z.md deleted file mode 100644 index acbb80c..0000000 --- a/src/todo/TODO_2026-02-21T19-48-18Z.md +++ /dev/null @@ -1,17 +0,0 @@ -agent: test-audit-agent -cadence: daily -session: daily-20260221T194818Z-test-audit-agent -run-start: 2026-02-21T19:48:18Z -prompt-file: src/prompts/daily/test-audit-agent.md - -Completed -- Read required baseline files and scheduler shared contract. -- Executed memory retrieval command and verified retrieval marker/artifacts. -- Ran static-analysis and flaky-check audit tools. -- Fixed flaky-check deterministic signal capture. -- Added regression test and deterministic fixtures. -- Reproduced unresolved scheduler platform mismatch and updated issue/incidents tracking. - -Remaining -- Execute memory store workflow. -- Final summary handoff to scheduler. diff --git a/src/todo/TODO_2026-02-21T20-22-32Z.md b/src/todo/TODO_2026-02-21T20-22-32Z.md deleted file mode 100644 index a47a646..0000000 --- a/src/todo/TODO_2026-02-21T20-22-32Z.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -agent: proposal-triage-agent -cadence: weekly -session: weekly-20260221T202232Z-proposal-triage-agent -run-start: 2026-02-21T20:22:32Z -prompt-file: src/prompts/weekly/proposal-triage-agent.md ---- - -# TODO — proposal-triage-agent — 2026-02-21T20:22:32Z - -## Completed -- [x] Read required startup files and scheduler shared contract. -- [x] Executed weekly memory retrieval command and checked retrieval evidence. -- [x] Reviewed proposals, coverage gaps, known issues, incidents, task-log failures, artifacts, TODO debt, and existing backlog. -- [x] Re-scored and reprioritized backlog items. -- [x] Updated `src/backlog/BACKLOG.md` with preserved IDs and new sequential IDs. -- [x] Wrote context/decision/test-log artifacts for this run. -- [x] Wrote memory update content for this run. -- [x] Executed weekly memory store command and verified storage evidence marker. - -## Pending -- [ ] Hand off results to scheduler-owned completion pipeline. diff --git a/task-logs/daily/2026-02-21T19-46-36Z__style-agent__failed.md b/task-logs/daily/2026-02-21T19-46-36Z__style-agent__failed.md deleted file mode 100644 index a74cd46..0000000 --- a/task-logs/daily/2026-02-21T19-46-36Z__style-agent__failed.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -cadence: daily -agent: style-agent -status: failed -reason: 'Prompt/handoff execution failed' -detail: 'Command failed: AGENT_PLATFORM=codex node scripts/agent/run-selected-prompt.mjs (stream disconnected before completion)' -created_at: 2026-02-21T19:46:36Z -timestamp: 2026-02-21T19:46:36Z -platform: 'codex' -failure_category: 'execution_error' -failure_class: 'prompt_validation_error' -prompt_path: 'src/prompts/daily/style-agent.md' ---- -# Scheduler failed -- reason: Prompt/handoff execution failed -- detail: Command failed: AGENT_PLATFORM=codex node scripts/agent/run-selected-prompt.mjs (stream disconnected before completion) -- platform: codex -- failure_category: execution_error -- failure_class: prompt_validation_error -- prompt: src/prompts/daily/style-agent.md diff --git a/task-logs/daily/2026-02-21T19-55-27Z__test-audit-agent__completed.md b/task-logs/daily/2026-02-21T19-55-27Z__test-audit-agent__completed.md deleted file mode 100644 index 7b82ccf..0000000 --- a/task-logs/daily/2026-02-21T19-55-27Z__test-audit-agent__completed.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -cadence: daily -agent: test-audit-agent -status: completed -reason: 'Completed successfully' -detail: 'Prompt executed, memory retrieval/storage evidence validated, lint passed, and completion published.' -created_at: 2026-02-21T19:55:27Z -timestamp: 2026-02-21T19:55:27Z -platform: 'codex' -prompt_path: 'src/prompts/daily/test-audit-agent.md' -memory_file: 'memory-updates/2026-02-21T19-48-22Z__test-audit-agent.md' ---- -# Scheduler completed -- reason: Completed successfully -- detail: Prompt executed, memory retrieval/storage evidence validated, lint passed, and completion published. -- platform: codex -- prompt: src/prompts/daily/test-audit-agent.md -- memory_file: memory-updates/2026-02-21T19-48-22Z__test-audit-agent.md diff --git a/task-logs/weekly/2026-02-21T20-25-17Z__proposal-triage-agent__completed.md b/task-logs/weekly/2026-02-21T20-25-17Z__proposal-triage-agent__completed.md deleted file mode 100644 index 8487be3..0000000 --- a/task-logs/weekly/2026-02-21T20-25-17Z__proposal-triage-agent__completed.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -cadence: weekly -agent: proposal-triage-agent -status: completed -reason: 'Completed successfully' -detail: 'Prompt executed, memory retrieval/storage evidence validated, lint passed, and completion published.' -created_at: 2026-02-21T20:25:17Z -timestamp: 2026-02-21T20:25:17Z -platform: 'codex' -prompt_path: 'src/prompts/weekly/proposal-triage-agent.md' -memory_file: 'memory-updates/2026-02-21T20-22-32Z__proposal-triage-agent.md' ---- -# Scheduler completed -- reason: Completed successfully -- detail: Prompt executed, memory retrieval/storage evidence validated, lint passed, and completion published. -- platform: codex -- prompt: src/prompts/weekly/proposal-triage-agent.md -- memory_file: memory-updates/2026-02-21T20-22-32Z__proposal-triage-agent.md diff --git a/task-logs/weekly/2026-02-21T20-27-39Z__repo-fit-agent__completed.md b/task-logs/weekly/2026-02-21T20-27-39Z__repo-fit-agent__completed.md deleted file mode 100644 index 15f96ad..0000000 --- a/task-logs/weekly/2026-02-21T20-27-39Z__repo-fit-agent__completed.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -cadence: weekly -agent: repo-fit-agent -status: completed -reason: 'Completed successfully' -detail: 'Prompt executed, memory retrieval/storage evidence validated, lint passed, and completion published.' -created_at: 2026-02-21T20:27:39Z -timestamp: 2026-02-21T20:27:39Z -platform: 'linux' -prompt_path: 'src/prompts/weekly/repo-fit-agent.md' -memory_file: 'memory-update.md' ---- -# Scheduler completed -- reason: Completed successfully -- detail: Prompt executed, memory retrieval/storage evidence validated, lint passed, and completion published. -- platform: linux -- prompt: src/prompts/weekly/repo-fit-agent.md -- memory_file: memory-update.md diff --git a/test/fixtures/flaky-check/fail.fixture.test.mjs b/test/fixtures/flaky-check/fail.fixture.test.mjs deleted file mode 100644 index 1ec5b57..0000000 --- a/test/fixtures/flaky-check/fail.fixture.test.mjs +++ /dev/null @@ -1,6 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; - -test('fail fixture stays red', () => { - assert.equal(1, 2); -}); diff --git a/test/fixtures/flaky-check/pass.fixture.test.mjs b/test/fixtures/flaky-check/pass.fixture.test.mjs deleted file mode 100644 index 4c96b53..0000000 --- a/test/fixtures/flaky-check/pass.fixture.test.mjs +++ /dev/null @@ -1,6 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; - -test('pass fixture stays green', () => { - assert.equal(2 + 2, 4); -}); diff --git a/test/governance-security-impl.mjs b/test/governance-security-impl.mjs deleted file mode 100644 index acdc109..0000000 --- a/test/governance-security-impl.mjs +++ /dev/null @@ -1,111 +0,0 @@ -import fs from 'node:fs/promises'; -import path from 'node:path'; -import { execSync } from 'node:child_process'; -import os from 'node:os'; -import { fileURLToPath } from 'node:url'; - -// Calculate paths relative to this file -const __dirname = path.dirname(fileURLToPath(import.meta.url)); -const repoRoot = path.resolve(__dirname, '..'); -const governanceServicePath = path.resolve(repoRoot, 'src/services/governance/index.js'); - -async function runTest() { - // Create temp dir - const tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'torch-gov-test-')); - console.log(`Using temp dir: ${tempDir}`); - - // Setup git repo - execSync('git init', { cwd: tempDir, stdio: 'ignore' }); - execSync('git config user.name "Test User"', { cwd: tempDir, stdio: 'ignore' }); - execSync('git config user.email "test@example.com"', { cwd: tempDir, stdio: 'ignore' }); - - // Create required directory structure - await fs.mkdir(path.join(tempDir, 'src/prompts/daily'), { recursive: true }); - await fs.mkdir(path.join(tempDir, 'src/prompts/weekly'), { recursive: true }); - // Proposals dir is created automatically by ensureDirs() but allowlist check needs prompts dir - - // Create a target file - const targetFile = 'src/prompts/daily/test-agent.md'; - const absoluteTarget = path.join(tempDir, targetFile); - await fs.writeFile(absoluteTarget, 'Original Content'); - - // Commit initial state so we have a HEAD - execSync(`git add ${targetFile}`, { cwd: tempDir }); - execSync('git commit -m "Initial commit"', { cwd: tempDir }); - - // Switch cwd to tempDir - const originalCwd = process.cwd(); - try { - process.chdir(tempDir); - console.log(`Changed cwd to: ${process.cwd()}`); - - // Import governance service dynamically so it picks up the new cwd - const governance = await import(governanceServicePath); - - // Malicious payload - const maliciousPayload = 'attacker"; touch /tmp/pwned_check; echo "'; - // const proposalId = `test-proposal-${Date.now()}`; // unused - - // Manually create proposal metadata and files because createProposal also uses git diff - // We can use createProposal from the service, but we need to pass the malicious agent name there. - // Let's try using createProposal first. - - const proposalContent = `Shared contract (required):\nRequired startup + artifacts + memory + issue capture\n\nNew Content`; - - console.log('Creating proposal...'); - const { id } = await governance.createProposal({ - agent: maliciousPayload, - target: targetFile, - newContent: proposalContent, - reason: 'Testing security' - }); - - console.log(`Proposal created with ID: ${id}`); - - // Verify metadata has the malicious author - const metaPath = path.join(tempDir, 'src/proposals', id, 'meta.json'); - const meta = JSON.parse(await fs.readFile(metaPath, 'utf8')); - if (meta.author !== maliciousPayload) { - throw new Error('Meta author does not match malicious payload'); - } - - // Apply proposal - console.log('Applying proposal...'); - await governance.applyProposal(id); - console.log('Proposal applied.'); - - // Verification 1: Check if /tmp/pwned_check exists - try { - await fs.access('/tmp/pwned_check'); - console.error('VULNERABILITY DETECTED: /tmp/pwned_check exists!'); - process.exit(1); - } catch { - console.log('Security check passed: /tmp/pwned_check does not exist.'); - } - - // Verification 2: Check git log for commit message - const log = execSync('git log -1 --pretty=%B', { cwd: tempDir }).toString(); - console.log(`Commit message: ${log}`); - - if (!log.includes(maliciousPayload)) { - console.error('Verification failed: Commit message does not contain the payload literally.'); - process.exit(1); - } - - // Check if the commit message looks "broken" (e.g. if newlines were injected) - // Here we just want to ensure the whole thing is in the message. - console.log('Verification passed: Commit message contains payload.'); - - } finally { - // Cleanup - process.chdir(originalCwd); - await fs.rm(tempDir, { recursive: true, force: true }); - // Also remove /tmp/pwned_check if it exists (it shouldn't) - try { await fs.unlink('/tmp/pwned_check'); } catch { /* ignore */ } - } -} - -runTest().catch(err => { - console.error('Test failed:', err); - process.exit(1); -}); diff --git a/test/governance-security.test.mjs b/test/governance-security.test.mjs deleted file mode 100644 index cefa3c1..0000000 --- a/test/governance-security.test.mjs +++ /dev/null @@ -1,25 +0,0 @@ -import { test } from 'node:test'; -import { execFileSync } from 'node:child_process'; -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; -import assert from 'node:assert'; - -const __dirname = path.dirname(fileURLToPath(import.meta.url)); -const implPath = path.join(__dirname, 'governance-security-impl.mjs'); - -test('Governance Service Security: Command Injection Prevention', (_t) => { - // We run the implementation in a separate process to ensure process.cwd() isolation - // and to verify that the dynamic import picks up the correct paths. - try { - const output = execFileSync(process.execPath, [implPath], { encoding: 'utf8' }); - // If we reach here, the process exited with code 0 (success) - // We can optionally check the output for specific messages if needed, - // but the implementation script asserts internally. - assert.ok(output.includes('Verification passed: Commit message contains payload.'), 'Output should confirm verification passed'); - } catch (err) { - console.error('Test implementation failed.'); - if (err.stdout) console.error('STDOUT:', err.stdout); - if (err.stderr) console.error('STDERR:', err.stderr); - assert.fail(`Security test failed with exit code ${err.status}: ${err.message}`); - } -}); diff --git a/test/lib.test.mjs b/test/lib.test.mjs index 04e10b8..050308e 100644 --- a/test/lib.test.mjs +++ b/test/lib.test.mjs @@ -96,24 +96,6 @@ describe('src/lib.mjs', () => { // unknown agents are not in roster, so available should be full roster (since no roster agent is locked) assert.deepStrictEqual(result.available, mockRoster.sort()); }); - - it('suppresses relay query loggers when quiet mode is enabled', async () => { - let receivedQueryDeps = null; - const deps = { - ...baseDeps, - json: true, - quiet: true, - queryLocks: async (_relays, _cadence, _dateStr, _namespace, queryDeps) => { - receivedQueryDeps = queryDeps; - return []; - }, - }; - - await cmdCheck('daily', deps); - - assert.equal(typeof receivedQueryDeps.errorLogger, 'function'); - assert.equal(typeof receivedQueryDeps.healthLogger, 'function'); - }); }); describe('cmdLock', () => { diff --git a/test/run-scheduler-cycle-memory-policy.test.mjs b/test/run-scheduler-cycle-memory-policy.test.mjs index 6af066b..b738e61 100644 --- a/test/run-scheduler-cycle-memory-policy.test.mjs +++ b/test/run-scheduler-cycle-memory-policy.test.mjs @@ -59,9 +59,6 @@ async function setupFixture({ roster = ['agent-a'], lockHealthPreflight = undefined, schedulerPolicy = {}, - handoffCommand = 'echo HANDOFF_OK', - validationCommands = ['true'], - lockCheckOutput = `echo '{"excluded":[]}'`, preflightScript = '#!/usr/bin/env node\nconsole.log(JSON.stringify({ ok: true, relays: ["wss://relay.test"] }));\nprocess.exit(0);\n', }) { const root = await fs.mkdtemp(path.join(os.tmpdir(), 'scheduler-memory-policy-')); @@ -106,8 +103,8 @@ async function setupFixture({ JSON.stringify({ scheduler: { firstPromptByCadence: { daily: 'agent-a' }, - handoffCommandByCadence: { daily: handoffCommand }, - validationCommandsByCadence: { daily: validationCommands }, + handoffCommandByCadence: { daily: 'echo HANDOFF_OK' }, + validationCommandsByCadence: { daily: ['true'] }, memoryPolicyByCadence: { daily: memoryPolicy }, ...schedulerPolicy, ...(lockHealthPreflight === undefined ? {} : { lockHealthPreflight }), @@ -125,7 +122,7 @@ if [[ "$1" != "run" ]]; then fi case "$2" in lock:check:daily) -${lockCheckOutput} + echo '{"excluded":[]}' ;; lock:health) shift 2 @@ -614,110 +611,3 @@ test('does not use backend retry flow for exit code 3 lock conflicts', { concurr assert.equal(result.code, 0, `stdout: ${result.stdout}\nstderr: ${result.stderr}`); assert.doesNotMatch(result.stdout, /"event":"scheduler.lock.retry"/); }); - -test('retries handoff command for retryable network failures and succeeds', { concurrency: false }, async () => { - const fixture = await setupFixture({ - memoryPolicy: { mode: 'optional' }, - handoffCommand: `count_file="$PWD/.handoff-count" -count=0 -if [[ -f "$count_file" ]]; then - count="$(cat "$count_file")" -fi -count=$((count + 1)) -echo "$count" > "$count_file" -if [[ "$count" -lt 2 ]]; then - echo "stream disconnected before completion" >&2 - exit 12 -fi -echo HANDOFF_OK`, - schedulerPolicy: { - handoffPolicyByCadence: { - daily: { - maxAttempts: 3, - retryBackoffMs: 0, - }, - }, - }, - }); - - const result = await runNode(fixture.scriptPath, ['--cadence', 'daily'], { - cwd: fixture.root, - env: fixture.env, - }); - - assert.equal(result.code, 0, `stdout: ${result.stdout}\nstderr: ${result.stderr}`); - const logs = await fs.readdir(path.join(fixture.root, 'task-logs', 'daily')); - assert.ok(logs.some((name) => name.endsWith('__completed.md'))); -}); - -test('uses fallback platform for handoff when primary platform fails', { concurrency: false }, async () => { - const fixture = await setupFixture({ - memoryPolicy: { mode: 'optional' }, - handoffCommand: `if [[ "$AGENT_PLATFORM" == "linux" ]]; then - echo HANDOFF_FALLBACK_OK - exit 0 -fi -echo "stream disconnected before completion" >&2 -exit 13`, - schedulerPolicy: { - handoffPolicyByCadence: { - daily: { - maxAttempts: 1, - fallbackPlatform: 'linux', - }, - }, - }, - }); - - const result = await runNode(fixture.scriptPath, ['--cadence', 'daily', '--platform', 'codex'], { - cwd: fixture.root, - env: fixture.env, - }); - - assert.equal(result.code, 0, `stdout: ${result.stdout}\nstderr: ${result.stderr}`); - const logs = await fs.readdir(path.join(fixture.root, 'task-logs', 'daily')); - assert.ok(logs.some((name) => name.endsWith('__completed.md'))); -}); - -test('fails before lock acquisition when runner health preflight command fails', { concurrency: false }, async () => { - const fixture = await setupFixture({ - memoryPolicy: { mode: 'optional' }, - schedulerPolicy: { - runnerHealthCommandByCadence: { - daily: 'echo RUNNER_UNAVAILABLE >&2; exit 9', - }, - }, - }); - - const result = await runNode(fixture.scriptPath, ['--cadence', 'daily'], { - cwd: fixture.root, - env: fixture.env, - }); - - assert.equal(result.code, 9, `stdout: ${result.stdout}\nstderr: ${result.stderr}`); - const logs = await fs.readdir(path.join(fixture.root, 'task-logs', 'daily')); - const failedLog = logs.find((name) => name.endsWith('__failed.md')); - assert.ok(failedLog); - const failedBody = await fs.readFile(path.join(fixture.root, 'task-logs', 'daily', failedLog), 'utf8'); - assert.match(failedBody, /reason: Runner health preflight failed/); - assert.match(failedBody, /failure_class: 'runner_unavailable'/); - assert.match(failedBody, /failure_category: 'execution_error'/); - assert.match(failedBody, /Prompt not executed\./); -}); - -test('uses exclusion payload from mixed JSON lock:check output', { concurrency: false }, async () => { - const fixture = await setupFixture({ - memoryPolicy: { mode: 'optional' }, - roster: ['agent-a', 'agent-b'], - lockCheckOutput: `echo '{"event":"relay_health_snapshot"}' -echo '{"excluded":["agent-a"]}'`, - }); - - const result = await runNode(fixture.scriptPath, ['--cadence', 'daily'], { - cwd: fixture.root, - env: fixture.env, - }); - - assert.equal(result.code, 0, `stdout: ${result.stdout}\nstderr: ${result.stderr}`); - assert.match(result.stdout, /Agent:\s+agent-b/); -}); diff --git a/test/test-audit-run-flaky-check.test.mjs b/test/test-audit-run-flaky-check.test.mjs deleted file mode 100644 index 73fceaf..0000000 --- a/test/test-audit-run-flaky-check.test.mjs +++ /dev/null @@ -1,45 +0,0 @@ -import { test } from 'node:test'; -import assert from 'node:assert/strict'; -import fs from 'node:fs/promises'; -import os from 'node:os'; -import path from 'node:path'; -import { spawn } from 'node:child_process'; - -const SCRIPT = path.resolve('scripts/test-audit/run-flaky-check.mjs'); - -function runFlakyCheck(args) { - return new Promise((resolve) => { - const childEnv = { ...process.env }; - delete childEnv.NODE_TEST_CONTEXT; - delete childEnv.NODE_UNIQUE_ID; - - const child = spawn(process.execPath, [SCRIPT, ...args], { - cwd: process.cwd(), - stdio: ['ignore', 'pipe', 'pipe'], - env: childEnv, - }); - - let stdout = ''; - let stderr = ''; - child.stdout.on('data', (chunk) => { stdout += chunk.toString(); }); - child.stderr.on('data', (chunk) => { stderr += chunk.toString(); }); - child.on('close', (code) => resolve({ code: code ?? 1, stdout, stderr })); - }); -} - -test('run-flaky-check reports pass/fail counts from TAP output files', async () => { - const outputDir = await fs.mkdtemp(path.join(os.tmpdir(), 'flaky-check-report-')); - const passFixture = 'test/fixtures/flaky-check/pass.fixture.test.mjs'; - const failFixture = 'test/fixtures/flaky-check/fail.fixture.test.mjs'; - - const result = await runFlakyCheck(['--output-dir', outputDir, passFixture, failFixture]); - assert.equal(result.code, 0, result.stderr || result.stdout); - - const matrix = JSON.parse(await fs.readFile(path.join(outputDir, 'flakiness-matrix.json'), 'utf8')); - assert.deepEqual(matrix[passFixture], { pass: 5, fail: 0 }); - assert.deepEqual(matrix[failFixture], { pass: 0, fail: 5 }); - - const diagnostics = JSON.parse(await fs.readFile(path.join(outputDir, 'flakiness-runs.json'), 'utf8')); - assert.equal(diagnostics.length, 5); - assert.ok(diagnostics.every((run) => run.observed >= 2)); -}); diff --git a/test/utils.test.mjs b/test/utils.test.mjs index da7213a..40db583 100644 --- a/test/utils.test.mjs +++ b/test/utils.test.mjs @@ -2,8 +2,7 @@ import { describe, it, after } from 'node:test'; import assert from 'node:assert'; import fs from 'node:fs'; import path from 'node:path'; -import { getIsoWeekStr, todayDateStr, nowUnix, ensureDir, detectPlatform, relayListLabel } from '../src/utils.mjs'; -import { mergeRelayList } from '../src/lock-utils.mjs'; +import { getIsoWeekStr, todayDateStr, nowUnix, ensureDir, detectPlatform, relayListLabel, mergeRelayList } from '../src/utils.mjs'; describe('Date Utilities', () => { describe('todayDateStr', () => { diff --git a/torch-config.example.json b/torch-config.example.json index dafd23d..aafd0bf 100644 --- a/torch-config.example.json +++ b/torch-config.example.json @@ -26,30 +26,6 @@ "daily": "scheduler-update-agent", "weekly": "bug-reproducer-agent" }, - "handoffCommandByCadence": { - "daily": "node torch/scripts/agent/run-selected-prompt.mjs", - "weekly": "node torch/scripts/agent/run-selected-prompt.mjs" - }, - "handoffPolicyByCadence": { - "daily": { - "maxAttempts": 2, - "retryBackoffMs": 1000, - "retryOnPatterns": [ - "stream disconnected", - "timeout", - "temporarily unavailable" - ], - "fallbackPlatform": "linux" - }, - "weekly": { - "maxAttempts": 2, - "retryBackoffMs": 1000 - } - }, - "runnerHealthCommandByCadence": { - "daily": "command -v codex >/dev/null 2>&1", - "weekly": "command -v codex >/dev/null 2>&1" - }, "memoryPolicyByCadence": { "daily": { "mode": "required", @@ -62,12 +38,10 @@ "MEMORY_STORED" ], "retrieveArtifacts": [ - ".scheduler-memory/latest/daily/retrieve.ok", - ".scheduler-memory/latest/daily/retrieve.json" + ".scheduler-memory/latest/daily/retrieve.ok" ], "storeArtifacts": [ - ".scheduler-memory/latest/daily/store.ok", - ".scheduler-memory/latest/daily/store.json" + ".scheduler-memory/latest/daily/store.ok" ] }, "weekly": { @@ -81,12 +55,10 @@ "MEMORY_STORED" ], "retrieveArtifacts": [ - ".scheduler-memory/latest/weekly/retrieve.ok", - ".scheduler-memory/latest/weekly/retrieve.json" + ".scheduler-memory/latest/weekly/retrieve.ok" ], "storeArtifacts": [ - ".scheduler-memory/latest/weekly/store.ok", - ".scheduler-memory/latest/weekly/store.json" + ".scheduler-memory/latest/weekly/store.ok" ] } }, diff --git a/torch-config.json b/torch-config.json index 96fe9b9..60cda0f 100644 --- a/torch-config.json +++ b/torch-config.json @@ -34,12 +34,10 @@ "MEMORY_STORED" ], "retrieveArtifacts": [ - ".scheduler-memory/latest/daily/retrieve.ok", - ".scheduler-memory/latest/daily/retrieve.json" + ".scheduler-memory/latest/daily/retrieve.ok" ], "storeArtifacts": [ - ".scheduler-memory/latest/daily/store.ok", - ".scheduler-memory/latest/daily/store.json" + ".scheduler-memory/latest/daily/store.ok" ] }, "weekly": { @@ -53,14 +51,12 @@ "MEMORY_STORED" ], "retrieveArtifacts": [ - ".scheduler-memory/latest/weekly/retrieve.ok", - ".scheduler-memory/latest/weekly/retrieve.json" + ".scheduler-memory/latest/weekly/retrieve.ok" ], "storeArtifacts": [ - ".scheduler-memory/latest/weekly/store.ok", - ".scheduler-memory/latest/weekly/store.json" + ".scheduler-memory/latest/weekly/store.ok" ] } } } -} +} \ No newline at end of file