loki-mode 9.54.0 → 9.54.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/completion-council.sh +10 -1
- package/autonomy/lib/proof-generator.py +36 -5
- package/autonomy/run.sh +234 -31
- package/dashboard/__init__.py +1 -1
- package/dashboard/api_v2.py +4 -0
- package/dashboard/audit.py +9 -1
- package/dashboard/auth.py +16 -4
- package/dashboard/registry.py +34 -12
- package/dashboard/rigour_integration.py +25 -17
- package/dashboard/server.py +252 -104
- package/dashboard/static/cost.html +55 -26
- package/dashboard/static/index.html +475 -1544
- package/dashboard/static/proofs.html +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/docs/air-gapped.md +7 -2
- package/docs/image-provenance.md +4 -2
- package/docs/v10/BACKLOG.md +41 -2
- package/docs/v10/BOARD.md +105 -0
- package/docs/v10/DECISIONS.md +71 -0
- package/docs/v10/PROGRESS.md +43 -0
- package/docs/v10/SWARM-PROMPT.md +98 -0
- package/docs/v10/SWARM.md +237 -0
- package/loki-ts/dist/loki.js +2 -2
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/providers/aider.sh +8 -0
- package/providers/cline.sh +8 -0
- package/providers/codex.sh +9 -0
- package/providers/opencode.sh +9 -0
- package/web-app/dist/assets/AdminPage-CZrBkzRF.js +32 -0
- package/web-app/dist/assets/Avatar-gQIp6FBI.js +11 -0
- package/web-app/dist/assets/{Badge-BF3mhT57.js → Badge-D2_fBTFY.js} +1 -1
- package/web-app/dist/assets/{Button-BDp9aJ9q.js → Button-D5qDd2ef.js} +1 -1
- package/web-app/dist/assets/CockpitPage-DVMk2RUK.js +47 -0
- package/web-app/dist/assets/ComparePage-NMLyE1xL.js +1 -0
- package/web-app/dist/assets/{ErrorBoundary-ut3wrUmu.js → ErrorBoundary-BRABI-BT.js} +1 -1
- package/web-app/dist/assets/EvidenceReceiptPanel-D2LNKqUx.js +1 -0
- package/web-app/dist/assets/GitHubIssuesPanel-BC5GzKUN.js +7 -0
- package/web-app/dist/assets/{GitHubPRsPanel-DurZgSaj.js → GitHubPRsPanel-BSlmoVTS.js} +3 -3
- package/web-app/dist/assets/HomePage-D_CDMoen.js +12 -0
- package/web-app/dist/assets/{LoginPage-HeRGJeZy.js → LoginPage-BBNA_N9t.js} +1 -1
- package/web-app/dist/assets/{MagicPage-CUKrqsZs.js → MagicPage-CnFRZCMx.js} +1 -1
- package/web-app/dist/assets/MetricsPage-CPfLMRlh.js +6 -0
- package/web-app/dist/assets/{NotFoundPage-BZDZ-B77.js → NotFoundPage-lA0XSGTz.js} +1 -1
- package/web-app/dist/assets/ProjectPage-CNAPbr9z.js +256 -0
- package/web-app/dist/assets/ProjectsPage-CMtm8goN.js +6 -0
- package/web-app/dist/assets/SettingsPage-BhIjVMYE.js +10 -0
- package/web-app/dist/assets/{ShowcasePage-BGS2jTGH.js → ShowcasePage-BndtGeYo.js} +1 -1
- package/web-app/dist/assets/SystemSettingsPage-euXI-KXE.js +1 -0
- package/web-app/dist/assets/TeamsPage-ClUKecun.js +11 -0
- package/web-app/dist/assets/TemplatesPage-BWHWVk0L.js +29 -0
- package/web-app/dist/assets/{TerminalOutput-togzv9Zl.js → TerminalOutput-Cv3N3Szf.js} +1 -1
- package/web-app/dist/assets/{activity-Dreyb_Kr.js → activity-dEhz-bXR.js} +1 -1
- package/web-app/dist/assets/{bell-DWH0drES.js → bell-B3XUMq1t.js} +1 -1
- package/web-app/dist/assets/{bot-78MoCuDl.js → bot-X-ssNlwR.js} +1 -1
- package/web-app/dist/assets/{check-ikfylPst.js → check-C_9Nx7kb.js} +1 -1
- package/web-app/dist/assets/{chevron-left-DXUqkd8J.js → chevron-left-tvNswo3A.js} +1 -1
- package/web-app/dist/assets/{circle-alert-Da74VO8P.js → circle-alert-CSB88nEs.js} +1 -1
- package/web-app/dist/assets/{clock-mlGCFq8l.js → clock-C8p2e4NI.js} +1 -1
- package/web-app/dist/assets/{cloud-B_Y5ZrIO.js → cloud-CKp2ZvhG.js} +1 -1
- package/web-app/dist/assets/{code-xml-Bbom7YWV.js → code-xml-dY70LCHD.js} +1 -1
- package/web-app/dist/assets/{database-CLcofiVp.js → database-DObn5fmn.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-C5mkjXIM.js → dollar-sign-DSu6n3K3.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-CVrkaOQP.js → file-code-corner-DpCnS73z.js} +1 -1
- package/web-app/dist/assets/{file-plus-BV9240gX.js → file-plus-D3IPKCf1.js} +1 -1
- package/web-app/dist/assets/{globe-aZ0Zso4I.js → globe-C9QXkgH_.js} +1 -1
- package/web-app/dist/assets/{hammer-EgOQNukG.js → hammer-D_FtWe1y.js} +1 -1
- package/web-app/dist/assets/index-CI54rara.css +1 -0
- package/web-app/dist/assets/{index-DvZ0Kk2x.js → index-Cz7q1bvC.js} +2 -2
- package/web-app/dist/assets/{layers-BOVKmepE.js → layers-DsW7jnJX.js} +1 -1
- package/web-app/dist/assets/{loader-circle-0K8yLgHl.js → loader-circle-B3HspjKR.js} +1 -1
- package/web-app/dist/assets/{lock-XzlDMy8M.js → lock-DSI29pct.js} +1 -1
- package/web-app/dist/assets/{package-BtXTKusI.js → package-CLNxtA2x.js} +1 -1
- package/web-app/dist/assets/{plus-PxeiD8ju.js → plus-DyI4WC4_.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-CjqzYczt.js → refresh-cw-D2dv0xA0.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-CY0os4DH.js → rotate-ccw-CBvihA-a.js} +1 -1
- package/web-app/dist/assets/scroll-text-DvoOvAl_.js +6 -0
- package/web-app/dist/assets/{server-pIIs9vNp.js → server-DenWvSUt.js} +1 -1
- package/web-app/dist/assets/{shield-alert-CsDqKXwA.js → shield-alert-40cX_FvG.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-CAh3HVzH.js → thumbs-up-BrjZ6QuV.js} +12 -7
- package/web-app/dist/assets/trash-2-C6evwkEH.js +16 -0
- package/web-app/dist/assets/{trending-down-DrtBd_C9.js → trending-down-CfbZis3O.js} +1 -1
- package/web-app/dist/assets/{trending-up-D-DbCHXm.js → trending-up-DWuEK3WC.js} +1 -1
- package/web-app/dist/assets/{upload-D4l6DCOt.js → upload-B9DFBcPG.js} +1 -1
- package/web-app/dist/assets/{usePolling-D0aoTX80.js → usePolling-BryVC-T1.js} +1 -1
- package/web-app/dist/assets/{user-BQf_XJO_.js → user-DMRXwZiw.js} +1 -1
- package/web-app/dist/index.html +2 -2
- package/web-app/server.py +122 -47
- package/web-app/dist/assets/AdminPage-y6_b2Xo4.js +0 -32
- package/web-app/dist/assets/Avatar-BFPkXhIJ.js +0 -6
- package/web-app/dist/assets/CockpitPage-5TKICCoA.js +0 -47
- package/web-app/dist/assets/ComparePage-BSuNsUHy.js +0 -1
- package/web-app/dist/assets/EvidenceReceiptPanel-CcaBwEI-.js +0 -1
- package/web-app/dist/assets/GitHubIssuesPanel-DJeYgzAa.js +0 -12
- package/web-app/dist/assets/HomePage-Bs451LAy.js +0 -28
- package/web-app/dist/assets/MetricsPage-DvY1csgz.js +0 -6
- package/web-app/dist/assets/ProjectPage-CqHkEZkl.js +0 -257
- package/web-app/dist/assets/ProjectsPage-CLvCK1Y8.js +0 -6
- package/web-app/dist/assets/SettingsPage-DP7OmdwP.js +0 -10
- package/web-app/dist/assets/SystemSettingsPage-P_rlLh0x.js +0 -1
- package/web-app/dist/assets/TeamsPage-DxtBDcBC.js +0 -11
- package/web-app/dist/assets/TemplatesPage-5e-faH3W.js +0 -29
- package/web-app/dist/assets/folder-open-D_6yV78G.js +0 -11
- package/web-app/dist/assets/index-BSgmPwC0.css +0 -1
- package/web-app/dist/assets/lightbulb-DdASgqOG.js +0 -6
- package/web-app/dist/assets/mail-COu670_W.js +0 -6
- package/web-app/dist/assets/minus-bQpUt9ff.js +0 -6
- package/web-app/dist/assets/save-v8qep5cY.js +0 -6
- package/web-app/dist/assets/trash-2-Dt6urTyY.js +0 -6
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
var rid = esc(p.run_id);
|
|
145
145
|
var usd = (p.cost_usd !== null && p.cost_usd !== undefined) ? fmtUsd(p.cost_usd) : "";
|
|
146
146
|
var fc = (p.files_changed !== null && p.files_changed !== undefined) ? (p.files_changed + " files") : "";
|
|
147
|
-
var verdict = p.final_verdict ? '<span class="badge ' + badgeClass(p.final_verdict) + '">' + esc(p.final_verdict) + "</span>" : "";
|
|
147
|
+
var verdict = p.final_verdict ? '<span class="badge ' + badgeClass(p.final_verdict) + '" title="Recorded council vote, not a verification result">council ' + esc(p.final_verdict) + "</span>" : "";
|
|
148
148
|
var ver = p.loki_version ? ("v" + esc(p.loki_version)) : "";
|
|
149
149
|
var ts = p.generated_at ? esc(p.generated_at) : "";
|
|
150
150
|
var href = p.has_html ? ("/api/proofs/" + encodeURIComponent(p.run_id) + "/html") : ("/api/proofs/" + encodeURIComponent(p.run_id));
|
package/docs/INSTALLATION.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The flagship product of [Autonomi](https://www.autonomi.dev/). Loki Mode is a spec-driven autonomous builder with a built-in trust layer that takes any spec to a deployed product and verifies completion with evidence (quality gates plus a completion council), not just a "done" claim. Complete installation instructions for all platforms and use cases.
|
|
4
4
|
|
|
5
|
-
**Version:** v9.54.
|
|
5
|
+
**Version:** v9.54.2
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
package/docs/air-gapped.md
CHANGED
|
@@ -45,10 +45,15 @@ That is the property competitors' dashboard-bound verification cannot have.
|
|
|
45
45
|
## The one required egress, stated plainly
|
|
46
46
|
|
|
47
47
|
```sh
|
|
48
|
-
loki doctor --airgap
|
|
48
|
+
LOKI_LEGACY_BASH=1 loki doctor --airgap
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
The `LOKI_LEGACY_BASH=1` prefix is required for now: the default (Bun) route
|
|
52
|
+
does not yet accept the `--airgap` flag (tracked as
|
|
53
|
+
`P5.airgap-audit-default-route`), so plain `loki doctor --airgap` fails on a
|
|
54
|
+
default install.
|
|
55
|
+
|
|
56
|
+
Once run, it prints the egress inventory. Today it reports exactly one REQUIRED point:
|
|
52
57
|
|
|
53
58
|
```
|
|
54
59
|
REQUIRED model inference -> https://api.anthropic.com
|
package/docs/image-provenance.md
CHANGED
|
@@ -108,8 +108,10 @@ cosign initialize --mirror <your-tuf-mirror> --root <your-root.json>
|
|
|
108
108
|
```
|
|
109
109
|
|
|
110
110
|
Then transfer `loki-image-bundle/` and verify with `cosign verify --local-image
|
|
111
|
-
./loki-image-bundle`. See `loki doctor --airgap` for the
|
|
112
|
-
the engine itself needs at runtime
|
|
111
|
+
./loki-image-bundle`. See `LOKI_LEGACY_BASH=1 loki doctor --airgap` for the
|
|
112
|
+
full host inventory the engine itself needs at runtime (the default Bun route
|
|
113
|
+
does not yet accept the `--airgap` flag, tracked as
|
|
114
|
+
`P5.airgap-audit-default-route`).
|
|
113
115
|
|
|
114
116
|
## If verification fails
|
|
115
117
|
|
package/docs/v10/BACKLOG.md
CHANGED
|
@@ -47,10 +47,10 @@ Status values: todo, in progress, shipped (version), parked (reason).
|
|
|
47
47
|
|
|
48
48
|
25. **`loki ci --report` crashes on large diffs** with "Argument list too long" (`autonomy/loki:33811` passes the diff to python3 as argv; exit 126). Seen on PR #216 and a 2026-08-30 PR via the "Loki CI Quality Gate" workflow, which runs the published package. Pass the diff on stdin or a file.
|
|
49
49
|
26. **Bun Parity `doctor-json` flake:** `disk.available_gb` read 94 vs 95 between the two routes on macOS (PR #216). Normalize or drop the value in the parity comparison.
|
|
50
|
-
27. **Dashboard routes vanish on newer FastAPI:** a clean `requirements-test.txt` install resolves FastAPI 0.141.1 / Starlette 1.7.0, where `dashboard.server.app.routes` has 191 routes and zero `/api/v2` paths, against 218 and 24 on FastAPI 0.128.0 (slice Z measurement). Users installing today may get a dashboard missing its v2 API. Pin or fix.
|
|
50
|
+
27. **(Resolved in cycle 4: a measurement bug, not a product bug. FastAPI 0.141 keeps included routers as lazy entries in `app.routes`; the routes were serving all along, `app.openapi()` is identical on both versions.) Dashboard routes vanish on newer FastAPI:** a clean `requirements-test.txt` install resolves FastAPI 0.141.1 / Starlette 1.7.0, where `dashboard.server.app.routes` has 191 routes and zero `/api/v2` paths, against 218 and 24 on FastAPI 0.128.0 (slice Z measurement). Users installing today may get a dashboard missing its v2 API. Pin or fix.
|
|
51
51
|
|
|
52
52
|
28. **Moat: pending-failure fingerprints.** A pending case that starts failing for a different reason (for example its own positive control broke) stays green. Give each pending entry an expected failure reason and fail on a mismatch (council round 2).
|
|
53
|
-
29. **P7 route count depends on the host** (9 missing on macOS, 21 on Linux CI) because optional routers do not mount there; tied to item 27.
|
|
53
|
+
29. **(Resolved in cycle 4: the P7 matcher asks the app router directly and fails closed per router.) P7 route count depends on the host** (9 missing on macOS, 21 on Linux CI) because optional routers do not mount there; tied to item 27.
|
|
54
54
|
30. **P4 results need provenance.** Once the corpus exists, a hand-written per-defect outcomes file could still pass; require a verifiable receipt per outcome.
|
|
55
55
|
31. **`proof-verify.py` reads "drift unverifiable" (not a git tree, no base_sha) as 1 (tampered)**; it should be 2 (could not check). (The Bun timeout part is fixed: exits above 128 map to 2.)
|
|
56
56
|
32. **Docs tell npm users to run `doctor --airgap`** (`docs/air-gapped.md:48`, `deploy/helm/README.md:413`), which the default route rejects. Note `LOKI_LEGACY_BASH=1` until `P5.airgap-audit-default-route` is fixed.
|
|
@@ -131,6 +131,45 @@ Status values: todo, in progress, shipped (version), parked (reason).
|
|
|
131
131
|
91. **Zero-test stage events:** a zero-test run still returns 0 from `enforce_test_coverage`, so the loop emits `stage_complete test_suite pass` (~24590) although the result is inconclusive.
|
|
132
132
|
92. **Receipt path bases mix under a subdirectory `TARGET_DIR`:** tracked entries are repo-top-relative, untracked and `preexisting_modified` entries are cwd-relative.
|
|
133
133
|
|
|
134
|
+
93. **`test-hard-deadline-confinement.sh` "zero-exit leader" case is load-sensitive:** the leader waits only 0.2s for the forked child to write its PID file, so under CI load the child PID is empty and the case fails although the product behaved correctly (rc 125, no mutation). Seen once, shard 2 at `1dd799f9` (v9.54.0 release run), passed 3/3 locally and on rerun. Wait for the PID file with a bounded, generous timeout.
|
|
135
|
+
|
|
136
|
+
94. **Scope-audit tests walk `app.routes`** (`test_all_data_gets_scoped`, `test_fleet_observability`, `test_fleet_retry`, `test_memory_read_scope_auth`), so on FastAPI >= 0.141 they never see a v2 or operator route: their v2 coverage is vacuous on CI. Use the same router-matching approach as the P7 case (cycle 4, slice D).
|
|
137
|
+
95. **(Fixed: cycle 4 nulled the dashboard fleet runs/summary and project totals; the P7 sweep nulled the web-app `/api/session/status` cost and its status push through one shared `_measured_state_cost` reader.) Servers still seed unmeasured cost as 0:** `web-app/server.py` `/api/session/status` seeds `cost_usd = 0.0` (~2932) and `dashboard/registry.py` does the same, so the UI can only treat values above 0 as readings. Send null when nothing was recorded.
|
|
138
|
+
96. **(Fixed in cycle 4: gauge and health grade removed, BuildInsights nulls, scanner rules 4 and 5.) More fabrications in `ProjectWorkspace.tsx`:** `testCoverage={buildStatus.iteration > 2 ? 60 : 20}`, `gatePassRate={0.8}` (~1559) and hardcoded zeros for `filesModified`/`linesGenerated` passed to BuildInsights. The P7 sample-data scanner misses assignment-form fallbacks and unconditional fakes; widen it.
|
|
139
|
+
97. **(Fixed in the P7 sweep: `run_check` call site, `skip_check` and `_FAST_KEEP` entry "webapp admin console renders honestly" in `scripts/local-ci.sh`, and a `run_test` line in `tests/run-all-tests.sh`; the harness now also drives the Teams page.) Register `scripts/run-webapp-admin-honesty.sh`** in `scripts/local-ci.sh` (~1850) and `tests/run-all-tests.sh` (~295) next to its sibling harnesses.
|
|
140
|
+
98. **Headline vs gate listing:** the stale-results fix (82) changes the unit_tests gate listing only; the headline comes from `facts.tests`, which should get the same freshness rule. The council member vote and `_council_convergence_evidence_green` still read `pass: true` as green whatever `failed_count` says, and the Bun npm fallback still reads an exit-0 run printing "Tests: 1 failed" as passed.
|
|
141
|
+
|
|
142
|
+
99. **The commit-hygiene prompt line does not reach the main build loop for codex, cline or aider:** the bash loop calls `codex exec ... "$prompt"` directly and uses run.sh's own `invoke_cline`/`invoke_aider`; the Bun providers push the raw prompt. Only opencode gets it. The untrack commit is the real guarantee; the cycle-4 commit message overstated the wiring.
|
|
143
|
+
100. **Interrupted self-commit loses user files:** the untrack step runs only at the normal end of a session (`commit_session_changes`); an agent self-commit followed by an interrupt and a base checkout still deletes the user's files. Run the untrack check in the interrupt path and on resume.
|
|
144
|
+
101. **Nested repo gitlink stays on the tip:** an untracked `vendor/lib/` with its own `.git` that the agent's `git add -A` records as a gitlink is not matched (`vendor/lib` vs snapshot entry `vendor/lib/`); nothing is lost (checkout keeps the directory).
|
|
145
|
+
102. **`.loki/state/agent-committed-user-files.z` has no reader** outside the lifecycle test and is never cleared by a later session with no hits.
|
|
146
|
+
103. **Bash failure-count gaps:** jest "Test Suites: 1 failed" with "Tests: 2 passed" (a suite that failed to compile), and vitest "Test Files 1 failed", still read as passed (`run.sh` ~12697-12707).
|
|
147
|
+
104. **Pre-existing failing node test:** `dashboard-ui/tests/loki-overview-issue-journey.node.test.mjs` fails 5/5 at v9.54.0 and before; not registered in any runner.
|
|
148
|
+
|
|
149
|
+
105. **User-committed files on the session branch are misattributed (council S4c):** a file the user deliberately commits on the session branch between sessions is taken off the tip by the next session's untrack step and reported as "the agent committed". It stays on disk. Needs a session-end marker written at every clean session end to tell user commits from an interrupted agent's.
|
|
150
|
+
106. **Unmeasured spend in the CLI and the budget breaker:** `loki cost` (autonomy/loki) reports `budget_used = 0.0` when unmeasured (ok/0%); `check_budget_limit` writes `0.0` to `budget.json` for a run it measured nothing for; the bash and Bun breakers treat unmeasured cost as $0 and never warn. Proposed default: warn (never pause) when a cap is set and spend is unmeasured, and show unknown in the CLI.
|
|
151
|
+
107. **(Mostly fixed in the P7 sweep: rule 4 now matches the whole file, so a multi-line ternary is one prop, and `tests/e2e/webapp-admin-honesty.mjs` renders the MetricsPage budget tile against a $10 cap with no spend and asserts "Not recorded". Open: rule 4 still only knows its listed metric names.) Test coverage for two honesty surfaces:** the web-app MetricsPage "Not recorded" budget label has no committed rendering test, and P7 rule 4 (hardcoded metric props) scans one line at a time (misses multi-line ternaries and metric names outside its list).
|
|
152
|
+
|
|
153
|
+
108. **High (secret exposure, opt-in path): `LOKI_AUTO_PR=1` pushes a branch whose history still holds user files.** After the untrack step warns "do not push <branch> as-is", `create_session_pr` prints push advice and, under `LOKI_AUTO_PR=1`, pushes the branch with the user's files (for example `.env.local`) still in history. Read `.loki/state/agent-committed-user-files.z` in `create_session_pr`; when non-empty, print the `git reset --soft <fork> && git commit` cleanup first and refuse the auto-push (also gives item 102 its reader). Predates cycle 4.
|
|
154
|
+
109. **The untrack step's global `git reset -q` drops force-staged ignored agent files** (`git add -f dist/bundle.js`) from the session commit with no warning (file stays on disk). Build the untrack commit on a temporary `GIT_INDEX_FILE` and force-remove only those paths from the real index.
|
|
155
|
+
110. **A resumed session minted by an older Loki (no `session-start-sha`) whose recorded base does not resolve fails closed on every resume**, even when the agent committed nothing, and the warning tells the user to run `git rm --cached` with nothing swept. When no fork resolves, intersect HEAD's tree with the snapshot's exact entries on disk and proceed if empty.
|
|
156
|
+
111. **pytest "1 passed, 1 error" parses as failed_count 0 and passes** (only "N failed" is counted in the bd39d359 summary parser).
|
|
157
|
+
|
|
158
|
+
112. **(Partly fixed in the P7 sweep: web-app `/api/session/status` and its status push, dashboard `/api/context` with no `tracking.json`, and the timeline per-iteration token counts and model now send null; `current_run` and the budget snapshot carry a `partial` flag; pinned in P7.unmeasured-cost-never-zero's server and web-app legs, except the WebSocket status push, which shares `_measured_state_cost` and `_max_iterations_or_none` with the pinned GET but whose own payload no test drives. Open: `/metrics` `loki_cost_usd`, the `/api/cost` tracker fallback, the per-run partial flag, and the R3 design doc.) Remaining server paths that send 0 for unmeasured cost:** `web-app/server.py` `/api/session/status` (~2932, ~2956) and its status push (~6292, ~6315); dashboard `/api/context` with no `tracking.json` (~8804, ~8810); `/metrics` `loki_cost_usd` (~10048, sums with no "measured" check; Prometheus needs its own decision); the `/api/cost` tracker fallback when tokens were seen but no cost (~7914, ~7919); timeline per-iteration token counts; a fleet run with mixed priced and unpriced records has no per-run partial flag. `docs/R3-COST-OBSERVABILITY-DESIGN.md` still describes `project_total_usd` as a plain sum.
|
|
159
|
+
113. **(Fixed in cycle 4, `3a139d81`: `get_proof` adds a computed `integrity_check`; the receipt panel and audit viewer render only computed verdicts; new case P2.console-verdict-needs-computed-result.)** **Critical (moat P1/P2, not P7): two panels state a verification verdict nothing computed.** Found by the P7 sweep; a different property, so not fixed there. `web-app/src/components/EvidenceReceiptPanel.tsx` `classify()` (~43, ~50, ~70-76) labels a receipt "Proven: internally consistent with its own integrity hash" although the browser never recomputes the hash (`dashboard/server.py` `get_proof` returns the raw proof.json with no verification result), labels a receipt with NO hash the same way (`!v.hash`), and can never return "tampered". `dashboard-ui/components/loki-audit-viewer.js` prints "[VALID] ... verified" for `valid !== false`, so `dashboard/audit.py` returning `valid: True, files_checked: 0` reads as verified, and its catch (~169) turns a failed request into "[TAMPERED]". Fix: a server verify endpoint (or the `loki proof verify` result) behind the receipt label; require `valid === true && files_checked > 0`; a failed request is NOT VERIFIED, never TAMPERED.
|
|
160
|
+
114. **False empty on a failed fetch (class, P7-adjacent).** A request that fails renders the same "nothing here" copy as a real empty result. Sites: `web-app/src/components/NLSearch.tsx` (~140-143, "No results found"), `CommandPalette.tsx` (~171-173), `pages/ProjectsPage.tsx` (~65, ~166-168 ignore the poll hook's error), `ProjectWorkspace.tsx` SecretsPanel (~248-256, ~366-372) and DocsPanel (~431-442, ~589-592), the cockpit (`cockpit/useCockpitState.ts` ~119-123 swallows git status and checkpoint failures, so `ChangeReview.tsx` says "The working tree is clean", `FinalActions.tsx` "Nothing to push", `RiskPanel.tsx` "No checkpoints were recorded"), `DeployConnections.tsx` (~353-370), `CICDPanel.tsx` (unknown conclusions shown as "Failed"), `AIChatPanel.tsx` (~543, ~622 "Done." with no output); dashboard `loki-checkpoint-viewer.js` (~95-106), `loki-task-board.js` (~164-169 hides the error when local tasks exist), `loki-log-stream.js` (~152-181), `loki-council-transcripts.js` (~111-114), `loki-managed-memory-panel.js` (~138-141 ignores `data.error`), `loki-migration-dashboard.js` (~94-98), `loki-api-keys.js` (~557-558). Fix per site: keep the error and render "Could not load ..."; a scanner rule for `.catch(() => [])` followed by an empty-state string would pin the class.
|
|
161
|
+
115. **Status inference presents a guess as a state.** `web-app/server.py` `_infer_session_status` (~3603-3666) returns "completed" for a failed or paused run once its state file is five minutes old, and for any directory with a top-level source file; the cockpit then shows "Run finished" with every step ticked. `cockpit/useCockpitState.ts` (~209-218) also falls back to "completed" for unknown statuses, and (~118) shows `/api/session/checklist`, which reads the globally running project, as a historical session's gates. `ProjectWorkspace.tsx` (~1403-1412) labels REASON/REFLECT and unknown phases "building"; `PhaseVisualizer.tsx` styles earlier RARV steps as done. Fix: an explicit "unknown"/"stale" status and a per-session checklist (or none).
|
|
162
|
+
116. **Key misreads that hide or zero real data.** `web-app/src/components/GitHubPRsPanel.tsx` reads `statusCheckRollup.contexts` (~204, ~713) although gh returns an array, so failing CI shows "No status checks"; `reviewDecision || "PENDING"` (~222); uppercase gh `state` never equals `'open'` (~751), which also hides the Close button that only posts a comment yet says "PR #N closed" (~592-606); `GitHubIssuesPanel.tsx`/`GitHubPRsPanel.tsx` comment counts read a number where gh sends an array. `EvidenceReceiptPanel.tsx` (~211, ~219) reads `detail.cost_usd`/`detail.files_changed` where proof.json stores `cost.usd` and `files_changed.count`, so a measured cost reads "unknown". `loki-memory-browser.js` episodes read camelCase keys (`actionLog`, `taskId`, `phase`) where the store writes snake_case, so episode details never open and every episode is titled "Task"; `/api/memory/stats` sends `episode_count`, the panel reads `episodes_count`. `loki-overview.js` `_renderCouncilGateCard` (~394) keys on `g.status`, which `/api/council/gate` never sends (it sends `blocked`), so a blocked gate reads "Not evaluated".
|
|
163
|
+
117. **Stale or false static copy.** `WhatsNew.tsx` `CURRENT_VERSION = '6.73.1'` and `Footer.tsx` `v6.73.0` (current 9.x); `SettingsPage.tsx` says License "MIT" (the LICENSE is BUSL-1.1) and a hardcoded build date; `ComparePage.tsx` lists Gemini as supported (runtime removed v7.5.18) and "9 automated quality gates", `BenefitCards.tsx` "10 quality gates" and Gemini (the canonical count is 8); `ProductTour.tsx`, `DocsSidebar.tsx` promise Railway deploys (only Vercel, Netlify, GitHub Pages exist) and a coverage gate; `ContextualHelp.tsx`, `SettingsPage.tsx` and `CostEstimator.tsx` still list Gemini; `Roadmap.tsx` hardcodes Q2 2026 as "Current"; `ChangelogWidget.tsx` shows March 2026 tags as "Recent Changes"; `TrustedBy.tsx` asserts "Trusted by developers building the future". The P7 scanner cannot see module-level copy tables (the deleted testimonials were one); a narrow rule for invented person/company rows would close that gap.
|
|
164
|
+
118. **Fabrications the P7 sweep found and did not fix (outside its enumerated shapes or needing a design).** Per-run `cost.cost_partial` is dropped by `/api/cost/timeline` `runs[]` and `/api/proofs`, so a partly priced run shows as complete (`dashboard/static/cost.html` ~287, ~301, `proofs.html` ~145, the dashboard receipts list); `workspace_diff.py` returns count 0 when the folder is not a git repo (feeds the receipt hash, so needs care); `trust.html` says "Stable" when no axis has two data points, and `trust_trajectory.py` maps any non-PASS verdict to 0.0; `/cost` prices a record with tokens but no `cost_usd` at Sonnet rates when the model is unknown, with no "estimate" label; `loki metrics --json` (`autonomy/loki` cmd_metrics) sends `tokens.total` 0 and `agent_activity.total_iterations` 0 when nothing was recorded; server-side zero or "not blocked" sentinels the panels now render as unknown only where the client can tell: the council-state fallback `total_votes: 0` (`dashboard/server.py` ~8617), a corrupt `notifications/active.json` answered with a zero summary (~8883), a waivers read error answered 200 (~10321), a corrupt app-runner state answered `{"status":"error"}` (~11240), `prompt_optimizer.py` (~73-84) never-ran sentinel zeros, `migration_engine.py` (~770-793) 0/0 progress; the dashboard `StatusResponse` model (~594-607) defaults iteration/pending to 0 and provider/complexity to "claude"/"standard", and the skill-session WS fallback hardcodes `running_agents: 0` (~1042); `loki-analytics.js` counts days outside the returned log window as 0 activities; `CostEstimator.tsx` prices the whole iteration cap as the estimate once a real cap (e.g. 1000) is known; the web-app "Replay Build" button can never appear (`buildPhase` is "idle" whenever no build runs) and the StatusBar "Built in" line no longer receives a value; the dashboard shell has two elements with `id="budget-banner"` (`build-standalone.js` ~1200, ~1801), reverses a newest-first receipts list under a "Newest first" label (~2510), and colours "VERIFIED WITH GAPS" as success (`/^VERIFIED/`).
|
|
165
|
+
119. **(Fixed in cycle 4, `3a139d81`: `validate_token` rejects a key past `rotation_expires_at`; `cleanup_expired_rotating_keys` still has no caller.)** **High (security, found by the P7 sweep): a rotating API key past its grace period still authenticates.** `dashboard/auth.py` `validate_token` (~346-390) checks `revoked` and `expires_at` but never `rotation_expires_at`, and `dashboard/api_keys.py` `cleanup_expired_rotating_keys` (~291) has no callers. The key panel now derives "rotating" from the timestamps, which still understates it. Fix: reject in `validate_token` once `rotation_expires_at` has passed, with a test.
|
|
166
|
+
120. **Two dashboard-ui test files do not test the shipped code.** `dashboard-ui/tests/ui-components.test.js` asserts hand-copied versions of `formatGateTime`, `summarizeGates` and `formatRunDuration` that still encode the old "Never" / "pending" / growing-duration behaviour, and jest is not installed, so nothing runs it. `dashboard-ui/tests/loki-overview-issue-journey.node.test.mjs` fails 0/5 at 61af5915 and after this change (the disconnected view hides the journey since 1a871725 and the test never sets `_data.connected`); it is registered in no runner. Import the real functions or delete the copies; fix and register the journey test.
|
|
167
|
+
121. **Browser-only settings still read like live config.** `web-app/src/pages/SettingsPage.tsx` stores provider API keys in plain text in localStorage, and "Budget limit" and "Auto-deploy on success" describe effects nothing implements; each category now carries a "saved in this browser only" note, but removing or wiring them is a product decision. `DeployConnections.tsx` still starts from `{connected:false}` and, if its own fetch fails, pushes those defaults up to `DeployPanel` on the next connect or disconnect.
|
|
168
|
+
|
|
169
|
+
122. **Receipt field `first_result_verified_patch` is `True` for any first code change** (`autonomy/lib/proof-generator.py:1164`, from `first-artifact.json`), so the name claims a verification nothing ran. The overview now labels it "first code change"; rename the field additively (`first_result_kind` already carries the kind) or set it only from a verified result.
|
|
170
|
+
123. **More verdict-class leftovers from the 113 sweep:** the `audit.py verify` CLI and `compute_chain_tip_in_dir` still report valid, exit 0, when nothing was checked (the cross-chain verifier reads them, so changing them needs its own review); the cockpit, overview, checklist, gate-card, standalone, proofs.html and cost.html verdict relabels have no test of their own (only the receipt and audit surfaces are pinned by the moat case); the standalone receipt list shows the oldest receipts first (see 118).
|
|
171
|
+
124. **Dashboard innerHTML audit:** the standalone receipt and learning panels interpolated run-written text into innerHTML unescaped (fixed in cycle 4, `f6050ef1`, with hostile-input tests). No systematic audit of the other `innerHTML` sites in `dashboard-ui/components` and `build-standalone.js` has been done; add a guard that flags a template literal or string concatenation of a response field into innerHTML without an escape.
|
|
172
|
+
|
|
134
173
|
## Later milestones
|
|
135
174
|
|
|
136
175
|
M1 one command, M2 Seal and Wall, M3 assign like a teammate, M4 system map, M5 the line, M6 ship and operate, M7 one screen, M8 legacy lane, M9 enterprise readiness, M10 simplify and ship v10.0.0. Items get broken out here when their milestone comes up.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Board
|
|
2
|
+
|
|
3
|
+
Written only by the Product Owner and the Release Captain. One row per
|
|
4
|
+
slice. Status values: `ready`, `building`, `review`, `review-blocked`,
|
|
5
|
+
`approved`, `merging`, `released`, `parked`. See `docs/v10/SWARM.md`.
|
|
6
|
+
|
|
7
|
+
## Grandfathered slices (in flight before the swarm existed)
|
|
8
|
+
|
|
9
|
+
These were built and reviewed under the cycle process, not cut by the PO.
|
|
10
|
+
They enter the Captain's merge queue as-is, each reviewed at HIGH tier before
|
|
11
|
+
merge (all touch trust-core or security-relevant surfaces), oldest first.
|
|
12
|
+
|
|
13
|
+
| ID | Owner | Branch @ SHA | File set (summary) | Tier | Status | Notes |
|
|
14
|
+
|---|---|---|---|---|---|---|
|
|
15
|
+
| GF-1 | cycle-4 (main) | main @ 779c50e5 (v9.54.1) | cycle 4 + verdict fix + XSS fix + pkill-scoping fix (D15/D16/D17, RELEASED) + D8-D17 | HIGH | review-blocked | PF-2 (P7 scanner gap fix) finished at ecfd9578, ready for review. Full council re-run required once merged (D12). PF-1 shipped separately as v9.54.1, ahead of GF-1. |
|
|
16
|
+
| GF-2 | P5 slice | worktree-agent-a2ff5f2304261e820 @ 7e5e303a | providers/loader.sh, autonomy/loki, bin/loki, docs/air-gapped.md, docs/enterprise/*, README.md, tests/moat/p5-*.sh, tests/test-doctor-json-sentrux.sh | HIGH | review | P5 PROVEN in worktree (9/9 cases). Not yet reviewed. Rebase onto GF-1's SHA before review. |
|
|
17
|
+
| GF-3 | P9 slice | worktree-agent-a706097c126bd997f @ 7a92f848 | .github/workflows/*.yml, .github/actions/issue-to-pr, autonomy/run.sh (github_token wrap), loki-ts/src/runner/github_token.ts, tests/moat/p9-rule-of-two.sh | HIGH | review | P9 PROVEN in worktree (4/4 cases). Needs a validation PR (auto-merge OFF; see SWARM.md Captain step 6) BEFORE counting P9 proven on main, per the workflow-YAML-is-untested-locally rule. Ship alone (touches release.yml). |
|
|
18
|
+
| GF-4 | P4 slice | worktree-agent-ab9323b385483298c @ 2282ff20 | providers/model_catalog.json, loki-ts/src/commands/start.ts, loki-ts/src/runner/providers.ts | MEDIUM | review | 2 of 4 P4 cases promoted (catalog, three-setups). Needs D10 recorded before merge (done, D10 is in DECISIONS.md). Rebase onto GF-1. |
|
|
19
|
+
| GF-5 | verdict/security fix | worktree-agent-a9b8124e8cfc6809a @ 399e1f3a | web-app/src/components/EvidenceReceiptPanel.tsx, dashboard-ui/components/loki-audit-viewer.js, dashboard/audit.py, dashboard/server.py (get_proof), dashboard/auth.py | HIGH | merged | Cherry-picked onto main as 3a139d81 (GF-1 now includes it). This row is historical; do not re-review separately. |
|
|
20
|
+
|
|
21
|
+
## Priority out-of-band fix (severity: kills unrelated user sessions)
|
|
22
|
+
|
|
23
|
+
| ID | Owner | Branch @ SHA | File set | Tier | Status | Notes |
|
|
24
|
+
|---|---|---|---|---|---|---|
|
|
25
|
+
| PF-1 | pkill-scoping fix | main @ 9cd51d1a | autonomy/run.sh (kill_provider_child), tests/test-kill-provider-child-scoping.sh, docs/v10/DECISIONS.md (D15) | HIGH | review | Founder-reported: every loki-mode session ending via signal (supervisor signal, double Ctrl+C, Ctrl+C in perpetual mode) ran an unscoped `pkill -f` matching ANY process on the machine by command-line substring, terminating unrelated Claude Code sessions. Fixed to scope by process group. Dedicated HIGH-tier council launched (4 lenses, all models pinned). Ships as its own patch release ahead of the swarm queue once approved. |
|
|
26
|
+
| PF-2 | P7 scanner gap fix | worktree-agent-a13474d006e084e33 @ ecfd9578 | tests/moat/p7-no-fabricated-data.sh | HIGH | review | Fixed the ||/??/ternary/Array.of gap; dedicated 4-lens council running (adversarial + deviation + ceiling audits). |
|
|
27
|
+
|
|
28
|
+
## Fixed on main already (not slices; recorded for PO context)
|
|
29
|
+
|
|
30
|
+
- BACKLOG 95, 97: fixed (cycle 4 + P7 sweep).
|
|
31
|
+
- BACKLOG 96, 98: partly fixed by the P7 sweep (0afb6e2c); remaining pieces
|
|
32
|
+
are BACKLOG 112, 118.
|
|
33
|
+
- BACKLOG 113, 119: fixed (3a139d81, in GF-1).
|
|
34
|
+
- XSS in receipt/learnings panels: fixed (f6050ef1, in GF-1).
|
|
35
|
+
|
|
36
|
+
## Ready queue (PO-cut)
|
|
37
|
+
|
|
38
|
+
Cut against BACKLOG items not already owned by an in-flight slice (PF-1, PF-2,
|
|
39
|
+
GF-2 P5, GF-3 P9, GF-4 P4, the repo-wide kill-scan agent). Each slice's file
|
|
40
|
+
set is declared to avoid overlap with those and with each other.
|
|
41
|
+
|
|
42
|
+
| ID | Owner | File set | Tier | Acceptance checks (Wall) | Status |
|
|
43
|
+
|---|---|---|---|---|---|
|
|
44
|
+
| S-01 | BACKLOG 22: orphaned `sleep 300` resource monitor | autonomy/run.sh (resource-monitor spawn/cleanup only, not kill_provider_child), one new test | MEDIUM | red: `loki start` then interrupt leaves a `sleep 300` orphan (ps shows it after exit); green: it is reaped or never orphaned, by PID recorded at spawn | merged (027ec085, local; approved unanimous) |
|
|
45
|
+
| S-02 | BACKLOG 23: client-route test hardcodes main checkout path | tests/lib-extract-client-paths.mjs, tests/lib-match-client-routes.py, tests/test-verify-client-routes.sh | LOW | red: run from a worktree, test checks the wrong tree (provably, by diffing what it scanned vs cwd); green: it resolves its own repo root dynamically | building |
|
|
46
|
+
| S-03 | BACKLOG 25: `loki ci --report` "Argument list too long" on a large diff | autonomy/loki (cmd_ci report path only), one new test | MEDIUM | red: a synthetic diff over the ARG_MAX threshold, exit 126; green: same diff passed via stdin/file, exit 0 | rejected -- real crash site (export-based ARG_MAX) misdiagnosed and left unfixed; sent back to builder |
|
|
47
|
+
| S-04 | BACKLOG 26: Bun Parity `doctor-json` flake (disk.available_gb 94 vs 95) | loki-ts/src (doctor json output only), tests/test-bun-parity or the parity comparison script | LOW | red: two consecutive doctor --json calls disagree on disk.available_gb and the parity check flags it; green: normalized (rounded/bucketed) or excluded from strict comparison, documented why | ready |
|
|
48
|
+
| S-05 | BACKLOG 31: `proof-verify.py` "drift unverifiable" reads 1 (tampered) instead of 2 (could not check) | autonomy/lib/proof-verify.py, its test | MEDIUM | red: verify a proof outside a git tree (or with no base_sha) and get exit 1; green: exit 2, message says "could not check drift" not "tampered" | ready |
|
|
49
|
+
| S-06 | BACKLOG 32: docs tell npm users to run `doctor --airgap`, which the default (Bun) route rejects | docs/air-gapped.md, deploy/helm/README.md | LOW | the doc now says `LOKI_LEGACY_BASH=1 loki doctor --airgap` (or notes the Bun-route gap) until P5.airgap-audit-default-route ships; grep confirms the old bare command is gone from both files | released (v9.54.1, in progress -- required-ci gate re-run needed after Tests finished mid-check) |
|
|
50
|
+
| S-07 | BACKLOG 33: council `runner=none` counts as a positive signal, a zero-test suite does not -- pick one rule | autonomy/completion-council.sh (the specific vote-reading site only), its test | MEDIUM | red: a case where `runner=none` passes and a real zero-test run does not, despite being equally uninformative; green: both read the same way, decision recorded in DECISIONS.md | ready |
|
|
51
|
+
| S-08 | BACKLOG 39: attestation edge labels (`{"keys": []}` reads FAILED not NOT CHECKED; `attestation: false` inconsistent local vs remote) | autonomy/receipt_jwt.py or the relevant attestation renderer, its test | MEDIUM | red: an empty keyset and a false-attestation receipt each render a misleading label on one route; green: both read NOT CHECKED consistently on both routes | ready |
|
|
52
|
+
| S-09 | BACKLOG 40: `P3.implementer-prompt-has-no-check-authoring` is phrase-based only | tests/moat/p3-*.sh (add a behavioral assertion; do not weaken the existing phrase check) | MEDIUM | new assertion: the implementer session does not actually write to the checklist file, not just that a phrase is absent from the prompt; red on a synthetic prompt that omits the phrase but still authors checks, green once caught | ready |
|
|
53
|
+
| S-10 | BACKLOG 41: `P1.different-tree-fails` lacks an in-script no-edit control | tests/moat/p1-*.sh | LOW | add the control described (an unedited copy verifies 0 / clean); case still passes, control documented inline | building |
|
|
54
|
+
| S-11 | BACKLOG 42: `doctor --airgap` "local" is a loose substring match, ignores remote `OLLAMA_HOST` | autonomy/loki (airgap audit only) or loki-ts doctor.ts, its test | MEDIUM | red: `OLLAMA_HOST=https://remote.example.com` still reads as local because the string contains "ollama"; green: a remote OLLAMA_HOST counts as required egress | ready |
|
|
55
|
+
| S-12 | BACKLOG 46: P2 advisory-only case's positive control differs from the probe in two variables | tests/moat/p2-*.sh | LOW | control now uses an exogenous gate with no tests, matching the probe's other variable exactly; case still passes | merged (0a59f420, local; awaiting release-workflow window to push) |
|
|
56
|
+
| S-13 | BACKLOG 48: same-class D7 hardening -- `loki outcomes canary verify`, `proof share`/`show` heredocs, empty PATH component | autonomy/loki (the specific inline python3 sites named), its test | MEDIUM | red: a committed gpg/git/python3 shim on an empty PATH component or importable cwd answers one of these commands; green: python3 -E plus PATH scrubbing closes it, matching the D7 pattern exactly | ready |
|
|
57
|
+
| S-14 | BACKLOG 49: verifier stdout still says `ok: true` on ABSENT/NOT CHECKED while exit is 1/2 | autonomy/lib/proof-verify.py (or the relevant verifier), its test | MEDIUM | red: stdout JSON says ok:true for an ABSENT/NOT CHECKED result although exit code disagrees; green: the JSON verdict field matches the exit code exactly | ready |
|
|
58
|
+
| S-15 | BACKLOG 50: remote NOT CHECKED returns 0, local returns 2 -- align or document | the remote verifier path, docs/exit-codes.md | LOW | either the remote exit is changed to 2 with a test proving it, or docs/exit-codes.md documents the divergence explicitly with the reason; pick one and record which in the commit message | review-pending (finished, ready to review) |
|
|
59
|
+
| S-16 | BACKLOG 22 follow-on / housekeeping: `scripts/release.sh` only bumps 3 of the 14 files CLAUDE.md's release checklist requires (VERSION, package.json, vscode-extension/package.json) | scripts/release.sh | MEDIUM | red: run --dry-run on a version bump, diff shows SKILL.md/Dockerfile/Dockerfile.sandbox/plugin.json/server.json/dashboard __init__.py/mcp __init__.py untouched; green: the script bumps all 14 files CLAUDE.md's Release Workflow section 1 lists, or the script explicitly documents which it intentionally leaves to the Captain and why | building |
|
|
60
|
+
|
|
61
|
+
Every slice above: implement with red-then-green tests, run diff-scoped tests
|
|
62
|
+
plus `bash tests/moat/run.sh` in your own worktree, never touch `main`,
|
|
63
|
+
`VERSION`, or a hot file/bundle (see below), and return BLOCKED (never guess
|
|
64
|
+
past your declared file set) if you need a file outside it. `git merge
|
|
65
|
+
--ff-only <captain's current main sha>` first; worktrees are cut from
|
|
66
|
+
origin/main. No version bumps, no emojis, no em or en dashes, bash 3.2
|
|
67
|
+
compatible, shellcheck clean at CI flags on changed .sh files. Stage by
|
|
68
|
+
name, conventional commit message, no Co-Authored-By, end with the line:
|
|
69
|
+
Claude-Session: https://claude.ai/code/session_019U6NAdpZyYeCEKzvHfZ4Tq. Do
|
|
70
|
+
not push.
|
|
71
|
+
|
|
72
|
+
## Hot files (Captain-owned; no builder file set may include these)
|
|
73
|
+
|
|
74
|
+
`tests/moat/cases.txt`, `tests/moat/pending.txt`, `CHANGELOG.md`,
|
|
75
|
+
`docs/v10/BACKLOG.md`, `docs/v10/BOARD.md`, `docs/v10/PROGRESS.md`,
|
|
76
|
+
`docs/v10/METRICS.md`, `scripts/local-ci.sh`, `tests/run-all-tests.sh`,
|
|
77
|
+
`VERSION`, `package.json`, `SKILL.md`, `Dockerfile`, `Dockerfile.sandbox`,
|
|
78
|
+
`plugins/loki-mode/.claude-plugin/plugin.json`, `server.json`,
|
|
79
|
+
`dashboard/__init__.py`, `mcp/__init__.py`, `CLAUDE.md`.
|
|
80
|
+
|
|
81
|
+
## Generated bundles (Captain rebuilds after every merge touching sources)
|
|
82
|
+
|
|
83
|
+
`loki-ts/dist/loki.js`, `dashboard/static/index.html`, `dashboard-ui/dist/*`,
|
|
84
|
+
`web-app/dist/*`.
|
|
85
|
+
|
|
86
|
+
## Wave log
|
|
87
|
+
|
|
88
|
+
Appended by the Captain after each wave closes. See METRICS.md for the
|
|
89
|
+
numeric rollup.
|
|
90
|
+
|
|
91
|
+
- **Wave 0 (setup, 2026-09-26):** SWARM.md and BOARD.md written. Council
|
|
92
|
+
round 4 (pre-swarm, cycle-4-only) killed mid-run: two of three lenses had
|
|
93
|
+
no pinned model and the session model changed under it (D13). Stray
|
|
94
|
+
worktrees `agent-a8fad9a6e301fe297` (old, pre-v10, already merged) and a
|
|
95
|
+
scratch `mutwt` checkout (0 commits ahead of main) removed; four real
|
|
96
|
+
in-flight worktrees (GF-2, GF-3, GF-4, GF-5) recorded above. GF-5
|
|
97
|
+
cherry-picked into main directly (it was a small, already-approved fix,
|
|
98
|
+
not a swarm-cut slice) plus a same-session XSS fix and D8-D13. No release
|
|
99
|
+
cut yet this wave.
|
|
100
|
+
|
|
101
|
+
## PF-3: repo-wide kill-by-name scan (severity: same class as PF-1/D14, found in shipped surfaces)
|
|
102
|
+
|
|
103
|
+
| ID | Owner | Branch | File set | Tier | Status | Notes |
|
|
104
|
+
|---|---|---|---|---|---|---|
|
|
105
|
+
| PF-3 | kill-scan sweep | worktree-agent-adbba28e01561483c (in rework) | autonomy/loki (cmd_web_stop, cmd_web_start), autonomy/verify.sh, .github/actions/.../action.yml (approved, keep), dashboard harness scripts (approved, keep), scripts/cleanup-test-processes.sh (approved, keep), test-hardening fixes | HIGH | review-blocked | REJECTED 3/4 (1 CONCERN): cmd_web_stop's added 'identity check' re-tests the same substring pgrep already matched, vacuous; the unfiltered SIGKILL loop bypasses even that. Reproduced: an unrelated project's dashboard gets killed. Sibling instances found in cmd_web_start and verify.sh's runtime teardown (unscoped lsof-ti port kills), plus 2 test-cleanup regressions the sweep itself missed. Sent back with full findings; action.yml/harness/cleanup-script fixes independently verified safe, keep those. |
|
package/docs/v10/DECISIONS.md
CHANGED
|
@@ -50,3 +50,74 @@ One entry per decision: context, choice, why, how to reverse. Newest last.
|
|
|
50
50
|
- Choice: every Python invocation on a verify path runs `python3 -E`: `proof verify` (bash and Bun), the remote and deploy verifiers, `proof passport`, `proof chain`, and each chain stage that `tools/verify-chain.py` spawns (a council round 8 finding: the stages had inherited `PYTHONPATH`). The inline heredocs also drop `''` and `'.'` from `sys.path` first. Running `tools/verify-chain.py` directly without `-E` is outside this guarantee for the parent process (its stages are still protected); `loki proof chain` is the covered entry point. `-I` was rejected: it drops the user site, so a user-site `cryptography` would degrade every check to NOT CHECKED.
|
|
51
51
|
- Why: an in-script guard cannot stop code that runs during interpreter start-up; `-E` ignores `PYTHON*` variables, so the environment cannot re-add the cwd.
|
|
52
52
|
- Reverse: remove `-E` from those calls (tests in `tests/test-proof-verify-jwks.sh` section 13 go red).
|
|
53
|
+
|
|
54
|
+
## D8. 2026-09-26: removing a console control that did nothing is not a breaking change
|
|
55
|
+
|
|
56
|
+
- Context: the cycle-4 P7 sweep found console controls whose effect was never stored or sent: team remove-member and change-role, the RBAC role editor, team sharing checkboxes, settings Save buttons, "Test Connection", a fake QR code, a newsletter signup, invented testimonials.
|
|
57
|
+
- Choice: remove them (or relabel them as browser-only) in a v9.x minor. A control that had no effect is a fabrication, not a feature a user depends on.
|
|
58
|
+
- Why: moat property P7. Before v10.0.0 releases are additive, and deleting something that never worked adds honesty without taking away a capability.
|
|
59
|
+
- Reverse: restore from `0afb6e2c^`, wired to a real endpoint.
|
|
60
|
+
|
|
61
|
+
## D9. 2026-09-26: a security or sovereignty default may tighten in a v9.x minor only with an opt-out that restores the old behavior and is itself reported
|
|
62
|
+
|
|
63
|
+
- Context: cycle 5 found two defaults that send data or power where the user did not choose: engine side steps sent prompts to the claude CLI when another provider was selected (P5), and the provider process inherited GH_TOKEN/GITHUB_TOKEN (P9).
|
|
64
|
+
- Choice: tighten the default now. `LOKI_ALLOW_CLAUDE_SIDECALLS=1` restores claude side steps (and `doctor --airgap` reports it as required egress); `LOKI_ALLOW_AGENT_GITHUB_TOKEN=1` restores the token to the agent (and `loki start` warns). The exact value `1` is required.
|
|
65
|
+
- Why: the vision's P5 says data leaves only to endpoints the user chooses; P9 says untrusted text never shares a step with the power to push. The opt-out keeps every v9.x minor additive for a user who relied on the old behavior.
|
|
66
|
+
- Reverse: default the two variables to `1`.
|
|
67
|
+
|
|
68
|
+
## D10. 2026-09-26: keep sonnet defaults; top, floor and routed are opt-in spellings until v10.0.0
|
|
69
|
+
|
|
70
|
+
- Context: since v7.104.0 every Claude tier defaults to sonnet, so `high` and `small` dispatch sonnet on both routes. The Bun route rejected `--session-model opus` and ignored `LOKI_CLAUDE_MODEL_*`. `docs/environment-variables.md` still says high is an Opus model.
|
|
71
|
+
- Choice: add `claude-opus-5-5` to the catalog (confirmed by a real CLI call) and make top, floor and routed reachable on both routes through the existing opt-in spellings (`--session-model opus`, `small` with `--allow-haiku`, `LOKI_CLAUDE_MODEL_*`). Defaults do not change.
|
|
72
|
+
- Why: before v10.0.0 releases are additive, and changing what `high` or `small` dispatches changes every existing user's cost. The docs contradict each other, so this is not simply a documented-behavior bug.
|
|
73
|
+
- Reverse: remove the alias values from `VALID_TIERS` in `loki-ts/src/commands/start.ts` and the opus-pin branch in `claudeModelFor`. At v10.0.0, decide whether `high`/`small` dispatch the catalog tier model.
|
|
74
|
+
|
|
75
|
+
## D11. 2026-09-26: the @claude bot workflow is deleted; the issue composite is agent-only
|
|
76
|
+
|
|
77
|
+
- Context: `.github/workflows/claude.yml` fed the whole issue or PR thread, including outsiders' text, to an agent holding an app token that can push; an author gate on the trigger does not remove the untrusted thread. The issue-to-pr composite action combined the agent and the push.
|
|
78
|
+
- Choice: delete `claude.yml` (repo-internal, last successful run February 2026). Split `loki-issue-to-pr.yml` into an agent job (read-only token, no persisted credential) and a publish job (write token, no agent); the composite runs only the agent and refuses a persisted push token.
|
|
79
|
+
- Why: moat property P9. Copied workflows pin a version tag, so existing users are unaffected until they re-pin; re-pinning without re-copying fails closed with a clear message.
|
|
80
|
+
- Reverse: `git revert` the deletion; restore the PR step in `.github/actions/issue-to-pr`.
|
|
81
|
+
|
|
82
|
+
## D12. 2026-09-26: council review needs unanimous APPROVE; a vote count never overrides a reproduced blocking finding
|
|
83
|
+
|
|
84
|
+
- Context: a swarm proposal for cycle 5 onward would have scored HIGH-tier review as "3 of 4 approve" and let one CONCERN with a reproduction be outvoted. CLAUDE.md's SDLC fleet pattern requires unanimous APPROVE and a full council re-run on any CONCERN or REJECT. Cycle-4 round 3 was itself APPROVE, APPROVE, CONCERN, and the concern (a false PROVEN on P7) was real; a 2-of-3 or 3-of-4 count would have shipped it.
|
|
85
|
+
- Choice: every review round still needs unanimous APPROVE. A HIGH-tier round may add a fourth adversarial reviewer for extra recall, but any reviewer's blocking finding with a working reproduction blocks the slice regardless of how many others voted APPROVE, and the whole council re-runs after a fix. A vote count only ever settles dissent that comes with no reproduction, and even then the default is to re-run, not to override.
|
|
86
|
+
- Why: moat property P2 and the honest-verdict discipline generally. A reviewer count is exactly the kind of aggregate "looks good" the moat exists to refuse; three agreeing votes are not evidence against one reproduced defect.
|
|
87
|
+
- Reverse: adopt a quorum threshold for HIGH-tier review and drop the mandatory full re-run after a CONCERN.
|
|
88
|
+
|
|
89
|
+
## D13. 2026-09-26: every council or review agent pins its model explicitly
|
|
90
|
+
|
|
91
|
+
- Context: cycle-4 council round 4 was launched with two of three lenses left to inherit the session model. The session model changed mid-conversation (Opus 5.5 to Sonnet 5) between launching the workflow and its lenses resolving, so a round meant to run 2 Opus + 1 Sonnet in fact ran 3 Sonnet-5 lenses. It was killed before completing and re-run correctly.
|
|
92
|
+
- Choice: every council, review or HIGH-tier agent call sets `model` explicitly in the workflow script. None inherit the session model. Composition (for example "2 Opus + 1 Sonnet") is enforced by the script, not assumed from context.
|
|
93
|
+
- Why: an unpinned model silently changes what was reviewed by what, and a session model change is invisible to a running workflow unless it is checked.
|
|
94
|
+
- Reverse: drop the explicit `model` fields and rely on a documented session-model convention instead.
|
|
95
|
+
|
|
96
|
+
## D14. 2026-09-26: root-caused three session terminations to an unscoped pkill -f in a test
|
|
97
|
+
|
|
98
|
+
- Context: this session's CLI process terminated cleanly (no crash report, no OOM/jetsam entry, no logged kill signal) three times in about 25 minutes, each time 2-4 minutes into a 4-agent HIGH-tier council review running tests against the main checkout. `tests/test-backend-floor.sh:43` ran `pkill -f "index.mjs"` with no path or PID scoping. Reproduced directly: a decoy process started with an unrelated "index.mjs" substring in its argv was killed by that line. In a shared process namespace (concurrent worktree agents, workflow subagents, the harness's own process tree), this can kill any process whose command line happens to contain that substring, including, plausibly, the session's own process or a concurrent agent's.
|
|
99
|
+
- Choice: fixed to find the PID actually listening on the target port via `lsof -ti tcp:<port> -sTCP:LISTEN` and kill only that PID (`61547203`). The already-scoped trap-line pkill on the unique mktemp path was left unchanged.
|
|
100
|
+
- Why: this is exactly the pattern global CLAUDE.md's cleanup rules and `docs/v10/SWARM.md`'s guardrails already ban (never kill by name or pattern, only by a PID you recorded), and it is the first concrete, reproduced explanation for an otherwise-unexplained class of session death.
|
|
101
|
+
- Reverse: revert `61547203`. Not recommended; the decoy reproduction is on record above and in the commit message.
|
|
102
|
+
|
|
103
|
+
## D15. 2026-09-26: kill_provider_child scoped to this run's own process group
|
|
104
|
+
|
|
105
|
+
- Context: user report, reproduced directly: every time a loki-mode session ended via a signal path (a supervisor signal, double Ctrl+C, a single Ctrl+C in perpetual/autonomous mode, or general interrupted-session cleanup), `kill_provider_child()` in `autonomy/run.sh` ran `pkill -f "^${proc}( |$)"` for proc in claude/codex/aider/cline with no scoping to a PID, process group, or working directory. `pkill -f` matches the full command line of every process on the machine, so this killed unrelated Claude Code sessions in other terminals and other projects the instant any loki-mode run ended that way, not just the one that was ending. Confirmed with a decoy process sharing no relationship to the run except the matching command-line substring.
|
|
106
|
+
- Choice: scope the reparented-leaf sweep to processes sharing this run's own process group id (a reparented process keeps its process group unless it explicitly calls setpgid/setsid, so this still catches the intended cleanup target). Fixed in the same change as a new regression test, `tests/test-kill-provider-child-scoping.sh`, that proves both directions: a same-process-group leak is still cleaned up, and a different-process-group "unrelated session" decoy survives.
|
|
107
|
+
- Why: this is a severe, live defect in the shipped product, not a test-only issue (see also D14, which found the sibling bug in a test script). It directly contradicts the moat's P9 (Rule of Two / safe by construction) spirit even though it is not one of P9's enumerated cases: a completing session should never be able to reach outside its own boundary and terminate another user's unrelated work.
|
|
108
|
+
- Why this ships ahead of the swarm queue: reported by the founder as actively recurring and affecting real, concurrent sessions right now. Treated as the single highest-priority fix, landed and reviewed on its own rather than batched into cycle 4 or a PO-cut slice.
|
|
109
|
+
- Reverse: revert to the bare `pkill -f "^${proc}( |$)"` sweep. Not recommended; this is confirmed to kill unrelated sessions.
|
|
110
|
+
|
|
111
|
+
## D16. 2026-09-26: a test can reintroduce the exact bug it guards against; verify the test's own kill/decoy logic as strictly as the fix
|
|
112
|
+
|
|
113
|
+
- Context: the first version of `tests/test-kill-provider-child-scoping.sh` (committed alongside the D15 fix) picked its "unrelated other session" decoy with `pgrep -f 'claude --dangerously-skip-permissions --continue' | tail -1` -- the literal argv of a real Claude Code session -- and unconditionally `kill -9`'d whatever PID that returned, with no verification it was the decoy the test itself launched. A 4-reviewer HIGH-tier council (all 4 flagged it, one REJECT) reproduced that on a PID-wrapped machine `tail -1` would select the live review session instead of the decoy. Separately, its "reparented leaf in this run's own process group" decoy was a direct child of a bash subprocess never in the same process group as the one that later called `kill_provider_child`, so that assertion never exercised the fix at all. A further, real bug surfaced while fixing this: `setsid()` changes a process's own session and process group but never its PPID, so a plain `setsid ... &` (no enclosing subshell) stays a `pgrep -P $$` direct child for as long as the launching shell lives, making it collateral of `kill_provider_child`'s separate SIGKILL-escalation pass regardless of the pgid fix.
|
|
114
|
+
- Choice: every decoy now records its own PID by writing it to a file immediately after `setsid`, uses a unique per-run token in its argv (never a real CLI invocation string), and is launched inside a subshell that exits immediately so it becomes a genuine grandchild-orphan (ppid=1) invisible to any `pgrep -P $$` pass, whichever pgid it ends up in. Each decoy's setup is asserted explicitly (ppid, pgid, not-a-direct-child) before the real cleanup assertion runs, so the test cannot go vacuous silently again.
|
|
115
|
+
- Why: a test whose own fixture logic reproduces the bug class under review is worse than no test, because it reads as a passing regression guard while remaining capable of the exact harm it exists to prevent. This generalizes past this one file: any test that kills, matches, or selects a live process by name or pattern must be reviewed at the same severity as product code that does the same thing.
|
|
116
|
+
- Reverse: none; the corrected test is strictly more conservative than the one it replaces.
|
|
117
|
+
|
|
118
|
+
## D17. 2026-09-26: the kill_provider_child regression test isolates itself into its own process group
|
|
119
|
+
|
|
120
|
+
- Context: round 2 of PF-1's council (3 APPROVE, 1 CONCERN with a reproduced blocking finding) found a fifth instance of the same bug class, this time in the test's own isolation rather than its decoy-selection logic (D16): once the decoys were fixed, the test still calls the REAL kill_provider_child in whatever process group it happens to inherit from its caller. That function's pgid sweep signals every claude/codex/aider/cline process sharing the CALLER's pgid, so a process the test never launched and never recorded (a sibling test-runner lane that does not detach its subprocesses, a CI step that backgrounds a provider before the suite runs, an agent harness with no job control) is exposed to it. Reproduced: an unrelated decoy sharing the test-runner shell's own pgid was terminated even though the test reported 6/6 pass.
|
|
121
|
+
- Choice: the test relaunches itself into a fresh session (fork, then setsid, then exec) as its very first action, before sourcing the function under test, so the only processes ever in its process group are its own. Also added a tripwire: pkill/killall are shadowed to log-and-fail rather than execute, so a future regression that reintroduces a bare pkill inside kill_provider_child fails the test loudly instead of depending on what happens to be running in the test's process group at that moment.
|
|
122
|
+
- Why: a test that calls the real function under test can be exposed to exactly the hazard that function exists to avoid, if the test itself is not equally isolated. This generalizes past this one file: any test that exercises a process-signaling function must isolate its own process group first, not just sanitize its fixtures.
|
|
123
|
+
- Reverse: remove the self-relaunch block and the tripwire shadows. Not recommended; both are reproduced, real protections with no behavioral cost to the test's own assertions.
|
package/docs/v10/PROGRESS.md
CHANGED
|
@@ -48,6 +48,13 @@
|
|
|
48
48
|
- Released as v9.54.0.
|
|
49
49
|
- Open items the slices found: BACKLOG 61-65.
|
|
50
50
|
|
|
51
|
+
### Cycle 4 (2026-09-26)
|
|
52
|
+
|
|
53
|
+
- v9.54.0 release: required-ci failed once on a load-sensitive test case (BACKLOG 93; product behaved correctly), passed on rerun; full Release rerun published npm (gitHead `1dd799f9`), tag and GitHub release; Docker/Homebrew in progress at the time of writing.
|
|
54
|
+
- Dev fleet (4 worktree slices): session commit never sweeps or loses a user file (BACKLOG 90 branch protection off, 85 test-gate bytecode, 74 agent self-commits); exit 0 with failures, failed_count and stale results never a pass (73, 81, 82, 89, 91); no fabricated console data and unmeasured cost never zero (P7 part 1); every console panel call reaches a real route on every FastAPI (P7 part 2; BACKLOG 27 and 29 were measurement bugs; six orphan demo-data components deleted).
|
|
55
|
+
- **Moat: 2 of 9 proven (P6, P7)**; 57 registered, 38 pass, 19 pending; ratchet against v9.52.0, v9.53.0, v9.54.0.
|
|
56
|
+
- Open items the slices found: BACKLOG 94-98.
|
|
57
|
+
|
|
51
58
|
## Next (after cycle 3)
|
|
52
59
|
|
|
53
60
|
1. BACKLOG 90 (branch-protection-off stale snapshot: data risk), then 74 (agent self-commits bypass the snapshot), 85 (test-gate `__pycache__`), 73 (exit-0 runs with failures).
|
|
@@ -64,3 +71,39 @@
|
|
|
64
71
|
|
|
65
72
|
1. Cycle 2: BACKLOG 15 (untracked files swept into the session commit: data risk), 37 (Bun passes an inconclusive test result) and 43 (inline Python on council verdict paths importable from the agent repo): honest-verdict and data-risk items first.
|
|
66
73
|
2. Then P7 (no fabricated data) and P9 (Rule of Two), the moat gaps with the smallest fix, and M0 measurement (catalog + seeded-defect corpus).
|
|
74
|
+
|
|
75
|
+
## Session interrupted and recovered (2026-09-26)
|
|
76
|
+
|
|
77
|
+
The CLI process terminated unexpectedly three times between 11:26 and 11:50
|
|
78
|
+
EDT, each time while a HIGH-tier council review (4 parallel agents) was
|
|
79
|
+
running against the main checkout. Root cause found and fixed: `D14`,
|
|
80
|
+
`61547203`. `tests/test-backend-floor.sh` used `pkill -f "index.mjs"` with no
|
|
81
|
+
scoping, which kills any process on the machine whose argv contains that
|
|
82
|
+
substring; in a shared process namespace with concurrent worktree agents and
|
|
83
|
+
the harness's own process tree, this could hit an unrelated process,
|
|
84
|
+
including plausibly this session itself. Reproduced with a decoy process,
|
|
85
|
+
fixed to kill only the PID actually listening on the target port
|
|
86
|
+
(`lsof -ti tcp:<port> -sTCP:LISTEN`), verified the test still passes 6/6.
|
|
87
|
+
|
|
88
|
+
Reconciliation on resume: `git status` clean, nothing to stash; the only
|
|
89
|
+
commits since `036458df` were the fix itself; all three remaining worktrees
|
|
90
|
+
(P5, P9, P4) intact at their recorded SHAs, matching `BOARD.md` exactly,
|
|
91
|
+
nothing orphaned (the already-merged GF-5 worktree was removed); `VERSION`,
|
|
92
|
+
the latest tag, and npm `latest` all agree at 9.54.0, gitHead `1dd799f9` --
|
|
93
|
+
no release was mid-flight; the two dashboard-server processes noticed
|
|
94
|
+
earlier in the session are unowned by any PID this session recorded, so left
|
|
95
|
+
running per the never-kill-by-name rule. No data or work was lost across the
|
|
96
|
+
three restarts: everything durable was already committed or in a worktree.
|
|
97
|
+
|
|
98
|
+
## v9.54.1 release (2026-09-26, swarm mode)
|
|
99
|
+
|
|
100
|
+
Shipped as the swarm's first release, ahead of the queue, per direct
|
|
101
|
+
founder priority: PF-1 (D15, kill_provider_child unscoped pkill killing
|
|
102
|
+
unrelated Claude Code sessions on session end) plus the D16/D17 test fixes
|
|
103
|
+
found by its own 2-round HIGH-tier council. Fast tier green (110/0) before
|
|
104
|
+
push; pushed at `779c50e5` with `PRE_PUSH_SKIP=1` (D5). See CHANGELOG.md for
|
|
105
|
+
the user-facing account.
|
|
106
|
+
|
|
107
|
+
Also merged in this release: S-06 (docs pointing at a rejected
|
|
108
|
+
`doctor --airgap` on the default route, cherry-picked as `c83732b2`, LOW
|
|
109
|
+
tier, single-reviewer APPROVE).
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Founder prompt: the swarm (2026-09-26)
|
|
2
|
+
|
|
3
|
+
Verbatim, as given. `docs/v10/SWARM.md` records what was adopted, the
|
|
4
|
+
reconciliations required by CLAUDE.md and the build prompt (D12, D13), and
|
|
5
|
+
why. Read SWARM.md first; this file is the historical source text.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
ultracode
|
|
10
|
+
|
|
11
|
+
Switch the v10 build from one loop to a coordinated swarm. Goal: 10-20x more releases per day than cycles 1-4 (about 3 releases in 18 hours), without weakening anything in docs/LOKI-10-BUILD-PROMPT.md sections 2, 5b and 5c. Every "never do" rule still applies. Save this prompt as docs/v10/SWARM.md and follow it until the v10 definition of done.
|
|
12
|
+
|
|
13
|
+
Why it is slow (docs/v10/PROGRESS.md): each cycle batches 3-6 slices into one release. It reviews the whole batch in serial council rounds (cycle 1 took 9 rounds, cycle 3 took 6). Then it verifies every channel before the next cycle starts. So each release waits on the slowest slice and on every round.
|
|
14
|
+
|
|
15
|
+
ROLES. All roles are agents you spawn through Workflow. You are the orchestrator, and the only one who writes FOUNDER-QUEUE.md.
|
|
16
|
+
|
|
17
|
+
1. Product Owner (1 agent; writes docs/v10/BACKLOG.md and docs/v10/BOARD.md, never code).
|
|
18
|
+
- Ranks the backlog per build prompt section 3.
|
|
19
|
+
- Cuts work into release-sized slices. Each slice has:
|
|
20
|
+
- under about 300 changed lines;
|
|
21
|
+
- one owner;
|
|
22
|
+
- a declared file set that overlaps no other in-flight slice;
|
|
23
|
+
- acceptance checks written before building (the Wall);
|
|
24
|
+
- a risk tier.
|
|
25
|
+
- Keeps twice the builder count of ready slices queued, so builders never wait.
|
|
26
|
+
|
|
27
|
+
2. Builders (6-10 in parallel; isolation: worktree; one slice each; single writer).
|
|
28
|
+
- Implement with red-then-green tests.
|
|
29
|
+
- Run diff-scoped tests plus tests/moat in the worktree.
|
|
30
|
+
- Return the patch and its evidence.
|
|
31
|
+
- Never touch main or VERSION, and never edit outside the declared file set. If that is needed, return BLOCKED and let the PO re-slice.
|
|
32
|
+
|
|
33
|
+
3. Reviewers (read-only, parallel, diff-scoped, tiered by risk). Each finding must come with a reproduction.
|
|
34
|
+
- HIGH tier (verifier, Seal, gates, council, exit codes, auth, secrets, tests/moat): 3 reviewers with different lenses (correctness, security/bypass, fail-closed), plus 1 adversarial reviewer told to find a false pass. APPROVE needs 3 of 4.
|
|
35
|
+
- MEDIUM tier (runtime, CLI behavior, dashboard logic): 2 reviewers.
|
|
36
|
+
- LOW tier (docs, copy, tests only, UI without a data path, deleting unreachable code): 1 reviewer.
|
|
37
|
+
- The builder fixes findings in the same worktree. After 3 rounds, the slice goes back to the PO to be cut smaller. It never blocks the line.
|
|
38
|
+
|
|
39
|
+
4. Release Captain (exactly 1; the only agent allowed to write main, bump VERSION, tag or publish). It runs a serial merge queue. For each approved slice:
|
|
40
|
+
- Rebase onto origin/main.
|
|
41
|
+
- Run bash scripts/local-ci.sh (fast tier) and tests/moat. The ratchet must not regress; if it does, refuse the merge.
|
|
42
|
+
- Stage by name, commit with the asklokesh identity, push.
|
|
43
|
+
- Cut a release through scripts/release.sh.
|
|
44
|
+
- Wait for the previous release's required-ci (Tests, Bun Parity, Security Audit) to go green before bumping VERSION again, so releases never cancel each other's CI (the v9.7-v9.9 failure).
|
|
45
|
+
- If several slices are waiting, ship them together as one version rather than wait.
|
|
46
|
+
- On a code conflict, send the slice back to its builder with the new base. Never resolve code conflicts itself.
|
|
47
|
+
|
|
48
|
+
5. Channel Verifier (1, async, read-only).
|
|
49
|
+
- After each release, check: npm latest and gitHead, the tag, the GitHub release, Docker amd64/arm64, the Homebrew sha256, and a smoke test from a fresh PATH.
|
|
50
|
+
- Never block the next merge.
|
|
51
|
+
- A failure becomes a HIGH-priority fix-forward slice. Never unpublish or delete a version.
|
|
52
|
+
|
|
53
|
+
ORCHESTRATION
|
|
54
|
+
- Run repeated Workflow waves. In each wave, the PO produces up to 10 slices, then run: pipeline(slices, build -> verify -> review/fix loop -> captain queue).
|
|
55
|
+
- Use pipeline, not barriers. A LOW slice ships while a HIGH slice is still in review.
|
|
56
|
+
- In the script, serialize the Captain with a promise chain, so exactly one merge or release runs at a time.
|
|
57
|
+
- Agents coordinate through BOARD.md (slice id, owner, file set, tier, status, blockers) and through structured return values. Only the PO and the Captain write BOARD.md.
|
|
58
|
+
- Start the next wave as soon as the PO has ready slices. Never wait on channel verification.
|
|
59
|
+
|
|
60
|
+
SPEED LEVERS, in order
|
|
61
|
+
1. One slice, one release.
|
|
62
|
+
2. Risk-tiered review; most slices are LOW or MEDIUM.
|
|
63
|
+
3. Parallel reviewers per slice instead of serial whole-batch rounds.
|
|
64
|
+
4. Asynchronous channel verification.
|
|
65
|
+
5. Diff-scoped tests while building; the full fast tier plus moat runs only at merge.
|
|
66
|
+
6. Flaky tests: rerun once, record it, open a slice. Never pass a flake silently (see BACKLOG 93).
|
|
67
|
+
|
|
68
|
+
GUARDRAILS (restated, because speed pressure erodes them)
|
|
69
|
+
- When goals conflict: moat > Seal accuracy > delivered accuracy > cost > speed.
|
|
70
|
+
- The moat ratchet never regresses on main.
|
|
71
|
+
- If two releases in a row fail required-ci, stop releasing, fix main, then resume.
|
|
72
|
+
- No force push. Never delete versions. Never disable tests.
|
|
73
|
+
- The swarm spends faster. Log spend per wave in METRICS.md. If a wave would push past founder-queue item 3, drop to 3 builders, keep shipping LOW slices, and add one founder-queue line asking for a higher budget.
|
|
74
|
+
|
|
75
|
+
METRICS (append to METRICS.md after every wave)
|
|
76
|
+
- releases in the last 24h
|
|
77
|
+
- median slice lead time (ready to npm)
|
|
78
|
+
- review rounds per slice, by tier
|
|
79
|
+
- moat proven count
|
|
80
|
+
- required-ci failures
|
|
81
|
+
- spend
|
|
82
|
+
|
|
83
|
+
Target: at least 30 releases per 24h at steady state, with the moat proven count never decreasing.
|
|
84
|
+
|
|
85
|
+
START NOW
|
|
86
|
+
1. Write docs/v10/SWARM.md and docs/v10/BOARD.md.
|
|
87
|
+
2. Have the PO slice the top of the backlog: BACKLOG 94-98, P9 Rule of Two, and M0 measurement (claude-opus-5-5 in the model catalog, the seeded-defect corpus, the adoption eval).
|
|
88
|
+
3. Launch wave 1.
|
|
89
|
+
4. After each wave, append a wave entry to PROGRESS.md.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
**Note on step 2 of START NOW:** BACKLOG 94-98, P9, and the model-catalog half
|
|
94
|
+
of M0 were already done or in flight when this prompt arrived (P9 fully done
|
|
95
|
+
awaiting a validation PR; P4's catalog and three-setups cases done awaiting
|
|
96
|
+
review; BACKLOG 95 and 97 fixed on main; 96 and 98 partly fixed by the P7
|
|
97
|
+
sweep). Wave 1's real seed is the actual repo state at adoption time, recorded
|
|
98
|
+
in `docs/v10/BOARD.md`, not this stale list.
|