From f1b06a7847841ac51c67b100f69e46a75684adf5 Mon Sep 17 00:00:00 2001 From: warren Date: Thu, 18 Jun 2026 10:45:29 +0000 Subject: [PATCH] chore(warren): seeds state --- .seeds/issues.jsonl | 3 +++ .seeds/plans.jsonl | 1 + 2 files changed, 4 insertions(+) diff --git a/.seeds/issues.jsonl b/.seeds/issues.jsonl index 13720ad2..63d4890f 100644 --- a/.seeds/issues.jsonl +++ b/.seeds/issues.jsonl @@ -761,3 +761,6 @@ {"id":"warren-59db","title":"Decompose src/server/handlers/plot-plan-runs.test.ts (640 lines, furthest-over grandfathered file not under an open seed) below the 500-line global limit. Extract the file-local helper/fixture group into a new sibling src/server/handlers/plot-plan-runs.test-helpers.ts and export each symbol: silentLogger, stubFetch, jsonRes, poolFor, makeSdSpawn, planShowResult, seedShowResult, makeAttachment, makePlotReader, makePlotResolver, makeSynthesizer, depsFor, tcpUrl, plus their helper-local types (SdCall, SynthesizeCall, BuildDepsInput). Carry the imports those helpers need into the helpers file (Attachment from @os-eco/plot-cli, BurrowClient/BurrowClientPool, openDatabase/WarrenDb, createRepos/Repos, ProjectRow, the plan-run/plot/synthesizer types, SpawnFn/SpawnOptions/SpawnResult, RunEventBroker, NO_AUTH, createBridgeRegistry, startServer, server types). Keep ONE copy of every helper and import it — do NOT duplicate, or jscpd check:dups will flag it. Split the 9 tests in the single describe(\"POST /plot-plan-runs\") block along theme seams into two sibling test files, each importing from ./plot-plan-runs.test-helpers.ts: keep plot-plan-runs.test.ts for the happy-path + filter tests ('happy path: synthesizes plan + persists plan-run + emits Plot dispatch event' and 'filters closed seeds + sd_plan attachments before synthesis'); create plot-plan-runs.validation.test.ts for the 7 validation/error tests (malformed plot_id 400, no .plot/ 400, no .seeds/ 400, plot_id not in project 400, zero dispatchable attachments 400, 404 project missing, synthesizer error 500). Do not alter any test body, assertion, stub, or fixture. Mirror the precedent of src/diagnostics/checks.test-helpers.ts (warren-7a15) and src/server/handlers/projects.test-helpers.ts (warren-a715). Verify: each of `wc -l src/server/handlers/plot-plan-runs.test.ts src/server/handlers/plot-plan-runs.validation.test.ts src/server/handlers/plot-plan-runs.test-helpers.ts` shows < 500 AND `bun test src/server/handlers/plot-plan-runs.test.ts src/server/handlers/plot-plan-runs.validation.test.ts` reports 9 pass / 0 fail (same total as before) AND `bun run typecheck` is clean AND `bun run check:dups` exits 0.","status":"closed","type":"task","priority":2,"plan_step_index":0,"description":"\nStep 1 of plan pl-7c4f.\n\nParent seed: warren-1c0d — ratchetwatch tightening: 2026-06-17\nPlan template: refactor\nPlan approach: Extract the file-local helper/fixture block (the ~16 helpers spanning silentLogger, stubFetch, jsonRes, poolFor, makeSdSpawn, planShowResult, seedShowResult, makeAttachment, makePlotReader, makePlotResolver, makeSynthesizer, depsFor,…\n\nRun `sd plan show pl-7c4f` for the full plan (context, alternatives, sibling steps, acceptance criteria).\n","createdAt":"2026-06-17T10:46:21.709Z","updatedAt":"2026-06-17T10:54:35.710Z","labels":["ratchetwatch"],"plan_id":"pl-7c4f","blocks":["warren-e304","warren-1c0d"],"extensions":{"role":"pi","lastRunId":"run_gwekz26ek6vm","lastRunAt":"2026-06-17T10:49:16.505Z"},"closedAt":"2026-06-17T10:54:35.710Z"} {"id":"warren-e304","title":"Remove the \"src/server/handlers/plot-plan-runs.test.ts\": 640 entry from scripts/file-size-budgets.json (delete that single line). Do NOT add budget entries for the new sibling files (plot-plan-runs.validation.test.ts, plot-plan-runs.test-helpers.ts) — they must default-pass under the 500-line threshold (confirm `wc -l` for each shows < 500). Per docs/CONSTITUTION.md Article VI, before declaring done run a repo-wide search for the old path across ALL file types — `rg -n \"plot-plan-runs.test\" --hidden -g '!node_modules' .` (or `git grep -n \"plot-plan-runs.test\"`) PLUS an explicit sweep of Dockerfile, docker-compose.yml, .github/workflows/*.yml, src/supervisor/ spawn/config strings, scripts/acceptance/, and docs/ — and fix any stale reference (file moves have broken production here before; encode the check, do not assume it). Verify: `bun run check:size` exits 0 AND `bun run check:all` is fully green (every gate stays green; the removed entry leaves all resulting files default-passing under the 500-line threshold).","status":"closed","type":"task","priority":2,"plan_step_index":1,"description":"\nStep 2 of plan pl-7c4f.\n\nParent seed: warren-1c0d — ratchetwatch tightening: 2026-06-17\nPlan template: refactor\nPlan approach: Extract the file-local helper/fixture block (the ~16 helpers spanning silentLogger, stubFetch, jsonRes, poolFor, makeSdSpawn, planShowResult, seedShowResult, makeAttachment, makePlotReader, makePlotResolver, makeSynthesizer, depsFor,…\n\nRun `sd plan show pl-7c4f` for the full plan (context, alternatives, sibling steps, acceptance criteria).\n","createdAt":"2026-06-17T10:46:21.709Z","updatedAt":"2026-06-17T10:59:24.445Z","labels":["ratchetwatch"],"plan_id":"pl-7c4f","blocks":["warren-1c0d"],"closedAt":"2026-06-17T10:59:24.445Z"} {"id":"warren-f248","title":"Auditor sandboxes lack WARREN_API_TOKEN — warden-conversation delivery (POST /conversations/:id/messages) returns 401 for gatewatch/ratchetwatch/tastewatch","status":"open","type":"bug","priority":2,"createdAt":"2026-06-17T10:47:09.663Z","updatedAt":"2026-06-17T10:47:09.663Z","description":"Evidence (ratchetwatch patrol 2026-06-17):\n- The warren API is reachable from the auditor burrow at http://localhost:8080 (e.g. GET/POST /conversations responds), but every request returns: {\"error\":{\"code\":\"unauthorized\",\"message\":\"missing Authorization header\"}}.\n- src/server/auth.ts requires a bearer token from WARREN_API_TOKEN; that env var is NOT present in the auditor sandbox (env shows only ANTHROPIC_API_KEY and WARREN_QUALITY_GATE). No token file is mounted (~/.warren absent; /data unreadable; no *.token anywhere outside node_modules).\n- Result: the operating contract added by warren-7f62 (post each finding to the standing 'Audit Warden' conversation over POST /conversations/:id/messages, 202 steering channel) cannot be fulfilled by ANY auditor — gatewatch, ratchetwatch, tastewatch — because they cannot authenticate or even resolve the conversation id (GET /conversations is also 401-gated).\n- This is a runtime/provisioning gap, not a prompt gap: warren-7f62 wired the prompts but the auditor runs are not given a credential (or a loopback no-auth exemption, or a pre-resolved conversation id) to reach the channel.\nSuggested fix directions (for a human/operator to choose): inject a scoped WARREN_API_TOKEN into auditor burrow env via composeRunEnv, OR expose a loopback no-auth path for the conversation-message endpoint, OR pass the resolved warden conversation id + token through the rendered agent context. Until then, auditors file seeds/plans correctly (this patrol filed warren-1c0d + plan pl-7c4f) but the warden transcript stays empty.","labels":["audit","warden"]} +{"id":"warren-bf70","title":"ratchetwatch tightening: 2026-06-18","status":"open","type":"task","priority":3,"createdAt":"2026-06-18T10:44:04.665Z","updatedAt":"2026-06-18T10:44:37.866Z","description":"Constitution Article II ratchet-slack patrol, 2026-06-18.\n\nMEASUREMENTS (ratchet | floor/limit | actual | slack | action):\n- Coverage functions | floor 88.60% | actual 88.95% | slack 0.35pt | none (<0.75pt). Note: a clean measurement required `bun install` first — the sandbox shipped with zod + @os-eco/burrow-cli uninstalled, which crashed several suites and depressed the reading to a false 88.07%. After install: 88.95%.\n- Coverage lines | floor 91.54% | actual 91.76% | slack 0.22pt | none (<0.75pt).\n- File-size grandfather list | global limit 500 | 0 entries now under 500 | none to remove.\n- Bundle creep (gzip js) | ~20KB/wk threshold | summed +2062 B of raises over trailing 7d (2978ba7 +569, f9194ad +525, ad6ceeca +635, fb6adfb +333), net ~flat after -2045/-137 decreases | none (well under threshold).\n- Debt-marker allowlist | must be empty | [] | none.\n- Grandfather-at-birth (24h) | none added | only file-size-budgets.json change in 24h was 7de08992 REMOVING plot-plan-runs.test.ts:640 | none.\n\nACTION: one decomposition (the single per-patrol slot) — see plan. src/runs/pr.ts (659, furthest over) is already covered by open plan pl-88bb (warren-db9a/warren-70d7); the furthest-over grandfathered file NOT covered by an open seed is a tie at 616 between src/diagnostics/checks.ts (production source) and src/runs/pause.test.ts (test). Tie broken toward the test file: lower Article VI runtime-path risk and a clean single-describe seam (tickPauseDetector is ~373 of the 616 lines).","labels":["audit","ratchetwatch"],"plan_id":"pl-1a01","blockedBy":["warren-0e98","warren-b7fa"]} +{"id":"warren-0e98","title":"Decompose src/runs/pause.test.ts (616 lines) below the 500-line global limit. First extract the shared file-local helper group into a new sibling src/runs/pause.test-helpers.ts and export each symbol: PROJECT_ID, PLOT_ID, makeAgentJson, poseEvent, answerEvent, stubReader, multiPlotReader. Carry the imports those helpers need into the helpers file (type PlotEvent from @os-eco/plot-cli, type PlotEventReader from ./pause.ts) and import every helper back into each resulting test file — keep ONE copy, do NOT duplicate, or jscpd check:dups will flag it. Then split the four top-level describe blocks along their existing seams into two sibling test files, each importing the helpers from ./pause.test-helpers.ts and the units under test from ./pause.ts: keep describe(\"pickUnansweredQuestion\"), describe(\"findAnswerFor\"), and describe(\"bootPauseDetector\") in src/runs/pause.test.ts; move describe(\"tickPauseDetector\") into a new src/runs/pause.tick.test.ts. Do not alter any test body, assertion, stub, or fixture. Mirror the precedent src/diagnostics/checks.test-helpers.ts (warren-7a15) and src/server/handlers/projects.test-helpers.ts (warren-a715). Verify: each of `wc -l src/runs/pause.test.ts src/runs/pause.tick.test.ts src/runs/pause.test-helpers.ts` shows < 500 AND `bun test src/runs/pause.test.ts src/runs/pause.tick.test.ts` reports 23 pass / 0 fail (same total as before) AND `bun run typecheck` is clean AND `bun run check:dups` exits 0.","status":"open","type":"task","priority":2,"plan_step_index":0,"description":"\nStep 1 of plan pl-1a01.\n\nParent seed: warren-bf70 — ratchetwatch tightening: 2026-06-18\nPlan template: refactor\nPlan approach: Mirror the established precedent src/diagnostics/checks.test-helpers.ts (warren-7a15) and src/server/handlers/projects.test-helpers.ts (warren-a715): extract the file-local test-helper group into a sibling src/runs/pause.test-helpers.ts…\n\nRun `sd plan show pl-1a01` for the full plan (context, alternatives, sibling steps, acceptance criteria).\n","createdAt":"2026-06-18T10:44:37.866Z","updatedAt":"2026-06-18T10:44:37.866Z","labels":["ratchetwatch"],"plan_id":"pl-1a01","blocks":["warren-bf70"]} +{"id":"warren-b7fa","title":"Remove the \"src/runs/pause.test.ts\": 616 entry from scripts/file-size-budgets.json (delete that single line). Do NOT add budget entries for the new sibling files (pause.tick.test.ts, pause.test-helpers.ts) — they must default-pass under the 500-line threshold (confirm `wc -l` for each shows < 500). Per docs/CONSTITUTION.md Article VI, before declaring done run a repo-wide search for the old path across ALL file types — `grep -rn \"runs/pause.test\" --include='*' . | grep -v node_modules` (or `git grep -n \"runs/pause.test\"`) PLUS an explicit sweep of Dockerfile, docker-compose.yml, .github/workflows/*.yml, src/supervisor/ spawn/config strings, scripts/acceptance/, and docs/ — and fix any stale reference (file moves have broken production here before; encode the check, do not assume it). Verify: `bun run check:size` exits 0 AND `bun run check:dups` exits 0 AND `bun run check:all` is fully green (every gate stays green; the removed entry leaves all resulting files default-passing under the 500-line threshold).","status":"open","type":"task","priority":2,"plan_step_index":1,"description":"\nStep 2 of plan pl-1a01.\n\nParent seed: warren-bf70 — ratchetwatch tightening: 2026-06-18\nPlan template: refactor\nPlan approach: Mirror the established precedent src/diagnostics/checks.test-helpers.ts (warren-7a15) and src/server/handlers/projects.test-helpers.ts (warren-a715): extract the file-local test-helper group into a sibling src/runs/pause.test-helpers.ts…\n\nRun `sd plan show pl-1a01` for the full plan (context, alternatives, sibling steps, acceptance criteria).\n","createdAt":"2026-06-18T10:44:37.866Z","updatedAt":"2026-06-18T10:44:37.866Z","labels":["ratchetwatch"],"plan_id":"pl-1a01","blocks":["warren-bf70"]} diff --git a/.seeds/plans.jsonl b/.seeds/plans.jsonl index 7ec328b1..b3a0afe3 100644 --- a/.seeds/plans.jsonl +++ b/.seeds/plans.jsonl @@ -72,3 +72,4 @@ {"id":"pl-dfb5","seed":"warren-1551","template":"feature","status":"done","revision":1,"sections":{"context":"Warren's UI has accumulated three concrete papercuts that this Plot (plot-9f03348c) targets. (1) Table sorting is inconsistent: Runs.tsx sorts server-side via a local SortHeader component, Workspace.tsx sorts client-side with inline ↑/↓ glyphs and its own SortKey/SortDir state, while Projects, PlanRuns, and Agents tables are not sortable at all. (2) The plan-run dispatch form (NewPlanRun.tsx) forces the operator to hand-type the plan id (`pl-a258`) into a free-text Input with no list to pick from — error-prone and undiscoverable. (3) Several pages (notably Runs.tsx and Workspace.tsx with zero responsive prefixes) break on phone-width viewports because their wide tables overflow and there is no standardized responsive pattern. This is responsive-web polish plus consistency work — no redesign, no native/PWA.","approach":"Tackle the three papercuts as independent, parallelizable workstreams that converge on a final release seed. SORTING: extract one canonical sortable column-header primitive into src/ui/src/components/ui/ that consolidates the two existing ad-hoc implementations (Workspace inline glyphs + Runs SortHeader), then wire it into every list table so sort affordances, glyphs, and toggle behaviour are identical everywhere. PLAN_ID PREFILL: add a read-side server endpoint that lists the available seeds plans for a project (shelling out through the existing src/seeds-cli/ helpers, mirroring `sd plan show`/`sd plan list`), expose it through the api client + types, then replace the free-text Plan ID Input in NewPlanRun.tsx with a populated selector that still allows a manual fallback. MOBILE: first standardize the responsive contract (canonical breakpoints targeting ~393px iPhone logical width degrading to ~360px, plus a reusable wide-table-on-mobile pattern — horizontal scroll / stacked), then apply it page-by-page so every page is usable on phones. Finish with the mandatory patch version bump via the .claude/commands/release.md flow. Chosen over a single monolithic 'fix the UI' seed because each papercut touches different modules, reviews independently, and the Plot constraint explicitly permits chunked mobile execution.","alternatives":[{"name":"One monolithic UI-polish seed","rejected_because":"Too large to review as a single PR and conflates three unrelated surfaces (table component, server endpoint + form, responsive CSS); the Plot intent explicitly allows the mobile work to be chunked."},{"name":"Client-side-only plan_id autocomplete (no new endpoint)","rejected_because":"The UI has no existing way to enumerate a project's plans; the plan list lives in `.seeds/plans.jsonl` inside the clone, only reachable server-side via the seeds-cli helpers, so a read endpoint is required to populate any selector."}],"steps":[{"title":"Extract a shared sortable table-head component into components/ui","type":"task","priority":2,"blocks":[2],"labels":["ui","sorting"]},{"title":"Apply the shared sortable header across all list tables (Runs, Workspace, Projects, PlanRuns, Agents)","type":"feature","priority":2,"blocks":[7],"labels":["ui","sorting"]},{"title":"Add a read endpoint + api client to list a project's seeds plans","type":"feature","priority":2,"blocks":[4],"labels":["server","plan-runs"]},{"title":"Replace free-text Plan ID input with a populated selector (manual fallback) on the plan-run form","type":"feature","priority":2,"blocks":[7],"labels":["ui","plan-runs"]},{"title":"Standardize the responsive contract: canonical breakpoints (~393px down to ~360px) and a reusable wide-table-on-mobile pattern","type":"feature","priority":2,"blocks":[6],"labels":["ui","mobile"]},{"title":"Apply the standardized mobile pattern across all pages so every page works on phones","type":"feature","priority":2,"blocks":[7],"labels":["ui","mobile"]},{"title":"Patch version bump via the .claude/commands/release.md flow (package.json + src/index.ts in sync, CHANGELOG.md, commit)","type":"task","priority":2,"labels":["release"]}],"risks":["Consolidating two sort implementations may regress Runs' server-side sort params vs Workspace's client-side sort — preserve each table's existing data source, change only the header affordance.","The plans-list endpoint shells out to the seeds CLI; handle projects without `.seeds/` (hasSeeds=false) and slow/erroring shell-outs gracefully, mirroring the existing hasSeeds gating.","Mobile table reflow can hide columns operators rely on; the standardized pattern must keep all data reachable (scroll or stack), not drop columns silently.","Bundle-size and per-file line-count ratchets (check:bundle-size, check:size) can trip on new components — keep additions lean and re-baseline only when legitimately grown."],"acceptance":["Every list table (Runs, Workspace, Projects, PlanRuns, Agents) uses the same sortable-header component with identical sort affordance, glyphs, and toggle behaviour.","The plan-run dispatch form lets the operator pick a plan id from a list of the selected project's plans, with a manual-entry fallback, and no longer requires hand-typing `pl-XXXX`.","All pages render and are usable at ~393px and degrade gracefully down to ~360px, with no horizontal overflow that hides data; wide tables follow the standardized responsive pattern.","A patch version bump is committed via the release.md flow with package.json and src/index.ts in sync and CHANGELOG.md updated.","bun run check:all passes (lint, typecheck, size, bundle-size, coverage, etc.) on the merged result."]},"children":["warren-9440","warren-5562","warren-9b49","warren-c030","warren-3315","warren-42ba","warren-1c81"],"createdAt":"2026-06-16T07:18:51.397Z","updatedAt":"2026-06-16T22:48:22.022Z","name":"UI Nits Redux"} {"id":"pl-2b5e","seed":"warren-882e","template":"refactor","status":"done","revision":1,"sections":{"context":"ratchetwatch patrol 2026-06-16, docs/CONSTITUTION.md Article II (ratchets only tighten). The file-size grandfather list (scripts/file-size-budgets.json, threshold 500) holds 23 entries, all still over the 500-line global limit, so none are removable this patrol. Coverage slack is tight (functions 88.97% vs floor 88.60% = 0.37pt; lines 91.70% vs floor 91.54% = 0.16pt; both under the 0.75pt threshold). Bundle creep is tight (~1.7KB summed gzip-js raises over the trailing 7 days, far under 20KB; an autoheal re-baseline at 9da86f5 dropped totals back down). Debt-marker allowlist is empty. The single warranted mechanical tightening is the one-per-patrol decomposition: src/diagnostics/checks.test.ts at 653 lines is the grandfathered file furthest over the limit (over by 153) that is NOT already covered by an open seed. The absolute furthest-over file, src/runs/pr.ts (659), is already covered by open seeds warren-db9a + warren-70d7, so it is skipped per the dedupe rule.","behavior_invariant":"All 53 tests currently in src/diagnostics/checks.test.ts must still exist and pass after the decomposition, with the same total count (53) across the resulting sibling files. The checks under test (checkBwrap, checkCanopyClone, checkCanopyClean, checkWarrenConfig, checkWarrenConfigDeprecations, checkWarrenDb, checkDatabaseReachable, checkPreviewPortAllocator, checkPreviewMaxLive, checkPreviewAuthStrength) and their assertions remain unchanged in meaning; only file boundaries move. No production source under src/diagnostics/ is modified. Every check:all gate stays green.","approach":"Split src/diagnostics/checks.test.ts (653 lines, 10 top-level describe blocks, 53 tests) along its existing describe seams into sibling test files under src/diagnostics/, each comfortably under the 500-line threshold. Hoist the single shared helper captureSpawnCalls (and the imports it needs: SpawnFn type from ../projects/clone.ts) into a new sibling src/diagnostics/checks.test-helpers.ts and import it from each split file rather than copy-pasting it (jscpd check:dups will flag a duplicate). Suggested grouping (executor may adjust as long as every file is < 500 lines and the shared helper lives in ONE place): keep checks.test.ts for the sandbox/clone group (checkBwrap, checkCanopyClone, checkCanopyClean); new checks.config.test.ts for the config group (checkWarrenConfig, checkWarrenConfigDeprecations, checkWarrenDb, checkDatabaseReachable); new checks.preview.test.ts for the preview group (checkPreviewPortAllocator, checkPreviewMaxLive, checkPreviewAuthStrength). Then remove the grandfather entry for checks.test.ts from scripts/file-size-budgets.json; do NOT add budget entries for the new siblings (they must default-pass under 500).","steps":[{"title":"Decompose src/diagnostics/checks.test.ts (653 lines) below the 500-line global limit. Extract the shared helper captureSpawnCalls plus the imports it needs (SpawnFn from ../projects/clone.ts) into a new sibling src/diagnostics/checks.test-helpers.ts and export it; import it from each resulting test file (keep ONE copy — do NOT duplicate, or jscpd check:dups will flag it). Split the 10 top-level describe blocks along their existing seams into sibling files under src/diagnostics/ so every resulting file is < 500 lines: keep checks.test.ts for checkBwrap/checkCanopyClone/checkCanopyClean; create checks.config.test.ts for checkWarrenConfig/checkWarrenConfigDeprecations/checkWarrenDb/checkDatabaseReachable; create checks.preview.test.ts for checkPreviewPortAllocator/checkPreviewMaxLive/checkPreviewAuthStrength. Each file imports the checks under test from ./checks.ts and the shared helper from ./checks.test-helpers.ts. Do not alter any test body or assertion. Verify: each of `wc -l src/diagnostics/checks.test.ts src/diagnostics/checks.config.test.ts src/diagnostics/checks.preview.test.ts src/diagnostics/checks.test-helpers.ts` shows < 500 AND `bun test src/diagnostics/checks.test.ts src/diagnostics/checks.config.test.ts src/diagnostics/checks.preview.test.ts` reports 53 pass / 0 fail (same total as before) AND `bun run typecheck` is clean AND `bun run check:dups` exits 0.","labels":["ratchetwatch"],"blocks":[2]},{"title":"Remove the \"src/diagnostics/checks.test.ts\": 653 entry from scripts/file-size-budgets.json (delete that single line). Do NOT add budget entries for the new sibling files (checks.config.test.ts, checks.preview.test.ts, checks.test-helpers.ts) — they must default-pass under the 500-line threshold (confirm `wc -l` for each shows < 500). Per docs/CONSTITUTION.md Article VI, before declaring done run a repo-wide search for the old path across ALL file types — `grep -rn \"diagnostics/checks.test\" --include='*' . | grep -v node_modules` (or `git grep -n \"diagnostics/checks.test\"`) PLUS an explicit sweep of Dockerfile, docker-compose.yml, .github/workflows/*.yml, src/supervisor/ spawn/config strings, scripts/acceptance/, and docs/ — and fix any stale reference (file moves have broken production here before; encode the check, do not assume it). Verify: `bun run check:size` exits 0 AND `bun run check:all` is fully green (every gate stays green; the removed entry leaves all resulting files default-passing under the 500-line threshold).","labels":["ratchetwatch"]}],"acceptance":["src/diagnostics/checks.test.ts and every new sibling (checks.config.test.ts, checks.preview.test.ts, checks.test-helpers.ts) are each < 500 lines (wc -l).","bun test over the resulting diagnostics check files reports 53 pass / 0 fail — the same total test count as the pre-split checks.test.ts.","scripts/file-size-budgets.json no longer lists src/diagnostics/checks.test.ts and adds NO entry for any new sibling file.","A repo-wide search for the old path 'diagnostics/checks.test' (incl. Dockerfile, workflow YAML, supervisor/config strings, scripts/acceptance, docs) finds no stale reference, per Article VI.","bun run check:all is fully green (check:size, check:dups, typecheck, coverage, all gates)."]},"children":["warren-7a15","warren-2c73"],"createdAt":"2026-06-16T10:44:38.043Z","updatedAt":"2026-06-16T10:56:50.995Z","name":"ratchetwatch tightening 2026-06-16: decompose checks.test.ts"} {"id":"pl-7c4f","seed":"warren-1c0d","template":"refactor","status":"done","revision":1,"sections":{"context":"Article II of docs/CONSTITUTION.md requires grandfather lists to burn down, not just hold. src/server/handlers/plot-plan-runs.test.ts is grandfathered in scripts/file-size-budgets.json at 640 lines (140 over the 500-line global limit) and is the furthest-over entry not already covered by an open seed (src/runs/pr.ts at 659 is covered by warren-db9a / warren-70d7). ratchetwatch decomposes at most one file per patrol; this is that file for 2026-06-17. No other mechanical tightening is warranted this patrol: coverage slack is under 0.75pt, bundle creep is under 20KB/7d, the debt allowlist is empty, and no other entry has fallen under the global limit.","behavior_invariant":"The same set of tests for POST /plot-plan-runs must continue to run and pass with the identical total count (9 tests across the original single describe block). No test body, assertion, stub, or fixture may change behavior — this is a pure file split, not a rewrite. bun run check:all must stay fully green.","approach":"Extract the file-local helper/fixture block (the ~16 helpers spanning silentLogger, stubFetch, jsonRes, poolFor, makeSdSpawn, planShowResult, seedShowResult, makeAttachment, makePlotReader, makePlotResolver, makeSynthesizer, depsFor, tcpUrl plus their helper-local types SdCall/SynthesizeCall/BuildDepsInput) into a new sibling src/server/handlers/plot-plan-runs.test-helpers.ts and export each symbol, carrying the imports those helpers need. Then split the 9 tests in the single `describe(\"POST /plot-plan-runs\")` block along theme seams into two sibling files, each importing the shared helpers (keep ONE copy of every helper — do NOT duplicate, or jscpd check:dups will flag it). Mirror the established precedent in this repo (warren-7a15 checks.test-helpers.ts, warren-a715 projects.test-helpers.ts). Finally remove the grandfather entry. Both budget changes leave every gate green: the resulting files all default-pass under the 500-line threshold.","steps":[{"title":"Decompose src/server/handlers/plot-plan-runs.test.ts (640 lines, furthest-over grandfathered file not under an open seed) below the 500-line global limit. Extract the file-local helper/fixture group into a new sibling src/server/handlers/plot-plan-runs.test-helpers.ts and export each symbol: silentLogger, stubFetch, jsonRes, poolFor, makeSdSpawn, planShowResult, seedShowResult, makeAttachment, makePlotReader, makePlotResolver, makeSynthesizer, depsFor, tcpUrl, plus their helper-local types (SdCall, SynthesizeCall, BuildDepsInput). Carry the imports those helpers need into the helpers file (Attachment from @os-eco/plot-cli, BurrowClient/BurrowClientPool, openDatabase/WarrenDb, createRepos/Repos, ProjectRow, the plan-run/plot/synthesizer types, SpawnFn/SpawnOptions/SpawnResult, RunEventBroker, NO_AUTH, createBridgeRegistry, startServer, server types). Keep ONE copy of every helper and import it — do NOT duplicate, or jscpd check:dups will flag it. Split the 9 tests in the single describe(\"POST /plot-plan-runs\") block along theme seams into two sibling test files, each importing from ./plot-plan-runs.test-helpers.ts: keep plot-plan-runs.test.ts for the happy-path + filter tests ('happy path: synthesizes plan + persists plan-run + emits Plot dispatch event' and 'filters closed seeds + sd_plan attachments before synthesis'); create plot-plan-runs.validation.test.ts for the 7 validation/error tests (malformed plot_id 400, no .plot/ 400, no .seeds/ 400, plot_id not in project 400, zero dispatchable attachments 400, 404 project missing, synthesizer error 500). Do not alter any test body, assertion, stub, or fixture. Mirror the precedent of src/diagnostics/checks.test-helpers.ts (warren-7a15) and src/server/handlers/projects.test-helpers.ts (warren-a715). Verify: each of `wc -l src/server/handlers/plot-plan-runs.test.ts src/server/handlers/plot-plan-runs.validation.test.ts src/server/handlers/plot-plan-runs.test-helpers.ts` shows < 500 AND `bun test src/server/handlers/plot-plan-runs.test.ts src/server/handlers/plot-plan-runs.validation.test.ts` reports 9 pass / 0 fail (same total as before) AND `bun run typecheck` is clean AND `bun run check:dups` exits 0.","labels":["ratchetwatch"],"blocks":[2]},{"title":"Remove the \"src/server/handlers/plot-plan-runs.test.ts\": 640 entry from scripts/file-size-budgets.json (delete that single line). Do NOT add budget entries for the new sibling files (plot-plan-runs.validation.test.ts, plot-plan-runs.test-helpers.ts) — they must default-pass under the 500-line threshold (confirm `wc -l` for each shows < 500). Per docs/CONSTITUTION.md Article VI, before declaring done run a repo-wide search for the old path across ALL file types — `rg -n \"plot-plan-runs.test\" --hidden -g '!node_modules' .` (or `git grep -n \"plot-plan-runs.test\"`) PLUS an explicit sweep of Dockerfile, docker-compose.yml, .github/workflows/*.yml, src/supervisor/ spawn/config strings, scripts/acceptance/, and docs/ — and fix any stale reference (file moves have broken production here before; encode the check, do not assume it). Verify: `bun run check:size` exits 0 AND `bun run check:all` is fully green (every gate stays green; the removed entry leaves all resulting files default-passing under the 500-line threshold).","labels":["ratchetwatch"]}],"acceptance":["src/server/handlers/plot-plan-runs.test.ts, plot-plan-runs.validation.test.ts, and plot-plan-runs.test-helpers.ts are each < 500 lines (wc -l).","bun test src/server/handlers/plot-plan-runs.test.ts src/server/handlers/plot-plan-runs.validation.test.ts reports 9 pass / 0 fail — same total as the original file.","The \"src/server/handlers/plot-plan-runs.test.ts\": 640 entry is removed from scripts/file-size-budgets.json with no new entries added for the sibling files.","A repo-wide search (rg/git grep across all file types plus Dockerfile, docker-compose.yml, .github/workflows/*.yml, src/supervisor/, scripts/acceptance/, docs/) finds no stale reference to the old single-file layout.","bun run check:all is fully green (check:size, check:dups, typecheck, and all other gates pass)."]},"children":["warren-59db","warren-e304"],"createdAt":"2026-06-17T10:46:21.709Z","updatedAt":"2026-06-17T10:59:24.445Z","name":"ratchetwatch tightening: 2026-06-17 (decompose plot-plan-runs.test.ts)"} +{"id":"pl-1a01","seed":"warren-bf70","template":"refactor","status":"approved","revision":1,"sections":{"context":"Constitution Article II ratchet tightening (2026-06-18 ratchetwatch patrol). src/runs/pause.test.ts is 616 lines — grandfathered at \"src/runs/pause.test.ts\": 616 in scripts/file-size-budgets.json. src/runs/pr.ts (659, furthest over the 500-line limit) is already covered by open plan pl-88bb (warren-db9a/warren-70d7), and src/plan-runs/coordinator.completion.test.ts (612) is covered by open warren-c65d. The remaining furthest-over grandfathered files NOT covered by an open seed tie at 616: src/diagnostics/checks.ts (production source) and src/runs/pause.test.ts (test). Per the one-decomposition-per-patrol limit and 'slow is safe', the tie is broken toward the test file — lower Article VI runtime-path exposure (no production import graph) and a clean single-describe seam (tickPauseDetector is ~373 of the 616 lines). Retiring it lets the budget entry be removed (ratchet only goes down).","approach":"Mirror the established precedent src/diagnostics/checks.test-helpers.ts (warren-7a15) and src/server/handlers/projects.test-helpers.ts (warren-a715): extract the file-local test-helper group into a sibling src/runs/pause.test-helpers.ts and import it back into each resulting test file. pause.test.ts has four top-level describe blocks — pickUnansweredQuestion, findAnswerFor (both small), tickPauseDetector (~373 lines, the bulk), and bootPauseDetector (~90 lines) — plus a shared helper block (PROJECT_ID, PLOT_ID, makeAgentJson, poseEvent, answerEvent, stubReader, multiPlotReader). Move the shared helpers into the new src/runs/pause.test-helpers.ts (keep ONE copy, import in both files — do NOT duplicate or jscpd check:dups will flag it). Split out the large tickPauseDetector describe into a new sibling src/runs/pause.tick.test.ts; keep pickUnansweredQuestion + findAnswerFor + bootPauseDetector in pause.test.ts. Removing the tickPauseDetector block and the hoisted helpers lands pause.test.ts well under 500; pause.tick.test.ts (~400 incl. header/imports) and pause.test-helpers.ts (~60) are both under 500. Test files are not auto-discovered by name beyond Bun's *.test.ts glob, so all three resulting test/helper files behave identically.","steps":[{"title":"Decompose src/runs/pause.test.ts (616 lines) below the 500-line global limit. First extract the shared file-local helper group into a new sibling src/runs/pause.test-helpers.ts and export each symbol: PROJECT_ID, PLOT_ID, makeAgentJson, poseEvent, answerEvent, stubReader, multiPlotReader. Carry the imports those helpers need into the helpers file (type PlotEvent from @os-eco/plot-cli, type PlotEventReader from ./pause.ts) and import every helper back into each resulting test file — keep ONE copy, do NOT duplicate, or jscpd check:dups will flag it. Then split the four top-level describe blocks along their existing seams into two sibling test files, each importing the helpers from ./pause.test-helpers.ts and the units under test from ./pause.ts: keep describe(\"pickUnansweredQuestion\"), describe(\"findAnswerFor\"), and describe(\"bootPauseDetector\") in src/runs/pause.test.ts; move describe(\"tickPauseDetector\") into a new src/runs/pause.tick.test.ts. Do not alter any test body, assertion, stub, or fixture. Mirror the precedent src/diagnostics/checks.test-helpers.ts (warren-7a15) and src/server/handlers/projects.test-helpers.ts (warren-a715). Verify: each of `wc -l src/runs/pause.test.ts src/runs/pause.tick.test.ts src/runs/pause.test-helpers.ts` shows < 500 AND `bun test src/runs/pause.test.ts src/runs/pause.tick.test.ts` reports 23 pass / 0 fail (same total as before) AND `bun run typecheck` is clean AND `bun run check:dups` exits 0.","labels":["ratchetwatch"]},{"title":"Remove the \"src/runs/pause.test.ts\": 616 entry from scripts/file-size-budgets.json (delete that single line). Do NOT add budget entries for the new sibling files (pause.tick.test.ts, pause.test-helpers.ts) — they must default-pass under the 500-line threshold (confirm `wc -l` for each shows < 500). Per docs/CONSTITUTION.md Article VI, before declaring done run a repo-wide search for the old path across ALL file types — `grep -rn \"runs/pause.test\" --include='*' . | grep -v node_modules` (or `git grep -n \"runs/pause.test\"`) PLUS an explicit sweep of Dockerfile, docker-compose.yml, .github/workflows/*.yml, src/supervisor/ spawn/config strings, scripts/acceptance/, and docs/ — and fix any stale reference (file moves have broken production here before; encode the check, do not assume it). Verify: `bun run check:size` exits 0 AND `bun run check:dups` exits 0 AND `bun run check:all` is fully green (every gate stays green; the removed entry leaves all resulting files default-passing under the 500-line threshold).","labels":["ratchetwatch"]}],"acceptance":["src/runs/pause.test.ts is < 500 lines and its 616-line budget entry is gone from scripts/file-size-budgets.json; src/runs/pause.tick.test.ts and src/runs/pause.test-helpers.ts are each < 500 lines with NO budget entry (default-pass under threshold).","`bun test src/runs/pause.test.ts src/runs/pause.tick.test.ts` reports 23 pass / 0 fail — the same total as the original pause.test.ts — and `bun run typecheck` is clean.","The Article VI repo-wide search for the old path (plus Dockerfile/compose/workflow YAML/supervisor strings/scripts/acceptance/docs sweep) shows no broken or stale reference.","`bun run check:size` and `bun run check:dups` exit 0 (no duplicated helper across the resulting files).","`bun run check:all` is fully green — no gate regresses and no release step is added (Article III: hygiene batches into the next real release)."],"behavior_invariant":"The exact 23 tests across pickUnansweredQuestion, findAnswerFor, tickPauseDetector, and bootPauseDetector continue to run and pass with identical bodies, assertions, stubs, and fixtures — only their file location and a shared-helper import seam change. pause.ts itself is untouched. No production code path or import of pause.ts changes."},"children":["warren-0e98","warren-b7fa"],"createdAt":"2026-06-18T10:44:37.866Z","updatedAt":"2026-06-18T10:44:37.866Z","name":"Decompose src/runs/pause.test.ts below the 500-line limit"}