loki-mode 11.10.1 → 11.15.0
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 +2 -2
- package/SKILL.md +3 -3
- package/VERSION +1 -1
- package/autonomy/lib/backlog.py +18 -3
- package/autonomy/lib/chat.sh +6 -0
- package/autonomy/lib/engine10-push.sh +26 -2
- package/autonomy/lib/proof-generator.py +16 -0
- package/autonomy/lib/trust_trajectory.py +130 -0
- package/autonomy/lib/workspace.py +2 -3
- package/autonomy/loki +263 -58
- package/autonomy/quickstart.sh +40 -0
- package/autonomy/run.sh +39 -15
- package/autonomy/trigger-server.py +452 -29
- package/bin/loki +4 -1
- package/completions/_loki +1 -1
- package/completions/loki.bash +16 -1
- package/dashboard/__init__.py +1 -1
- package/docs/CLI-REFERENCE.md +7 -4
- package/docs/DEPLOYMENT.md +12 -5
- package/docs/EVALUATING.md +13 -0
- package/docs/INSTALLATION.md +2 -2
- package/docs/SIGNED-RECEIPTS.md +7 -0
- package/docs/WORKSPACES.md +2 -2
- package/docs/cost-controls.md +26 -0
- package/docs/merge-queue.md +19 -0
- package/docs/sentry-intake.md +4 -0
- package/docs/slack.md +2 -1
- package/docs/trackers.md +12 -1
- package/docs/v10/BOARD.md +140 -85
- package/docs/v10/CLI-MODERN.md +5 -4
- package/docs/v10/DECISIONS.md +1 -0
- package/docs/v10/ENGINE.md +2 -0
- package/docs/v10/FAILURE-CLASSES.md +3 -3
- package/docs/v10/MODERNIZE.md +34 -2
- package/docs/v10/PROGRESS.md +15 -0
- package/loki-ts/dist/loki.js +1225 -1139
- package/mcp/__init__.py +1 -1
- package/package.json +2 -2
- package/packages/control-plane/dist/server.js +1889 -1577
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/schemas/loki-yaml.schema.json +5 -0
- package/web-app/dist/assets/{AdminPage-D3PgG7SH.js → AdminPage-bZlvH4TL.js} +1 -1
- package/web-app/dist/assets/{Avatar-Ct77hvlG.js → Avatar-BZrBstQe.js} +1 -1
- package/web-app/dist/assets/{Badge-Cg_gZaJF.js → Badge-Q8l8r4Vq.js} +1 -1
- package/web-app/dist/assets/{Button-i9r2G84n.js → Button-B8Bt0A3S.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-C3UyLXyp.js → CockpitPage-CIYExrXa.js} +1 -1
- package/web-app/dist/assets/{ComparePage-B1dXHga_.js → ComparePage-CBOmHdam.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-CQ_xREw0.js → ErrorBoundary-BKwDPSnK.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-DwUxd_Xi.js → EvidenceReceiptPanel-KqzjphWl.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-C0jAnuAd.js → GitHubIssuesPanel-lF3GkHRv.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-B4pNXJMz.js → GitHubPRsPanel-BCzipPWD.js} +1 -1
- package/web-app/dist/assets/{HomePage-BC9UTS1l.js → HomePage-CIdnkzaN.js} +2 -2
- package/web-app/dist/assets/{LoginPage-CnpdwK8F.js → LoginPage-D-178nTT.js} +1 -1
- package/web-app/dist/assets/{MagicPage-Bj0lZuNp.js → MagicPage-BmHuzMT8.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-yyw3VnfX.js → MetricsPage-CPCiyDFn.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-LMxkJP15.js → NotFoundPage-B2T6n1gx.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-2x0MRkNu.js → ProjectPage-DQmpFhb0.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-A8J8o1gj.js → ProjectsPage-BmugzFEd.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-fwvOVcRb.js → SettingsPage-ZB-RrmgM.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-DqI4sUwk.js → ShowcasePage-BAhwHt4_.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-CyytfNo_.js → SystemSettingsPage-Bt7sf2Vu.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-BTTe76W1.js → TeamsPage-B-v5j_8q.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-CIp3OTlL.js → TemplatesPage-bdqUL-LG.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-dX5L4ky-.js → TerminalOutput-CRHEXBwS.js} +1 -1
- package/web-app/dist/assets/{activity-uHXr2AaF.js → activity-C-ROkmXt.js} +1 -1
- package/web-app/dist/assets/{bell-D6RbxRMo.js → bell-DbiCBxQA.js} +1 -1
- package/web-app/dist/assets/{bot-D31w2Mu6.js → bot-DsIgE_qr.js} +1 -1
- package/web-app/dist/assets/{check-CoKJksbr.js → check-CkAdmHWP.js} +1 -1
- package/web-app/dist/assets/{chevron-left-Bjx7oX7s.js → chevron-left-CYTLivAo.js} +1 -1
- package/web-app/dist/assets/{circle-alert-DOAh8Jmi.js → circle-alert-BVIcAsFJ.js} +1 -1
- package/web-app/dist/assets/{clock-DgEXPNWH.js → clock-Dg3Rq0go.js} +1 -1
- package/web-app/dist/assets/{cloud-0dXJFzBv.js → cloud-CenrqHFl.js} +1 -1
- package/web-app/dist/assets/{code-xml-DytQ_bq7.js → code-xml-C2mvfoug.js} +1 -1
- package/web-app/dist/assets/{database-Qyjryb72.js → database-BKa0_eCb.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-BzhTVy1e.js → dollar-sign-DfelUK1S.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-DTdSOALw.js → file-code-corner-CZKWoHVg.js} +1 -1
- package/web-app/dist/assets/{file-plus-VdjOG1RK.js → file-plus-CZ-m1zMX.js} +1 -1
- package/web-app/dist/assets/{globe-BhxNOfyM.js → globe-S0kv_GwC.js} +1 -1
- package/web-app/dist/assets/{hammer-MQzrw8ee.js → hammer-BW1MDdu1.js} +1 -1
- package/web-app/dist/assets/{index-DaxrMbHf.js → index-ACEYsTc2.js} +3 -3
- package/web-app/dist/assets/{layers-C7nusTP-.js → layers-BrXHYZ-L.js} +1 -1
- package/web-app/dist/assets/{loader-circle-B1qBkgOY.js → loader-circle-DOdhKFx0.js} +1 -1
- package/web-app/dist/assets/{lock-BdkOxK2O.js → lock-BcFTyg8J.js} +1 -1
- package/web-app/dist/assets/{package-RVyK96Zn.js → package-D34cMVQG.js} +1 -1
- package/web-app/dist/assets/{plus-ntmwFRrp.js → plus-CEaMeBxL.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-BJ39b_PP.js → refresh-cw-D2Rzxr5U.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-uPx_-3vz.js → rotate-ccw-C_-EjRLh.js} +1 -1
- package/web-app/dist/assets/{scroll-text-D9qvXkj-.js → scroll-text-BSSCMI_c.js} +1 -1
- package/web-app/dist/assets/{server-gs4xmD8Y.js → server-BKvLonWt.js} +1 -1
- package/web-app/dist/assets/{shield-alert-O2_YffGI.js → shield-alert-DbbQbPdW.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-B3RVBhQx.js → thumbs-up-NoBD1fUR.js} +1 -1
- package/web-app/dist/assets/{trash-2-DEUt7qhq.js → trash-2-BXz8rAyd.js} +1 -1
- package/web-app/dist/assets/{trending-down-oyTns4UZ.js → trending-down-D8u535Re.js} +1 -1
- package/web-app/dist/assets/{trending-up-CdpZK0Oc.js → trending-up-q8k3kgiy.js} +1 -1
- package/web-app/dist/assets/{upload-D9sbjjC8.js → upload-Cp7_zeBI.js} +1 -1
- package/web-app/dist/assets/{usePolling-6ognrnyV.js → usePolling-CTHVdcuX.js} +1 -1
- package/web-app/dist/assets/{user-CBKc8QoI.js → user-DF7bfSf_.js} +1 -1
- package/web-app/dist/index.html +1 -1
- package/autonomy/lib/doctor-fix.py +0 -279
package/completions/_loki
CHANGED
|
@@ -286,7 +286,7 @@ function _loki_commands {
|
|
|
286
286
|
'crash:Crash report management'
|
|
287
287
|
'otel:OpenTelemetry management'
|
|
288
288
|
'wiki:Wiki commands'
|
|
289
|
-
'answer:
|
|
289
|
+
'answer:Start a follow-up run from a BLOCKED run with your answer'
|
|
290
290
|
'verify-pr:Verify a PR against its linked issue in a sandbox'
|
|
291
291
|
'queue:Overnight issue queue with a morning digest'
|
|
292
292
|
'issues:Run every open issue in a repo and open PRs'
|
package/completions/loki.bash
CHANGED
|
@@ -59,7 +59,7 @@ _loki_completion() {
|
|
|
59
59
|
memory)
|
|
60
60
|
local memory_cmds="list show search stats export clear dedupe index timeline consolidate economics retrieve lessons learn forget episode pattern skill vectors brief help"
|
|
61
61
|
if [[ "$cur" == -* ]]; then
|
|
62
|
-
COMPREPLY=( $(compgen -W "--task --help" -- "$cur") )
|
|
62
|
+
COMPREPLY=( $(compgen -W "--task --recent --repo --help" -- "$cur") )
|
|
63
63
|
return 0
|
|
64
64
|
fi
|
|
65
65
|
COMPREPLY=( $(compgen -W "${memory_cmds}" -- "$cur") )
|
|
@@ -226,6 +226,13 @@ _loki_completion() {
|
|
|
226
226
|
fi
|
|
227
227
|
;;
|
|
228
228
|
|
|
229
|
+
quickstart)
|
|
230
|
+
if [[ "$cur" == -* ]]; then
|
|
231
|
+
COMPREPLY=( $(compgen -W "--dry-run --explain-match --from-preview --verify-preview --json --list-templates --template --yes --help" -- "$cur") )
|
|
232
|
+
return 0
|
|
233
|
+
fi
|
|
234
|
+
;;
|
|
235
|
+
|
|
229
236
|
plan)
|
|
230
237
|
if [[ "$cur" == -* ]]; then
|
|
231
238
|
COMPREPLY=( $(compgen -W "--json --verbose --spec --requirements --help" -- "$cur") )
|
|
@@ -242,6 +249,14 @@ _loki_completion() {
|
|
|
242
249
|
COMPREPLY=( $(compgen -W "${issue_cmds}" -- "$cur") )
|
|
243
250
|
;;
|
|
244
251
|
|
|
252
|
+
modernize)
|
|
253
|
+
if [[ "$cur" == -* ]]; then
|
|
254
|
+
COMPREPLY=( $(compgen -W "--repo --ref --unit --mid --target --help" -- "$cur") )
|
|
255
|
+
return 0
|
|
256
|
+
fi
|
|
257
|
+
COMPREPLY=( $(compgen -W "heal migrate unit" -- "$cur") )
|
|
258
|
+
;;
|
|
259
|
+
|
|
245
260
|
onboard)
|
|
246
261
|
if [[ "$cur" == -* ]]; then
|
|
247
262
|
COMPREPLY=( $(compgen -W "--depth --format --output --stdout --update --help" -- "$cur") )
|
package/dashboard/__init__.py
CHANGED
package/docs/CLI-REFERENCE.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
# CLI reference
|
|
2
2
|
|
|
3
|
-
Generated from `loki-ts/src/cli/registry.ts` by `scripts/generate-stale-zero.sh` for v11.
|
|
3
|
+
Generated from `loki-ts/src/cli/registry.ts` by `scripts/generate-stale-zero.sh` for v11.15.0. Do not edit by hand.
|
|
4
4
|
Hidden and legacy-only commands are omitted; see `docs/v10/CLI-MODERN.md` for the full inventory.
|
|
5
5
|
|
|
6
6
|
| Command | Description |
|
|
7
7
|
| --- | --- |
|
|
8
8
|
| `loki version` | Show version |
|
|
9
9
|
| `loki status` | Show current run status |
|
|
10
|
-
| `loki doctor` | System prerequisites health check |
|
|
10
|
+
| `loki doctor` | System prerequisites health check; --json, --fix, --requirements, --repo (repo profile with a 0-100 readiness score and fixes) |
|
|
11
11
|
| `loki provider` | Show, list or set the AI provider |
|
|
12
12
|
| `loki provider show` | Show current provider |
|
|
13
13
|
| `loki provider list` | List providers and install status |
|
|
@@ -44,6 +44,8 @@ Hidden and legacy-only commands are omitted; see `docs/v10/CLI-MODERN.md` for th
|
|
|
44
44
|
| `loki control backfill` | Ship DIR/.loki/runs to the control plane |
|
|
45
45
|
| `loki control prune` | Delete matching runs |
|
|
46
46
|
| `loki control status` | Show control plane reachability |
|
|
47
|
+
| `loki intent` | Show a past run's intent card |
|
|
48
|
+
| `loki intent show` | Print the intent card and answer |
|
|
47
49
|
| `loki kpis` | KPI snapshot (alias of report kpis) |
|
|
48
50
|
| `loki report` | Reporting: kpis, session, metrics, cost, export, share, dogfood |
|
|
49
51
|
| `loki report kpis` | Canonical KPI snapshot |
|
|
@@ -57,7 +59,7 @@ Hidden and legacy-only commands are omitted; see `docs/v10/CLI-MODERN.md` for th
|
|
|
57
59
|
| `loki trust detail` | Trust metrics detail |
|
|
58
60
|
| `loki crash` | Inspect or submit scrubbed crash reports |
|
|
59
61
|
| `loki contract` | Print the spec delivery contract |
|
|
60
|
-
| `loki start` | Run the autonomous build |
|
|
62
|
+
| `loki start` | Run the autonomous build (a `jira:KEY` or `linear:KEY` ref also writes the outcome back to that ticket, see docs/trackers.md) |
|
|
61
63
|
| `loki slack` | Slack inbound handler |
|
|
62
64
|
| `loki slack serve` | Serve the Slack handler |
|
|
63
65
|
| `loki queue` | Overnight issue queue with a morning digest |
|
|
@@ -68,7 +70,8 @@ Hidden and legacy-only commands are omitted; see `docs/v10/CLI-MODERN.md` for th
|
|
|
68
70
|
| `loki issues run` | Triage and run open issues; split too-large ones into stacked PRs |
|
|
69
71
|
| `loki undo` | Plan or apply an undo of a run |
|
|
70
72
|
| `loki verify-pr` | Verify a PR against its linked issue in a sandbox |
|
|
71
|
-
| `loki
|
|
73
|
+
| `loki verify-pr respond` | Fix open review comments on the PR branch, one commit each, reply with the sha |
|
|
74
|
+
| `loki answer` | Start a follow-up run from a BLOCKED run with your answer |
|
|
72
75
|
| `loki engine10` | v10 engine router |
|
|
73
76
|
| `loki engine10 run` | Run the v10 engine |
|
|
74
77
|
| `loki engine10 status` | v10 status |
|
package/docs/DEPLOYMENT.md
CHANGED
|
@@ -238,18 +238,25 @@ is the better option if you inject secrets as files rather than env vars.
|
|
|
238
238
|
|
|
239
239
|
---
|
|
240
240
|
|
|
241
|
+
## Issue comment steering and author gate
|
|
242
|
+
|
|
243
|
+
The `issue_comment` event steers a live run. A newly created comment on an issue
|
|
244
|
+
that has a live Loki run (matched by `owner/repo#N`) is written to that run with
|
|
245
|
+
`loki steer`, only when the comment's `author_association` is OWNER, MEMBER or
|
|
246
|
+
COLLABORATOR. Bot comments, edits and deletions are ignored, the body is cut to
|
|
247
|
+
one line of at most 1000 characters, and an unauthorized comment or an issue with
|
|
248
|
+
no live run is skipped with nothing written. Subscribe the webhook to "Issue
|
|
249
|
+
comments" to use it. The `issues` `opened` trigger applies the same author gate;
|
|
250
|
+
set `LOKI_TRIGGER_ALLOW_ANY_ISSUE_AUTHOR=1` to let any author start a build.
|
|
251
|
+
|
|
241
252
|
## Triggers that do not exist yet
|
|
242
253
|
|
|
243
254
|
Documented so you do not go looking for them:
|
|
244
255
|
|
|
245
256
|
- **Issue labelled** (add a `loki` label to start a build). Not implemented.
|
|
246
257
|
The `issues` handler acts on `opened` only.
|
|
247
|
-
- **Issue comment commands** (`/loki build`). Not implemented. The receiver has
|
|
248
|
-
no `issue_comment` handler; GitHub will deliver the event and get back
|
|
249
|
-
`unsupported event: issue_comment`.
|
|
250
258
|
|
|
251
|
-
|
|
252
|
-
ground manually today.
|
|
259
|
+
Not implemented in this release. Path 2 covers the same ground manually today.
|
|
253
260
|
|
|
254
261
|
---
|
|
255
262
|
|
package/docs/EVALUATING.md
CHANGED
|
@@ -217,6 +217,19 @@ Not measured: human effort, recovery success, review quality. Output: `--out-dir
|
|
|
217
217
|
|
|
218
218
|
---
|
|
219
219
|
|
|
220
|
+
## Outcome analytics
|
|
221
|
+
|
|
222
|
+
One set of definitions for the effort and honesty numbers, used by the bench report (`benchmarks/bench/attribution.py`) and by real-run reports (`loki trust`, `.loki/state/interventions.json`, HANDOFF.md). It answers the Factory comparison gate "metrics include failures and measure user effort" (FACTORY_VS_LOKI section 8, P2). Failures are counted, never dropped.
|
|
223
|
+
|
|
224
|
+
- Term accepted outcome: bench, a run whose held-out acceptance check passed. Real runs, a proof with verdict VERIFIED that was not later contradicted by a FAILED outcome.
|
|
225
|
+
- Term misleading completion: Loki or the agent claimed done and was wrong. Bench name `false_completion` = (reported success and not accepted) / reported success. `loki trust` name `false_verified` = VERIFIED claims later FAILED / VERIFIED claims. Same idea, same denominator (claims of success). Null when nothing claimed success.
|
|
226
|
+
- Term cost per accepted: total spend across ALL attempts, failures included, divided by accepted. Null when nothing was accepted, and null when any run's cost is unmeasured (a partial sum is not a total; the bench also reports a lower bound). Never zero for an unknown.
|
|
227
|
+
- Interventions by type: counts of blocking pauses that waited on a person, split into `steer`, `input`, `authorization` and `repair` (a fixed enum, no free text). Written to `.loki/state/interventions.json` at the pause site; shown in `loki trust`, HANDOFF.md and the proof as `interventions_detail`. Absent means not recorded, not zero.
|
|
228
|
+
- Waited versus active minutes: only `waited_s` is measured, the wall-clock seconds a run sat blocked on a person. It is an upper bound on human attention. Active minutes (time a person actually spent working) are NOT measured and are never reported. `loki trust` labels the figure "waited, upper bound".
|
|
229
|
+
- Retries: iterations to completion, taken from the proof `iterations.count` (`loki trust` iterations axis). A retry is not an intervention.
|
|
230
|
+
|
|
231
|
+
---
|
|
232
|
+
|
|
220
233
|
## What we do not have
|
|
221
234
|
|
|
222
235
|
Stating this plainly, because you will find it out anyway and it is cheaper for
|
package/docs/INSTALLATION.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Loki Mode, by [Autonomi](https://www.autonomi.dev/), turns a spec or an issue into a verified pull request with a receipt you can check. This page covers installing it, a first run, and the options around it.
|
|
4
4
|
|
|
5
|
-
**Version:** v11.
|
|
5
|
+
**Version:** v11.15.0
|
|
6
6
|
|
|
7
7
|
**Engine note:** `loki start` is the primary command. `loki start`, `loki "<task>"`, `loki owner/repo#N` and `loki quick` all run the Loki 10 engine, whatever the flag order or input form (PRD file, issue ref, task or one-word brief). The previous loop runs only on `--engine legacy`, `LOKI_ENGINE=legacy`, or for one call when a flag Loki 10 cannot honor is present. See the [user guide](v10/GUIDE.md) and the [5-minute quickstart](QUICKSTART.md).
|
|
8
8
|
|
|
@@ -57,7 +57,7 @@ Required (`loki doctor` fails without them):
|
|
|
57
57
|
|
|
58
58
|
| Tool | Minimum |
|
|
59
59
|
|------|---------|
|
|
60
|
-
| Node.js |
|
|
60
|
+
| Node.js | 20+ (22 LTS is the CI target) |
|
|
61
61
|
| Python 3 | 3.8 |
|
|
62
62
|
| git | any recent version |
|
|
63
63
|
| jq | any |
|
package/docs/SIGNED-RECEIPTS.md
CHANGED
|
@@ -39,6 +39,13 @@ it", not an independent build. A receipt signed by a key the gate does not hold
|
|
|
39
39
|
UNCHECKED and refuses; it is never reported as TAMPERED. Keep retired public
|
|
40
40
|
keys listed after a rotation so old receipts stay VERIFIED.
|
|
41
41
|
|
|
42
|
+
The signed `loki.deploy/1` record also carries the post-deploy facts:
|
|
43
|
+
`health_status`, `health_http_code`, and, when `--auto-rollback` ran, whether the
|
|
44
|
+
rolled-back service answered again (`post_rollback_health`: `healthy`,
|
|
45
|
+
`FAILED_HEALTH` or `unchecked`). A rollback that leaves the service down exits 5.
|
|
46
|
+
With `--health-match STR` the probe body must contain STR, and the record stores
|
|
47
|
+
`health_match` and the deployed `tree_sha`.
|
|
48
|
+
|
|
42
49
|
## Honest limits
|
|
43
50
|
|
|
44
51
|
- A signature proves **provenance and integrity**, not correctness. The
|
package/docs/WORKSPACES.md
CHANGED
|
@@ -36,7 +36,7 @@ loki workspace status <run-id>
|
|
|
36
36
|
- A failing repo does not stop the others (continue and report). The command exits 0 only when every repo succeeded and the integration step did not fail. It exits 3 when the only non-ok outcomes are budget stops (a child exited 3, or a dependent was skipped behind one), and 1 for any other failure. Ctrl-C (SIGINT) stops the recorded child process groups like SIGTERM.
|
|
37
37
|
- The repo that owns the issue ref gets the ref; other repos get a task text naming the ref and the sibling worktree paths as read-only context.
|
|
38
38
|
- After all repos finish, the `integration` command runs once from the run directory with `LOKI_WS_DIR_<OWNER>_<REPO>` pointing at each worktree. A timeout counts as failed. With no integration configured the status is `not_configured`.
|
|
39
|
-
- Evidence is written to `.loki/workspaces/<name>/<run-id>/integration.json`: head SHA per repo, exit code, log sha256. When every repo succeeded, integration did not fail and every child sealed a receipt, the run also seals a signed `composite.json` that binds integration.json and every child receipt (see "Verify a workspace run").
|
|
39
|
+
- Evidence is written to `.loki/workspaces/<name>/<run-id>/integration.json`: head SHA per repo, exit code, log sha256. When every repo succeeded, integration did not fail and every child sealed a receipt, the run also seals a signed `composite.json` that binds integration.json (its status, exit code and log hash), `integration.log`, every repo head SHA and every child receipt (see "Verify a workspace run"). Sealing refuses a failed or interrupted integration run, a nonzero exit code, a missing integrated head and a log that does not match its recorded hash.
|
|
40
40
|
- `loki workspace infer <name>` prints suggested `after:` edges read from package.json, go.mod and pyproject.toml dependencies on other listed repos. It also suggests an edge from (1) a source import (TS/JS import or require, Python import, Go import path) of a sibling's package or module name even when the manifest does not declare it, scanning at most 400 source files per repo, and (2) a client generator config (openapitools.json, openapi-generator*.yaml, orval.config.*) whose input spec path lies inside a sibling checkout. Each inferred edge prints its evidence as `file:line`. It is print-only and cycle-checked; it never edits loki.yaml.
|
|
41
41
|
- `plan: true` (or `LOKI_WORKSPACE_PLAN=1`) makes one provider call that decomposes the brief per repo into `<run-dir>/plan.json`. A valid plan gives each listed repo its own task; an invalid one falls back to the generic text and prints the reason.
|
|
42
42
|
- `integration: {per_stage: true}` also runs the integration command after each topological layer. A failing stage SKIPs every later layer, so a broken contract stops before downstream repos build on it.
|
|
@@ -55,7 +55,7 @@ After `loki workspace run <name> <ref>` finishes, check the evidence rather than
|
|
|
55
55
|
3. `.loki/workspaces/<name>/<run-id>/integration.json` holds `status`, the head SHA per repo and `timing`.
|
|
56
56
|
4. `python3 autonomy/lib/workspace_metrics.py <run-dir> --attention-min <minutes>` prints `prs`, `prs_per_hour` and `prs_per_attention_minute`; any value it cannot measure prints `unmeasured`.
|
|
57
57
|
5. Each repo PR for the run branch carries exactly one integration comment.
|
|
58
|
-
6. `loki verify <run-dir>/composite.json` re-checks the composite offline (add `--pubkey FILE` on another machine). It recomputes the composite hash, re-verifies every child receipt from disk and checks the signature.
|
|
58
|
+
6. `loki verify <run-dir>/composite.json` re-checks the composite offline (add `--pubkey FILE` on another machine). It recomputes the composite hash, re-verifies every child receipt from disk and checks the signature. It prints the integration result and every repo head SHA it attests. It is TAMPERED for a tampered or swapped child, a child head that is not the integrated head, a failed or interrupted integration status or nonzero exit code, an edited integration section, or an `integration.log` that no longer matches its recorded hash. It is UNCHECKED for an unsigned child under a signed composite, and for a legacy composite that predates the integration section and has no integrated head to compare. Deployed-SHA binding is not implemented: the composite attests what was integrated and tested, not what is running anywhere. Exit codes are the single-receipt ones: 0 VERIFIED, 1 TAMPERED, 2 UNCHECKED, 3 UNSIGNED. The composite never reads higher than its weakest child: one PARTIAL child caps it at PARTIAL.
|
|
59
59
|
7. A run that could not seal prints `composite not sealed: <reason>` (for example a repo with no receipt). Seal by hand with `loki verify --seal-composite <run-dir>`; it refuses unless every child has a receipt.
|
|
60
60
|
|
|
61
61
|
Not measured: no scale test exists for large repo counts. Claim only what you have run.
|
package/docs/cost-controls.md
CHANGED
|
@@ -225,3 +225,29 @@ One table in `loki-ts/src/providers/provider_guard.ts` (`CAPABILITIES`) records
|
|
|
225
225
|
| cline | engine10 | estimated | post-iteration | yes | none | yes | no | post-iteration | none |
|
|
226
226
|
| aider | engine10 | estimated | post-iteration | yes | --no-auto-commits | yes | no | post-iteration | none |
|
|
227
227
|
| opencode | engine10 | none | none | yes | none | yes | no | post-iteration | none |
|
|
228
|
+
|
|
229
|
+
### Parallel units and groups
|
|
230
|
+
|
|
231
|
+
A decomposed run (`loki backlog --dag`, or a spec that splits into a unit group) shares one
|
|
232
|
+
total. The resolved cap is exported to every unit as `LOKI_BUDGET_LIMIT`, and the backlog
|
|
233
|
+
runner stops launching pending units with `BUDGET_STOP` once the summed measured cost of
|
|
234
|
+
finished units reaches that cap. Units already running when the cap is crossed finish, so
|
|
235
|
+
the total can overshoot by at most the in-flight units. `budgets.per_run` is accepted as an
|
|
236
|
+
alias of `budgets.per_run_usd` in `loki.yaml`.
|
|
237
|
+
|
|
238
|
+
## A budget stop survives a rerun
|
|
239
|
+
|
|
240
|
+
When the Bun engine stops a run on its dollar cap it writes
|
|
241
|
+
`.loki/runs/<id>/budget.json` with the cap, the amount spent, where the cap
|
|
242
|
+
came from, and the outcome `budget_stopped`. `loki status` shows the latest
|
|
243
|
+
stop, and the run summary's next step reads "raise with --max-cost, then rerun
|
|
244
|
+
the same task".
|
|
245
|
+
|
|
246
|
+
Rerunning the same task does not reset the meter. The supervisor finds the
|
|
247
|
+
newest budget stop for that exact task text and hands its spend to the worker
|
|
248
|
+
as `LOKI_E10_SPENT_USD`, so the cap counts the earlier spend too. To continue,
|
|
249
|
+
raise the cap with `--max-cost`.
|
|
250
|
+
|
|
251
|
+
When a dollar cap is set but the provider reports no cost, the start output
|
|
252
|
+
adds a warning: the cap cannot be enforced, because unmeasured sessions never
|
|
253
|
+
count toward it.
|
package/docs/merge-queue.md
CHANGED
|
@@ -11,3 +11,22 @@ polled (LOKI_MERGE_POLL_S, default 20s; LOKI_MERGE_MAX_POLLS, default 90). After
|
|
|
11
11
|
each merge the next PR is rebased onto the new base and must pass checks again.
|
|
12
12
|
PRs that are red, time out, or fail to rebase stay in the queue; the command
|
|
13
13
|
exits nonzero. Nothing is force-pushed and no check is bypassed.
|
|
14
|
+
|
|
15
|
+
loki merge pr <pr|branch> [--require-verified] [--delete-branch]
|
|
16
|
+
|
|
17
|
+
One PR through the same gate. It is refused (PR left open) when it is a draft,
|
|
18
|
+
when `gh pr checks` is not green after polling, or, with --require-verified,
|
|
19
|
+
when the run verdict is not VERIFIED. The refusal names the gate. `loki start
|
|
20
|
+
--ship` auto-merge uses this command, so it cannot bypass red, pending or draft
|
|
21
|
+
PRs or a non-VERIFIED run.
|
|
22
|
+
|
|
23
|
+
loki merge watch <pr|branch> [--require-verified] [--delete-branch]
|
|
24
|
+
|
|
25
|
+
CI repair loop. Waits for checks; when they are red it passes the failed-run log
|
|
26
|
+
tail to a bounded repair session on the PR branch (LOKI_PR_REPAIR_CMD, default a
|
|
27
|
+
`loki start` of a generated brief; it gets the evidence file path as its last
|
|
28
|
+
argument), pushes, and re-checks, up to LOKI_PR_REPAIR_MAX attempts (default 2).
|
|
29
|
+
Green goes through the same merge gate as `loki merge pr`. When attempts run out
|
|
30
|
+
the PR is returned to draft, nothing merges, and the last failure log is printed.
|
|
31
|
+
`loki start --ship` calls this after it opens the PR; `/merge watch <pr>` runs it
|
|
32
|
+
from `loki chat`.
|
package/docs/sentry-intake.md
CHANGED
|
@@ -20,6 +20,8 @@ The token is sent only to the Sentry host through a curl config on stdin, never
|
|
|
20
20
|
2. Start the server: `python3 autonomy/trigger-server.py --port 8080` and point the Sentry alert webhook at `/sentry`.
|
|
21
21
|
3. A valid alert is normalized with `normalize_sentry_json` and enqueues `loki start "<brief>" --pr --detach`. A bad signature gets 401.
|
|
22
22
|
|
|
23
|
+
The brief also carries the event's release and environment, the newest `.loki/deploys` record (`last deploy <sha7> <finished_at> health=<status>`) and, when the culprit file resolves inside the project, its last `git log -1` author. All of it is sanitized to one line and capped; it adds no authority.
|
|
24
|
+
|
|
23
25
|
The output is a receipt-gated PR only, never a deploy. Whether the PR opens is still decided by the policy file (`autonomy`).
|
|
24
26
|
|
|
25
27
|
|
|
@@ -55,6 +57,8 @@ Teams (`POST /teams`):
|
|
|
55
57
|
2. `Authorization: HMAC <base64>` is the base64 HMAC-SHA256 of the raw body keyed by the base64-decoded token. Bad signature: 401. The activity `timestamp` must be within 300s; a stale or missing one is refused with 401.
|
|
56
58
|
3. The message text (with `<at>` mentions and tags removed) is the brief and runs as `loki start --brief "<brief>" --pr --detach`. Teams gets a synchronous reply whose text starts with "Queued" and ends with the job id. A repeated activity id is not queued twice.
|
|
57
59
|
|
|
60
|
+
Jira completion comments: set `JIRA_BASE_URL` (https only), `JIRA_EMAIL` and `JIRA_API_TOKEN`; the result is then posted as a comment on the issue that triggered the run. Without all three nothing is posted, and `JIRA_API_TOKEN` never reaches the `loki start` child environment.
|
|
61
|
+
|
|
58
62
|
Jira and Teams runs are receipt-gated PR runs only: the server always passes `--pr` and never a deploy argument, so shipping stays a separate gated step. `--brief` forces brief mode, so text that ends in `.md` or contains an issue URL is never reclassified, and `loki start --brief ... --pr/--worktree/--detach` runs in an isolated worktree, detached, and opens a PR carrying the Evidence Receipt (the same machinery as `loki start <issue>`). Sentry alerts use the same form. Neither secret reaches the `loki start` child environment, and both must differ from every other credential. A missing secret answers 503 naming the variable.
|
|
59
63
|
|
|
60
64
|
Reply targets are stored server side keyed by job id, captured only after verification. Notifier errors are logged and never fail the job. Poll status with `GET /jobs/<id>`.
|
package/docs/slack.md
CHANGED
|
@@ -16,12 +16,13 @@ Point the Slack Events API request URL at this server through a tunnel or revers
|
|
|
16
16
|
|
|
17
17
|
- `@loki <issue ref or task text>` in a channel starts a Loki 10 run (it launches `bin/loki "<task>"`; the text must be at least two words and must not start with `-`, otherwise the bot replies asking you to describe the task, so a lone word like `reset` can never reach a legacy subcommand) and replies in the thread with the run id.
|
|
18
18
|
- When the run ends BLOCKED, the question is posted in the same thread. A reply in that thread starts a follow-up run with your answer added to the original task (v10 has no in-place resume, BLOCKED is terminal).
|
|
19
|
+
- The CLI `loki answer` has the same semantics: it starts a fresh follow-up run that carries the original task plus your answer, it does not resume the BLOCKED run.
|
|
19
20
|
- Runs are launched through the repo `bin/loki` with the two Slack secrets removed from the child environment and `LOKI_NO_BROWSER=1` set. A failed Slack post logs one redacted line to stderr.
|
|
20
21
|
- Every request is verified with the Slack signature (HMAC sha256 over `v0:timestamp:body`, constant-time compare, timestamps older than 5 minutes are rejected). Retried events are deduplicated.
|
|
21
22
|
|
|
22
23
|
## Who can start a run
|
|
23
24
|
|
|
24
|
-
Set `LOKI_SLACK_ALLOWED_USERS` to a comma-separated list of Slack user IDs (for example `U012ABC,U034DEF`). A mention or a BLOCKED-thread answer from any other user is rejected with a short thread reply and nothing is spawned. When it is unset
|
|
25
|
+
Set `LOKI_SLACK_ALLOWED_USERS` to a comma-separated list of Slack user IDs (for example `U012ABC,U034DEF`). A mention or a BLOCKED-thread answer from any other user is rejected with a short thread reply and nothing is spawned. When it is unset or blank, every mention is rejected (fail closed) and `loki slack serve` prints one startup line saying so. Set it to `*` to explicitly allow anyone in the workspace. The trigger server `/slack` slash command applies the same variable to the form `user_id`.
|
|
25
26
|
|
|
26
27
|
Limits: task text over 64 KB is rejected with "task too long" and no run starts. If a run cannot be launched, the thread gets a generic message and the detail (which may include local paths) is logged to stderr only. `--port` must be a whole number (an empty value exits 2).
|
|
27
28
|
|
package/docs/trackers.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Jira and Linear intake
|
|
2
2
|
|
|
3
|
-
Loki 10 can start a run from a Jira or Linear issue.
|
|
3
|
+
Loki 10 can start a run from a Jira or Linear issue. The issue is fetched once, before any model runs, and normalized into the same `issue.json` GitHub intake writes (with a `source` field of `jira` or `linear`). Loki can also write the outcome back to the ticket (see Writeback below); it never syncs status beyond that.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
loki jira:PROJ-123
|
|
@@ -14,6 +14,17 @@ loki linear:ENG-42
|
|
|
14
14
|
|
|
15
15
|
A missing variable stops the run with an error that names it. A Linear HTTP 401, or a GraphQL response with errors and no data, also names `LINEAR_API_KEY`.
|
|
16
16
|
|
|
17
|
+
## Writeback
|
|
18
|
+
|
|
19
|
+
When the run starts from a `jira:` or `linear:` ref, `loki start` exports `LOKI_WRITEBACK_ISSUE` with the issue key, and the same credentials used for intake enable writeback. With no ref, writeback stays off unless the legacy `LOKI_JIRA_URL`, `LOKI_JIRA_TOKEN`, `LOKI_JIRA_EMAIL` or `LOKI_LINEAR_TOKEN` variables are set. With nothing configured, no network call is made.
|
|
20
|
+
|
|
21
|
+
- done: a comment with the verdict, the PR URL and the receipt sha256.
|
|
22
|
+
- blocked: a comment that the run needs input, with the reason.
|
|
23
|
+
- failed: a comment that the run ended without a PR, with the reason.
|
|
24
|
+
- started: supported by the contract, with its own comment text; the engine does not emit it today.
|
|
25
|
+
|
|
26
|
+
Optional status moves happen only on done: `LOKI_JIRA_DONE_TRANSITION` (a Jira transition id) and `LOKI_LINEAR_DONE_STATE` (a Linear workflow state id). Failures warn on stderr and never change a verdict or exit code. Tokens are never logged.
|
|
27
|
+
|
|
17
28
|
## Self-hosted Jira
|
|
18
29
|
|
|
19
30
|
`<JIRA_BASE_URL>/browse/KEY` is accepted as a ref only when its origin equals the origin of `JIRA_BASE_URL`. A browse URL on any other host is not treated as a tracker ref.
|