loki-mode 10.8.0 → 10.10.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/.github/actions/issue-to-pr/action.yml +2 -2
- package/README.md +11 -5
- package/SKILL.md +12 -2
- package/VERSION +1 -1
- package/autonomy/lib/proof-generator.py +1 -0
- package/autonomy/loki +55 -40
- package/autonomy/receipt_jwt.py +46 -1
- package/autonomy/run.sh +1 -1
- package/autonomy/telemetry.sh +1 -1
- package/autonomy/trigger-server.py +1 -0
- package/autonomy/tui.sh +5 -1
- package/bin/loki +12 -1
- package/bin/loki-postinstall.js +12 -0
- package/dashboard/__init__.py +1 -1
- package/dashboard/api_phases.py +1 -1
- package/dashboard/api_start.py +0 -1
- package/dashboard/server.py +22 -138
- package/docs/CLI-REFERENCE.md +139 -0
- package/docs/COCKPIT-SPEC.md +3 -1
- package/docs/DASHBOARD-9.12-EVIDENCE.md +1 -1
- package/docs/DASHBOARD-ARCHITECTURE.md +13 -11
- package/docs/DASHBOARD_V2_CHECKLIST.md +2 -0
- package/docs/INSTALLATION.md +12 -11
- package/docs/LOKI-10-BUILD-PROMPT.md +2 -2
- package/docs/MERGE-DEDUP-MAP.md +1 -1
- package/docs/MERGE-ROUTE-MAP.md +1 -1
- package/docs/MERGE3-PLAN.md +2 -2
- package/docs/PLANS-INDEX.md +2 -3
- package/docs/R3-COST-OBSERVABILITY-DESIGN.md +2 -2
- package/docs/R4-TRUST-TRAJECTORY-DESIGN.md +1 -1
- package/docs/R5-AUTO-WIKI-DESIGN.md +1 -1
- package/docs/R6-ROLLBACK-CHECKPOINT-PLAN.md +1 -1
- package/docs/RARV-C-100X-PLAN.md +3 -3
- package/docs/SLO.md +3 -3
- package/docs/SONNET5-DEFAULT-PLAN.md +2 -2
- package/docs/SYNERGY-TASKS.md +1 -1
- package/docs/TOOL-INTEGRATION.md +1 -1
- package/docs/TOP-100-BACKLOG.md +1 -1
- package/docs/alternative-installations.md +2 -2
- package/docs/architecture/ADR-001-runtime-migration.md +1 -1
- package/docs/architecture/DASHBOARD_V2_ARCHITECTURE.md +2 -0
- package/docs/audit-logging.md +2 -0
- package/docs/authentication.md +2 -0
- package/docs/authorization.md +2 -0
- package/docs/bug-fixes/agent-04-memory-fixes.md +1 -1
- package/docs/certification/02-enterprise-features/lab.md +2 -0
- package/docs/certification/02-enterprise-features/lesson.md +2 -0
- package/docs/certification/04-production-deployment/lab.md +2 -0
- package/docs/certification/04-production-deployment/lesson.md +2 -0
- package/docs/control-plane-migration.md +97 -0
- package/docs/dashboard-guide.md +6 -7
- package/docs/dev/release-checklist.md +10 -12
- package/docs/enterprise/integration-cookbook.md +2 -0
- package/docs/enterprise/migration.md +1 -1
- package/docs/enterprise/performance.md +3 -1
- package/docs/enterprise/sdk-guide.md +2 -0
- package/docs/enterprise/security.md +2 -0
- package/{.github/workflows/loki-issue-to-pr.yml → docs/examples/loki-issue-to-pr.yml.example} +2 -0
- package/docs/{ONE-RUN-AUDIT.md → history/one-run-audit.md} +6 -0
- package/docs/{BUG-AUDIT-v6.61.0.md → history/v6.61.0-audit.md} +6 -0
- package/docs/{V8-AGENT-SDK-PLAN.md → history/v8-agent-sdk-plan.md} +6 -0
- package/docs/{CONFIG-FILE-PLAN.md → history/v8-config-plan.md} +6 -0
- package/docs/plans/FORGE-AUTONOMOUS-QUEUE.md +2 -2
- package/docs/research-2026-07/OBSERVABILITY-TOOL-SPEC.md +1 -1
- package/docs/retrospectives/v7.5.15-honesty-audit.md +2 -2
- package/docs/test-scenarios/enterprise-scenarios.md +3 -3
- package/docs/v10/ARCHITECT-CUTS.md +9 -9
- package/docs/v10/BACKLOG.md +7 -7
- package/docs/v10/BOARD.md +28 -25
- package/docs/v10/CLI-MODERN.md +190 -0
- package/docs/v10/CONTROL-PLANE.md +4 -4
- package/docs/v10/CP-ENTERPRISE-UI.md +66 -66
- package/docs/v10/D51-PHASE-B.md +1 -1
- package/docs/v10/DECISIONS.md +3 -3
- package/docs/v10/DEPS.md +148 -169
- package/docs/v10/FAILURE-CLASSES.md +63 -1
- package/docs/v10/LEGACY-REMOVAL.md +335 -26
- package/docs/v10/PROGRESS.md +15 -0
- package/docs/v10/SWARM.md +2 -2
- package/loki-ts/dist/cockpit.js +11 -11
- package/loki-ts/dist/loki.js +1610 -1813
- package/magic/core/design_tokens.py +1 -2
- package/magic/core/generator.py +2 -2
- package/magic/tokens/README.md +1 -3
- package/mcp/__init__.py +1 -1
- package/package.json +4 -8
- package/packages/control-plane/dist/server.js +1956 -1019
- package/packages/control-plane/src/db/fixture-cleanup.ts +47 -0
- package/packages/control-plane/src/server/app.ts +2 -0
- package/packages/control-plane/src/server/integrity.ts +48 -9
- package/packages/control-plane/src/server/legacy/routes-audit.ts +50 -0
- package/packages/control-plane/src/server/legacy/routes-control.ts +26 -0
- package/packages/control-plane/src/server/legacy/routes-memory.ts +30 -0
- package/packages/control-plane/src/server/legacy/routes.ts +58 -58
- package/packages/control-plane/src/server/legacy/shim.ts +10 -4
- package/packages/control-plane/src/server/routes/checkpoints.ts +171 -0
- package/packages/control-plane/src/server/routes/index.ts +4 -1
- package/packages/control-plane/src/server/routes/memory.ts +219 -0
- package/packages/control-plane/src/server/routes/session_control.ts +155 -0
- package/packages/control-plane/src/server/routes/stats.ts +16 -5
- package/packages/control-plane/src/server/runs.ts +16 -4
- package/packages/control-plane/ui/dist/assets/index-NAMkcA9N.js +165 -0
- package/packages/control-plane/ui/dist/index.html +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/references/magic-modules-patterns.md +2 -2
- package/schemas/status-result.schema.json +13 -22
- package/skills/factory-operations.md +3 -3
- package/skills/magic-modules.md +1 -1
- package/skills/release-cadence.md +6 -6
- package/tools/audit-docs.py +1 -1
- package/tools/index-codebase.py +1 -1
- package/web-app/dist/assets/{AdminPage-DDDvUz0N.js → AdminPage-B8RjG3sy.js} +1 -1
- package/web-app/dist/assets/{Avatar-Dcdz46i6.js → Avatar-Dttmvqc-.js} +1 -1
- package/web-app/dist/assets/{Badge-BB24cCpK.js → Badge-Bvyp8VrD.js} +1 -1
- package/web-app/dist/assets/{Button-D0-DmPZL.js → Button-DtY5ZrZw.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-CdjpU2JW.js → CockpitPage-B2gbOwRp.js} +1 -1
- package/web-app/dist/assets/{ComparePage-DT5U0y0d.js → ComparePage-CHi5nZTU.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-lEHcl0EO.js → ErrorBoundary-BUuTj-OQ.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-GpnWvdCr.js → EvidenceReceiptPanel-C5aOn4ES.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-C7VOh1B7.js → GitHubIssuesPanel-isVxxHXb.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-G_kOuINv.js → GitHubPRsPanel-DtDpxyQl.js} +1 -1
- package/web-app/dist/assets/{HomePage-PqRisOny.js → HomePage-Casf-LUB.js} +2 -2
- package/web-app/dist/assets/{LoginPage-DU7pFAkf.js → LoginPage-DvB78691.js} +1 -1
- package/web-app/dist/assets/{MagicPage-C5JWIWMk.js → MagicPage-DU6hmbnC.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-CbIGS_qo.js → MetricsPage-DcPwzoS8.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-vU1pvdSt.js → NotFoundPage-Bs6WxAZ8.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-SsixIPPv.js → ProjectPage-RBIqC-DJ.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-BfQKSR9k.js → ProjectsPage-CogXD7jM.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-B8YfXAom.js → SettingsPage-pAyJAfPt.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-Ba407f2-.js → ShowcasePage-D6bT2bDd.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-DzNQhhBS.js → SystemSettingsPage-CE8xiJRh.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-tqUnpZ15.js → TeamsPage-wMS55TDT.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-ClB5EpI3.js → TemplatesPage-COJNVQqu.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-CBvpYfEu.js → TerminalOutput-Cc2XASxd.js} +1 -1
- package/web-app/dist/assets/{activity-C1s0L_X9.js → activity-C6eHFDjL.js} +1 -1
- package/web-app/dist/assets/{bell-DMEiXr73.js → bell-BJpVYj4n.js} +1 -1
- package/web-app/dist/assets/{bot-BF_xIOxu.js → bot-BwRVVUQL.js} +1 -1
- package/web-app/dist/assets/{check-Dv1Ynvrs.js → check-CGDwoKy8.js} +1 -1
- package/web-app/dist/assets/{chevron-left-Ddhsod7S.js → chevron-left-CF2Nilj6.js} +1 -1
- package/web-app/dist/assets/{circle-alert-OATHUkBZ.js → circle-alert-D0RyRec1.js} +1 -1
- package/web-app/dist/assets/{clock-C1Ltva07.js → clock-xeF3gW0W.js} +1 -1
- package/web-app/dist/assets/{cloud-B-S4oOy9.js → cloud-D5Sy69ZZ.js} +1 -1
- package/web-app/dist/assets/{code-xml-D3Femn_F.js → code-xml-C6-5Ql9I.js} +1 -1
- package/web-app/dist/assets/{database-DBSeFgO3.js → database-BSjG1_z0.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-sgDgNuGE.js → dollar-sign-FnDR2QUu.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-C-MbdZEc.js → file-code-corner-BiOK9vR6.js} +1 -1
- package/web-app/dist/assets/{file-plus-CCB6yqXv.js → file-plus-3WALQDEE.js} +1 -1
- package/web-app/dist/assets/{globe-DlbrNAj1.js → globe-vUdUrQqp.js} +1 -1
- package/web-app/dist/assets/{hammer-B-DWm695.js → hammer-0VwHUEpa.js} +1 -1
- package/web-app/dist/assets/{index-Dvny-1SU.js → index-BMKIwteZ.js} +3 -3
- package/web-app/dist/assets/{layers-99qsKpOT.js → layers-C6q8kzST.js} +1 -1
- package/web-app/dist/assets/{loader-circle-ZvZyZl3J.js → loader-circle-B4Tz724d.js} +1 -1
- package/web-app/dist/assets/{lock-DosGjcxP.js → lock-yxvEA65n.js} +1 -1
- package/web-app/dist/assets/{package-C-PumesN.js → package-BpKD0Ot0.js} +1 -1
- package/web-app/dist/assets/{plus-CTYYskTB.js → plus-Ibqx_Vo9.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-qW2ztTFS.js → refresh-cw-C9auyvi-.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-ZIKrf-vO.js → rotate-ccw-2cEiXm6O.js} +1 -1
- package/web-app/dist/assets/{scroll-text-BamlXjAT.js → scroll-text-BPAWML-w.js} +1 -1
- package/web-app/dist/assets/{server-BljXb79I.js → server-CZh6B1zx.js} +1 -1
- package/web-app/dist/assets/{shield-alert-Dr6eT9c_.js → shield-alert-CivolUIx.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-v3oBXZgU.js → thumbs-up-BP9covEH.js} +1 -1
- package/web-app/dist/assets/{trash-2-BOuIrCpi.js → trash-2-BCDfTcNx.js} +1 -1
- package/web-app/dist/assets/{trending-down-Dp7jMCgH.js → trending-down-5LypivXh.js} +1 -1
- package/web-app/dist/assets/{trending-up-CDiur-nP.js → trending-up-DNt4SFdk.js} +1 -1
- package/web-app/dist/assets/{upload-DxIHXhNE.js → upload-DBmHbY6y.js} +1 -1
- package/web-app/dist/assets/{usePolling-D2Uu-YZb.js → usePolling-DOPZcbUL.js} +1 -1
- package/web-app/dist/assets/{user-BVWCUAfF.js → user-BQTJJDCG.js} +1 -1
- package/web-app/dist/index.html +1 -1
- package/dashboard/static/assets/mermaid.min.js +0 -2030
- package/dashboard/static/cost.html +0 -344
- package/dashboard/static/favicon.svg +0 -5
- package/dashboard/static/index.html +0 -15577
- package/dashboard/static/proofs.html +0 -194
- package/dashboard/static/start.html +0 -131
- package/dashboard/static/trust.html +0 -325
- package/docs/BRANCH-LIFECYCLE-PLAN.md +0 -354
- package/docs/EXECUTION-COCKPIT-PLAN.md +0 -289
- package/packages/control-plane/ui/dist/assets/index-Dbhu244h.js +0 -155
|
@@ -10,7 +10,7 @@ branding:
|
|
|
10
10
|
# must not hold a write token. Run it with `permissions: contents: read,
|
|
11
11
|
# issues: read` and `actions/checkout` with `persist-credentials: false`, upload
|
|
12
12
|
# `outputs.patch`, and push and open the PR from a second job that runs no
|
|
13
|
-
# agent.
|
|
13
|
+
# agent. docs/examples/loki-issue-to-pr.yml.example in asklokesh/loki-mode is the
|
|
14
14
|
# reference. Earlier versions pushed and opened the PR from the same step that
|
|
15
15
|
# ran the agent; this one does not.
|
|
16
16
|
#
|
|
@@ -247,7 +247,7 @@ runs:
|
|
|
247
247
|
echo "patch=$OUT/loki.patch" >> "$GITHUB_OUTPUT"
|
|
248
248
|
echo "pr_body=$OUT/pr-body.md" >> "$GITHUB_OUTPUT"
|
|
249
249
|
|
|
250
|
-
echo "::warning::This action does not open the pull request (Rule of Two). Upload outputs.patch and open the PR from a job that holds the write token and runs no agent; see
|
|
250
|
+
echo "::warning::This action does not open the pull request (Rule of Two). Upload outputs.patch and open the PR from a job that holds the write token and runs no agent; see docs/examples/loki-issue-to-pr.yml.example in asklokesh/loki-mode."
|
|
251
251
|
if [ -n "$RUN_DIR" ]; then
|
|
252
252
|
echo "Loki 10 receipt under $RUN_DIR/"
|
|
253
253
|
fi
|
package/README.md
CHANGED
|
@@ -9,6 +9,12 @@ An autonomous software factory that knows what it is supposed to deliver, and pr
|
|
|
9
9
|
|
|
10
10
|
[Website](https://www.autonomi.dev/) | [Documentation](wiki/Home.md) | [Installation](docs/INSTALLATION.md) | [Changelog](CHANGELOG.md)
|
|
11
11
|
|
|
12
|
+
<!-- generated:facts -->
|
|
13
|
+
The npm badge above tracks the current release; see [CHANGELOG.md](CHANGELOG.md) for release notes.
|
|
14
|
+
|
|
15
|
+
CLI reference: [docs/CLI-REFERENCE.md](docs/CLI-REFERENCE.md) (generated from the command registry).
|
|
16
|
+
<!-- /generated -->
|
|
17
|
+
|
|
12
18
|
Loki Mode is a free, source-available autonomous coding agent by [Autonomi](https://www.autonomi.dev/). Hand it a PRD, GitHub issue, OpenAPI doc or one-line brief. It derives a delivery contract (the acceptance criteria), builds against it, and ends with a signed Evidence Receipt that states what was proven and what was not. If the contract cannot be derived, it stops and asks one question instead of guessing.
|
|
13
19
|
|
|
14
20
|
Before a build counts as done, a review council selects reviewers from a specialist pool (`agents/types.json`, scored by `run.sh:FOCUS_KEYWORDS`). The bundled MCP server exposes 39 tools over stdio (`mcp/server.py`), including `loki_v10_run`, `loki_v10_status` and `loki_v10_verify` to start a Loki 10 run in the background, read its phase, verdict and cost, and verify its receipt (`BLOCKED` runs report their question). Add it with `claude mcp add loki-mode -- python3 -m mcp.server` from the install directory.
|
|
@@ -88,7 +94,7 @@ loki owner/repo#123
|
|
|
88
94
|
|
|
89
95
|
The v10 engine accepts a quoted multi-word task, a GitHub, GitLab or Jira issue reference, `status`, `verify`, `dashboard`, and other subcommands. Flags (`loki-ts/src/engine10/cli.ts` USAGE): `--no-pr` builds and verifies without opening a pull request, `--deep` requests the deep verify pass and a longer implement budget, `--provider <name>` picks the coding provider, `--max-cost <usd>` sets the per-run cost cap (default $100.00 when an API key is set, no dollar cap on a subscription run where the start line adds `subscription: no dollar cap; usage counts against your plan limits`; or `budgets.per_run` in `loki.yaml`; the flag wins; the start line prints it as `cap $100.00 (default)`; reaching it ends the run BUDGET_STOP, exit 3) (`--json` and `--verbose` are also parsed by the supervisor, see [Quiet output](#quiet-output)). The engine needs Bun; without it the command exits 1 with a message and installation instructions.
|
|
90
96
|
|
|
91
|
-
**Legacy engine (being removed).**
|
|
97
|
+
**Legacy engine (being removed).** Migration note: the previous engine is being removed and has no engine switch; use `loki "<task>"` and `loki owner/repo#N`. `loki start owner/repo#N`, `loki start <issue URL>` and `loki start "<multi-word task>"` run on Loki 10, the same as `loki owner/repo#N` and `loki "<task>"`; `loki start ./prd.md`, a flag-first call and a one-word start stay on the legacy engine. For many issues use `loki backlog owner/repo --all|--label X|--issues N,N` (many issues, N in parallel, each on a `loki/backlog-N` worktree branch) instead. Legacy removal is planned and resumes on 2026-10-07; see [docs/v10/LEGACY-REMOVAL.md](docs/v10/LEGACY-REMOVAL.md). Sections below marked "legacy" describe features that run only on that engine.
|
|
92
98
|
|
|
93
99
|
### The state machine
|
|
94
100
|
|
|
@@ -154,7 +160,7 @@ The run cap is 900s (2700s with `--deep`, `DEFAULT_CAP_S` and `DEEP_CAP_S` in `t
|
|
|
154
160
|
|
|
155
161
|
A finished run prints a short summary (see [Quiet output](#quiet-output), which also shows an example) whose `NOT PROVEN` line is never empty by omission: deep checks deferred to the deep-verify pass are always listed there.
|
|
156
162
|
|
|
157
|
-
`loki status [run-id]` and `loki verify [run-id]` are built on the v10 path (bare `loki verify` follows the newest run, v10 or legacy).
|
|
163
|
+
`loki status [run-id]` and `loki verify [run-id]` are built on the v10 path (bare `loki verify` follows the newest run, v10 or legacy). Two-way Slack (`loki slack serve`) is on by default and documented in [docs/slack.md](docs/slack.md); outbound notifications use `LOKI_SLACK_WEBHOOK_URL`.
|
|
158
164
|
|
|
159
165
|
## Run from Jira or Linear
|
|
160
166
|
|
|
@@ -182,7 +188,7 @@ On by default; set `LOKI_CONTRACT=0` to turn it off. It does nothing unless `.lo
|
|
|
182
188
|
|
|
183
189
|
Both run on your own GitHub Actions minutes; there is no hosted service.
|
|
184
190
|
|
|
185
|
-
- Issue to PR: copy `.github/workflows/loki-issue-to-pr.yml`
|
|
191
|
+
- Issue to PR: copy `docs/examples/loki-issue-to-pr.yml.example` to `.github/workflows/loki-issue-to-pr.yml` in your repository. Label an issue `loki`, or comment `/loki` as an owner, member or collaborator, and it runs `loki owner/repo#N` (the Loki 10 engine) and opens a pull request with an evidence receipt. The agent job holds a read-only token; a separate publish job opens the PR. Set `ANTHROPIC_API_KEY` in repository secrets.
|
|
186
192
|
- Nightly backlog: copy `examples/loki-nightly-backlog.yml` into `.github/workflows/`. Its `schedule:` trigger runs `loki backlog owner/repo --label loki`, one Loki 10 run per labeled open issue:
|
|
187
193
|
|
|
188
194
|
```yaml
|
|
@@ -310,7 +316,7 @@ The URL comes from `LOKI_CONTROL_URL`, else `http://127.0.0.1:${LOKI_CONTROL_POR
|
|
|
310
316
|
|
|
311
317
|
Answering a BLOCKED run: when a run stops on a spec conflict, its run page shows the question and an answer box. Submitting posts to `POST /v1/runs/<source>/<run>/answer` (JSON `{"answer": "..."}`, up to 4000 characters, loopback only) and writes `~/.loki/control/answers/<source>/<run>.answer.txt` (override the directory with `LOKI_CONTROL_ANSWER_DIR`). The page prints the resume command, `loki answer <run>`, which starts a fresh run carrying the task, the question and that file's text (or pass `--text "..."` yourself; with no run id it picks the newest BLOCKED run). A run that is not BLOCKED exits 2.
|
|
312
318
|
|
|
313
|
-
|
|
319
|
+
The Control Plane is the only UI. `loki dashboard`, `loki dashboard start` and `loki dashboard open` open it (starting `loki control serve` if none is running). The classic dashboard UI and its port 57374 are removed in 10.8; see [docs/control-plane-migration.md](docs/control-plane-migration.md) for the route mapping and what is not yet available.
|
|
314
320
|
|
|
315
321
|
Container, Helm and ECS deployment: [docs/control-plane-container.md](docs/control-plane-container.md).
|
|
316
322
|
|
|
@@ -588,7 +594,7 @@ Legacy engine, being removed (these run on the previous engine; `loki --help` st
|
|
|
588
594
|
| `loki stop`, `pause`, `resume` | Control a legacy run |
|
|
589
595
|
| `loki steer "<note>"` | Nudge a legacy run (needs `LOKI_PROMPT_INJECTION=1`) |
|
|
590
596
|
| `loki why`, `loki next` | Explain or continue a legacy run |
|
|
591
|
-
| `loki dashboard` |
|
|
597
|
+
| `loki dashboard` | Open the Control Plane UI (see [docs/control-plane-migration.md](docs/control-plane-migration.md)) |
|
|
592
598
|
| `loki review`, `loki test`, `loki analyze`, `loki memory`, `loki failover`, `loki enterprise`, `loki import`, `loki ci` | Review, test generation, codebase analysis, memory, failover, enterprise, issue import, CI gate |
|
|
593
599
|
| `loki modernize heal <path>` | Legacy system healing |
|
|
594
600
|
|
package/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: loki-mode
|
|
|
3
3
|
description: An autonomous software factory that knows what it is supposed to deliver, and proves it did. Use when the user says Loki Mode or asks to build, fix or verify software autonomously.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Loki Mode v10.
|
|
6
|
+
# Loki Mode v10.10.1
|
|
7
7
|
|
|
8
8
|
**Current entry points (Loki 10 engine):** `loki "<task>"`, `loki owner/repo#N` and `loki quick "<task>"` run the Loki 10 engine and end with a signed receipt (`loki verify`). `loki backlog owner/repo --all` runs many issues in parallel. Guide: `docs/v10/GUIDE.md`. The skill instructions below, and `loki start`, describe the legacy engine, which still ships and is being removed (`loki start owner/repo#N` still routes to it; prefer `loki owner/repo#N`).
|
|
9
9
|
|
|
@@ -195,6 +195,16 @@ This protocol governs **skill module** loading -- task-scoped instruction files
|
|
|
195
195
|
|
|
196
196
|
---
|
|
197
197
|
|
|
198
|
+
## Command list
|
|
199
|
+
|
|
200
|
+
<!-- generated:commands -->
|
|
201
|
+
Commands (generated from `loki-ts/src/cli/registry.ts`; full reference in `docs/CLI-REFERENCE.md`):
|
|
202
|
+
|
|
203
|
+
`version`, `status`, `doctor`, `provider`, `memory`, `rollback`, `proof`, `wiki`, `control`, `kpis`, `report`, `trust`, `crash`, `contract`, `start`, `slack`, `answer`, `engine10`, `help`, `quick`, `quickstart`, `init`, `template`, `verify`, `keys`, `review`, `dashboard`, `config`, `mcp`, `acp`, `stop`, `pause`, `resume`, `why`, `next`, `logs`, `ship`, `deploy`, `import`, `github`, `issue`, `ci`, `modernize`, `share`, `assets`, `export`, `notify`, `tour`, `welcome`, `onboard`, `setup-skill`, `self-update`, `remote`, `cockpit`, `code`, `context`, `secrets`, `api`, `sandbox`, `docker`, `web`, `preview`, `telemetry`, `syslog`, `explain`, `docs`, `test`, `bench`, `voice`, `own`, `secure`, `compliance`, `enterprise`, `projects`, `audit`, `cost`, `metrics`, `sentrux`, `magic`
|
|
204
|
+
<!-- /generated -->
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
198
208
|
## Invocation
|
|
199
209
|
|
|
200
210
|
**Legacy entry point (v6.84.0, being removed; for Loki 10 use `loki "<task>"` or `loki owner/repo#N`):** `loki start [SPEC|ISSUE-REF]` auto-detects whether the input is a PRD file, an issue URL, an issue number, or another spec format (e.g. OpenAPI). No need to pick between `loki start` and `loki run` -- the single command handles all cases.
|
|
@@ -473,4 +483,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
|
|
|
473
483
|
|
|
474
484
|
---
|
|
475
485
|
|
|
476
|
-
**v10.
|
|
486
|
+
**v10.10.1 | [Autonomi](https://www.autonomi.dev/) flagship product | core skill**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
10.
|
|
1
|
+
10.10.1
|
package/autonomy/loki
CHANGED
|
@@ -918,7 +918,7 @@ import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
|
918
918
|
import json, sys, hashlib, urllib.request
|
|
919
919
|
sys.path.insert(0, sys.argv[3])
|
|
920
920
|
try:
|
|
921
|
-
from receipt_jwt import verify_attestation, _CRYPTO_AVAILABLE
|
|
921
|
+
from receipt_jwt import verify_attestation, check_seal_meta, _CRYPTO_AVAILABLE
|
|
922
922
|
except ImportError:
|
|
923
923
|
sys.exit(1) # -> "" : cannot check, never a verdict
|
|
924
924
|
proof = json.load(open(sys.argv[1]))
|
|
@@ -966,10 +966,14 @@ if not ok:
|
|
|
966
966
|
# receipt. Recompute the digest the same way the receipt records it (with
|
|
967
967
|
# `verification` stripped) and require the signed claim to match, or a valid
|
|
968
968
|
# token lifted from a different run would vouch for these bytes.
|
|
969
|
-
proof.pop("verification", None)
|
|
969
|
+
_vmeta = proof.pop("verification", None)
|
|
970
970
|
canon = json.dumps(proof, sort_keys=True, separators=(",", ":")).encode()
|
|
971
|
-
|
|
972
|
-
|
|
971
|
+
if claims.get("receipt_sha256") != hashlib.sha256(canon).hexdigest():
|
|
972
|
+
print("bad"); sys.exit(0)
|
|
973
|
+
# seal.v2: the verification.* metadata (scope, algo, attestation_kid, ...) is
|
|
974
|
+
# inside the signature; a token that signs different metadata is refused. A
|
|
975
|
+
# legacy seal.v1 token still verifies (its metadata is simply unsigned).
|
|
976
|
+
print("ok" if check_seal_meta(tok, claims, _vmeta)[0] != "bad" else "bad")
|
|
973
977
|
PY
|
|
974
978
|
}
|
|
975
979
|
|
|
@@ -1052,7 +1056,7 @@ import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
|
1052
1056
|
import json, sys, os, hashlib, urllib.request
|
|
1053
1057
|
sys.path.insert(0, sys.argv[3])
|
|
1054
1058
|
try:
|
|
1055
|
-
from receipt_jwt import verify_attestation, _CRYPTO_AVAILABLE
|
|
1059
|
+
from receipt_jwt import verify_attestation, check_seal_meta, _CRYPTO_AVAILABLE
|
|
1056
1060
|
except ImportError:
|
|
1057
1061
|
sys.exit(1) # "" : cannot check
|
|
1058
1062
|
try:
|
|
@@ -1117,10 +1121,32 @@ if not ok:
|
|
|
1117
1121
|
# A verifying signature is not enough: it must attest to THESE bytes. Recompute
|
|
1118
1122
|
# the digest the way the receipt records it, so a token lifted from another run
|
|
1119
1123
|
# cannot vouch for this one.
|
|
1120
|
-
proof.pop("verification", None)
|
|
1124
|
+
_vmeta = proof.pop("verification", None)
|
|
1121
1125
|
canon = json.dumps(proof, sort_keys=True, separators=(",", ":")).encode()
|
|
1122
|
-
|
|
1123
|
-
|
|
1126
|
+
if claims.get("receipt_sha256") != hashlib.sha256(canon).hexdigest():
|
|
1127
|
+
print("bad"); sys.exit(0)
|
|
1128
|
+
# seal.v2: the verification.* metadata (scope, algo, attestation_kid, ...) is
|
|
1129
|
+
# inside the signature; a token that signs different metadata is refused. A
|
|
1130
|
+
# legacy seal.v1 token still verifies (its metadata is simply unsigned).
|
|
1131
|
+
print("ok" if check_seal_meta(tok, claims, _vmeta)[0] != "bad" else "bad")
|
|
1132
|
+
PY
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
# Prints "legacy" when the receipt's attestation is a seal.v1 token (the
|
|
1136
|
+
# verification.* metadata is NOT inside the signature), else nothing. Callers
|
|
1137
|
+
# append "metadata not signed (legacy seal.v1)" to a VERIFIED line.
|
|
1138
|
+
loki_proof_seal_legacy() {
|
|
1139
|
+
python3 -E - "$1" "${_LOKI_SCRIPT_DIR}" 2>/dev/null <<'PY' || true
|
|
1140
|
+
import sys; sys.path[:] = [p for p in sys.path if p not in ("", ".")]
|
|
1141
|
+
import json, sys
|
|
1142
|
+
sys.path.insert(0, sys.argv[2])
|
|
1143
|
+
from receipt_jwt import _b64url_decode
|
|
1144
|
+
try:
|
|
1145
|
+
tok = json.load(open(sys.argv[1]))["verification"]["attestation"]
|
|
1146
|
+
claims = json.loads(_b64url_decode(tok.split(".")[1]))
|
|
1147
|
+
print("legacy" if "seal" not in claims else "")
|
|
1148
|
+
except Exception:
|
|
1149
|
+
print("")
|
|
1124
1150
|
PY
|
|
1125
1151
|
}
|
|
1126
1152
|
|
|
@@ -2032,12 +2058,11 @@ cmd_ui() {
|
|
|
2032
2058
|
LOKI_DASHBOARD_CORS="http://localhost:$port,http://127.0.0.1:$port" \
|
|
2033
2059
|
cmd_dashboard_start --host 127.0.0.1 --port "$port" >&2 || return 1
|
|
2034
2060
|
fi
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
fi
|
|
2061
|
+
# The classic server is API-only; the UI is the Control Plane.
|
|
2062
|
+
local url="http://127.0.0.1:${port}"
|
|
2063
|
+
echo "loki: the classic dashboard at $url serves the API only (the browser UI moved to the Control Plane)." >&2
|
|
2064
|
+
echo "loki: start the Control Plane UI with: loki ui (needs bun)" >&2
|
|
2065
|
+
echo "$url"
|
|
2041
2066
|
}
|
|
2042
2067
|
|
|
2043
2068
|
# Tight newcomer landing for the bare `loki` invocation (no args).
|
|
@@ -3915,18 +3940,9 @@ cmd_start() {
|
|
|
3915
3940
|
# + cockpit, honoring the card's "open dashboard" promise. The
|
|
3916
3941
|
# cockpit hint is printed by _loki_start_handoff for the Both path.
|
|
3917
3942
|
args+=("--bg")
|
|
3918
|
-
#
|
|
3919
|
-
#
|
|
3920
|
-
|
|
3921
|
-
# stay unredirected: loki_open_url checks the TTY.
|
|
3922
|
-
local _dfile="${PWD}/.loki/dashboard/url"
|
|
3923
|
-
rm -f "$_dfile" 2>/dev/null
|
|
3924
|
-
(
|
|
3925
|
-
for _ in $(seq 1 120); do
|
|
3926
|
-
if [ -s "$_dfile" ]; then loki_open_url "$(head -1 "$_dfile")" 2>/dev/null; exit 0; fi
|
|
3927
|
-
sleep 0.5
|
|
3928
|
-
done
|
|
3929
|
-
) &
|
|
3943
|
+
# The browser UI is the Control Plane; open it (guarded by
|
|
3944
|
+
# loki_open_url: no-op headless and in tests).
|
|
3945
|
+
( LOKI_UI_NO_CLASSIC=1 cmd_ui 2>/dev/null || true ) &
|
|
3930
3946
|
;;
|
|
3931
3947
|
launch-bg-watch)
|
|
3932
3948
|
# Watch (cockpit only) detaches without opening the browser.
|
|
@@ -7561,7 +7577,7 @@ cmd_dashboard_help() {
|
|
|
7561
7577
|
echo " loki dashboard start --tls-cert cert.pem --tls-key key.pem"
|
|
7562
7578
|
echo " loki dashboard status # Check if running"
|
|
7563
7579
|
echo " loki dashboard url --format json # Get URL as JSON"
|
|
7564
|
-
echo " loki dashboard open #
|
|
7580
|
+
echo " loki dashboard open # Print the Control Plane hint (no browser)"
|
|
7565
7581
|
echo " loki dashboard stop # Stop server"
|
|
7566
7582
|
}
|
|
7567
7583
|
|
|
@@ -7789,7 +7805,7 @@ cmd_dashboard_start() {
|
|
|
7789
7805
|
# a second port.
|
|
7790
7806
|
echo -e "${DIM}Want to submit a spec in the browser? Open the 'Lab' tab in this dashboard.${NC}"
|
|
7791
7807
|
echo ""
|
|
7792
|
-
echo -e "
|
|
7808
|
+
echo -e "Control Plane UI: ${CYAN}loki ui${NC}"
|
|
7793
7809
|
echo -e "Check status: ${CYAN}loki dashboard status${NC}"
|
|
7794
7810
|
echo -e "Stop server: ${CYAN}loki dashboard stop${NC}"
|
|
7795
7811
|
else
|
|
@@ -7907,7 +7923,7 @@ cmd_dashboard_status() {
|
|
|
7907
7923
|
fi
|
|
7908
7924
|
|
|
7909
7925
|
echo ""
|
|
7910
|
-
echo -e "
|
|
7926
|
+
echo -e "Control Plane UI: ${CYAN}loki ui${NC}"
|
|
7911
7927
|
echo -e "Stop server: ${CYAN}loki dashboard stop${NC}"
|
|
7912
7928
|
else
|
|
7913
7929
|
echo -e "${YELLOW}Status: Not running (stale PID file)${NC}"
|
|
@@ -8040,14 +8056,10 @@ cmd_dashboard_open() {
|
|
|
8040
8056
|
|
|
8041
8057
|
local url="${scheme}://${host}:${port}"
|
|
8042
8058
|
|
|
8043
|
-
|
|
8044
|
-
|
|
8045
|
-
|
|
8046
|
-
|
|
8047
|
-
echo ""
|
|
8048
|
-
echo "Browser not opened (headless, test, or no opener)."
|
|
8049
|
-
echo "Please open in browser: $url"
|
|
8050
|
-
fi
|
|
8059
|
+
# The legacy browser UI was removed; this server is API-only. Never open a
|
|
8060
|
+
# browser here: point at the Control Plane instead.
|
|
8061
|
+
echo -e "${YELLOW}The dashboard server at $url serves the API only; the browser UI is now the Control Plane.${NC}"
|
|
8062
|
+
echo -e "Open the Control Plane with: ${CYAN}loki ui${NC}"
|
|
8051
8063
|
}
|
|
8052
8064
|
|
|
8053
8065
|
# Welcome opener (the "magic opener"). Shows a branded welcome page in the
|
|
@@ -18401,8 +18413,7 @@ print(json.dumps({'id': manifest.id, 'dir': str(pipeline.migration_dir)}))
|
|
|
18401
18413
|
|
|
18402
18414
|
sleep 2
|
|
18403
18415
|
if kill -0 "$migrate_dashboard_pid" 2>/dev/null; then
|
|
18404
|
-
echo -e " Dashboard:
|
|
18405
|
-
loki_open_url "${url_scheme}://127.0.0.1:${dashboard_port}/" 2>/dev/null || true
|
|
18416
|
+
echo -e " Dashboard API: ${CYAN}${url_scheme}://127.0.0.1:${dashboard_port}/${NC} (UI: loki ui)"
|
|
18406
18417
|
echo ""
|
|
18407
18418
|
else
|
|
18408
18419
|
echo -e " ${YELLOW}Dashboard failed to start (check logs)${NC}"
|
|
@@ -37675,7 +37686,11 @@ print(json.dumps(json.load(open(os.environ['LOKI_PROOF_JSON'])), indent=2))
|
|
|
37675
37686
|
_pv_att="$(loki_proof_attestation_check "$pj" "$_pv_jwks")"
|
|
37676
37687
|
case "$_pv_att" in
|
|
37677
37688
|
ok)
|
|
37678
|
-
|
|
37689
|
+
if [ "$(loki_proof_seal_legacy "$pj")" = "legacy" ]; then
|
|
37690
|
+
echo "attestation: VERIFIED against ${_pv_jwks} (metadata not signed (legacy seal.v1): scope, algo and attestation_kid are not covered by the signature)" >&2
|
|
37691
|
+
else
|
|
37692
|
+
echo "attestation: VERIFIED against ${_pv_jwks}" >&2
|
|
37693
|
+
fi
|
|
37679
37694
|
echo " Proven: these bytes were signed by the holder of a key in that set." >&2
|
|
37680
37695
|
echo " NOT proven: that the code is correct. A receipt records which checks ran." >&2
|
|
37681
37696
|
_pv_attestation_field="VERIFIED"
|
package/autonomy/receipt_jwt.py
CHANGED
|
@@ -265,8 +265,49 @@ def build_jwks(private_key=None, retired_public_keys=None) -> dict:
|
|
|
265
265
|
return {"keys": keys}
|
|
266
266
|
|
|
267
267
|
|
|
268
|
+
SEAL_V2 = "seal.v2"
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
def seal_meta(verification, kid):
|
|
272
|
+
"""The verification.* metadata a seal.v2 token signs.
|
|
273
|
+
|
|
274
|
+
Every key of `verification` except the token itself and attestation_kid
|
|
275
|
+
(which is replaced by the signing kid, so a forged kid can never match).
|
|
276
|
+
Any extra key a forger adds (for example gpg_signature) changes this dict
|
|
277
|
+
and so fails the comparison in check_seal_meta.
|
|
278
|
+
"""
|
|
279
|
+
meta = {k: v for k, v in (verification or {}).items()
|
|
280
|
+
if k not in ("attestation", "attestation_kid")}
|
|
281
|
+
meta["attestation_kid"] = kid
|
|
282
|
+
return meta
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def check_seal_meta(token, claims, verification):
|
|
286
|
+
"""Bind verification.* metadata to a verified token. Returns (status, why).
|
|
287
|
+
|
|
288
|
+
status is "v2" (metadata signed and matching), "legacy" (seal.v1 token: the
|
|
289
|
+
metadata is NOT signed, the caller must say so), or "bad" (a seal.v2 token
|
|
290
|
+
whose signed metadata differs from what the receipt now shows).
|
|
291
|
+
"""
|
|
292
|
+
if not isinstance(claims, dict) or "seal" not in claims:
|
|
293
|
+
return "legacy", "metadata not signed (legacy seal.v1)"
|
|
294
|
+
if claims.get("seal") != SEAL_V2:
|
|
295
|
+
return "bad", "unknown seal version"
|
|
296
|
+
try:
|
|
297
|
+
kid = json.loads(_b64url_decode(token.split(".")[0])).get("kid", "")
|
|
298
|
+
except Exception:
|
|
299
|
+
return "bad", "malformed token"
|
|
300
|
+
if not isinstance(verification, dict):
|
|
301
|
+
return "bad", "verification block missing"
|
|
302
|
+
if verification.get("attestation_kid") != kid:
|
|
303
|
+
return "bad", "attestation_kid differs from the signing kid"
|
|
304
|
+
if claims.get("meta") != seal_meta(verification, kid):
|
|
305
|
+
return "bad", "verification metadata differs from the signed metadata"
|
|
306
|
+
return "v2", ""
|
|
307
|
+
|
|
308
|
+
|
|
268
309
|
def sign_attestation(private_key, kid, *, job_id, run_id, receipt_hash,
|
|
269
|
-
submitter="", issued_at=None, issuer=""):
|
|
310
|
+
submitter="", issued_at=None, issuer="", verification=None):
|
|
270
311
|
"""Return a compact JWT binding a receipt hash to a job identity.
|
|
271
312
|
|
|
272
313
|
The signed claims are what gpg could never carry: WHICH job produced this
|
|
@@ -294,6 +335,10 @@ def sign_attestation(private_key, kid, *, job_id, run_id, receipt_hash,
|
|
|
294
335
|
# Optional claims are omitted rather than emitted empty: a present-but-blank
|
|
295
336
|
# `sub` reads as "an anonymous submitter was recorded" instead of "no
|
|
296
337
|
# submitter identity was available".
|
|
338
|
+
if verification is not None:
|
|
339
|
+
# seal.v2: the verification.* metadata is inside the signature.
|
|
340
|
+
payload["seal"] = SEAL_V2
|
|
341
|
+
payload["meta"] = seal_meta(verification, kid)
|
|
297
342
|
if submitter:
|
|
298
343
|
payload["sub"] = submitter
|
|
299
344
|
if issuer:
|
package/autonomy/run.sh
CHANGED
|
@@ -5553,7 +5553,7 @@ except Exception:
|
|
|
5553
5553
|
# prompt over IPC; it is left untouched here) explicitly to route around
|
|
5554
5554
|
# this. The boundary is a CI job that holds
|
|
5555
5555
|
# no write token and no SSH agent while the agent runs (see
|
|
5556
|
-
#
|
|
5556
|
+
# docs/examples/loki-issue-to-pr.yml.example).
|
|
5557
5557
|
#===============================================================================
|
|
5558
5558
|
_LOKI_WITHHELD_TOKENS=""
|
|
5559
5559
|
_LOKI_GIT_CONFIG_COUNT_UNSUPPORTED=""
|
package/autonomy/telemetry.sh
CHANGED
|
@@ -168,7 +168,7 @@ _loki_known_command() {
|
|
|
168
168
|
case "${1:-}" in
|
|
169
169
|
--help|--version|-h|-v|agent|analyze|api|assets\
|
|
170
170
|
|audit|bench|checkpoint|ci|cleanup|cluster|cockpit|code\
|
|
171
|
-
|completions|compliance|compound|config|context|control|cost|council|cp\
|
|
171
|
+
|completion|completions|compliance|compound|config|context|control|cost|council|cp\
|
|
172
172
|
|crash|ctx|dashboard|demo|deploy|docker|docs|doctor\
|
|
173
173
|
|dogfood|enterprise|explain|export|failover|github|grill|handoff\
|
|
174
174
|
|heal|help|import|init|internal|issue|kpis|logs\
|
|
@@ -1069,6 +1069,7 @@ class WebhookHandler(http.server.BaseHTTPRequestHandler):
|
|
|
1069
1069
|
token = sign_attestation(
|
|
1070
1070
|
self.signing_key, self.signing_kid,
|
|
1071
1071
|
job_id=job_id, run_id=run_id, receipt_hash=receipt_hash,
|
|
1072
|
+
verification=verification,
|
|
1072
1073
|
)
|
|
1073
1074
|
if not token:
|
|
1074
1075
|
return proof
|
package/autonomy/tui.sh
CHANGED
|
@@ -24,7 +24,11 @@ TUI_HAS_COLOR=false
|
|
|
24
24
|
TUI_COLS=80
|
|
25
25
|
if [ -t 1 ]; then
|
|
26
26
|
TUI_HAS_COLOR=true
|
|
27
|
-
|
|
27
|
+
# FC-10: tput can print 0 or nothing on a pty with no size; fall back to COLUMNS, then 80
|
|
28
|
+
TUI_COLS=$(tput cols 2>/dev/null || true)
|
|
29
|
+
case "$TUI_COLS" in '' | *[!0-9]*) TUI_COLS="${COLUMNS:-80}" ;; esac
|
|
30
|
+
case "$TUI_COLS" in '' | *[!0-9]*) TUI_COLS=80 ;; esac
|
|
31
|
+
[ "$TUI_COLS" -ge 40 ] || TUI_COLS=80
|
|
28
32
|
fi
|
|
29
33
|
|
|
30
34
|
# Unicode box drawing (degrade to ASCII if terminal doesn't support)
|
package/bin/loki
CHANGED
|
@@ -115,6 +115,17 @@ else
|
|
|
115
115
|
exec "$BASH_CLI" "$@"
|
|
116
116
|
fi
|
|
117
117
|
|
|
118
|
+
# Shell completions install themselves: once per VERSION, on the first interactive
|
|
119
|
+
# run after an install or upgrade (stamp: ~/.loki/completions-version). Never needed
|
|
120
|
+
# by the user; skipped under CI, LOKI_NO_COMPLETIONS=1 and non-TTY stdout. Failure
|
|
121
|
+
# is silent and never blocks the command.
|
|
122
|
+
if [ -t 1 ] && [ -z "${CI:-}" ] && [ "${LOKI_NO_COMPLETIONS:-}" != "1" ] \
|
|
123
|
+
&& [ "${1:-}" != "completion" ] && [ "${1:-}" != "__complete" ] \
|
|
124
|
+
&& [ "$(cat "${HOME}/.loki/completions-version" 2>/dev/null)" != "$(cat "$REPO_ROOT/VERSION" 2>/dev/null)" ] \
|
|
125
|
+
&& command -v bun >/dev/null 2>&1; then
|
|
126
|
+
bun "$BUN_CLI" completion --auto </dev/null || true
|
|
127
|
+
fi
|
|
128
|
+
|
|
118
129
|
# v7.88.1 covert-path fix (council cF_r2 + cG_r2 sentinel edge): under on-by-default
|
|
119
130
|
# diagnostics, NO telemetry may egress before the user has seen a disclosure once.
|
|
120
131
|
# The cmd_start welcome only shows on `loki start`, so a first `loki version`/`doctor`
|
|
@@ -567,7 +578,7 @@ fi
|
|
|
567
578
|
# Two-token routes (provider show/list, memory list/index) match on the first
|
|
568
579
|
# token only; the Bun dispatcher handles subcommand routing internally.
|
|
569
580
|
case "${1:-}" in
|
|
570
|
-
version|--version|-v|status|stats|doctor|provider|memory|rollback|internal|kpis|trust|proof|receipt|wiki|crash|control|contract|slack|answer)
|
|
581
|
+
version|--version|-v|status|stats|doctor|provider|memory|rollback|internal|kpis|trust|proof|receipt|wiki|crash|control|contract|slack|answer|completion|__complete)
|
|
571
582
|
# v7.5.2: rollback added (wires loki-ts/src/commands/rollback.ts).
|
|
572
583
|
# v7.5.3: internal added for autonomy/run.sh phase1-hooks calls.
|
|
573
584
|
# v7.5.28: kpis added (Phase K MVP: read-only KPI snapshot).
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// npm postinstall: install shell completions. Must never fail the install.
|
|
3
|
+
try {
|
|
4
|
+
const { spawnSync } = require("node:child_process");
|
|
5
|
+
const path = require("node:path");
|
|
6
|
+
if (!process.env.CI && process.env.LOKI_NO_COMPLETIONS !== "1") {
|
|
7
|
+
spawnSync(path.join(__dirname, "loki"), ["completion", "--postinstall"], { stdio: "ignore", timeout: 20000 });
|
|
8
|
+
}
|
|
9
|
+
} catch (e) {
|
|
10
|
+
// ignore: completions are a convenience
|
|
11
|
+
}
|
|
12
|
+
process.exit(0);
|
package/dashboard/__init__.py
CHANGED
package/dashboard/api_phases.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Read-only phase history for a run, derived from real `phase_change` events.
|
|
2
2
|
|
|
3
|
-
WHY THIS EXISTS. dashboard
|
|
3
|
+
WHY THIS EXISTS. The legacy dashboard session timeline (removed in CPE-24) SYNTHESIZED
|
|
4
4
|
its timeline. It took a scalar status (uptime, current phase, iteration count),
|
|
5
5
|
rotated a fixed list `['planning','building','testing','reviewing']`, and gave
|
|
6
6
|
each invented segment a randomized duration:
|
package/dashboard/api_start.py
CHANGED
|
@@ -37,7 +37,6 @@ from . import auth
|
|
|
37
37
|
logger = logging.getLogger(__name__)
|
|
38
38
|
router = APIRouter(tags=["start"])
|
|
39
39
|
|
|
40
|
-
START_HTML = os.path.join(os.path.dirname(os.path.abspath(__file__)), "static", "start.html")
|
|
41
40
|
_LOKI_BIN = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "bin", "loki")
|
|
42
41
|
_REPO_RE = re.compile(r"^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$")
|
|
43
42
|
_TOKEN_RE = re.compile(r"^[A-Za-z0-9_\-]{10,255}$")
|