loki-mode 11.74.2 → 11.75.1
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/README.md +1 -1
- package/SKILL.md +2 -3
- package/VERSION +1 -1
- package/autonomy/completion-council.sh +10 -10
- package/autonomy/council-v2.sh +4 -4
- package/autonomy/grill.sh +1 -1
- package/autonomy/lib/browser-open.sh +1 -1
- package/autonomy/lib/chat.sh +1 -1
- package/autonomy/lib/cockpit-render.sh +1 -1
- package/autonomy/lib/done-recognition.sh +4 -4
- package/autonomy/lib/efficiency_cost.py +1 -1
- package/autonomy/lib/engine10-push.sh +2 -2
- package/autonomy/lib/prd-enrich.sh +1 -1
- package/autonomy/lib/proof-check.sh +1 -1
- package/autonomy/lib/proof-generator.py +3 -3
- package/autonomy/lib/proof-pr.sh +1 -1
- package/autonomy/lib/skill-link-heal.sh +1 -1
- package/autonomy/lib/voter-agents.sh +1 -1
- package/autonomy/loki +26 -37
- package/autonomy/prd-checklist.sh +1 -1
- package/autonomy/receipt_jwt.py +1 -1
- package/autonomy/run.sh +28 -28
- package/autonomy/trigger-schedule.py +6 -414
- package/autonomy/tui.sh +1 -1
- package/autonomy/verify.sh +4 -4
- package/completions/loki.bash +0 -5
- package/dashboard/__init__.py +1 -1
- package/docs/ARCHITECTURE.md +1 -2
- package/docs/CLI-REFERENCE.md +1 -1
- package/docs/COMPONENTS.md +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/docs/ROUTING-EVIDENCE.md +1 -2
- package/docs/V10-RESEARCH.md +1 -1
- package/docs/dev/architecture-reference.md +3 -7
- package/docs/dev/project-structure.md +1 -4
- package/docs/dev/release-checklist.md +13 -31
- package/docs/research-2026-07/OBSERVABILITY-TOOL-SPEC.md +1 -1
- package/docs/v11/MARKET-SLICES.md +1 -1
- package/docs/v11/REGISTRIES.md +1 -1
- package/docs/v11/ROUTER-1.md +2 -2
- package/loki-ts/dist/loki.js +2 -2
- package/mcp/__init__.py +1 -1
- package/package.json +2 -2
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/skills/extending.md +2 -3
- package/skills/factory-operations.md +11 -18
- package/skills/release-cadence.md +2 -2
- package/web-app/dist/assets/{AdminPage-jkjilfbl.js → AdminPage-xKgtIhk2.js} +1 -1
- package/web-app/dist/assets/{Avatar-bd5JWkSJ.js → Avatar-Q14AHox9.js} +1 -1
- package/web-app/dist/assets/{Badge-DVRit2Xw.js → Badge-yk5M-lip.js} +1 -1
- package/web-app/dist/assets/{Button-BNAB-pVZ.js → Button-ynznk0At.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-DpG29h_w.js → CockpitPage-C8B765za.js} +1 -1
- package/web-app/dist/assets/{ComparePage-Dasg5V41.js → ComparePage-DqzmWKnf.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-DJojse6b.js → ErrorBoundary-DdBPd_Lq.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-Blxw7_u1.js → EvidenceReceiptPanel-jb4Tp38b.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-BBvSFj80.js → GitHubIssuesPanel-xJQiLcxs.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-BCIKeSBg.js → GitHubPRsPanel-84W3Dhk_.js} +1 -1
- package/web-app/dist/assets/{HomePage-C7d__oNG.js → HomePage-St1Xl2tu.js} +2 -2
- package/web-app/dist/assets/{LoginPage-BXljL3yY.js → LoginPage-jRt0NUHb.js} +1 -1
- package/web-app/dist/assets/{MagicPage-Xjkts_yE.js → MagicPage-CQLFe7LR.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-kQvVp-j2.js → MetricsPage-zzX9eTC5.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-D-4ZlEaO.js → NotFoundPage-DDu023SY.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-DfzR5RXP.js → ProjectPage-D60UURaH.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-DFDsWzkV.js → ProjectsPage-DqVsKxlt.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-CLPIoYT3.js → SettingsPage-G7pPKvo0.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-PZKkyGeY.js → ShowcasePage-CrU_aKgS.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-BsBlcnzo.js → SystemSettingsPage-ClKGQFsB.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-BSjgNhoU.js → TeamsPage-B530vSNe.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-W2KeAzbg.js → TemplatesPage-COmv_Cqd.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-BjroTiCC.js → TerminalOutput-CufG9YzF.js} +1 -1
- package/web-app/dist/assets/{activity-BXZ5YYes.js → activity-Ct1Updr6.js} +1 -1
- package/web-app/dist/assets/{bell-D1urp5pa.js → bell-rcvhQuGr.js} +1 -1
- package/web-app/dist/assets/{bot-Chedf2bF.js → bot-DzeqEI-b.js} +1 -1
- package/web-app/dist/assets/{check-DhaCuOCV.js → check-zacnZHyC.js} +1 -1
- package/web-app/dist/assets/{chevron-left-D7BpQyA6.js → chevron-left-Lxnkl8Qg.js} +1 -1
- package/web-app/dist/assets/{circle-alert-DnGvQ_AQ.js → circle-alert-DoqSdQdB.js} +1 -1
- package/web-app/dist/assets/{clock-CqfxWhHM.js → clock-B7bJcVIC.js} +1 -1
- package/web-app/dist/assets/{cloud-BKxp5AWB.js → cloud-DdA9Bu6q.js} +1 -1
- package/web-app/dist/assets/{code-xml-BDQ6GBtt.js → code-xml-CAZEZ9T8.js} +1 -1
- package/web-app/dist/assets/{database-BmpEx1y_.js → database-Da2GkEIN.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-DYNY9R_C.js → dollar-sign-DjDiG-37.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-BJi0IBFd.js → file-code-corner-CSL-Jij-.js} +1 -1
- package/web-app/dist/assets/{file-plus-Dqyb2bcQ.js → file-plus-02DRA8pV.js} +1 -1
- package/web-app/dist/assets/{globe-DPh4RWfM.js → globe-CGyB90kK.js} +1 -1
- package/web-app/dist/assets/{hammer-B3xnuoA1.js → hammer-BaQB96TG.js} +1 -1
- package/web-app/dist/assets/{index-BpX8DcTr.js → index-lcoI1_Kk.js} +3 -3
- package/web-app/dist/assets/{layers-BRCmyCW8.js → layers-BWJBvoeg.js} +1 -1
- package/web-app/dist/assets/{loader-circle-n07Pky0M.js → loader-circle-CdcI0FeS.js} +1 -1
- package/web-app/dist/assets/{lock-BWqOuQmS.js → lock-BBkw5NJx.js} +1 -1
- package/web-app/dist/assets/{package-BJlB_Z-Z.js → package-BpPRO3LM.js} +1 -1
- package/web-app/dist/assets/{plus-oH17BZu2.js → plus-D7XbyK29.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-CPQ476LL.js → refresh-cw-DLG3hyAi.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-7hLvOcnS.js → rotate-ccw-Bqau4R_S.js} +1 -1
- package/web-app/dist/assets/{scroll-text-BCmLauQn.js → scroll-text-BtIL3cNk.js} +1 -1
- package/web-app/dist/assets/{server-DfTfvW84.js → server-tZCmZ4yH.js} +1 -1
- package/web-app/dist/assets/{shield-alert-CaeGRq19.js → shield-alert-K5JXzFKg.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-Dz-l2GPC.js → thumbs-up-CHCVyJdw.js} +1 -1
- package/web-app/dist/assets/{trash-2-B-OsDmSo.js → trash-2-DncNxVq0.js} +1 -1
- package/web-app/dist/assets/{trending-down-CXTFOxzq.js → trending-down-D8Bp0azX.js} +1 -1
- package/web-app/dist/assets/{trending-up-FQEdqr3v.js → trending-up-AixETdKR.js} +1 -1
- package/web-app/dist/assets/{upload-CacWSNTg.js → upload-VCbjFn2H.js} +1 -1
- package/web-app/dist/assets/{usePolling-cIjZ9qd2.js → usePolling-CQvKD2Jj.js} +1 -1
- package/web-app/dist/assets/{user-DAouWFHi.js → user-SK-YguQ6.js} +1 -1
- package/web-app/dist/index.html +1 -1
- package/autonomy/company-seats.json +0 -82
- package/docs/COMPETITIVE-INTEL-2026-09.md +0 -444
- package/docs/FOUNDER-DECISIONS-TRUST-SEMANTICS-2026-08-01.md +0 -145
- package/docs/FOUNDER-STATUS-AND-DECISIONS-2026-07-01.md +0 -132
- package/docs/LOKI-10-BUILD-PROMPT.md +0 -350
- package/docs/STRATEGY-2026-2028.md +0 -124
- package/docs/V10-VISION.md +0 -161
- package/docs/v10/ADOPTION-PLAN.md +0 -375
- package/docs/v10/ARCHITECT-CUTS.md +0 -744
- package/docs/v10/BACKLOG.md +0 -231
- package/docs/v10/BOARD.md +0 -1403
- package/docs/v10/CONTROL-PLANE.md +0 -120
- package/docs/v10/CONTROL.md +0 -36
- package/docs/v10/CP-ASK-PLAN.md +0 -85
- package/docs/v10/CP-ENTERPRISE-UI.md +0 -537
- package/docs/v10/D51-PHASE-B.md +0 -120
- package/docs/v10/D61-SPEED.md +0 -105
- package/docs/v10/D63-CARDS.md +0 -354
- package/docs/v10/DECISIONS.md +0 -915
- package/docs/v10/E2E-D65.md +0 -123
- package/docs/v10/ENGINE-LAWS.md +0 -163
- package/docs/v10/ENGINE-MEASURE.md +0 -69
- package/docs/v10/ENGINE.md +0 -743
- package/docs/v10/FAILURE-CLASSES.md +0 -2026
- package/docs/v10/FC21B-FC22-PLAN.md +0 -107
- package/docs/v10/FIRST-RUN-GATE.md +0 -39
- package/docs/v10/FOUNDER-QUEUE.md +0 -29
- package/docs/v10/GAP-RESEARCH-1003.md +0 -32
- package/docs/v10/GUARDS.md +0 -883
- package/docs/v10/L0-WAVE1.md +0 -81
- package/docs/v10/LEGACY-REMOVAL.md +0 -408
- package/docs/v10/MEDIUM-ANALYSIS.md +0 -346
- package/docs/v10/METRICS.md +0 -645
- package/docs/v10/MODERNIZE.md +0 -437
- package/docs/v10/OPENCODE-PARITY-PLAN.md +0 -84
- package/docs/v10/OPERATING-MODEL.md +0 -60
- package/docs/v10/PLAN-V12.md +0 -896
- package/docs/v10/PROGRESS.md +0 -2735
- package/docs/v10/RELEASE-11.md +0 -77
- package/docs/v10/RETRO-2026.md +0 -650
- package/docs/v10/ROADMAP-D63.md +0 -35
- package/docs/v10/SCALE.md +0 -140
- package/docs/v10/SCORECARD-PLAN.md +0 -250
- package/docs/v10/SWARM-PROMPT.md +0 -98
- package/docs/v10/SWARM.md +0 -293
- package/docs/v10/cp-redesign/PARITY.md +0 -188
- package/docs/v10/cp-redesign/legacy/INDEX.md +0 -1167
- package/docs/v10/roadmap-10/01-measurement.md +0 -113
- package/docs/v10/roadmap-10/02-cost.md +0 -75
- package/docs/v10/roadmap-10/03-speed.md +0 -65
- package/docs/v10/roadmap-10/04-first-run.md +0 -61
- package/docs/v10/roadmap-10/05-deploy.md +0 -61
- package/docs/v10/roadmap-10/06-stability.md +0 -64
- package/docs/v10/roadmap-10/07-quality.md +0 -57
- package/docs/v10/roadmap-10/08-proof.md +0 -48
- package/docs/v10/roadmap-10/09-safety.md +0 -74
- package/docs/v10/roadmap-10/README.md +0 -1464
- package/skills/sdlc-fleet.md +0 -170
- package/tools/cockpit/SPEC.md +0 -275
- package/tools/cockpit/index.html +0 -146
- package/tools/cockpit/roi-basis.json +0 -33
- package/tools/cockpit/server.py +0 -946
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
# Loki Control Plane (D56)
|
|
2
|
-
|
|
3
|
-
Architect design, 2026-10-01, base 1dfc87103. Design only. Flag: `LOKI_CONTROL=1` until acceptance (slice CP-17).
|
|
4
|
-
|
|
5
|
-
## 1. Goal
|
|
6
|
-
1. One service plus one UI, `loki control`, replaces dashboard/, legacy-ui/ and engine10/dashboard. Zero config locally; deployed once for hundreds of runs.
|
|
7
|
-
2. Stateless processes, all state in one DB (SQLite by default, Postgres via DATABASE_URL), self-healing, horizontally scalable on Postgres.
|
|
8
|
-
3. Every number is folded from ingested run events. A panel with no data says "no data ingested", never 0.
|
|
9
|
-
|
|
10
|
-
## 2. Data sources today
|
|
11
|
-
| Source | Where | Status |
|
|
12
|
-
|---|---|---|
|
|
13
|
-
| Run event log, append-only JSONL, envelope `{v,seq,ts,run,type,stage,data}` | engine10/events.ts:11-23 (validate), :54-89 (single writer), types.ts:26-43 (26 types) | REAL. The spool. |
|
|
14
|
-
| Folded run state: verdict, stages, cost (usd null when any session unpriced) | events.ts:106-140 `fold()`, :143-152 `partialCost()` | REAL. Reuse as is. |
|
|
15
|
-
| Run start data: task_source, issue_ref, provider, model, deep, cap_s, branch, origin_repo | supervisor.ts:194, cli data at supervisor.ts:331-334 | REAL |
|
|
16
|
-
| PR URL | `pr.opened {url,draft,existing}` supervisor.ts:233; `run.completed.pr_url` supervisor.ts:252 | REAL (opened only) |
|
|
17
|
-
| PR merged, issue closed | nowhere | MISSING. No event records merge or close. |
|
|
18
|
-
| Cost per session: usd, tokens, cache tokens, model, source | `cost` event session.ts:127-130 | REAL |
|
|
19
|
-
| Receipt and NOT PROVEN | receipt.json, schema types.ts:139-181; `receipt.sealed {path,receipt_sha256,signed,verdict,not_proven}` stages/seal.ts:292; `run.completed.not_proven` supervisor.ts:252 | REAL |
|
|
20
|
-
| Backlog queue (queued, running, BUDGET_STOP) | autonomy/lib/backlog.py:194-257, in memory only | MISSING from any durable store |
|
|
21
|
-
| Workspace group state | `~/.loki/workspaces/<ws>/<group>/group.json`, docs/v10/D51-PHASE-B.md | NOT BUILT (design only) |
|
|
22
|
-
| engine10 dashboard | engine10/dashboard/server.ts:30-57 (fold-based), routes :116-125 | REAL, but one repo, one process, 127.0.0.1 |
|
|
23
|
-
| Python dashboard, 168 routes | dashboard/server.py (13,171 lines); cost reads `.loki/metrics/efficiency` server.py:7869 | REAL but legacy: reads run.sh state that v10 runs never write |
|
|
24
|
-
| Pricing table | dashboard/server.py:7748, :8582 ("Unverified placeholder rate") | INVENTED |
|
|
25
|
-
| legacy-ui /api/v2 activity, agents/leaderboard, cost/breakdown, memory/graph, pipeline/status, providers/health | legacy-ui/index.js:100-105, issue #203 | INVENTED (no server route) |
|
|
26
|
-
| Secret redaction | util/redact.ts:4-14 `redactSecrets`; seal.ts:30 `sanitizeReason`; output.ts:79 Reason line | REAL. Reuse. |
|
|
27
|
-
|
|
28
|
-
## 3. Data model (Drizzle, one schema for SQLite and Postgres)
|
|
29
|
-
- `sources(id PK, host_hash, repo_path_hash, origin_repo, first_seen, last_seen)`. id = sha256(hostname + "\0" + realpath(repo)) truncated to 16 hex, computed by the shipper. No raw paths or hostnames stored.
|
|
30
|
-
- `events(source_id, run_id, seq, PK(source_id, run_id, seq), ts, type, stage, data JSON, line_sha256, received_at)`. Index (run_id, seq), (type, ts).
|
|
31
|
-
- `runs(source_id, run_id, PK(source_id, run_id), origin_repo, issue_ref, task_source, provider, model, started_at, ended_at, verdict, outcome, pr_url, pr_draft, cost_usd NULL, partial_usd, measured_sessions, total_sessions, input_tokens, output_tokens, wall_s, last_seq, last_event_at, tampered, conflict)`. A projection, rebuilt from `events` by `fold()` on every ingest batch for the touched runs; never written any other way.
|
|
32
|
-
- `receipts(source_id, run_id, PK, receipt_sha256, verdict, not_proven JSON, body JSON)`.
|
|
33
|
-
- `work_items(origin_repo, kind 'issue'|'pr', number, PK(origin_repo, kind, number), state, url, observed_at, run_id NULL)`. Fed only by `work.observed` events (CP-12).
|
|
34
|
-
- Event id = `source_id:run_id:seq`. Same id and same line_sha256 is a no-op (idempotent retry). Same id with a different hash returns 409, sets `runs.conflict = 1` and never overwrites.
|
|
35
|
-
- Derived views (SQL, not tables): in-progress = started, no run.completed, last_event_at within 10 min; stale = same but older (heartbeat lost); per-day cost; verdict counts; issue to PR join on (origin_repo, issue_ref).
|
|
36
|
-
- Seal verification stays with `loki verify` on local files: the shipper redacts, so stored bytes may differ from events.jsonl.
|
|
37
|
-
|
|
38
|
-
## 4. API (Hono, JSON, prefix /v1)
|
|
39
|
-
- `POST /v1/ingest {source, run_id, events[]}`: at most 500 events or 1 MB, each validated with `validateEnvelope()` (events.ts:11), redacted again server-side with `redactSecrets`. Returns `{accepted, duplicate, conflict, last_seq}`.
|
|
40
|
-
- `PUT /v1/runs/:source/:run/receipt`: receipt.json; 400 unless its receipt_sha256 matches a received `receipt.sealed` event.
|
|
41
|
-
- Reads: `GET /v1/runs?repo=&verdict=&provider=&since=&cursor=`, `/v1/runs/:source/:run` (summary + timeline), `/v1/runs/:source/:run/events?after_seq=`, `/v1/stats`, `/v1/costs?group=day|repo|model`, `/v1/compare?ids=`, `/v1/work`, `/v1/backlog`.
|
|
42
|
-
- `GET /health` (process up; `{service:"loki-control", version, install_path, pid}`, the P0-DASH-STATIC identity); `GET /ready` (DB reachable and migrations at head, else 503).
|
|
43
|
-
- Auth (enforced in `src/server/auth.ts`): binds 127.0.0.1 by default. With `LOKI_CONTROL_TOKEN` set, every `/v1/*` call (ingest, reads, answer) needs `Authorization: Bearer <token>`, compared in constant time; missing or wrong gives 401. `/health` and `/ready` need no token. A non-loopback `LOKI_CONTROL_HOST` with no token exits 2 naming `LOKI_CONTROL_TOKEN` before binding; `LOKI_CONTROL_ALLOW_INSECURE_BIND=1` overrides. On a loopback bind a request whose Host is not `127.0.0.1`, `localhost` or `[::1]` (any port) gets 403, which blocks DNS rebinding. The UI takes `#token=<token>` once, keeps it in sessionStorage and sends it on every call. Ingest and read share the token in v1.
|
|
44
|
-
|
|
45
|
-
## 5. Shipper and spool
|
|
46
|
-
- events.jsonl is the spool. The shipper never writes to it (the supervisor treats outside writes as tamper). Its acked cursor lives in `.loki/runs/<id>/ship.json {acked_seq, url}`, written atomically.
|
|
47
|
-
- Started by the supervisor next to the log (one hook line, skipped when `LOKI_CONTROL=0`; the url comes from `LOKI_CONTROL_URL` or local discovery, section 6), it uses `tail()` (events.ts:155), batches up to 200 events or 1 s, and POSTs. Backoff 1, 2, 4 ... 60 s with jitter. It never blocks or fails the run: on supervisor exit it flushes for at most 5 s, then leaves the rest for replay.
|
|
48
|
-
- Every string in `data` goes through `redactSecrets` before sending.
|
|
49
|
-
- Cleanup: `loki control prune --repo OWNER/NAME` and/or `--before ISO_DATE` (`--dry-run` previews) deletes matching runs, their events and orphaned sources in one transaction, direct on the SQLite file (WAL, 5 s busy timeout), so it works with the server up or down. `DELETE /v1/runs/:source/:run` (JSON content type, same-host Origin, bearer when a token is set) removes one run and writes an `audit` row first; the UI Run detail page has a Remove button with a confirm step.
|
|
50
|
-
- Replay: `loki control backfill [--repo DIR]` and every `loki` start ship each run whose ship.json acked_seq is below its last seq. Backfill of old .loki/runs uses the same code path.
|
|
51
|
-
|
|
52
|
-
## 6. Local discovery (on by default)
|
|
53
|
-
- `LOKI_CONTROL` defaults on; `LOKI_CONTROL=0` makes `loki control` print one "off" line and exit 0, and disables discovery.
|
|
54
|
-
- `loki control serve` reads the child's "listening on" line and writes `~/.loki/control/instance.json {pid, port, url, version, install_path, db}` (mode 0600), removed when the CLI exits.
|
|
55
|
-
- A run ships when `LOKI_CONTROL_URL` is set, or when `instance.json` names a live pid (`kill -0`) whose `/health` answers `service=loki-control` within 300 ms (`packages/control-plane/src/shipper/discover.ts`). A run never starts a server and never kills a process it did not record.
|
|
56
|
-
- The server binds loopback by default; discovery only reads the url the local serve published. The DB defaults to `~/.loki/control/control.db`. Tests always pass a temp HOME, an ephemeral port and `LOKI_NO_BROWSER=1`, and stop by recorded PID.
|
|
57
|
-
|
|
58
|
-
## 7. Deploy
|
|
59
|
-
- One image: `oven/bun` base, the service plus built UI assets, `bun packages/control-plane/dist/server.js`. Probes: liveness /health, readiness /ready.
|
|
60
|
-
- Helm chart `deploy/helm/loki-control`: replicas 1 with SQLite on a PVC (single writer, documented); replicas N only with DATABASE_URL. Migrations run on boot under a Postgres advisory lock. No in-process pub/sub: the UI polls with a cursor, so any replica serves any request.
|
|
61
|
-
- Clients set `LOKI_CONTROL_URL` and `LOKI_CONTROL_TOKEN`; containers and Helm runs of `loki start` ship the same way.
|
|
62
|
-
|
|
63
|
-
## 8. Migration and deletion
|
|
64
|
-
1. Build in packages/control-plane/ behind LOKI_CONTROL=1. The old UIs keep running; old-dashboard bug work is retired (D56.6).
|
|
65
|
-
2. Acceptance (CP-17): real runs in, correct counts out, on SQLite and Postgres; first-run gate passes with the flag on.
|
|
66
|
-
3. Flip the default. One release later, delete dashboard/, legacy-ui/, engine10/dashboard/ (and its registry.ts:19 line), `loki dashboard` becomes an alias of `loki control`, and the dashboard tests are removed (CP-18).
|
|
67
|
-
|
|
68
|
-
## 9. v0 (ships in 1 to 2 hours on a D46 train)
|
|
69
|
-
CP-00 corpus, then CP-01, CP-02 and CP-03 in parallel, then CP-04 to wire them: SQLite service with ingest, the shipper with backfill, and a UI with the Runs list and detail, all behind the flag.
|
|
70
|
-
|
|
71
|
-
## 10. Slices
|
|
72
|
-
Rules for every card: file sets do not overlap; only CP-02 touches supervisor.ts and registry.ts, only CP-04 touches autonomy/loki and root package.json. Every Wall check feeds the CP-00 corpus through the real ingest path and asserts exact counts, starting the service on an ephemeral port with a temp DB under LOKI_RUN_TMP. Any new tests/*.sh needs runner registration, a shard row, `timeout -k` and shellcheck.
|
|
73
|
-
|
|
74
|
-
| ID | Scope and file set | Wall check (fixture in, counts out) | Tier | Deps |
|
|
75
|
-
|---|---|---|---|---|
|
|
76
|
-
| CP-00 | Corpus: events.jsonl and receipts written by the real supervisor under the engine10 e2e fake sessions (VERIFIED, PARTIAL, FAILED, BLOCKED, cap.hit, tampered, unpriced cost, resumed). `packages/control-plane/test/fixtures/runs/` + `EXPECTED.json` | EXPECTED.json counts equal a direct `fold()` over each file | LOW | none |
|
|
77
|
-
| CP-01 | **Parallel A.** Service + DB: `src/server/{app,ingest,runs}.ts`, `src/db/{schema,migrate}.ts`, `drizzle/`, `package.json` | ingest corpus twice: run count, verdict counts, cost_usd (null where expected), duplicate=all on 2nd pass; changed line gives 409 | MEDIUM | CP-00 |
|
|
78
|
-
| CP-02 | **Parallel B.** Shipper + backfill: `src/shipper/{ship,backfill}.ts`, hook `loki-ts/src/e10ext/ship_hook.ts`, one line each in supervisor.ts and registry.ts | backfill corpus into a CP-01 stub server; kill mid-batch, rerun: every event exactly once; redacted token never appears in the posted body; ship.json advances | MEDIUM | CP-00 |
|
|
79
|
-
| CP-03 | **Parallel C.** UI: `ui/` (Vite, React, Tailwind), Runs list with filters, run detail timeline, receipt and NOT PROVEN panel; empty states | build, render against section 4 JSON captured from the corpus: row count, verdict badges and NOT PROVEN items match EXPECTED.json; empty DB shows "no runs ingested" | MEDIUM | CP-00 |
|
|
80
|
-
| CP-04 | Wire: service serves `ui/dist`; `loki control [serve,backfill,status]` in autonomy/loki + loki-ts cli; bundle into the npm package (`files[]`) | `npm pack` tarball contains server and UI; `loki control serve` + backfill corpus: /v1/runs count = corpus | MEDIUM | 01,02,03 |
|
|
81
|
-
| CP-05 | Local lifecycle: `src/local/lifecycle.ts` (instance.json, reuse rule, restart, replay) | stale-version instance not reused; dead pid restarted and replayed; never touches unrecorded pid | MEDIUM | CP-04 |
|
|
82
|
-
| CP-06 | Auth and bind: `src/server/auth.ts` | non-loopback bind without token exits non-zero; wrong token 401 on ingest and read; loopback no token 200 | HIGH | CP-01 |
|
|
83
|
-
| CP-07 | Postgres: `src/db/pg.ts`, advisory-lock migrations | with DATABASE_URL: two instances ingest corpus concurrently, counts equal SQLite run | MEDIUM | CP-01 |
|
|
84
|
-
| CP-08 | Receipts: `src/server/receipts.ts` + `ui/src/receipt/` | receipt PUT accepted only with matching sealed hash; NOT PROVEN items equal receipt.json | MEDIUM | 01,03 |
|
|
85
|
-
| CP-09 | Overview: `src/server/stats.ts`, `ui/src/overview/` | totals, verdict split, in-progress and stale counts equal EXPECTED.json | LOW | 01,03 |
|
|
86
|
-
| CP-10 | Costs: `src/server/costs.ts`, `ui/src/costs/` | per-day and per-model usd; unpriced run shows partial "N of M sessions", never 0 | MEDIUM | 01,03 |
|
|
87
|
-
| CP-11 | Compare: `src/server/compare.ts`, `ui/src/compare/` | two runs: stage times, cost, verdict, not_proven diff match fixtures | LOW | 01,03 |
|
|
88
|
-
| CP-12 | Work: issues to PRs; `loki control sync` turns `gh pr view`/`gh issue view` on the client into `work.observed` events (no token on the server). `src/sync/`, `src/server/work.ts`, `ui/src/work/` | open, merged, blocked, pending counts from fixture gh JSON; without sync the panel says "merge state not ingested" | MEDIUM | 01,03 |
|
|
89
|
-
| CP-13 | Backlog: backlog.py writes envelope events (`backlog.queued`, `backlog.dispatched`, `backlog.stopped`) to `.loki/backlog/<batch>/events.jsonl`; backfill ships it. `autonomy/lib/backlog.py`, `src/server/backlog.ts`, `ui/src/backlog/` | 5-issue fixture batch: queued, running, done and BUDGET_STOP counts | MEDIUM | 02,03 |
|
|
90
|
-
| CP-14 | Live: cursor polling `ui/src/live/`, `?after_seq=` | append 3 events to a fixture run while open: detail shows them within 2 polls | LOW | 01,03 |
|
|
91
|
-
| CP-15 | Deploy: `packages/control-plane/Dockerfile`, `deploy/helm/loki-control/` | image boots, /ready 200 after migrations; `helm template` renders probes; replicas>1 without DATABASE_URL fails render | MEDIUM | CP-07 |
|
|
92
|
-
| CP-16 | Self-heal: /ready gating, stale-run derivation, replay on boot | DB file removed while up: /ready 503, recovers; stale run flagged after heartbeat gap | LOW | 01,05 |
|
|
93
|
-
| CP-17 | Acceptance + flag flip | full corpus and one real first-run demo run on SQLite and Postgres: every view's counts equal EXPECTED.json | HIGH | all above |
|
|
94
|
-
| CP-18 | Delete dashboard/, legacy-ui/, engine10/dashboard/, their tests and references | `rg` finds no imports; local-ci fast tier green; first-run gate opens the control UI | HIGH | CP-17 + 1 release |
|
|
95
|
-
|
|
96
|
-
Dependencies to add (none present today; web-app/package.json pins react 19, vite 6, tailwind 3, so align): hono, drizzle-orm, drizzle-kit (dev), react, react-dom, vite, @vitejs/plugin-react, tailwindcss. SQLite uses built-in `bun:sqlite`. Postgres uses drizzle's `bun-sql` driver if the pinned drizzle-orm exports it, otherwise `postgres` is the one extra. No hard blocker found: Bun is already the runtime (bin/loki:94).
|
|
97
|
-
|
|
98
|
-
## 11. Open questions
|
|
99
|
-
1. Merge state source: client-side `loki control sync` (chosen default, no server secret) versus a GitHub webhook or App into the service. Webhooks need a public endpoint and a secret.
|
|
100
|
-
2. Legacy run.sh runs (`LOKI_ENGINE=legacy`) write no events.jsonl. Proposed: not shown. Confirm.
|
|
101
|
-
3. web-app/ is a fourth UI (Purple Lab, already deprecated). In scope for deletion or not?
|
|
102
|
-
4. Retention: keep events forever, or prune `heartbeat` after N days?
|
|
103
|
-
5. One shared token for ingest and read, or separate ingest-only tokens per team (D54 scale, team budgets)?
|
|
104
|
-
6. Workspaces: once D51 Phase B lands, should group.json also be shipped as envelope events, the same way as backlog (CP-13)?
|
|
105
|
-
|
|
106
|
-
## BLOCKED answer and default entry (D65)
|
|
107
|
-
|
|
108
|
-
A run blocked on a spec conflict shows its question in the run view with an answer box. The answer is POSTed to `/v1/runs/<source>/<run>/answer` (application/json, `answer` up to 4000 chars, the run must be blocked, ids are validated, the server binds 127.0.0.1) and written to `$LOKI_CONTROL_ANSWER_DIR` (default `~/.loki/control/answers`) as `<source>/<run>.answer.txt`, mode 0600. The engine has no in-place resume reader, so resuming starts a fresh run with the answer as task context: `loki answer <run>`.
|
|
109
|
-
|
|
110
|
-
### Answering a BLOCKED run
|
|
111
|
-
|
|
112
|
-
`loki answer [<run-id>] [--text "..."]` reads the run's task and question from `.loki/runs/<run>/events.jsonl` and the answer from `--text` or the answer file above, then launches `bin/loki "<task>\n\nClarification answering \"<question>\": <answer>"` and prints the new run id. The default run is the newest BLOCKED run in the current repo. The child env drops every `SLACK_*` variable and `LOKI_CONTROL_TOKEN` and sets `LOKI_NO_BROWSER=1`. A run that is not BLOCKED, or has no answer, exits 2 with the reason.
|
|
113
|
-
|
|
114
|
-
`LOKI_CONTROL_DEFAULT=1` (off by default) makes `loki dashboard` open the Control Plane.
|
|
115
|
-
|
|
116
|
-
### Integrity and the display verdict (D86, FC-08)
|
|
117
|
-
|
|
118
|
-
Ingest runs a pure verifier (`src/server/integrity.ts`) over every stored run and persists `tampered`, `attested`, `sig_checked` and `integrity_reasons`. Only the sealed prefix (events through `log.sealed`) supplies the verdict; a second `run.completed`, or any verdict-bearing event after `log.sealed`, is TAMPERED. The `log.sealed` kid must equal the signed receipt kid, and with keys configured an unknown kid is TAMPERED.
|
|
119
|
-
|
|
120
|
-
Display verdicts (`effective_verdict`, mirrored by `ui/src/api.ts`): TAMPERED; UNVERIFIED (a VERIFIED claim that is not attested); "VERIFIED (signature not checked)" (attested, but no key in `LOKI_CP_RECEIPT_PUBKEYS` checked the seal signature); VERIFIED (attested and signature-checked). With no keys configured nothing can be plain VERIFIED. Choice for the list filter: `?verdict=VERIFIED` lists signature-checked runs only; `?verdict=VERIFIED (signature not checked)` lists the rest. ALREADY_SATISFIED is a success outcome and needs a seal exactly like VERIFIED (same UNVERIFIED and signature-not-checked rules). Any other verdict on an unattested run shows `<verdict> (unattested)`, so an edited or redacted FAILED or PARTIAL never reads as plain. The Overview VERIFIED tile counts only plain VERIFIED; a separate tile counts signature-not-checked runs. Redaction (Q17-05b): the engine redacts event data with `redactEnvelope` (`loki-ts/src/util/redact.ts`) before it hashes the log and signs the seal; the shipper and ingest apply the same function, which is a fixpoint, so on an engine-written line both are no-ops. Seal crypto fields of the exact engine shape are exempt. A log whose bytes no longer match its seal, including one rewritten by redaction after sealing, is TAMPERED; there is no UNVERIFIED escape for redaction. Rows are recomputed at boot in chunks (one transaction each) when attested is NULL or the stored key-set fingerprint (`integrity_key_fp`) differs from the configured one; rows whose events are gone are marked unattested once and not retried.
|
package/docs/v10/CONTROL.md
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# Control
|
|
2
|
-
|
|
3
|
-
Mission: ship correct, reviewed, verified slices to npm continuously, faster
|
|
4
|
-
than drift can accumulate.
|
|
5
|
-
|
|
6
|
-
Priority order when anything conflicts: moat > seal accuracy > delivered
|
|
7
|
-
accuracy > cost > speed. Never trade a higher one for a lower one.
|
|
8
|
-
|
|
9
|
-
## Decisions (one line each; full text and Why/Reverse in DECISIONS.md)
|
|
10
|
-
|
|
11
|
-
- D12: unanimous APPROVE required; a reproduced blocking finding always
|
|
12
|
-
vetoes; a bucket-(b) pre-existing gap the diff doesn't worsen is a new
|
|
13
|
-
slice, never a veto (D21).
|
|
14
|
-
- D13: every review agent pins its model, never inherits the session's.
|
|
15
|
-
- D14-D17: root-caused session terminations to an unscoped `pkill -f`;
|
|
16
|
-
fixed by scoping to the process group; the regression test itself
|
|
17
|
-
twice reintroduced the bug (unsafe decoys, shared process group) until
|
|
18
|
-
self-recorded PIDs, unique tokens, and self-isolation closed it.
|
|
19
|
-
- D18: a hot file was emptied by a scripted write with no read-back
|
|
20
|
-
guard; Read-then-Edit or diff-verify before any scripted hot-file write.
|
|
21
|
-
- D19: a "confirmed solid" verdict only covers what was tested.
|
|
22
|
-
|
|
23
|
-
## Velocity targets
|
|
24
|
-
|
|
25
|
-
- Releases (D37): a cut at :00, :20 and :40 whenever main is green and
|
|
26
|
-
a merged-unreleased slice exists; trains overlap after publish-npm.
|
|
27
|
-
- Ready slices: at least 8 at all times.
|
|
28
|
-
- Active builders: at least 6 while ready slices exist.
|
|
29
|
-
- Review-pending age: fix or escalate past 45 minutes.
|
|
30
|
-
- Merged-but-unreleased age: cut a release past 30 minutes while CI is
|
|
31
|
-
green.
|
|
32
|
-
|
|
33
|
-
## Rule
|
|
34
|
-
|
|
35
|
-
The first action of every turn addresses the top VIOLATION from
|
|
36
|
-
`scripts/v10-pulse.sh`, before anything else.
|
package/docs/v10/CP-ASK-PLAN.md
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
# CP-ASK slice plan (Architect, 2026-10-04T00:05Z)
|
|
2
|
-
|
|
3
|
-
Founder 22:03Z: the CP home box stops being "what should Loki build" and becomes Ask Loki.
|
|
4
|
-
- What it does: search, learn and compare across runs, receipts, repos and issues.
|
|
5
|
-
- How it runs: asynchronously, on the user's provider (default claude).
|
|
6
|
-
|
|
7
|
-
Everything ships behind LOKI_CP_ASK=1 (default off). Ask is a read-only async job: the provider calls tools from the existing MCP server, and threads are stored in control.db. It never starts a build.
|
|
8
|
-
|
|
9
|
-
## Findings (file:line; CP = packages/control-plane)
|
|
10
|
-
- **The box today:** CP/ui/src/pages/home/Hero.tsx:45-68, mounted at home/index.tsx:8.
|
|
11
|
-
- Submit (:26-40) calls POST /v1/start, which reaches spawn.ts:52 planStart, then spawnStart (:73), which runs `loki start --brief`.
|
|
12
|
-
- Compose (ui/src/pages/compose/index.tsx:75) is a second start path, so builds keep a home.
|
|
13
|
-
- **CP data that already exists:**
|
|
14
|
-
- control.db holds events, runs, audit, local_repos and actions (src/db/schema.ts:3-89).
|
|
15
|
-
- HTTP reads: /v1/runs (app.ts:55), /v1/runs/:s/:r (:63), events and the artifact allowlist (artifacts.ts:53, :68), plus stats, cost, fleet, metrics, memory, audit, checkpoints and providers.
|
|
16
|
-
- There is no /v1/compare route (CONTROL-PLANE.md:41 lists one).
|
|
17
|
-
- **mcp/server.py (3028 lines) mixes read and write tools.**
|
|
18
|
-
- Read tools: memory_retrieve, state_get, metrics_efficiency, v10_status, project_status, agent_metrics, quality_report, code_search, mem_search, timeline, get, hotspots, co_changes, doc_coverage, findings, learnings, graph_query.
|
|
19
|
-
- Write or spawn tools: store_pattern, task_queue_add, task_queue_update, capture_session_summary, consolidate_memory, complete_task, v10_run, start_project, checkpoint_restore, loki_start, verify_fast, v10_verify.
|
|
20
|
-
- It is stdio and works relative to its cwd's .loki.
|
|
21
|
-
- **Repos:** ~/.loki/dashboard/projects.json (spawn.ts:34) plus local_repos.
|
|
22
|
-
- **GitHub:** nothing in the CP; gh is on the host.
|
|
23
|
-
- **Read-only primitives per provider:**
|
|
24
|
-
- claude: --mcp-config (loki-ts/src/providers/mcp_config.ts) and --allowedTools/--disallowedTools, with deny taking precedence (claude_flags.ts:472-512).
|
|
25
|
-
- codex: `exec --sandbox read-only`.
|
|
26
|
-
- opencode: MCP (opencode.sh:72).
|
|
27
|
-
- cline and aider: no MCP on our path.
|
|
28
|
-
- **Reusable CP helpers:** the SSE helper stream.ts:20-44 and child env scrubbing spawn.ts:14 childEnv.
|
|
29
|
-
|
|
30
|
-
## Decisions
|
|
31
|
-
- **Data access is tools only (ADOPT, no prompt stuffing).**
|
|
32
|
-
- mcp/server.py gets `--read-only`, which registers only the read allowlist.
|
|
33
|
-
- A new mcp/cp_tools.py calls the CP's own HTTP read API: runs_search, run_get, run_events, run_artifact, runs_compare, stats, cost and repos_list (names only).
|
|
34
|
-
- gh_issues and gh_prs use fixed argv (`gh issue list|view`, `gh pr list|view`), with the repo validated against a known origin_repo.
|
|
35
|
-
- The CP token reaches only the MCP child env, never the model.
|
|
36
|
-
- **Async job.**
|
|
37
|
-
- POST /v1/ask writes ask_threads and ask_messages rows, then spawns a detached ask worker (argv, no shell, childEnv).
|
|
38
|
-
- The worker parses the provider's stream-json into ask_events and records cost.
|
|
39
|
-
- A message ends as done, failed, timeout (600s), over_budget or interrupted.
|
|
40
|
-
- The UI streams over SSE; the user can leave and come back, and follow-ups replay prior turns.
|
|
41
|
-
- **Security boundary, three layers:**
|
|
42
|
-
1. Tools: claude gets --strict-mcp-config with allowedTools Read,Grep,Glob,mcp__loki__* and disallowedTools Write,Edit,NotebookEdit,Bash,WebFetch,WebSearch; codex gets --sandbox read-only.
|
|
43
|
-
2. cwd is an empty 0700 per-job scratch dir, never a repo, removed at the end.
|
|
44
|
-
3. The MCP surface is read-only and gh runs with fixed argv.
|
|
45
|
-
- The ask module never imports planStart or spawnStart (guard test).
|
|
46
|
-
- All run, event and issue text is untrusted data.
|
|
47
|
-
- POST requires loopback or a bearer token, accepts JSON only and questions up to 4000 chars, and allows at most 2 concurrent jobs.
|
|
48
|
-
- cline and aider are refused with "Ask needs a provider with MCP; use claude, codex or opencode".
|
|
49
|
-
|
|
50
|
-
## Founder questions (decided by the CoS under the standing mandate; FOUNDER-QUEUE row 20, reversible)
|
|
51
|
-
- (a) With the flag on, the home box is Ask only, with a visible "Start a build" link to Compose. This follows the founder's words directly.
|
|
52
|
-
- (b) Defaults are $1.00 per ask (LOKI_ASK_MAX_USD) and a 600s timeout, both configurable. Ask spend is tracked and shown on the Cost page apart from run budgets.
|
|
53
|
-
- (c) Scope:
|
|
54
|
-
- CP-level data (runs, receipts and events across every repo, since they are already in control.db) is always available.
|
|
55
|
-
- Per-repo memory and code tools use one repo per ask (the repo chip, default the CP repo).
|
|
56
|
-
- All-repos memory fan-out is a later slice.
|
|
57
|
-
|
|
58
|
-
## Slices (no shared files)
|
|
59
|
-
| # | Slice | Tier | Needs | Files | Wall checks |
|
|
60
|
-
|---|---|---|---|---|---|
|
|
61
|
-
| 1 | MCP read-only mode | HIGH | none | mcp/server.py, mcp/tests/test_read_only.py, tests/test-mcp-tool-surface-guard-rejects.sh | The tool list equals the read allowlist exactly; each write tool is absent (re-adding store_pattern goes red); default mode is unchanged. |
|
|
62
|
-
| 2 | CP data tools | HIGH | 1 | mcp/cp_tools.py, mcp/tests/test_cp_tools.py, mcp/tests/fixtures/cp_api/*.json | runs_compare of two fixture runs returns both ids, verdicts and costs; an artifact outside the allowlist is refused; no CP URL or token is returned. |
|
|
63
|
-
| 3 | gh read tools | HIGH | 2 | mcp/gh_tools.py, mcp/tests/test_gh_tools.py | Only list/view argv is spawned; an unknown repo is refused; gh api is unreachable. |
|
|
64
|
-
| 4 | DB schema | MEDIUM | none | CP/src/db/schema.ts, CP/drizzle/0005_ask.sql, CP/drizzle/meta/*, CP/test/db/ask_schema.test.ts | Migrating a 0004 db keeps runs rows byte-equal. |
|
|
65
|
-
| 5 | Ask store | MEDIUM | 4 | CP/src/ask/store.ts, CP/test/server/ask_store.test.ts | Append order is kept; markInterrupted flips only dead-pid running rows. |
|
|
66
|
-
| 6 | Policy and job dir | HIGH | none | CP/src/ask/policy.ts, CP/test/server/ask_policy.test.ts | The deny list covers the loki-ts REVIEW denylist; mcp.json names --read-only; the scratch dir is 0700 and outside every repo. |
|
|
67
|
-
| 7 | Provider argv | HIGH | 6 | CP/src/ask/invoke.ts, CP/test/server/ask_invoke.test.ts | claude has --strict-mcp-config and the deny list and has no --dangerously-skip-permissions; codex has --sandbox read-only; cline and aider are refused; the default model is omitted (L1). |
|
|
68
|
-
| 8 | Stream parser | MEDIUM | none | CP/src/ask/parse.ts, CP/test/server/ask_parse.test.ts, CP/test/fixtures/ask/{claude,codex}-stream.jsonl | Deltas concatenate to the final text; tool_use is captured; the cost comes from the result line; a truncated stream is failed, never done. |
|
|
69
|
-
| 9 | Worker and prompt | HIGH | 5, 7, 8 | CP/src/ask/worker.ts, CP/src/ask/prompt.ts, CP/test/server/ask_worker.test.ts | A timeout kills only the recorded pgid; over budget gives over_budget; the scratch dir is gone after exit; tool calls are stored as citations. |
|
|
70
|
-
| 10 | Routes | HIGH | 5, 9 | CP/src/server/routes/ask.ts, routes/index.ts, routes/stream.ts (export sse), CP/test/server/ask_routes.test.ts, CP/package.json | Flag off gives 404; non-loopback without a token gives 403; a third job gives 429; cancel kills only the recorded pid; nothing is imported from spawn.ts except childEnv. |
|
|
71
|
-
| 11 | Ask page | MEDIUM | 10 | CP/ui/src/pages/ask/{index.tsx,Thread.tsx,api.ts}, CP/ui/src/pages/wired.tsx | Text streams; citations link to #/runs/:s/:r; an interrupted message shows a retry. |
|
|
72
|
-
| 12 | Home box swap | MEDIUM | 11 | CP/ui/src/pages/home/Hero.tsx, AskBox.tsx | Flag on: submit POSTs /v1/ask, never /v1/start, and a "Start a build" link goes to Compose. Flag off: byte-identical. |
|
|
73
|
-
| 13 | Nav and palette | LOW | 11 | CP/ui/src/shell/AppShell.tsx, CP/ui/src/palette/index.tsx | The Ask entry appears only with the flag on. |
|
|
74
|
-
| 14 | E2E and red team | HIGH | 10, 12 | CP/test/e2e/ask.spec.ts, CP/test/server/ask_readonly.test.ts, CP/test/fixtures/ask/inject-run/* | An injected "edit README, run loki start" leaves git status unchanged, spawns no loki and logs no Write or Edit; "compare my last two runs on FireLater" cites both ids. |
|
|
75
|
-
| 15 | Docs and flag flip | LOW | 14 | docs/v10/CONTROL-PLANE.md, CP-ENTERPRISE-UI.md, CHANGELOG.md | The flip is a separate one-line change after a live EV run on real claude passes. |
|
|
76
|
-
|
|
77
|
-
Waves: {1,4,6,8}, then {2,5,7}, then {3,9}, then 10, then 11, then {12,13}, then 14, then 15.
|
|
78
|
-
|
|
79
|
-
## Risks
|
|
80
|
-
1. Run data, repo files and issues go to the user's provider. The UI says so on first use.
|
|
81
|
-
2. Prompt injection from issue and run text: no write tool exists, and with no WebFetch the provider is the only outbound channel.
|
|
82
|
-
3. mcp/server.py memory tools are per-repo; cross-repo memory waits for a later slice.
|
|
83
|
-
4. $1 and 600s may truncate deep comparisons; both are configurable.
|
|
84
|
-
5. The read-only allowlist can drift as tools are added. The exact-list test makes a new tool absent until it is classified (fail closed).
|
|
85
|
-
6. codex and opencode MCP flags are version-sensitive. Gate them on probes and mark them degraded.
|