loki-mode 11.3.1 → 11.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +4 -4
- package/VERSION +1 -1
- package/autonomy/lib/efficiency_cost.py +8 -0
- package/autonomy/lib/engine10-push.sh +22 -8
- package/autonomy/loki +62 -30
- package/bin/loki +30 -1
- package/completions/_loki +6 -0
- package/completions/loki.bash +2 -2
- package/dashboard/__init__.py +1 -1
- package/dashboard/server.py +22 -14
- package/docs/AGENT-CHANGE-RECEIPT.md +2 -2
- package/docs/CLI-REFERENCE.md +5 -1
- package/docs/INSTALLATION.md +1 -1
- package/docs/OTEL-COLLECTOR.md +24 -0
- package/docs/ROUTING-EVIDENCE.md +32 -0
- package/docs/environment-variables.md +1 -0
- package/docs/spec-first-intent.md +28 -0
- package/docs/v10/CLI-MODERN.md +6 -3
- package/docs/v10/DECISIONS.md +15 -0
- package/docs/v10/FAILURE-CLASSES.md +95 -1
- package/docs/v10/GUARDS.md +18 -0
- package/docs/v10/GUIDE.md +7 -5
- package/docs/v10/METRICS.md +12 -0
- package/docs/v10/OPERATING-MODEL.md +3 -3
- package/docs/v10/PROGRESS.md +6 -0
- package/docs/v11/INTOTO-AGENT-CHANGE-PREDICATE.md +77 -0
- package/docs/v11/MCP-2026-07-28.md +55 -0
- package/docs/v11/VERIFY-PR-SANDBOX.md +41 -0
- package/loki-ts/dist/loki.js +1130 -969
- package/mcp/__init__.py +1 -1
- package/mcp/v10_tools.py +29 -0
- package/package.json +9 -11
- package/packages/control-plane/dist/ask-tools-server.js +8 -2
- package/packages/control-plane/dist/server.js +15728 -13988
- package/packages/control-plane/drizzle/0006_token_sessions.sql +1 -0
- package/packages/control-plane/drizzle/meta/0006_snapshot.json +807 -0
- package/packages/control-plane/drizzle/meta/_journal.json +7 -0
- package/packages/control-plane/src/db/schema.ts +1 -0
- package/packages/control-plane/src/server/routes/cost.ts +4 -3
- package/packages/control-plane/src/server/runs.ts +3 -3
- package/packages/control-plane/ui/dist/assets/index-DbLzr87u.js +190 -0
- package/packages/control-plane/ui/dist/index.html +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/providers/opencode.sh +2 -3
- package/src/observability/genai-spans.js +104 -0
- package/src/observability/otel-bridge.js +49 -1
- package/src/observability/otel.js +2 -2
- package/src/protocols/mcp-server.js +180 -5
- package/src/protocols/transport/sse.js +23 -2
- package/web-app/dist/assets/{AdminPage-CMkHNJbF.js → AdminPage-DuRQZsF9.js} +1 -1
- package/web-app/dist/assets/{Avatar-BJyjV7Zi.js → Avatar-7GtOQvsO.js} +1 -1
- package/web-app/dist/assets/{Badge-D572l0uq.js → Badge-CYgTnIxj.js} +1 -1
- package/web-app/dist/assets/{Button-T4BnOZgl.js → Button-rYSyIu7X.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-Cj_GFsNn.js → CockpitPage-9adANY4o.js} +1 -1
- package/web-app/dist/assets/{ComparePage-A8m4ZXak.js → ComparePage-DEG2oA-R.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-hugCg5yg.js → ErrorBoundary-CwtvY4xs.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-CuJKDC2G.js → EvidenceReceiptPanel-DTT73pPB.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-BYGKjarC.js → GitHubIssuesPanel-CpWZLz2x.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-c7sFIJlf.js → GitHubPRsPanel-H293R7E2.js} +1 -1
- package/web-app/dist/assets/{HomePage-A1MIkG2P.js → HomePage-B11Imp9k.js} +2 -2
- package/web-app/dist/assets/{LoginPage-8KQMRhtR.js → LoginPage-BZBgx5Jr.js} +1 -1
- package/web-app/dist/assets/{MagicPage-C05QW2Lx.js → MagicPage-B27S4_X8.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-Oukv5hme.js → MetricsPage-CfbJWNDG.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-DKIwsawz.js → NotFoundPage-Tp_4zMSm.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-DwFRPLCG.js → ProjectPage-CM4fgMsV.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-CgY4YYDX.js → ProjectsPage-DP2Fvsrd.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-BpfcSjUA.js → SettingsPage-C4G9-EAy.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-BqBakC4K.js → ShowcasePage-Dj-n4dwu.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-CZLu5VB0.js → SystemSettingsPage-BqMLpuGt.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-D55S1jKz.js → TeamsPage-mIH8H96m.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-D3SydvxN.js → TemplatesPage-BagW-v4n.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-hNg8G1-e.js → TerminalOutput-CTQRHhnK.js} +1 -1
- package/web-app/dist/assets/{activity-D2C0VagO.js → activity-DNQiBDDL.js} +1 -1
- package/web-app/dist/assets/{bell-CMvYi36w.js → bell-Coiwdad1.js} +1 -1
- package/web-app/dist/assets/{bot-BvtQ6lmo.js → bot-Cou-rTgR.js} +1 -1
- package/web-app/dist/assets/{check-B13xkXed.js → check-CsF-XtQp.js} +1 -1
- package/web-app/dist/assets/{chevron-left-emu6r49E.js → chevron-left-BJiy55Ht.js} +1 -1
- package/web-app/dist/assets/{circle-alert-CExlwjuy.js → circle-alert-D6-pQQWq.js} +1 -1
- package/web-app/dist/assets/{clock-D7Uas3oL.js → clock-BOGqwgt9.js} +1 -1
- package/web-app/dist/assets/{cloud-CkB4S86C.js → cloud-DsxhTtf5.js} +1 -1
- package/web-app/dist/assets/{code-xml-SL9IIWIn.js → code-xml-CxJDHUlE.js} +1 -1
- package/web-app/dist/assets/{database-BQFkd7t1.js → database-BJePscl_.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-qHmnNYsU.js → dollar-sign-6qWGAkZo.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-C2YUDP0K.js → file-code-corner-DcOtYeDb.js} +1 -1
- package/web-app/dist/assets/{file-plus-C_ooIkDe.js → file-plus-WuRyLFo0.js} +1 -1
- package/web-app/dist/assets/{globe-CQ-GL485.js → globe-r-xCP4DE.js} +1 -1
- package/web-app/dist/assets/{hammer-U05L_D7V.js → hammer-DTt0SsCB.js} +1 -1
- package/web-app/dist/assets/{index-CooHd7I-.js → index-BkbXyH8y.js} +3 -3
- package/web-app/dist/assets/{layers-Buo17rjW.js → layers-BvZhvSMY.js} +1 -1
- package/web-app/dist/assets/{loader-circle-15vK3oV1.js → loader-circle-3gosTei9.js} +1 -1
- package/web-app/dist/assets/{lock-BeXLebuJ.js → lock-CZZMxP0U.js} +1 -1
- package/web-app/dist/assets/{package-MVh_6-6R.js → package-C5A8CkJr.js} +1 -1
- package/web-app/dist/assets/{plus-Dh_nd9vS.js → plus-Btv7tTIF.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-C9cBJEAT.js → refresh-cw-DsWLXgs_.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-D3PAtzST.js → rotate-ccw-DOVDjway.js} +1 -1
- package/web-app/dist/assets/{scroll-text-DZCoXQjo.js → scroll-text-smySzlrX.js} +1 -1
- package/web-app/dist/assets/{server-OCOLI5J_.js → server-b5PHsqAU.js} +1 -1
- package/web-app/dist/assets/{shield-alert-oVhmf1_h.js → shield-alert-BD7FDlh-.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-B-kbX4vN.js → thumbs-up-CAsFzbyE.js} +1 -1
- package/web-app/dist/assets/{trash-2-EL6moveW.js → trash-2-BJ35qHgl.js} +1 -1
- package/web-app/dist/assets/{trending-down-Cl3kjpsx.js → trending-down-Ozrd26cZ.js} +1 -1
- package/web-app/dist/assets/{trending-up-DST7I6M2.js → trending-up-BhnMcM32.js} +1 -1
- package/web-app/dist/assets/{upload-CUOT780G.js → upload-JVHfdwoA.js} +1 -1
- package/web-app/dist/assets/{usePolling-Djmt90eb.js → usePolling-CTzbDV-e.js} +1 -1
- package/web-app/dist/assets/{user-BRBohA6J.js → user-Bks3-GYv.js} +1 -1
- package/web-app/dist/index.html +1 -1
- package/packages/control-plane/ui/dist/assets/index-DcBJXjCJ.js +0 -190
package/SKILL.md
CHANGED
|
@@ -3,9 +3,9 @@ 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 v11.3.
|
|
6
|
+
# Loki Mode v11.3.2
|
|
7
7
|
|
|
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
|
|
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 previous bash loop. PRD-file starts (`loki start ./prd.md`) and the opencode provider still run on it until FC38-SWEEP ports them; the legacy-engine command and the LOKI_ENGINE switch remain removed. Prefer `loki owner/repo#N` for issues.
|
|
9
9
|
|
|
10
10
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
11
11
|
|
|
@@ -200,7 +200,7 @@ This protocol governs **skill module** loading -- task-scoped instruction files
|
|
|
200
200
|
<!-- generated:commands -->
|
|
201
201
|
Commands (generated from `loki-ts/src/cli/registry.ts`; full reference in `docs/CLI-REFERENCE.md`):
|
|
202
202
|
|
|
203
|
-
`version`, `status`, `doctor`, `provider`, `memory`, `rollback`, `proof`, `wiki`, `control`, `kpis`, `report`, `trust`, `crash`, `contract`, `start`, `slack`, `queue`, `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`
|
|
203
|
+
`version`, `status`, `doctor`, `provider`, `memory`, `rollback`, `proof`, `wiki`, `control`, `kpis`, `report`, `trust`, `crash`, `contract`, `start`, `slack`, `queue`, `issues`, `undo`, `verify-pr`, `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
204
|
<!-- /generated -->
|
|
205
205
|
|
|
206
206
|
---
|
|
@@ -483,4 +483,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
|
|
|
483
483
|
|
|
484
484
|
---
|
|
485
485
|
|
|
486
|
-
**v11.3.
|
|
486
|
+
**v11.3.2 | [Autonomi](https://www.autonomi.dev/) flagship product | core skill**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
11.3.
|
|
1
|
+
11.3.2
|
|
@@ -192,6 +192,9 @@ def collect_efficiency(loki_dir):
|
|
|
192
192
|
# real observation, and nulling it would be its own dishonesty (existing
|
|
193
193
|
# contract: test_genuine_zero_cost_stays_zero_not_null). What is unknown is a
|
|
194
194
|
# record that never carried the field at all.
|
|
195
|
+
# FC-44: a record flagged tokens_measured:false (an ambiguous resumed session) carries no usage keys. One of them makes every
|
|
196
|
+
# token total NOT RECORDED (None); the flag keys are added only then, so a complete run's dict is unchanged.
|
|
197
|
+
_unmeasured_tokens = sum(1 for r in _records if r.get("tokens_measured") is False)
|
|
195
198
|
_any_cost = any("cost_usd" in r for r in _records)
|
|
196
199
|
_missing_cost = sum(1 for r in _records if "cost_usd" not in r)
|
|
197
200
|
if collected and _observed:
|
|
@@ -208,6 +211,11 @@ def collect_efficiency(loki_dir):
|
|
|
208
211
|
# Some records priced, others not: the total is a LOWER BOUND.
|
|
209
212
|
cost["cost_partial"] = _missing_cost > 0
|
|
210
213
|
cost["cost_unpriced_records"] = _missing_cost
|
|
214
|
+
if _unmeasured_tokens:
|
|
215
|
+
for key in ("input_tokens", "output_tokens", "cache_read_tokens", "cache_creation_tokens"):
|
|
216
|
+
cost[key] = None
|
|
217
|
+
cost["tokens_partial"] = True
|
|
218
|
+
cost["tokens_unmeasured_records"] = _unmeasured_tokens
|
|
211
219
|
else:
|
|
212
220
|
# No record means unavailable, never an observed zero.
|
|
213
221
|
for key in (
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
2
|
# Loki 10 engine P4 push child (ENGINE.md sections 6 and 7).
|
|
3
3
|
#
|
|
4
|
-
# engine10-push.sh push-pr <repo-dir> <branch> <title> <body-file> [--draft]
|
|
4
|
+
# engine10-push.sh push-pr <repo-dir> <branch> <title> <body-file> [--draft] [--base <branch>]
|
|
5
|
+
# engine10-push.sh check-origin (exit 0 when the pinned origin is acceptable to push-pr, else the refusal; no network)
|
|
5
6
|
# engine10-push.sh comment <pr-number> <body-file>
|
|
6
7
|
# engine10-push.sh issue-comment <issue-ref> <body-file>
|
|
7
8
|
# engine10-push.sh status <sha> <pending|success|failure|error> <description>
|
|
@@ -111,13 +112,26 @@ _e10_gh() { _loki_with_github_tokens _loki_run_neutral "$_e10_repo" command gh "
|
|
|
111
112
|
mode="${1:-}"
|
|
112
113
|
shift || true
|
|
113
114
|
case "$mode" in
|
|
115
|
+
check-origin)
|
|
116
|
+
# The origin validation above already ran and died on a refusal; reaching here means push-pr would accept it.
|
|
117
|
+
exit 0
|
|
118
|
+
;;
|
|
114
119
|
push-pr)
|
|
115
|
-
[ "$#" -ge 4 ] && [ "$#" -le
|
|
116
|
-
dir="$1" branch="$2" title="$3" body="$4" draft=()
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
120
|
+
[ "$#" -ge 4 ] && [ "$#" -le 7 ] || die "usage: push-pr <repo-dir> <branch> <title> <body-file> [--draft] [--base <branch>]"
|
|
121
|
+
dir="$1" branch="$2" title="$3" body="$4" draft=() base=()
|
|
122
|
+
shift 4
|
|
123
|
+
# MASS-2: --base stacks the PR on a parent slice's branch; a name git would not accept is refused.
|
|
124
|
+
while [ "$#" -gt 0 ]; do
|
|
125
|
+
case "$1" in
|
|
126
|
+
--draft) draft=(--draft); shift ;;
|
|
127
|
+
--base)
|
|
128
|
+
[ "$#" -ge 2 ] || die "--base needs a branch"
|
|
129
|
+
case "$2" in -* | '') die "invalid base branch: $2" ;; esac
|
|
130
|
+
git check-ref-format --branch "$2" >/dev/null 2>&1 || die "invalid base branch: $2"
|
|
131
|
+
base=(--base "$2"); shift 2 ;;
|
|
132
|
+
*) die "unknown flag: $1" ;;
|
|
133
|
+
esac
|
|
134
|
+
done
|
|
121
135
|
[ -f "$body" ] || die "body file not found: $body"
|
|
122
136
|
if [ -n "$_e10_local" ]; then
|
|
123
137
|
_e10_local_push "$dir" "$branch" || die "push refused or failed (rc=$?)"
|
|
@@ -128,7 +142,7 @@ case "$mode" in
|
|
|
128
142
|
url="$(_e10_gh pr list --repo "$_e10_repo" --head "$branch" --state open --json url --jq '.[0].url')" \
|
|
129
143
|
|| die "gh pr list failed"
|
|
130
144
|
if [ -z "$url" ] || [ "$url" = "null" ]; then
|
|
131
|
-
url="$(_e10_gh pr create --repo "$_e10_repo" --head "$branch" --title "$title" --body-file "$body" "${draft[@]}")" \
|
|
145
|
+
url="$(_e10_gh pr create --repo "$_e10_repo" --head "$branch" --title "$title" --body-file "$body" "${draft[@]}" "${base[@]}")" \
|
|
132
146
|
|| die "gh pr create failed"
|
|
133
147
|
url="$(printf '%s\n' "$url" | tail -n 1)"
|
|
134
148
|
fi
|
package/autonomy/loki
CHANGED
|
@@ -1691,6 +1691,22 @@ _help_answer() {
|
|
|
1691
1691
|
echo "and sets LOKI_NO_BROWSER=1."
|
|
1692
1692
|
}
|
|
1693
1693
|
|
|
1694
|
+
# `loki help verify-pr`: a Bun-only command (loki-ts), so its help lives here.
|
|
1695
|
+
_help_verify_pr() {
|
|
1696
|
+
echo -e "${BOLD}loki verify-pr${NC} - Verify a PR against its linked issue (experimental, LOKI_VERIFY_PR=1)"
|
|
1697
|
+
echo ""
|
|
1698
|
+
echo "Usage: loki verify-pr <https://github.com/o/r/pull/N | o/r#N> [--out DIR]"
|
|
1699
|
+
echo ""
|
|
1700
|
+
echo "Derives a check from the PR's linked issue (Check: \`cmd\` or a loki-check fence)."
|
|
1701
|
+
echo "VERIFIED only if the check fails on the PR base, passes on its head, and the"
|
|
1702
|
+
echo "touched packages' suites pass. A PR with no linked issue, no check, a removed"
|
|
1703
|
+
echo "test or a non-discriminating check is NOT PROVEN. Writes verify-pr-result.json."
|
|
1704
|
+
echo "PR code runs only in the container sandbox (scripts/verify-pr-sandbox.sh); set"
|
|
1705
|
+
echo "LOKI_VPR_IMAGE to a locally present image."
|
|
1706
|
+
echo ""
|
|
1707
|
+
echo "Exit codes: 0 verified, 2 usage or sandbox blocked, 4 not proven."
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1694
1710
|
# Appended to `loki help verify`: the v10 DSSE export flag (docs/exit-codes.md).
|
|
1695
1711
|
_help_verify_dsse() {
|
|
1696
1712
|
echo ""
|
|
@@ -1763,6 +1779,7 @@ show_help() {
|
|
|
1763
1779
|
echo " review [opts] Standalone code review with quality gates"
|
|
1764
1780
|
echo " ultracode \"task\" Run a task as a native Claude Code Dynamic Workflow (opt-in, Claude-only)"
|
|
1765
1781
|
echo " trust [cmd] Visible trust trajectory; 'trust detail' for metrics"
|
|
1782
|
+
echo " undo <run> [--plan] Plan or apply (LOKI_UNDO=1) an undo of a run; verifies the receipt"
|
|
1766
1783
|
echo ""
|
|
1767
1784
|
echo "Observe:"
|
|
1768
1785
|
echo " dashboard [cmd] Operations UI server (start|stop|status|url|open)"
|
|
@@ -1798,13 +1815,9 @@ show_help() {
|
|
|
1798
1815
|
echo ""
|
|
1799
1816
|
echo "Options for 'start':"
|
|
1800
1817
|
echo " --provider NAME AI provider: claude (default), codex, cline, aider, opencode"
|
|
1801
|
-
echo " --parallel Enable parallel mode with git worktrees"
|
|
1802
|
-
echo " --bg, --background Run in background mode"
|
|
1803
1818
|
echo " --simple Force simple complexity tier (3 phases)"
|
|
1804
1819
|
echo " --complex Force complex complexity tier (8 phases)"
|
|
1805
|
-
echo " --github Enable GitHub issue import"
|
|
1806
1820
|
echo " --no-dashboard Disable web dashboard"
|
|
1807
|
-
echo " --sandbox Run in Docker sandbox for isolation (default: off; requires Docker)"
|
|
1808
1821
|
echo " --isolation LVL Per-run isolation dial: none (default) | worktree | docker"
|
|
1809
1822
|
echo " --skip-memory Skip loading memory context at startup"
|
|
1810
1823
|
echo " --fresh-prd Regenerate the PRD from the codebase (no-PRD runs; ignores the reusable generated PRD)"
|
|
@@ -1824,8 +1837,6 @@ show_help() {
|
|
|
1824
1837
|
echo " loki start ./prd.md # Start with PRD file"
|
|
1825
1838
|
echo " loki start owner/repo#123 # GitHub issue (auto-fetches)"
|
|
1826
1839
|
echo " loki start PROJ-456 # Jira issue"
|
|
1827
|
-
echo " loki start --bg ./prd.md # Start in background"
|
|
1828
|
-
echo " loki start --parallel ./prd.md # Parallel mode (git worktrees)"
|
|
1829
1840
|
echo " loki quick \"add dark mode\" # Single-task mode (Loki 10 engine)"
|
|
1830
1841
|
echo " loki tour # See a real sample result (no provider, no key, no spend)"
|
|
1831
1842
|
echo " loki demo # Build a sample todo app end to end"
|
|
@@ -1898,7 +1909,7 @@ show_help() {
|
|
|
1898
1909
|
echo " merge resume review rollback run sandbox secrets secure self-update sentrux"
|
|
1899
1910
|
echo " serve setup-skill share ship spec start state stats status steer stop"
|
|
1900
1911
|
echo " syslog telemetry template test tour trigger trust trust-metrics"
|
|
1901
|
-
echo " ultracode update verify version voice watch watchdog web welcome why"
|
|
1912
|
+
echo " ultracode undo update verify version voice watch watchdog web welcome why"
|
|
1902
1913
|
echo " wiki workspace worktree (wt)"
|
|
1903
1914
|
echo " control"
|
|
1904
1915
|
echo ""
|
|
@@ -2563,17 +2574,13 @@ cmd_start() {
|
|
|
2563
2574
|
echo " Token from LOKI_REMOTE_TOKEN / LOKI_REMOTE_TOKEN_FILE"
|
|
2564
2575
|
echo " (never an argument). Env: LOKI_REMOTE_URL."
|
|
2565
2576
|
echo " --provider NAME AI provider: claude (default), codex, cline, aider, opencode"
|
|
2566
|
-
echo " --parallel Enable parallel mode with git worktrees"
|
|
2567
2577
|
echo " --allow-haiku Enable Haiku model for the fast tier (default: disabled)"
|
|
2568
|
-
echo " --bg, --background Run in background mode"
|
|
2569
2578
|
echo " --simple Force simple complexity tier (3 phases)"
|
|
2570
2579
|
echo " --complex Force complex complexity tier (8 phases)"
|
|
2571
|
-
echo " --github Enable GitHub issue import"
|
|
2572
2580
|
echo " --no-dashboard Disable web dashboard"
|
|
2573
2581
|
echo " --api Start dashboard API server alongside the build"
|
|
2574
|
-
echo " --sandbox Run in Docker sandbox (default: off; requires Docker)"
|
|
2575
2582
|
echo " --isolation LEVEL Per-run isolation: none (default) | worktree | docker."
|
|
2576
|
-
echo " Unified dial
|
|
2583
|
+
echo " Unified dial."
|
|
2577
2584
|
echo " --attempts N Run N (1-5, default 1) independent attempts in separate git worktrees;"
|
|
2578
2585
|
echo " the most executed passing checks wins, losers are recorded on the receipt"
|
|
2579
2586
|
echo " --skip-memory Skip loading memory context at startup"
|
|
@@ -2608,7 +2615,6 @@ cmd_start() {
|
|
|
2608
2615
|
echo " --worktree, -w Git worktree isolation (separate branch)"
|
|
2609
2616
|
echo " --pr Worktree + auto-create PR"
|
|
2610
2617
|
echo " --ship Worktree + PR + auto-merge"
|
|
2611
|
-
echo " --detach, -d Run in background"
|
|
2612
2618
|
echo ""
|
|
2613
2619
|
echo "Preview without spending (any input mode):"
|
|
2614
2620
|
echo " loki plan <PRD> Analyze a spec WITHOUT executing: complexity,"
|
|
@@ -2637,7 +2643,6 @@ cmd_start() {
|
|
|
2637
2643
|
echo " loki start 123 # ISSUE mode (current repo GitHub issue)"
|
|
2638
2644
|
echo " loki start PROJ-456 # ISSUE mode (Jira)"
|
|
2639
2645
|
echo " loki start owner/repo#789 # ISSUE mode (GitHub specific repo)"
|
|
2640
|
-
echo " loki start --prd ./prd.md --parallel # Explicit PRD, parallel mode"
|
|
2641
2646
|
echo " loki start --issue 123 --ship # Explicit issue, full automation"
|
|
2642
2647
|
echo " loki start --provider codex # Use OpenAI Codex CLI"
|
|
2643
2648
|
echo " loki start --bmad-project ./my-project # Start from BMAD artifacts"
|
|
@@ -6424,22 +6429,35 @@ except Exception:
|
|
|
6424
6429
|
fi
|
|
6425
6430
|
fi
|
|
6426
6431
|
|
|
6427
|
-
#
|
|
6428
|
-
#
|
|
6429
|
-
# the
|
|
6430
|
-
|
|
6431
|
-
|
|
6432
|
-
|
|
6433
|
-
|
|
6432
|
+
# 133-F4: newest sealed receipt's verdict, read from the receipt field only
|
|
6433
|
+
# (never recomputed). Missing, empty or unparseable receipts never read as
|
|
6434
|
+
# VERIFIED. This replaces the old completion.json one-liner (Bun never had it).
|
|
6435
|
+
local receipt_line
|
|
6436
|
+
receipt_line=$(_LOKI_RUNS="$LOKI_DIR/runs" python3 -c "
|
|
6437
|
+
import json, os, re
|
|
6438
|
+
runs = os.environ['_LOKI_RUNS']
|
|
6434
6439
|
try:
|
|
6435
|
-
|
|
6436
|
-
print(d.get('outcome', '') or '')
|
|
6440
|
+
ids = sorted(d for d in os.listdir(runs) if os.path.isdir(os.path.join(runs, d)))
|
|
6437
6441
|
except Exception:
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6442
|
+
ids = []
|
|
6443
|
+
if not ids:
|
|
6444
|
+
print('Last run: no receipt (verdict NOT AVAILABLE)')
|
|
6445
|
+
else:
|
|
6446
|
+
try:
|
|
6447
|
+
d = json.load(open(os.path.join(runs, ids[-1], 'receipt.json')))
|
|
6448
|
+
v = d['verdict']
|
|
6449
|
+
h = d['receipt_sha256']
|
|
6450
|
+
if not (isinstance(v, str) and re.fullmatch(r'[A-Z_]+', v) and isinstance(h, str)):
|
|
6451
|
+
raise ValueError
|
|
6452
|
+
h = h[7:] if h.startswith('sha256:') else h
|
|
6453
|
+
if not re.fullmatch(r'[0-9a-f]{12,}', h):
|
|
6454
|
+
raise ValueError
|
|
6455
|
+
print('Last run: %s (receipt sha256:%s)' % (v, h[:12]))
|
|
6456
|
+
except Exception:
|
|
6457
|
+
print('Last run: receipt unreadable')
|
|
6458
|
+
" 2>/dev/null)
|
|
6459
|
+
[ -n "$receipt_line" ] || receipt_line="Last run: receipt unreadable"
|
|
6460
|
+
echo -e "${DIM}${receipt_line}${NC}"
|
|
6443
6461
|
|
|
6444
6462
|
echo ""
|
|
6445
6463
|
echo -e "${DIM} Tip: loki analyze context show - detailed token breakdown${NC}"
|
|
@@ -12394,6 +12412,9 @@ cmd_export() {
|
|
|
12394
12412
|
echo " csv Task queue as CSV"
|
|
12395
12413
|
echo " timeline Iteration timeline as JSON"
|
|
12396
12414
|
echo ""
|
|
12415
|
+
echo "Flags:"
|
|
12416
|
+
echo " --sarif [run-id] Write .loki/runs/<id>/findings.sarif (SARIF 2.1.0; needs bun)"
|
|
12417
|
+
echo ""
|
|
12397
12418
|
echo "Examples:"
|
|
12398
12419
|
echo " loki export json # Print to stdout"
|
|
12399
12420
|
echo " loki export json session-export.json # Save to file"
|
|
@@ -12416,6 +12437,10 @@ cmd_export() {
|
|
|
12416
12437
|
require_jq || return 1
|
|
12417
12438
|
_export_timeline "$output_path"
|
|
12418
12439
|
;;
|
|
12440
|
+
--sarif)
|
|
12441
|
+
echo -e "${RED}loki export --sarif needs bun (https://bun.sh).${NC}" >&2
|
|
12442
|
+
return 1
|
|
12443
|
+
;;
|
|
12419
12444
|
*)
|
|
12420
12445
|
echo -e "${RED}Unknown format: $format${NC}"
|
|
12421
12446
|
echo "Supported: json, markdown, csv, timeline"
|
|
@@ -21201,6 +21226,11 @@ main() {
|
|
|
21201
21226
|
mcp)
|
|
21202
21227
|
cmd_mcp "$@"
|
|
21203
21228
|
;;
|
|
21229
|
+
undo)
|
|
21230
|
+
# UNDO-1: Bun-only (verifies the receipt with the Bun verifier); bin/loki routes here only when bun is absent.
|
|
21231
|
+
echo "loki undo needs the Bun runtime (install bun, then re-run: loki undo <run-id> --plan)" >&2
|
|
21232
|
+
exit 2
|
|
21233
|
+
;;
|
|
21204
21234
|
acp)
|
|
21205
21235
|
# ACP agent over stdio; stdout is protocol-only. See docs/acp-editors.md.
|
|
21206
21236
|
LOKI_ACP_LOKI="${LOKI_ACP_LOKI:-$_LOKI_SCRIPT_DIR/loki}" exec python3 "$_LOKI_SCRIPT_DIR/acp-agent.py"
|
|
@@ -21413,6 +21443,8 @@ main() {
|
|
|
21413
21443
|
show_help
|
|
21414
21444
|
elif [ "$_help_target" = "answer" ]; then
|
|
21415
21445
|
_help_answer
|
|
21446
|
+
elif [ "$_help_target" = "verify-pr" ]; then
|
|
21447
|
+
_help_verify_pr
|
|
21416
21448
|
else
|
|
21417
21449
|
LOKI_HELP_ONLY=1 "$0" "$_help_target" --help "$@"
|
|
21418
21450
|
local _help_rc=$?
|
|
@@ -30164,7 +30196,7 @@ except: pass
|
|
|
30164
30196
|
|
|
30165
30197
|
# Detect shell scripts
|
|
30166
30198
|
local shell_count=0
|
|
30167
|
-
shell_count=$(find "$target_path" -maxdepth 2 -name "*.sh" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
30199
|
+
shell_count=$(find "$target_path" -maxdepth 2 -name "*.sh" -type f 2>/dev/null | wc -l | tr -d ' ' || true)
|
|
30168
30200
|
if [ "$shell_count" -gt 0 ]; then
|
|
30169
30201
|
languages="$languages Bash"
|
|
30170
30202
|
fi
|
|
@@ -30602,7 +30634,7 @@ Files: $src_count source, $test_count test, $doc_count docs"
|
|
|
30602
30634
|
if [ -d "$target_path/$dir" ]; then
|
|
30603
30635
|
# Count files in directory
|
|
30604
30636
|
local dir_count
|
|
30605
|
-
dir_count=$(echo "$tree_output" | grep "^${dir}/" | wc -l | tr -d ' ')
|
|
30637
|
+
dir_count=$(echo "$tree_output" | grep "^${dir}/" | wc -l | tr -d ' ' || true)
|
|
30606
30638
|
output="$output
|
|
30607
30639
|
$dir/ ($dir_count files)"
|
|
30608
30640
|
else
|
package/bin/loki
CHANGED
|
@@ -467,6 +467,21 @@ if [ "${1:-}" = "start" ]; then
|
|
|
467
467
|
unset _loki_att_args _loki_att_n _loki_att_skip _loki_att_a
|
|
468
468
|
fi
|
|
469
469
|
|
|
470
|
+
# SPEC-FIRST-INTENT: `start --spec FILE` and `start --spec-first` are parsed by the Bun start command,
|
|
471
|
+
# which forwards them to engine10; they never reach the positional-task route or the legacy loop.
|
|
472
|
+
if [ "${1:-}" = "start" ]; then
|
|
473
|
+
for _loki_sp_a in "${@:2}"; do
|
|
474
|
+
case "$_loki_sp_a" in
|
|
475
|
+
--spec|--spec=*|--spec-first)
|
|
476
|
+
_lb=$(_loki_bun)
|
|
477
|
+
[ -n "$_lb" ] || { echo "loki: --spec needs bun (install from https://bun.sh)." >&2; exit 1; }
|
|
478
|
+
exec "$_lb" "$BUN_CLI" "$@"
|
|
479
|
+
;;
|
|
480
|
+
esac
|
|
481
|
+
done
|
|
482
|
+
unset _loki_sp_a
|
|
483
|
+
fi
|
|
484
|
+
|
|
470
485
|
# Loki 10 engine (D29, the only engine from 11.0.0). Routes `loki "<task>"`,
|
|
471
486
|
# `loki owner/repo#N`, `loki quick "<task>"`, `keys` and `verify --pubkey` to engine10.
|
|
472
487
|
# shellcheck disable=SC2194
|
|
@@ -477,6 +492,13 @@ case "v10" in
|
|
|
477
492
|
_e10_args=("$@")
|
|
478
493
|
case "${1:-}" in
|
|
479
494
|
keys) _e10=1; _e10_hard=1 ;;
|
|
495
|
+
# SARIF-2: `export --sarif` has no bash implementation; it runs on bun only.
|
|
496
|
+
export)
|
|
497
|
+
for _sa in "$@"; do
|
|
498
|
+
case "$_sa" in --sarif) _e10=1; _e10_hard=1; _e10_args=(export-sarif "${@:2}") ;; esac
|
|
499
|
+
done
|
|
500
|
+
unset _sa
|
|
501
|
+
;;
|
|
480
502
|
status|verify|dashboard)
|
|
481
503
|
if [ "$1" = "verify" ]; then
|
|
482
504
|
for _pk in "$@"; do
|
|
@@ -495,6 +517,13 @@ case "v10" in
|
|
|
495
517
|
unset _r10 _p10 _d
|
|
496
518
|
fi
|
|
497
519
|
;;
|
|
520
|
+
# SPEC-FIRST-INTENT: only `plan ... --spec` is a v10 command; every other plan call stays on the legacy CLI.
|
|
521
|
+
plan)
|
|
522
|
+
for _pa in "$@"; do
|
|
523
|
+
[ "$_pa" = "--spec" ] && { _e10=1; _e10_hard=1; }
|
|
524
|
+
done
|
|
525
|
+
unset _pa
|
|
526
|
+
;;
|
|
498
527
|
""|-*) _e10=0 ;;
|
|
499
528
|
# quick: the lean small path, no PR (legacy quick never opened one). A flag-first
|
|
500
529
|
# call (--help, -v) stays on the legacy quick.
|
|
@@ -710,7 +739,7 @@ fi
|
|
|
710
739
|
# Two-token routes (provider show/list, memory list/index) match on the first
|
|
711
740
|
# token only; the Bun dispatcher handles subcommand routing internally.
|
|
712
741
|
case "${1:-}" in
|
|
713
|
-
version|--version|-v|status|stats|doctor|provider|memory|rollback|internal|kpis|trust|proof|receipt|wiki|crash|control|contract|slack|queue|answer|completion|__complete)
|
|
742
|
+
version|--version|-v|status|stats|doctor|provider|memory|rollback|internal|kpis|trust|proof|receipt|wiki|crash|control|contract|slack|queue|issues|answer|undo|verify-pr|completion|__complete)
|
|
714
743
|
# v7.5.2: rollback added (wires loki-ts/src/commands/rollback.ts).
|
|
715
744
|
# v7.5.3: internal added for autonomy/run.sh phase1-hooks calls.
|
|
716
745
|
# v7.5.28: kpis added (Phase K MVP: read-only KPI snapshot).
|
package/completions/_loki
CHANGED
|
@@ -209,7 +209,10 @@ function _loki_commands {
|
|
|
209
209
|
'otel:OpenTelemetry management'
|
|
210
210
|
'wiki:Wiki commands'
|
|
211
211
|
'answer:Resume a BLOCKED run with an answer'
|
|
212
|
+
'verify-pr:Verify a PR against its linked issue in a sandbox'
|
|
212
213
|
'queue:Overnight issue queue with a morning digest'
|
|
214
|
+
'issues:Run every open issue in a repo and open PRs'
|
|
215
|
+
'undo:Show what undoing a run would do (read-only plan)'
|
|
213
216
|
'control:Control plane (preview, LOKI_CONTROL=1)'
|
|
214
217
|
'workspace:Multi-project workspaces (preview, LOKI_WORKSPACES=1)'
|
|
215
218
|
'backlog:Run every matching open issue, N in parallel'
|
|
@@ -337,6 +340,9 @@ function _loki_memory {
|
|
|
337
340
|
'pattern:Manage patterns'
|
|
338
341
|
'skill:Manage skills'
|
|
339
342
|
'vectors:Vector search'
|
|
343
|
+
'lessons:List PR lessons (--json)'
|
|
344
|
+
'learn:Learn from a merged PR'
|
|
345
|
+
'forget:Delete a PR lesson'
|
|
340
346
|
'help:Memory help'
|
|
341
347
|
)
|
|
342
348
|
_describe -t cmds 'memory subcommand' cmds
|
package/completions/loki.bash
CHANGED
|
@@ -5,7 +5,7 @@ _loki_completion() {
|
|
|
5
5
|
_init_completion || return
|
|
6
6
|
|
|
7
7
|
# Main subcommands (must match autonomy/loki main case statement)
|
|
8
|
-
local main_commands="start backlog quick monitor demo tour welcome init stop pause resume steer status next ship dashboard web serve api sandbox notify import github issue intent config provider reset memory compound checkpoint council dogfood projects enterprise secrets cockpit secure own handoff doctor watchdog audit metrics syslog onboard share proof receipt outcomes explain plan report cost estimate kpis stats test ci watch telemetry agent context ctx code run export review optimize heal modernize migrate cluster worktree wt trigger failover remote deploy docker mcp magic assets analyze compliance crash control workspace open otel preview quickstart rc rollback merge self-update sentrux setup-skill spec state template trust trust-metrics ultracode update verify voice why wiki bench cleanup logs grill docs cp version completions help keys answer queue acp"
|
|
8
|
+
local main_commands="start backlog quick monitor demo tour welcome init stop pause resume steer status next ship dashboard web serve api sandbox notify import github issue intent config provider reset memory compound checkpoint council dogfood projects enterprise secrets cockpit secure own handoff doctor watchdog audit metrics syslog onboard share proof receipt outcomes explain plan report cost estimate kpis stats test ci watch telemetry agent context ctx code run export review optimize heal modernize migrate cluster worktree wt trigger failover remote deploy docker mcp magic assets analyze compliance crash control workspace open otel preview quickstart rc rollback merge self-update sentrux setup-skill spec state template trust trust-metrics ultracode update verify voice why wiki bench cleanup logs grill docs cp version completions help keys answer queue issues undo acp verify-pr"
|
|
9
9
|
|
|
10
10
|
# 1. If we are on the first argument (subcommand)
|
|
11
11
|
if [[ $cword -eq 1 ]]; then
|
|
@@ -57,7 +57,7 @@ _loki_completion() {
|
|
|
57
57
|
;;
|
|
58
58
|
|
|
59
59
|
memory)
|
|
60
|
-
local memory_cmds="list show search stats export clear dedupe index timeline consolidate economics retrieve episode pattern skill vectors help"
|
|
60
|
+
local memory_cmds="list show search stats export clear dedupe index timeline consolidate economics retrieve lessons learn forget episode pattern skill vectors help"
|
|
61
61
|
COMPREPLY=( $(compgen -W "${memory_cmds}" -- "$cur") )
|
|
62
62
|
;;
|
|
63
63
|
|
package/dashboard/__init__.py
CHANGED
package/dashboard/server.py
CHANGED
|
@@ -7889,6 +7889,9 @@ def _compute_cost_snapshot() -> dict:
|
|
|
7889
7889
|
cost_recorded = False
|
|
7890
7890
|
# Tokens were measured (tracker fallback) but no USD figure was recorded.
|
|
7891
7891
|
cost_unknown = False
|
|
7892
|
+
# FC-44: sessions whose usage could not be recorded (efficiency record flagged tokens_measured:false). Any of them makes
|
|
7893
|
+
# every token and dollar total NOT RECORDED; the response key appears only then.
|
|
7894
|
+
unmeasured_sessions = 0
|
|
7892
7895
|
|
|
7893
7896
|
# Read efficiency files (one JSON file per iteration/task).
|
|
7894
7897
|
# Use the iteration-*.json pattern so this reader sees the same
|
|
@@ -7906,6 +7909,9 @@ def _compute_cost_snapshot() -> dict:
|
|
|
7906
7909
|
if not isinstance(data, dict):
|
|
7907
7910
|
continue
|
|
7908
7911
|
measured = _record_is_measured(data)
|
|
7912
|
+
rec_unmeasured = data.get("tokens_measured") is False
|
|
7913
|
+
if rec_unmeasured:
|
|
7914
|
+
unmeasured_sessions += 1
|
|
7909
7915
|
if measured:
|
|
7910
7916
|
cost_recorded = True
|
|
7911
7917
|
# Tokens are measured apart from cost: a record that priced an
|
|
@@ -7941,17 +7947,18 @@ def _compute_cost_snapshot() -> dict:
|
|
|
7941
7947
|
for bucket, name in ((by_phase, phase), (by_model, model)):
|
|
7942
7948
|
if name not in bucket:
|
|
7943
7949
|
bucket[name] = {"input_tokens": 0, "output_tokens": 0, "cost_usd": 0.0,
|
|
7944
|
-
"measured": False, "tokens_measured": False}
|
|
7950
|
+
"measured": False, "tokens_measured": False, "unmeasured": False}
|
|
7945
7951
|
bucket[name]["input_tokens"] += inp
|
|
7946
7952
|
bucket[name]["output_tokens"] += out
|
|
7947
7953
|
bucket[name]["cost_usd"] += cost
|
|
7948
7954
|
bucket[name]["measured"] = bucket[name]["measured"] or measured
|
|
7949
7955
|
bucket[name]["tokens_measured"] = bucket[name]["tokens_measured"] or tokens_measured
|
|
7956
|
+
bucket[name]["unmeasured"] = bucket[name]["unmeasured"] or rec_unmeasured
|
|
7950
7957
|
except (json.JSONDecodeError, KeyError, TypeError, AttributeError):
|
|
7951
7958
|
pass
|
|
7952
7959
|
|
|
7953
7960
|
# Fallback: read from context tracking if efficiency files have no token data
|
|
7954
|
-
if total_input == 0 and total_output == 0:
|
|
7961
|
+
if total_input == 0 and total_output == 0 and not unmeasured_sessions:
|
|
7955
7962
|
ctx_file = loki_dir / "context" / "tracking.json"
|
|
7956
7963
|
if ctx_file.exists():
|
|
7957
7964
|
try:
|
|
@@ -8024,25 +8031,26 @@ def _compute_cost_snapshot() -> dict:
|
|
|
8024
8031
|
# set of measured records that genuinely sums to zero still renders 0.0 --
|
|
8025
8032
|
# the direction that would otherwise blank real data (the v8.72.0 trap).
|
|
8026
8033
|
return {
|
|
8027
|
-
"
|
|
8028
|
-
"
|
|
8029
|
-
"
|
|
8030
|
-
"
|
|
8034
|
+
**({"unmeasured_sessions": unmeasured_sessions} if unmeasured_sessions else {}),
|
|
8035
|
+
"total_input_tokens": total_input if cost_recorded and not unmeasured_sessions else None,
|
|
8036
|
+
"total_output_tokens": total_output if cost_recorded and not unmeasured_sessions else None,
|
|
8037
|
+
"total_cache_read_tokens": total_cache_read if cost_recorded and not unmeasured_sessions else None,
|
|
8038
|
+
"total_cache_creation_tokens": total_cache_creation if cost_recorded and not unmeasured_sessions else None,
|
|
8031
8039
|
"total_tokens": (
|
|
8032
8040
|
total_input + total_output + total_cache_read + total_cache_creation
|
|
8033
|
-
) if cost_recorded else None,
|
|
8041
|
+
) if cost_recorded and not unmeasured_sessions else None,
|
|
8034
8042
|
"cache_hit_ratio": round(total_cache_read / _read_in, 4) if _read_in > 0 else None,
|
|
8035
|
-
"estimated_cost_usd": round(estimated_cost, 6) if cost_recorded and not cost_unknown else None,
|
|
8043
|
+
"estimated_cost_usd": round(estimated_cost, 6) if cost_recorded and not cost_unknown and not unmeasured_sessions else None,
|
|
8036
8044
|
"cost_recorded": cost_recorded,
|
|
8037
8045
|
"by_phase": {k: {
|
|
8038
|
-
"input_tokens": v["input_tokens"] if v.get("tokens_measured") else None,
|
|
8039
|
-
"output_tokens": v["output_tokens"] if v.get("tokens_measured") else None,
|
|
8040
|
-
"cost_usd": round(v["cost_usd"], 6) if v.get("measured") else None,
|
|
8046
|
+
"input_tokens": v["input_tokens"] if v.get("tokens_measured") and not v.get("unmeasured") else None,
|
|
8047
|
+
"output_tokens": v["output_tokens"] if v.get("tokens_measured") and not v.get("unmeasured") else None,
|
|
8048
|
+
"cost_usd": round(v["cost_usd"], 6) if v.get("measured") and not v.get("unmeasured") else None,
|
|
8041
8049
|
} for k, v in by_phase.items()},
|
|
8042
8050
|
"by_model": {k: {
|
|
8043
|
-
"input_tokens": v["input_tokens"] if v.get("tokens_measured") else None,
|
|
8044
|
-
"output_tokens": v["output_tokens"] if v.get("tokens_measured") else None,
|
|
8045
|
-
"cost_usd": round(v["cost_usd"], 6) if v.get("measured") else None,
|
|
8051
|
+
"input_tokens": v["input_tokens"] if v.get("tokens_measured") and not v.get("unmeasured") else None,
|
|
8052
|
+
"output_tokens": v["output_tokens"] if v.get("tokens_measured") and not v.get("unmeasured") else None,
|
|
8053
|
+
"cost_usd": round(v["cost_usd"], 6) if v.get("measured") and not v.get("unmeasured") else None,
|
|
8046
8054
|
} for k, v in by_model.items()},
|
|
8047
8055
|
"budget_limit": budget_limit,
|
|
8048
8056
|
"budget_used": round(budget_used, 6) if budget_limit is not None and budget_used is not None else None,
|
|
@@ -13,8 +13,8 @@ An Agent Change Receipt is the JSON file a Loki 10 run seals at `.loki/runs/<run
|
|
|
13
13
|
- `not_proven`: list of strings naming what the run did not prove.
|
|
14
14
|
- `verdict`: one of `VERIFIED`, `PARTIAL`, `ALREADY_SATISFIED`, `SPEC_CONFLICT`, `FAILED` (`types.ts:44`).
|
|
15
15
|
- `evidence`: list of strings (search hits and citation for an ALREADY_SATISFIED verdict).
|
|
16
|
-
- `cost`: `{ usd (number or null), input_tokens, output_tokens, measured_sessions, total_sessions, partial_usd, source? }`.
|
|
17
|
-
- `time`: `{ wall_s, stages }`.
|
|
16
|
+
- `cost`: `{ usd (number or null), input_tokens, output_tokens, cache_read_tokens?, cache_creation_tokens?, sdk_duration_ms?, measured_sessions, total_sessions, partial_usd, source? }`.
|
|
17
|
+
- `time`: `{ wall_s, total_s?, stages, stage_s? }`. `stages` is a disjoint partition of `total_s`: `setup` (first event to machine start), each stage, a parallel group as one bucket (for example `plan+wall`), `orchestration` gaps and `seal`, so a consumer may simply add them. `stage_s` holds each stage's own seconds (parallel members overlap, so they can add to more than their bucket). `wall_s` is the stage buckets without setup, orchestration and seal. `total_s` is elapsed seconds from the run's first event to seal (PR stage excluded); treat it as NOT RECORDED unless every bucket is a non-negative number and they sum to it within 1%. `total_s`, `stage_s` and the cache token keys are additive: older receipts omit them, which reads NOT RECORDED, never 0.
|
|
18
18
|
- `events_sha256`: digest of the run event log.
|
|
19
19
|
- `receipt_sha256`: sha256 of the canonical JSON with `verification` and `receipt_sha256` removed (`loki-ts/src/engine10/verify_cmd.ts:19`).
|
|
20
20
|
- `verification`: `{ jwt, kid }`. `jwt` is a compact EdDSA (Ed25519) token binding the receipt hash; both are null when the receipt is unsigned (`stages/seal.ts:92-95`).
|
package/docs/CLI-REFERENCE.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# CLI reference
|
|
2
2
|
|
|
3
|
-
Generated from `loki-ts/src/cli/registry.ts` by `scripts/generate-stale-zero.sh` for v11.3.
|
|
3
|
+
Generated from `loki-ts/src/cli/registry.ts` by `scripts/generate-stale-zero.sh` for v11.3.2. 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 |
|
|
@@ -61,6 +61,10 @@ Hidden and legacy-only commands are omitted; see `docs/v10/CLI-MODERN.md` for th
|
|
|
61
61
|
| `loki queue add` | Queue issue refs |
|
|
62
62
|
| `loki queue list` | Show the queue |
|
|
63
63
|
| `loki queue run` | Process the queue |
|
|
64
|
+
| `loki issues` | Run every open issue in a repo and open PRs |
|
|
65
|
+
| `loki issues run` | Triage and run open issues; split too-large ones into stacked PRs |
|
|
66
|
+
| `loki undo` | Plan or apply an undo of a run |
|
|
67
|
+
| `loki verify-pr` | Verify a PR against its linked issue in a sandbox |
|
|
64
68
|
| `loki answer` | Resume a BLOCKED run with an answer |
|
|
65
69
|
| `loki engine10` | v10 engine router |
|
|
66
70
|
| `loki engine10 run` | Run the v10 engine |
|
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.3.
|
|
5
|
+
**Version:** v11.3.2
|
|
6
6
|
|
|
7
7
|
**Engine note:** `loki "<task>"`, `loki owner/repo#N` and `loki quick` run the Loki 10 engine. `loki start` still routes to the older engine, which is being removed; prefer `loki owner/repo#N`. See the [user guide](v10/GUIDE.md).
|
|
8
8
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Loki traces in Grafana, Honeycomb and Datadog
|
|
2
|
+
|
|
3
|
+
Loki exports OTLP/HTTP JSON traces to `LOKI_OTEL_ENDPOINT` (path `/v1/traces`). With `LOKI_OTEL_GENAI=1` the engine10 events map to `gen_ai` spans: `invoke_agent loki` for the run, `stage <name>` per stage, `execute_tool <name>` per tool call. Prompt and completion content never reach a span, and unknown token usage is absent, not 0.
|
|
4
|
+
|
|
5
|
+
The collector config `config/otel-collector/loki-collector.yaml` fans those spans out to three backends.
|
|
6
|
+
|
|
7
|
+
## Use it
|
|
8
|
+
|
|
9
|
+
1. Set the credentials for the vendors you use (the config reads them from the environment, nothing is stored in the file):
|
|
10
|
+
- Grafana Cloud: `GRAFANA_OTLP_ENDPOINT`, `GRAFANA_OTLP_AUTH` (the full header value, `Basic <base64 instanceId:token>`).
|
|
11
|
+
- Honeycomb: `HONEYCOMB_API_KEY` (ingest key).
|
|
12
|
+
- Datadog: `DD_API_KEY`, `DD_SITE` (for example `datadoghq.com`). Needs a collector build that includes the Datadog exporter (collector-contrib).
|
|
13
|
+
2. Start the collector: `otelcol-contrib --config config/otel-collector/loki-collector.yaml`.
|
|
14
|
+
3. Point Loki at it: `LOKI_OTEL_ENDPOINT=http://localhost:4318 LOKI_OTEL_GENAI=1 loki start ...`.
|
|
15
|
+
|
|
16
|
+
To use a subset of vendors, edit only `service.pipelines.traces.exporters` and list the vendors you use. The collector validates every defined exporter even when it is not listed, so the required fields of the other vendors carry inert defaults (`https://unset.invalid` for the Grafana endpoint, `unset` for the Datadog key, `datadoghq.com` for the Datadog site). Those defaults are never used by a vendor that is not in the list, and are not credentials. A listed vendor with its variables unset sends to the inert default and fails at export time, so set the variables for every vendor you list.
|
|
17
|
+
|
|
18
|
+
## Receipt link
|
|
19
|
+
|
|
20
|
+
When tracing was on, the receipt carries a signed `trace_id` (see `docs/AGENT-CHANGE-RECEIPT.md`). Search for that id in the backend to open the run's trace.
|
|
21
|
+
|
|
22
|
+
## Offline check
|
|
23
|
+
|
|
24
|
+
`bash tests/test-otel-collector-config.sh` parses the config, asserts the receiver, processor, exporters and traces pipeline, asserts every credential is an `${env:NAME}` placeholder (an optional `:-default` is allowed and must not be key-shaped), asserts that every required field still resolves to a non-empty default when a vendor's variables are unset, and maps the deterministic fixture in `tests/fixtures/otel/` (fixed run id and timestamps) to the golden span list. It makes no network call. When `otelcol-contrib` is on PATH it also runs `otelcol-contrib validate` with only `HONEYCOMB_API_KEY` set; that step is skipped, not passed, when the binary is absent. It does not contact a vendor; import into each vendor UI is not tested.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Routing evidence
|
|
2
|
+
|
|
3
|
+
Measurements cited by provider and routing code. Each entry records the number,
|
|
4
|
+
its source and the date it was taken. Code comments point here instead of
|
|
5
|
+
carrying the figures.
|
|
6
|
+
|
|
7
|
+
## Cost parity: MiniMax M2.5 vs Claude Opus 4.6
|
|
8
|
+
|
|
9
|
+
Status: a SINGLE internal run, not re-measured. Do not use it to drive routing
|
|
10
|
+
or in any external claim until it is re-derived (issue 210).
|
|
11
|
+
|
|
12
|
+
- Benchmark: SWE-bench, uniform scaffold.
|
|
13
|
+
- Harness: mini-swe-agent v2.0.0.
|
|
14
|
+
- Date: 2026-02-17.
|
|
15
|
+
- MiniMax M2.5: resolved 75.8 at $36.64 total.
|
|
16
|
+
- Claude Opus 4.6: resolved 75.6 at $275.76 total.
|
|
17
|
+
- Derived: an open model matching frontier accuracy at ~7.5x lower cost.
|
|
18
|
+
- Source: cited from the cost-context comment that previously lived in
|
|
19
|
+
providers/opencode.sh; competitive context in docs/COMPETITIVE-INTEL-2026-09.md
|
|
20
|
+
item 3.
|
|
21
|
+
|
|
22
|
+
## opencode viability
|
|
23
|
+
|
|
24
|
+
Date verified: 2026-07-29/30.
|
|
25
|
+
|
|
26
|
+
- Source opencode.ai/docs/providers documents 75+ providers and custom
|
|
27
|
+
OpenAI-compatible endpoints.
|
|
28
|
+
- Source anomalyco/opencode: 190,871 stars, release v1.18.9 (2026-07-28),
|
|
29
|
+
pushed the same week.
|
|
30
|
+
- Source aider: last release v0.86.0 from 2025-08-09.
|
|
31
|
+
- Roo Code is archived; Continue is read-only.
|
|
32
|
+
- CLI surface checked against the installed opencode v1.17.9.
|
|
@@ -135,6 +135,7 @@ banners you might expect. These variables control the remaining `[INFO]` and
|
|
|
135
135
|
| `LOKI_DURABLE_STATE` | `0` | `1` enables durable state **and** the richer process-exit contract that lets Kubernetes distinguish a deterministic failure from a crash. See [exit codes](./exit-codes.md). |
|
|
136
136
|
| `LOKI_SDK_LOOP` | unset | Routes the run through the Bun/TypeScript runner instead of bash. Both implement the same exit contract. |
|
|
137
137
|
| `LOKI_ALLOW_AGENT_GITHUB_TOKEN` | unset | By default `GH_TOKEN`, `GITHUB_TOKEN`, `GH_ENTERPRISE_TOKEN`, and `GITHUB_ENTERPRISE_TOKEN` are withheld from agent sessions. The two routes differ: on the bash route (`autonomy/run.sh`) the withheld tokens are re-granted only for Loki's own trusted calls, namely the `gh()` CLI wrapper, the `_loki_net` helper used by the optional local-PR path in `on_run_complete()`, the session-end `create_session_pr` call, and `autonomy/lib/proof-check.sh`'s network probe. On the Bun route (`loki-ts/src/runner/github_token.ts`'s `withholdGithubTokens()`) the tokens are dropped from the process outright, with no re-grant and no push/PR step of its own. Exactly `1` lets the agent inherit the tokens as before, on either route; that is a Rule of Two exposure, and a one-line stderr warning is printed. |
|
|
138
|
+
| `LOKI_AI_MARKING` | unset (off) | `1` (exactly) adds machine-readable trailers to the Loki commit (`AI-Generated: true`, `AI-Provider`, `AI-Model`, `Loki-Receipt`, after `Loki-Run`) and one `AI-Generated: true (...)` marker line under the verdict in the PR body. Values are single-line and bounded. Off, the commit and PR body are byte-identical to before. |
|
|
138
139
|
|
|
139
140
|
`LOKI_DURABLE_STATE=1` is the one to set in a Job or task definition. Without
|
|
140
141
|
it every failure collapses to exit 1 and the platform cannot tell "re-running
|