loki-mode 11.17.57 → 11.17.59
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 +13 -4
- package/SKILL.md +3 -3
- package/VERSION +1 -1
- package/autonomy/lib/engine10-push.sh +22 -5
- package/autonomy/loki +384 -9
- package/autonomy/telemetry.sh +2 -2
- package/bin/loki +105 -0
- package/completions/_loki +13 -0
- package/completions/loki.bash +15 -1
- package/dashboard/__init__.py +1 -1
- package/docs/CLI-REFERENCE.md +3 -1
- package/docs/COMPARE-OPENCODE.md +18 -6
- package/docs/INSTALLATION.md +6 -2
- package/docs/v10/CLI-MODERN.md +5 -3
- package/docs/v10/PROGRESS.md +3 -0
- package/loki-ts/dist/loki.js +1128 -1117
- package/mcp/__init__.py +1 -1
- package/package.json +2 -2
- package/packages/control-plane/dist/server.js +15 -1
- package/packages/control-plane/ui/dist/assets/{index-CxZWgwie.css → index-DeSVrWgd.css} +1 -1
- package/packages/control-plane/ui/dist/assets/{index-u8cd6TRQ.js → index-Dww-8G06.js} +10 -10
- package/packages/control-plane/ui/dist/index.html +2 -2
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/web-app/dist/assets/{AdminPage-D9vxsKmh.js → AdminPage-CCO9zGD0.js} +1 -1
- package/web-app/dist/assets/{Avatar-DfxBpPUo.js → Avatar-JPtFS3re.js} +1 -1
- package/web-app/dist/assets/{Badge-Jtp0w19_.js → Badge-1bUFOFcI.js} +1 -1
- package/web-app/dist/assets/{Button-Cfl_Ygum.js → Button-BQn8thxN.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-t_xLPM1y.js → CockpitPage-olBRJMLN.js} +1 -1
- package/web-app/dist/assets/{ComparePage-00e9eUgR.js → ComparePage-B-o4mxlZ.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-DfoBT_kK.js → ErrorBoundary-C4IN6YYt.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-Cm--Zldw.js → EvidenceReceiptPanel-CH4iRJiJ.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-CmZoYExK.js → GitHubIssuesPanel-BNgRlwGt.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-rehTMC_P.js → GitHubPRsPanel-B6M_lVU3.js} +1 -1
- package/web-app/dist/assets/{HomePage-CKgOAUqm.js → HomePage-CSlr_5vo.js} +2 -2
- package/web-app/dist/assets/{LoginPage-DWMk7D-V.js → LoginPage-DJhYZ0SQ.js} +1 -1
- package/web-app/dist/assets/{MagicPage-BdIzYkjN.js → MagicPage-B4XpvDFP.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-DdjN5LJL.js → MetricsPage-DlgPEc5f.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-Cf4GHp9Z.js → NotFoundPage-oE1Fvllj.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-BP8u2iFN.js → ProjectPage-B94pP0UO.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-CK7R-DIh.js → ProjectsPage-Bk67iaJq.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-DNMqOUrM.js → SettingsPage-BGVzSJ3n.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-RkPgacU3.js → ShowcasePage-DtGaDxE5.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-COqYOPAP.js → SystemSettingsPage-CfyOGdC-.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-CyBIuYhv.js → TeamsPage-CuGmdY85.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-5cMJ3uaP.js → TemplatesPage-Db4OZ-o0.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-D2as8CHU.js → TerminalOutput-B1W28fpH.js} +1 -1
- package/web-app/dist/assets/{activity-B0HWAVsH.js → activity-DKFtW1Dz.js} +1 -1
- package/web-app/dist/assets/{bell-CeapvdDm.js → bell-D2iqUEiO.js} +1 -1
- package/web-app/dist/assets/{bot-C9_qiFCl.js → bot-DgV5jnOz.js} +1 -1
- package/web-app/dist/assets/{check-ZLkbkjP8.js → check-BgJBmYEn.js} +1 -1
- package/web-app/dist/assets/{chevron-left-DzAOofqV.js → chevron-left-lPbv6ogy.js} +1 -1
- package/web-app/dist/assets/{circle-alert-C_P6Sbnq.js → circle-alert-CKhQ_hdo.js} +1 -1
- package/web-app/dist/assets/{clock-hlFBiyvc.js → clock-DWq8vor5.js} +1 -1
- package/web-app/dist/assets/{cloud-gpl8_jQe.js → cloud-BvQxG3Q2.js} +1 -1
- package/web-app/dist/assets/{code-xml-CJ7WRPDY.js → code-xml-aL36Csaf.js} +1 -1
- package/web-app/dist/assets/{database-C0waxSTC.js → database-CFzHMx2h.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-TFqYdT4P.js → dollar-sign-C-jqbXs_.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-Cklb7xuW.js → file-code-corner-pZ_KZ1YO.js} +1 -1
- package/web-app/dist/assets/{file-plus-vY6Bgsjz.js → file-plus-fRMGiUh4.js} +1 -1
- package/web-app/dist/assets/{globe-4A2JXvUS.js → globe-CVyRdgIZ.js} +1 -1
- package/web-app/dist/assets/{hammer-ZHnY2Erh.js → hammer-DRokcz-I.js} +1 -1
- package/web-app/dist/assets/{index-CgCOQR3S.js → index-CLY7CAQL.js} +3 -3
- package/web-app/dist/assets/{layers-By5ECd5H.js → layers-CEWB89or.js} +1 -1
- package/web-app/dist/assets/{loader-circle-yM_E0C2Q.js → loader-circle-C5OvUx9K.js} +1 -1
- package/web-app/dist/assets/{lock-lSNyrxDR.js → lock-TGMA_-t0.js} +1 -1
- package/web-app/dist/assets/{package-BKFtRuCB.js → package-QJ4Wad2J.js} +1 -1
- package/web-app/dist/assets/{plus-CjV1F6qp.js → plus-Dgj8mPvu.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-DTSM4-_Q.js → refresh-cw-AGMW2syT.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-CiCkyt92.js → rotate-ccw-BvQ3PO0r.js} +1 -1
- package/web-app/dist/assets/{scroll-text-D1Ruxchx.js → scroll-text-iwC90pRp.js} +1 -1
- package/web-app/dist/assets/{server-DhT2dH_l.js → server-TUwkkzsm.js} +1 -1
- package/web-app/dist/assets/{shield-alert-CFFYVEiJ.js → shield-alert-CR3ONYJ5.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-Dl4lQ_rS.js → thumbs-up-DC2-6Rb1.js} +1 -1
- package/web-app/dist/assets/{trash-2-DMJUQZ_M.js → trash-2-o9Iijmor.js} +1 -1
- package/web-app/dist/assets/{trending-down-C4mhp6Ua.js → trending-down-d0olJaN5.js} +1 -1
- package/web-app/dist/assets/{trending-up-D534cAuW.js → trending-up-BB6Q7LpE.js} +1 -1
- package/web-app/dist/assets/{upload-nhP5uhIQ.js → upload-5ck9hJ9r.js} +1 -1
- package/web-app/dist/assets/{usePolling-CWFsCezc.js → usePolling-BLGH4uFR.js} +1 -1
- package/web-app/dist/assets/{user-5TMGZ6m7.js → user-CNCAMMb7.js} +1 -1
- package/web-app/dist/index.html +1 -1
package/README.md
CHANGED
|
@@ -26,7 +26,14 @@ The npm package installs the Bun runtime the engine needs as an optional depende
|
|
|
26
26
|
Want to see a result before you install or spend anything?
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
-
npx loki-mode
|
|
29
|
+
npx loki-mode start # no git repo: a real receipt, no key, no spend
|
|
30
|
+
npx loki-mode tour # the same receipt when you are already inside a repo
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
`npx` downloads the package the first time, so that step needs the network. The receipt itself replays offline and checks with no provider and no key.
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npx loki-mode wow # a provider is ready: one tiny real task in a temp repo, its own receipt
|
|
30
37
|
```
|
|
31
38
|
|
|
32
39
|
## First run
|
|
@@ -57,7 +64,7 @@ Every run starts from a delivery contract derived from your task, writes checks
|
|
|
57
64
|
loki verify # newest run; or: loki verify <run-id>
|
|
58
65
|
```
|
|
59
66
|
|
|
60
|
-
`loki verify` re-hashes the receipt, checks its signature and checks it against the run's event log. It prints a verdict and exits 0 (VERIFIED), 1 (TAMPERED), 2 (UNCHECKED), 3 (UNSIGNED, refused unless `--allow-unsigned`), 4 (run outcome not verified) or 66 (no runs); `[ $rc -eq 0 ]` is the only safe test for "verified". Full table: [docs/exit-codes.md](docs/exit-codes.md). On another machine, export the public key with `loki keys export` and pass it with `loki verify --pubkey <file>`. A receipt claims only what its checks ran, and lists what they did not; signing proves who produced it, not that the code is bug-free. Details: [docs/SIGNED-RECEIPTS.md](docs/SIGNED-RECEIPTS.md).
|
|
67
|
+
`loki verify` re-hashes the receipt, checks its signature and checks it against the run's event log. It prints a verdict and exits 0 (VERIFIED), 1 (TAMPERED), 2 (UNCHECKED), 3 (UNSIGNED, refused unless `--allow-unsigned`), 4 (run outcome not verified) or 66 (no runs); `[ $rc -eq 0 ]` is the only safe test for "verified". `loki start` also requires fail-to-pass for a declared behavior change: a Wall test must fail on the old code and pass after, or the verdict stays PARTIAL (`LOKI_MUTATION_STRICT=0` opts out). Full table: [docs/exit-codes.md](docs/exit-codes.md). On another machine, export the public key with `loki keys export` and pass it with `loki verify --pubkey <file>`. A receipt claims only what its checks ran, and lists what they did not; signing proves who produced it, not that the code is bug-free. Details: [docs/SIGNED-RECEIPTS.md](docs/SIGNED-RECEIPTS.md).
|
|
61
68
|
|
|
62
69
|
For a multi-repo change set, `loki start --workspace <name> "<brief>"` seals one signed `composite.json` over every child receipt, and `loki verify <run-dir>/composite.json` re-checks it offline ([docs/WORKSPACES.md](docs/WORKSPACES.md)). A composite never reads higher than its weakest child.
|
|
63
70
|
|
|
@@ -91,7 +98,7 @@ Time: 4m12s (intake 11s, plan 20s, implement 3m10s, verify 31s)
|
|
|
91
98
|
|
|
92
99
|
| Command | What it does |
|
|
93
100
|
|---------|--------------|
|
|
94
|
-
| `loki start "<task>"` | The
|
|
101
|
+
| `loki start "<task>"` | The command you run: same provider model as a raw session, then the harness re-runs the checks and seals a receipt (`--no-pr`, `--provider`, `--max-cost`, `--haiku` to opt the first implement onto haiku). `loki "<task>"` and `loki owner/repo#N` are shorthand. No task and no git repo shows a receipt and spends nothing |
|
|
95
102
|
| `loki edit "<change>"` | One targeted change in one pass, no PR, plan or council (`--verify`, `--receipt`, `--commit`, `--dry-run`) |
|
|
96
103
|
| `loki quick "<task>"` | One small task with a verify loop, no PR |
|
|
97
104
|
| `loki chat` | Interactive alternative: Plan and Build modes, slash commands, `/run` starts a `loki start` run, `--attach` joins one |
|
|
@@ -106,7 +113,9 @@ Time: 4m12s (intake 11s, plan 20s, implement 3m10s, verify 31s)
|
|
|
106
113
|
| `loki doctor [--fix] [--json]` | Check prerequisites, providers and login; `--fix` applies safe fixes |
|
|
107
114
|
| `loki control serve` | Start the Control Plane (see below) |
|
|
108
115
|
| `loki dashboard` | Open the Control Plane UI, starting it if needed |
|
|
109
|
-
| `loki tour` | Show a sample receipt offline |
|
|
116
|
+
| `loki tour` | Show a sample receipt offline. `loki start` does this when you are not in a git repo and did not pass a task |
|
|
117
|
+
| `loki wow` | Same live mini-task as a normal start, in a temp repo. Offline sample when no provider is ready |
|
|
118
|
+
| `loki factory "<task>"` | Same as `loki start`. The policy line is printed by start |
|
|
110
119
|
| `loki --help` | Everything else; `loki help <command>` for one command |
|
|
111
120
|
|
|
112
121
|
Core verbs: [docs/CLI-CORE-VERBS.md](docs/CLI-CORE-VERBS.md). Every command (generated): [docs/CLI-REFERENCE.md](docs/CLI-REFERENCE.md). Engine guide, provider table, model routes, custom agents and chat: [docs/v10/GUIDE.md](docs/v10/GUIDE.md). Honest comparison with opencode: [docs/COMPARE-OPENCODE.md](docs/COMPARE-OPENCODE.md).
|
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 v11.17.
|
|
6
|
+
# Loki Mode v11.17.59
|
|
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 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
|
|
|
@@ -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`, `backup`, `restore`, `proof`, `wiki`, `control`, `intent`, `kpis`, `report`, `trust`, `crash`, `contract`, `start`, `slack`, `queue`, `issues`, `undo`, `verify-pr`, `answer`, `engine10`, `help`, `chat`, `edit`, `diff`, `models`, `setup`, `quick`, `quickstart`, `init`, `template`, `verify`, `keys`, `review`, `dashboard`, `config`, `mcp`, `acp`, `stop`, `pause`, `resume`, `cancel`, `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`, `steer`
|
|
203
|
+
`version`, `status`, `doctor`, `provider`, `memory`, `rollback`, `backup`, `restore`, `proof`, `wiki`, `control`, `intent`, `kpis`, `report`, `trust`, `crash`, `contract`, `start`, `slack`, `queue`, `issues`, `undo`, `verify-pr`, `answer`, `engine10`, `help`, `chat`, `edit`, `diff`, `models`, `setup`, `quick`, `quickstart`, `init`, `template`, `verify`, `keys`, `review`, `dashboard`, `config`, `mcp`, `acp`, `stop`, `pause`, `resume`, `cancel`, `why`, `next`, `logs`, `ship`, `deploy`, `import`, `github`, `issue`, `ci`, `modernize`, `share`, `assets`, `export`, `notify`, `tour`, `wow`, `factory`, `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`, `steer`
|
|
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.17.
|
|
486
|
+
**v11.17.59 | [Autonomi](https://www.autonomi.dev/) flagship product | core skill**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
11.17.
|
|
1
|
+
11.17.59
|
|
@@ -207,6 +207,7 @@ case "$mode" in
|
|
|
207
207
|
# --update: the status projector. One comment carrying the marker below is edited in place (created when absent),
|
|
208
208
|
# so an issue shows live run state without a new comment per event. Only a comment written by the authenticated
|
|
209
209
|
# gh user counts, and the body file must carry the marker (it is built by the supervisor, never from task text).
|
|
210
|
+
# The PR receipt comment (<!-- loki-receipt -->) uses the same upsert: a PR number is an issue number to the API.
|
|
210
211
|
_e10_upd=""
|
|
211
212
|
[ "${1:-}" != "--update" ] || { _e10_upd=1; shift; }
|
|
212
213
|
[ "$#" -eq 2 ] || die "usage: issue-comment [--update] <issue-ref> <body-file>"
|
|
@@ -215,16 +216,32 @@ case "$mode" in
|
|
|
215
216
|
[ -f "$2" ] || die "body file not found: $2"
|
|
216
217
|
[ -z "$_e10_local" ] || { log_info "local origin: no issue to comment on (no-op)"; exit 0; }
|
|
217
218
|
if [ -n "$_e10_upd" ]; then
|
|
218
|
-
_e10_marker=
|
|
219
|
-
|
|
219
|
+
_e10_marker=""
|
|
220
|
+
for _e10_m in '<!-- loki-status -->' '<!-- loki-receipt -->'; do
|
|
221
|
+
if grep -qF -- "$_e10_m" "$2"; then _e10_marker="$_e10_m"; break; fi
|
|
222
|
+
done
|
|
223
|
+
[ -n "$_e10_marker" ] || die "status body must carry <!-- loki-status --> or <!-- loki-receipt -->"
|
|
220
224
|
_e10_me="$(_e10_gh api user --jq .login 2>/dev/null)" || _e10_me=""
|
|
221
225
|
_e10_cid=""
|
|
226
|
+
# A receipt upsert never posts on a failed lookup: that would stack a duplicate and still report success.
|
|
227
|
+
if [ -z "$_e10_me" ] && [ "$_e10_marker" = '<!-- loki-receipt -->' ]; then die "cannot resolve the gh user for the receipt comment lookup"; fi
|
|
222
228
|
if [ -n "$_e10_me" ]; then
|
|
223
|
-
|
|
224
|
-
--jq ".[] | select(.user.login == \"$_e10_me\") | select(.body | contains(\"$_e10_marker\")) | .id" 2>/dev/null
|
|
229
|
+
if _e10_ids="$(_e10_gh api "repos/$_e10_repo/issues/$num/comments" --paginate \
|
|
230
|
+
--jq ".[] | select(.user.login == \"$_e10_me\") | select(.body | contains(\"$_e10_marker\")) | .id" 2>/dev/null)"; then
|
|
231
|
+
_e10_cid="$(printf '%s\n' "$_e10_ids" | head -n 1)"
|
|
232
|
+
elif [ "$_e10_marker" = '<!-- loki-receipt -->' ]; then
|
|
233
|
+
die "receipt comment lookup failed"
|
|
234
|
+
fi
|
|
225
235
|
fi
|
|
226
236
|
case "$_e10_cid" in
|
|
227
|
-
'')
|
|
237
|
+
'')
|
|
238
|
+
# A PR number is not an issue to `gh issue comment`; the receipt marker only ever rides a PR.
|
|
239
|
+
if [ "$_e10_marker" = '<!-- loki-receipt -->' ]; then
|
|
240
|
+
_e10_gh pr comment "$num" --repo "$_e10_repo" --body-file "$2" || die "gh pr comment failed"
|
|
241
|
+
else
|
|
242
|
+
_e10_gh issue comment "$num" --repo "$_e10_repo" --body-file "$2" || die "gh issue comment failed"
|
|
243
|
+
fi
|
|
244
|
+
;;
|
|
228
245
|
*[!0-9]*) die "unexpected comment id" ;;
|
|
229
246
|
*) _e10_gh api -X PATCH "repos/$_e10_repo/issues/comments/$_e10_cid" -F "body=@$2" >/dev/null || die "gh api comment update failed" ;;
|
|
230
247
|
esac
|
package/autonomy/loki
CHANGED
|
@@ -1929,6 +1929,9 @@ show_help_all() {
|
|
|
1929
1929
|
echo " loki start PROJ-456 # Jira issue"
|
|
1930
1930
|
echo " loki quick \"add dark mode\" # Single-task mode (Loki 10 engine)"
|
|
1931
1931
|
echo " loki tour # See a real sample result (no provider, no key, no spend)"
|
|
1932
|
+
echo " loki tour --live # Same as loki wow: a tiny real task when a provider is ready"
|
|
1933
|
+
echo " loki wow # Live mini-task, or the offline sample when no key is available"
|
|
1934
|
+
echo " loki factory \"<task>\" # loki start, and print the autonomy policy"
|
|
1932
1935
|
echo " loki demo # Build a sample todo app end to end"
|
|
1933
1936
|
echo " loki init -t saas-starter # Scaffold from template"
|
|
1934
1937
|
echo " loki template install <src> # Install a community PRD template"
|
|
@@ -1994,7 +1997,7 @@ show_help_all() {
|
|
|
1994
1997
|
echo " acp agent analyze api assets audit backlog backup bench cancel checkpoint (cp) ci cleanup"
|
|
1995
1998
|
echo " cluster cockpit code compliance completions compound config context (ctx)"
|
|
1996
1999
|
echo " cost council crash dashboard demo deploy docker docs doctor dogfood"
|
|
1997
|
-
echo " enterprise estimate explain export failover github grill heal help"
|
|
2000
|
+
echo " enterprise estimate explain export factory failover github grill heal help"
|
|
1998
2001
|
echo " import init intent"
|
|
1999
2002
|
echo " issue keys kpis logs magic mcp memory metrics migrate modernize monitor"
|
|
2000
2003
|
echo " next notify onboard open optimize otel outcomes own (handoff) pause plan preview"
|
|
@@ -2003,7 +2006,7 @@ show_help_all() {
|
|
|
2003
2006
|
echo " serve setup setup-skill share ship spec start state stats status steer stop"
|
|
2004
2007
|
echo " syslog telemetry template test tour trigger trust trust-metrics"
|
|
2005
2008
|
echo " ultracode undo update verify version voice watch watchdog web welcome why"
|
|
2006
|
-
echo " wiki workspace worktree (wt)"
|
|
2009
|
+
echo " wiki workspace worktree (wt) wow"
|
|
2007
2010
|
echo " control"
|
|
2008
2011
|
echo ""
|
|
2009
2012
|
echo "Any command: loki <command> --help"
|
|
@@ -2596,7 +2599,7 @@ _loki_start_flag_kind() {
|
|
|
2596
2599
|
case "${1%%=*}" in
|
|
2597
2600
|
--provider|--brief|--budget|--cost|--prd|--issue|--isolation|--aider-model|--aider-flags|--cline-model|--compliance|--max-duration|--log-level|--bmad-project|--openspec|--mirofish-rounds|--mirofish-timeout|--output|--config|--vars|--env-file|--remote|--attempts|--mirofish-docker) _LOKI_START_FLAG_KIND=value ;;
|
|
2598
2601
|
--mirofish) _LOKI_START_FLAG_KIND=optional ;;
|
|
2599
|
-
--parallel|--allow-haiku|--regen-prd|--regenerate-prd|--regen|--fresh-prd|--bg|--background|--simple|--complex|--github|--no-dashboard|--api|--sandbox|--skip-memory|--yes|-y|--quiet|--mirofish-bg|--no-mirofish|--no-plan|--fast|--repo-fast|--full|--repo-full|--dry-run|--no-start|--worktree|-w|--pr|--prepare-pr|--ship|--detach|-d|--help|-h|--resume|--) _LOKI_START_FLAG_KIND=bool ;;
|
|
2602
|
+
--parallel|--allow-haiku|--haiku|--regen-prd|--regenerate-prd|--regen|--fresh-prd|--bg|--background|--simple|--complex|--github|--no-dashboard|--api|--sandbox|--skip-memory|--yes|-y|--quiet|--mirofish-bg|--no-mirofish|--no-plan|--fast|--repo-fast|--full|--repo-full|--dry-run|--no-start|--worktree|-w|--pr|--prepare-pr|--ship|--detach|-d|--help|-h|--resume|--) _LOKI_START_FLAG_KIND=bool ;;
|
|
2600
2603
|
*) return 1 ;;
|
|
2601
2604
|
esac
|
|
2602
2605
|
# A "--flag=value" token carries its own value, so it never consumes the next one.
|
|
@@ -2624,6 +2627,73 @@ _loki_e10_resume_map() {
|
|
|
2624
2627
|
return 0
|
|
2625
2628
|
}
|
|
2626
2629
|
|
|
2630
|
+
# TEN-COST-01 lean levers (the bash twin of COST_PROFILES.lean in loki-ts/src/util/cost_profile.ts).
|
|
2631
|
+
# Fills only unset variables, so explicit env wins. Shared by --cost lean and --haiku.
|
|
2632
|
+
loki_lean_levers() {
|
|
2633
|
+
: "${LOKI_IMPLEMENT_HAIKU_FIRST:=1}" "${LOKI_E10_TRIM:=1}" "${LOKI_E10_SMALL_NO_RUNNER:=1}" "${LOKI_E10_SMALL_MAX_CHARS:=1200}"
|
|
2634
|
+
export LOKI_IMPLEMENT_HAIKU_FIRST LOKI_E10_TRIM LOKI_E10_SMALL_NO_RUNNER LOKI_E10_SMALL_MAX_CHARS
|
|
2635
|
+
}
|
|
2636
|
+
|
|
2637
|
+
# --haiku opt-in: the lean levers plus LOKI_COST_FIRST=1. Does not change the
|
|
2638
|
+
# default model. bin/loki strips the flag and sets the same levers before
|
|
2639
|
+
# engine10; this covers a direct bash start and LOKI_CONFIG_DUMP.
|
|
2640
|
+
loki_apply_haiku_optin() {
|
|
2641
|
+
local _a
|
|
2642
|
+
for _a in "$@"; do
|
|
2643
|
+
[ "$_a" = "--haiku" ] || continue
|
|
2644
|
+
loki_lean_levers
|
|
2645
|
+
: "${LOKI_COST_FIRST:=1}"
|
|
2646
|
+
export LOKI_COST_FIRST
|
|
2647
|
+
return 0
|
|
2648
|
+
done
|
|
2649
|
+
}
|
|
2650
|
+
|
|
2651
|
+
# Same fail-to-pass default as _loki_f2p_default in bin/loki. Direct bash
|
|
2652
|
+
# starts never see the shim. Explicit 0 or 1 wins. --help does not set it.
|
|
2653
|
+
loki_f2p_default() {
|
|
2654
|
+
case "${1:-}" in
|
|
2655
|
+
start|run|quick) ;;
|
|
2656
|
+
*) return 0 ;;
|
|
2657
|
+
esac
|
|
2658
|
+
local _a
|
|
2659
|
+
for _a in "$@"; do
|
|
2660
|
+
case "$_a" in --help|-h) return 0 ;; esac
|
|
2661
|
+
done
|
|
2662
|
+
if [ -z "${LOKI_MUTATION_STRICT:-}" ]; then
|
|
2663
|
+
export LOKI_MUTATION_STRICT=1
|
|
2664
|
+
export LOKI_F2P_DEFAULTED=1
|
|
2665
|
+
fi
|
|
2666
|
+
if [ -z "${LOKI_E10_TRIM:-}" ]; then
|
|
2667
|
+
export LOKI_E10_TRIM=1
|
|
2668
|
+
export LOKI_TRIM_DEFAULTED=1
|
|
2669
|
+
fi
|
|
2670
|
+
}
|
|
2671
|
+
# Names only the defaults this run actually turned on (an explicit 0 or 1 is the user's, not a default).
|
|
2672
|
+
loki_f2p_banner() {
|
|
2673
|
+
local f2p="${LOKI_F2P_DEFAULTED:-}" trim="${LOKI_TRIM_DEFAULTED:-}"
|
|
2674
|
+
if [ "$f2p" = "1" ] && [ "$trim" = "1" ]; then
|
|
2675
|
+
echo "Factory: a behavior change is verified only when a Wall test fails on the old code, and tool logs are trimmed before the next turn. Opt out: LOKI_MUTATION_STRICT=0, LOKI_E10_TRIM=0." >&2
|
|
2676
|
+
elif [ "$f2p" = "1" ]; then
|
|
2677
|
+
echo "Factory: a behavior change is verified only when a Wall test fails on the old code. Opt out: LOKI_MUTATION_STRICT=0." >&2
|
|
2678
|
+
elif [ "$trim" = "1" ]; then
|
|
2679
|
+
echo "Factory: tool logs are trimmed before the next turn. Opt out: LOKI_E10_TRIM=0." >&2
|
|
2680
|
+
fi
|
|
2681
|
+
}
|
|
2682
|
+
|
|
2683
|
+
# $1 (optional): the repo the run targets, so `loki factory ./other-repo` reports that repo's policy.
|
|
2684
|
+
loki_print_autonomy() {
|
|
2685
|
+
local pol="" f pre="" data_dir="${LOKI_DATA_DIR:-${HOME}/.loki}"
|
|
2686
|
+
if [ -n "${1:-}" ] && [ "$1" != "." ] && [ -d "$1" ]; then pre="${1%/}/"; fi
|
|
2687
|
+
for f in "${pre}.loki/policies.json" "${pre}.loki/policies.yaml" "${data_dir}/policies.json" "${data_dir}/policies.yaml"; do
|
|
2688
|
+
if [ -f "$f" ]; then pol="$f"; break; fi
|
|
2689
|
+
done
|
|
2690
|
+
if [ -n "$pol" ]; then
|
|
2691
|
+
echo "Autonomy: policy file $pol (propose, execute, operate; the file decides PR allow, draft or deny)." >&2
|
|
2692
|
+
else
|
|
2693
|
+
echo "Autonomy: execute (no policy file). Levels: propose, execute, operate." >&2
|
|
2694
|
+
fi
|
|
2695
|
+
}
|
|
2696
|
+
|
|
2627
2697
|
cmd_start() {
|
|
2628
2698
|
# First-run welcome (once): open the branded welcome page on the very
|
|
2629
2699
|
# first start. Writes ~/.loki/.welcomed and never repeats; non-blocking,
|
|
@@ -2853,7 +2923,7 @@ cmd_start() {
|
|
|
2853
2923
|
echo " PROJ-123, #123, or bare number -> generate PRD from issue"
|
|
2854
2924
|
echo " BRIEF mode - a quoted one-line description (with spaces) -> fast"
|
|
2855
2925
|
echo " zero-config first run; visible artifact + proof quickly"
|
|
2856
|
-
echo " no input - analyze current directory, auto-generate PRD"
|
|
2926
|
+
echo " no input - analyze current directory, auto-generate PRD (outside a git repo: the offline sample receipt)"
|
|
2857
2927
|
echo ""
|
|
2858
2928
|
echo "Arguments:"
|
|
2859
2929
|
echo " REPO Existing project directory"
|
|
@@ -2890,6 +2960,8 @@ cmd_start() {
|
|
|
2890
2960
|
echo " --compliance PRESET Enable compliance mode (default|healthcare|fintech|government)"
|
|
2891
2961
|
echo " --budget USD Per-run cost cap (default $(loki_budget_default_usd); auto-pause when exceeded)"
|
|
2892
2962
|
echo " --cost PROFILE Opt-in cost profile: lean (LOKI_IMPLEMENT_HAIKU_FIRST=1, LOKI_E10_TRIM=1, LOKI_E10_SMALL_NO_RUNNER=1, LOKI_E10_SMALL_MAX_CHARS=1200 unless already set) or off"
|
|
2963
|
+
echo " --haiku Opt in to haiku for the first implement. Same levers as --cost lean, plus LOKI_COST_FIRST=1. A failed check climbs back to the session model. Default is the provider model"
|
|
2964
|
+
echo " Proof Default LOKI_MUTATION_STRICT=1 and LOKI_E10_TRIM=1. A behavior change is VERIFIED only when a Wall test fails on the old code. Tool logs are trimmed before the next turn; a command's tail is kept. Opt out: LOKI_MUTATION_STRICT=0, LOKI_E10_TRIM=0"
|
|
2893
2965
|
echo " --bmad-project PATH Use BMAD Method project artifacts as input"
|
|
2894
2966
|
echo " --openspec PATH Use OpenSpec change directory as input"
|
|
2895
2967
|
echo " --mirofish [URL] Enable MiroFish market validation (default: localhost:5001)"
|
|
@@ -2942,7 +3014,7 @@ cmd_start() {
|
|
|
2942
3014
|
echo " LOKI_BUDGET_LIMIT Cost cap in USD (default $(loki_budget_default_usd); empty means unlimited)"
|
|
2943
3015
|
echo ""
|
|
2944
3016
|
echo "Examples:"
|
|
2945
|
-
echo " loki start # Interactive, analyze current dir"
|
|
3017
|
+
echo " loki start # Interactive, analyze current dir (no git repo: offline sample)"
|
|
2946
3018
|
echo " loki start ./my-project # Improve an existing project"
|
|
2947
3019
|
echo " loki start \"build a todo app\" # BRIEF mode (zero-config fast run)"
|
|
2948
3020
|
echo " loki start --brief \"snake\" # BRIEF mode (single-word escape hatch)"
|
|
@@ -3359,11 +3431,15 @@ cmd_start() {
|
|
|
3359
3431
|
shift
|
|
3360
3432
|
;;
|
|
3361
3433
|
# TEN-COST-01: opt-in cost profile; fills only unset levers (explicit env wins).
|
|
3434
|
+
--haiku)
|
|
3435
|
+
loki_apply_haiku_optin --haiku
|
|
3436
|
+
shift
|
|
3437
|
+
;;
|
|
3362
3438
|
--cost|--cost=*)
|
|
3363
3439
|
if [[ "$1" == --cost=* ]]; then _cost_val="${1#*=}"; _cost_n=1; else _cost_val="${2:-}"; _cost_n=2; fi
|
|
3364
3440
|
case "$_cost_val" in
|
|
3365
|
-
lean)
|
|
3366
|
-
export
|
|
3441
|
+
lean) loki_lean_levers
|
|
3442
|
+
export LOKI_COST_PROFILE=lean
|
|
3367
3443
|
echo "cost profile lean: LOKI_IMPLEMENT_HAIKU_FIRST=$LOKI_IMPLEMENT_HAIKU_FIRST LOKI_E10_TRIM=$LOKI_E10_TRIM LOKI_E10_SMALL_NO_RUNNER=$LOKI_E10_SMALL_NO_RUNNER LOKI_E10_SMALL_MAX_CHARS=$LOKI_E10_SMALL_MAX_CHARS" ;;
|
|
3368
3444
|
off) ;;
|
|
3369
3445
|
*) echo -e "${RED}--cost must be lean or off${NC}" >&2; exit 2 ;;
|
|
@@ -3514,6 +3590,23 @@ cmd_start() {
|
|
|
3514
3590
|
esac
|
|
3515
3591
|
done
|
|
3516
3592
|
|
|
3593
|
+
# No task and no git repo: do not ask for a provider and do not spend.
|
|
3594
|
+
# The offline receipt (same sample as loki tour) is the first thing they see.
|
|
3595
|
+
# An explicit provider (--provider or LOKI_PROVIDER) keeps its preflight, so a
|
|
3596
|
+
# missing or unknown provider still fails loudly instead of showing a sample.
|
|
3597
|
+
if [ -z "$brief_text" ] && [ -z "$prd_file" ] && [ -z "$positional_arg" ] \
|
|
3598
|
+
&& [ -z "$provider" ] && [ -z "${LOKI_PROVIDER:-}" ] \
|
|
3599
|
+
&& [ -z "$explicit_mode" ] && [ -z "${LOKI_PRD_FILE:-}" ] \
|
|
3600
|
+
&& [ -z "$remote_url" ] && [ -z "${_ps_ws:-}" ] && [ "${_ps_deploy:-0}" != 1 ] \
|
|
3601
|
+
&& [ -z "${bmad_project_path:-}" ] && [ -z "${openspec_change_path:-}" ]; then
|
|
3602
|
+
if ! git rev-parse --is-inside-work-tree >/dev/null 2>&1; then
|
|
3603
|
+
echo "No repo and no task. Showing a real receipt (no key, no spend)."
|
|
3604
|
+
echo ""
|
|
3605
|
+
wow_offline_finish
|
|
3606
|
+
return $?
|
|
3607
|
+
fi
|
|
3608
|
+
fi
|
|
3609
|
+
|
|
3517
3610
|
# --remote: submit to a deployed cluster instead of building locally.
|
|
3518
3611
|
#
|
|
3519
3612
|
# Branches HERE, after arg parsing but BEFORE the provider pre-flight and
|
|
@@ -3601,6 +3694,12 @@ cmd_start() {
|
|
|
3601
3694
|
fi
|
|
3602
3695
|
fi
|
|
3603
3696
|
|
|
3697
|
+
# One line each. Printed on the path that will spend, not on --help or the
|
|
3698
|
+
# empty non-repo receipt above. The Loki 10 engine path prints the same
|
|
3699
|
+
# lines from bin/loki and does not reach here.
|
|
3700
|
+
loki_print_autonomy "${positional_arg:-}"
|
|
3701
|
+
loki_f2p_banner
|
|
3702
|
+
|
|
3604
3703
|
# Clear any stale raw-brief marker from a PRIOR run before we decide the
|
|
3605
3704
|
# mode of THIS run. Only the brief branch (below) re-writes it. Without this,
|
|
3606
3705
|
# a brief run leaves .loki/state/brief.txt behind and a later non-brief run
|
|
@@ -16490,6 +16589,266 @@ print('{}{}'.format(iters, rng_str))
|
|
|
16490
16589
|
return 0
|
|
16491
16590
|
}
|
|
16492
16591
|
|
|
16592
|
+
# loki wow: a tiny real Loki 10 task in a temp repo, or the offline tour when no provider is ready.
|
|
16593
|
+
wow_offline_finish() {
|
|
16594
|
+
echo "No live provider for this run. Showing the offline sample (no key, no spend)."
|
|
16595
|
+
echo ""
|
|
16596
|
+
cmd_demo --offline
|
|
16597
|
+
echo ""
|
|
16598
|
+
echo "Ready for your repo? loki start"
|
|
16599
|
+
}
|
|
16600
|
+
|
|
16601
|
+
# Heuristic, not an auth check: an installed claude CLI with a key, an OAuth token,
|
|
16602
|
+
# or a config dir counts as ready. A logged-out install passes this and then fails
|
|
16603
|
+
# the live run; cmd_wow reports that failure and its exit code, it never hides it.
|
|
16604
|
+
wow_provider_ready() {
|
|
16605
|
+
local p="${1:-}"
|
|
16606
|
+
[ -n "$p" ] || p="${LOKI_PROVIDER:-claude}"
|
|
16607
|
+
case "$p" in
|
|
16608
|
+
claude)
|
|
16609
|
+
command -v claude >/dev/null 2>&1 || return 1
|
|
16610
|
+
if [ -n "${ANTHROPIC_API_KEY:-}${CLAUDE_CODE_OAUTH_TOKEN:-}" ]; then return 0; fi
|
|
16611
|
+
[ -e "${HOME}/.claude.json" ] || [ -d "${HOME}/.claude" ] || return 1
|
|
16612
|
+
return 0
|
|
16613
|
+
;;
|
|
16614
|
+
opencode|codex|cline|aider)
|
|
16615
|
+
command -v "$p" >/dev/null 2>&1
|
|
16616
|
+
;;
|
|
16617
|
+
*)
|
|
16618
|
+
return 1
|
|
16619
|
+
;;
|
|
16620
|
+
esac
|
|
16621
|
+
}
|
|
16622
|
+
|
|
16623
|
+
# Prints the newest receipt under $1/.loki/runs. Returns 1 when none was written.
|
|
16624
|
+
wow_show_receipt() {
|
|
16625
|
+
local demo_dir="$1" receipt vrc=0
|
|
16626
|
+
receipt="$(python3 - "$demo_dir/.loki/runs" <<'PY'
|
|
16627
|
+
import os, sys
|
|
16628
|
+
root, best = sys.argv[1], None
|
|
16629
|
+
for d, _, files in os.walk(root):
|
|
16630
|
+
if "receipt.json" in files:
|
|
16631
|
+
p = os.path.join(d, "receipt.json")
|
|
16632
|
+
if best is None or os.path.getmtime(p) > os.path.getmtime(best):
|
|
16633
|
+
best = p
|
|
16634
|
+
print(best or "")
|
|
16635
|
+
PY
|
|
16636
|
+
)" || receipt=""
|
|
16637
|
+
if [ -z "$receipt" ]; then
|
|
16638
|
+
return 1
|
|
16639
|
+
fi
|
|
16640
|
+
echo ""
|
|
16641
|
+
echo "Receipt: $receipt"
|
|
16642
|
+
python3 - "$receipt" <<'PY'
|
|
16643
|
+
import json, sys
|
|
16644
|
+
try:
|
|
16645
|
+
with open(sys.argv[1], encoding="utf-8") as fh:
|
|
16646
|
+
r = json.load(fh)
|
|
16647
|
+
if not isinstance(r, dict):
|
|
16648
|
+
raise ValueError("not a JSON object")
|
|
16649
|
+
except (OSError, ValueError) as exc:
|
|
16650
|
+
print(f"Outcome: unreadable receipt ({exc.__class__.__name__}); loki verify below is the check")
|
|
16651
|
+
sys.exit(0)
|
|
16652
|
+
verdict = str(r.get("verdict") or "unknown")
|
|
16653
|
+
cost = r.get("cost") if isinstance(r.get("cost"), dict) else {}
|
|
16654
|
+
usd = cost.get("usd")
|
|
16655
|
+
tokens = 0
|
|
16656
|
+
for k in ("input_tokens", "output_tokens", "cache_read_tokens", "cache_creation_tokens"):
|
|
16657
|
+
try:
|
|
16658
|
+
tokens += int(cost.get(k) or 0)
|
|
16659
|
+
except (TypeError, ValueError):
|
|
16660
|
+
pass
|
|
16661
|
+
np = r.get("not_proven") if isinstance(r.get("not_proven"), list) else []
|
|
16662
|
+
print(f"Outcome: {verdict}")
|
|
16663
|
+
print(f"Cost: ${usd:.4f}" if isinstance(usd, (int, float)) else "Cost: not recorded on the receipt")
|
|
16664
|
+
print(f"Tokens: {tokens}")
|
|
16665
|
+
print("PROVEN: sealed verdict VERIFIED" if verdict == "VERIFIED" else f"PROVEN: no verified claim (verdict {verdict})")
|
|
16666
|
+
print("NOT PROVEN:")
|
|
16667
|
+
for item in np or ["none"]:
|
|
16668
|
+
print(f" - {item}")
|
|
16669
|
+
PY
|
|
16670
|
+
echo ""
|
|
16671
|
+
echo "Verify offline:"
|
|
16672
|
+
(cd "$demo_dir" && "$SKILL_DIR/bin/loki" verify) || vrc=$?
|
|
16673
|
+
if [ "$vrc" = "0" ]; then
|
|
16674
|
+
echo "loki verify exited 0"
|
|
16675
|
+
else
|
|
16676
|
+
echo "loki verify exited $vrc (the receipt did not check out; that is the evidence)"
|
|
16677
|
+
fi
|
|
16678
|
+
return 0
|
|
16679
|
+
}
|
|
16680
|
+
|
|
16681
|
+
# Removes only a directory this command created: a direct child of the temp root named loki-wow.*.
|
|
16682
|
+
wow_cleanup_dir() {
|
|
16683
|
+
local d="${1:-}" root
|
|
16684
|
+
[ -n "$d" ] && [ -d "$d" ] && [ ! -L "$d" ] || return 0
|
|
16685
|
+
root="$(cd "${TMPDIR:-/tmp}" 2>/dev/null && pwd -P)" || return 0
|
|
16686
|
+
case "$d" in "$root"/loki-wow.*) ;; *) return 0 ;; esac
|
|
16687
|
+
[ "$(dirname -- "$d")" = "$root" ] || return 0
|
|
16688
|
+
rm -rf -- "$d"
|
|
16689
|
+
}
|
|
16690
|
+
|
|
16691
|
+
cmd_wow() {
|
|
16692
|
+
local offline=false dry_run=false keep=false provider="" max_cost="2"
|
|
16693
|
+
while [[ $# -gt 0 ]]; do
|
|
16694
|
+
case "$1" in
|
|
16695
|
+
--help|-h)
|
|
16696
|
+
echo "loki wow - a tiny real task in a temporary git repo"
|
|
16697
|
+
echo ""
|
|
16698
|
+
echo "Creates a temp repo, runs one small fix through the Loki 10 engine,"
|
|
16699
|
+
echo "seals a receipt, and prints PROVEN vs NOT PROVEN, cost and tokens."
|
|
16700
|
+
echo "With no provider key it runs the offline sample instead (loki tour)."
|
|
16701
|
+
echo "A failed live run shows its own receipt and exit code, never the sample."
|
|
16702
|
+
echo ""
|
|
16703
|
+
echo "Usage: loki wow [--offline] [--dry-run] [--keep] [--provider P] [--max-cost N]"
|
|
16704
|
+
echo ""
|
|
16705
|
+
echo " --offline Always show the offline sample"
|
|
16706
|
+
echo " --dry-run Print the plan. No model call, no spend"
|
|
16707
|
+
echo " --keep Keep the temp repo (default: removed after the receipt is printed)"
|
|
16708
|
+
echo " --provider P claude (default) or opencode, codex, cline, aider"
|
|
16709
|
+
echo " --max-cost N Hard per-run cap in USD, a positive number (default 2). budgets.per_run still applies"
|
|
16710
|
+
echo ""
|
|
16711
|
+
echo "loki tour stays the offline sample. loki tour --live is this command."
|
|
16712
|
+
echo "Ready for your repo? loki start"
|
|
16713
|
+
return 0
|
|
16714
|
+
;;
|
|
16715
|
+
--offline) offline=true; shift ;;
|
|
16716
|
+
--dry-run) dry_run=true; shift ;;
|
|
16717
|
+
--keep) keep=true; shift ;;
|
|
16718
|
+
--provider)
|
|
16719
|
+
provider="${2:-}"
|
|
16720
|
+
if [ -z "$provider" ]; then echo "loki wow: --provider requires a value" >&2; return 1; fi
|
|
16721
|
+
shift 2
|
|
16722
|
+
;;
|
|
16723
|
+
--provider=*) provider="${1#*=}"; shift ;;
|
|
16724
|
+
--max-cost)
|
|
16725
|
+
max_cost="${2:-}"
|
|
16726
|
+
if [ -z "$max_cost" ]; then echo "loki wow: --max-cost requires a value" >&2; return 1; fi
|
|
16727
|
+
shift 2
|
|
16728
|
+
;;
|
|
16729
|
+
--max-cost=*) max_cost="${1#*=}"; shift ;;
|
|
16730
|
+
*)
|
|
16731
|
+
echo "loki wow: unknown option: $1" >&2
|
|
16732
|
+
echo "Run 'loki wow --help'." >&2
|
|
16733
|
+
return 1
|
|
16734
|
+
;;
|
|
16735
|
+
esac
|
|
16736
|
+
done
|
|
16737
|
+
if ! [[ "$max_cost" =~ ^[0-9]+(\.[0-9]+)?$ ]] || ! awk -v c="$max_cost" 'BEGIN { exit !(c > 0) }'; then
|
|
16738
|
+
echo "loki wow: --max-cost must be a positive number of USD, got: $max_cost" >&2
|
|
16739
|
+
return 2
|
|
16740
|
+
fi
|
|
16741
|
+
|
|
16742
|
+
if [ "$offline" = true ]; then
|
|
16743
|
+
wow_offline_finish
|
|
16744
|
+
return $?
|
|
16745
|
+
fi
|
|
16746
|
+
|
|
16747
|
+
local use_provider="${provider:-${LOKI_PROVIDER:-claude}}"
|
|
16748
|
+
case "$use_provider" in
|
|
16749
|
+
claude|opencode|codex|cline|aider) ;;
|
|
16750
|
+
*) echo "loki wow: unknown provider '$use_provider' (use claude, opencode, codex, cline or aider)" >&2; return 2 ;;
|
|
16751
|
+
esac
|
|
16752
|
+
if ! wow_provider_ready "$use_provider"; then
|
|
16753
|
+
if [ "$dry_run" = true ]; then
|
|
16754
|
+
echo "loki wow: no provider ready for '$use_provider'. A real run would show the offline sample."
|
|
16755
|
+
echo "Ready for your repo? loki start"
|
|
16756
|
+
return 0
|
|
16757
|
+
fi
|
|
16758
|
+
wow_offline_finish
|
|
16759
|
+
return $?
|
|
16760
|
+
fi
|
|
16761
|
+
|
|
16762
|
+
local task='Make greet() in greet.js return the string hello so `node --test greet.test.js` passes. Do not change the test.'
|
|
16763
|
+
echo "loki wow: temp repo, provider $use_provider, max-cost \$$max_cost, no PR (local receipt)."
|
|
16764
|
+
echo "Task: $task"
|
|
16765
|
+
if [ "$dry_run" = true ]; then
|
|
16766
|
+
echo "[dry-run] Would create a git repo with a failing node:test and run:"
|
|
16767
|
+
echo " loki start \"<task>\" --no-pr --provider $use_provider --max-cost $max_cost"
|
|
16768
|
+
echo "Then print the receipt, PROVEN vs NOT PROVEN, and: Ready for your repo? loki start"
|
|
16769
|
+
return 0
|
|
16770
|
+
fi
|
|
16771
|
+
|
|
16772
|
+
local demo_dir temp_root
|
|
16773
|
+
temp_root="$(cd "${TMPDIR:-/tmp}" 2>/dev/null && pwd -P)" || { echo "loki wow: cannot resolve the temp root" >&2; return 1; }
|
|
16774
|
+
demo_dir="$(mktemp -d "${temp_root}/loki-wow.XXXXXXXX")" || return 1
|
|
16775
|
+
if [ "$keep" != true ]; then
|
|
16776
|
+
# shellcheck disable=SC2064 # expand demo_dir now; it is local to this call
|
|
16777
|
+
trap "wow_cleanup_dir '$demo_dir'; trap - INT TERM; exit 130" INT TERM
|
|
16778
|
+
fi
|
|
16779
|
+
printf '%s\n' '{ "type": "module", "name": "loki-wow" }' > "$demo_dir/package.json"
|
|
16780
|
+
printf '%s\n' 'export function greet() { return "hi"; }' > "$demo_dir/greet.js"
|
|
16781
|
+
printf '%s\n' \
|
|
16782
|
+
'import assert from "node:assert/strict";' \
|
|
16783
|
+
'import test from "node:test";' \
|
|
16784
|
+
'import { greet } from "./greet.js";' \
|
|
16785
|
+
'test("greet says hello", () => { assert.equal(greet(), "hello"); });' > "$demo_dir/greet.test.js"
|
|
16786
|
+
# Inherited GIT_DIR and friends would point -C at the caller's repo; signing or hooks could fail the commit.
|
|
16787
|
+
if ! (
|
|
16788
|
+
unset GIT_DIR GIT_WORK_TREE GIT_COMMON_DIR GIT_INDEX_FILE GIT_OBJECT_DIRECTORY GIT_ALTERNATE_OBJECT_DIRECTORIES GIT_PREFIX
|
|
16789
|
+
g() { git -c commit.gpgsign=false -c core.hooksPath=/dev/null -C "$demo_dir" "$@"; }
|
|
16790
|
+
g init -q && g config user.email "loki-wow@example.com" && g config user.name "Loki Wow" \
|
|
16791
|
+
&& g add package.json greet.js greet.test.js && g commit -q -m "failing greet"
|
|
16792
|
+
); then
|
|
16793
|
+
echo "loki wow: could not set up the temp git repo" >&2
|
|
16794
|
+
if [ "$keep" != true ]; then trap - INT TERM; wow_cleanup_dir "$demo_dir"; fi
|
|
16795
|
+
return 1
|
|
16796
|
+
fi
|
|
16797
|
+
echo "Directory: $demo_dir"
|
|
16798
|
+
local rc=0
|
|
16799
|
+
(
|
|
16800
|
+
cd "$demo_dir" && LOKI_ASSUME_YES=1 "$SKILL_DIR/bin/loki" start "$task" --no-pr --provider "$use_provider" --max-cost "$max_cost"
|
|
16801
|
+
) || rc=$?
|
|
16802
|
+
if ! wow_show_receipt "$demo_dir"; then
|
|
16803
|
+
echo ""
|
|
16804
|
+
if [ "$rc" != "0" ]; then
|
|
16805
|
+
echo "The live mini-task exited $rc before a receipt was sealed (often a provider that is installed but not logged in)."
|
|
16806
|
+
echo "Nothing below is the result of this run. It is the offline sample, for reference."
|
|
16807
|
+
echo ""
|
|
16808
|
+
cmd_demo --offline
|
|
16809
|
+
else
|
|
16810
|
+
echo "No receipt file was written. The run summary above is the record."
|
|
16811
|
+
fi
|
|
16812
|
+
elif [ "$rc" != "0" ]; then
|
|
16813
|
+
echo ""
|
|
16814
|
+
echo "The live mini-task exited $rc. The receipt above is this run's own result."
|
|
16815
|
+
fi
|
|
16816
|
+
if [ "$keep" = true ]; then
|
|
16817
|
+
echo ""
|
|
16818
|
+
echo "Kept: $demo_dir (remove it with: rm -rf \"$demo_dir\")"
|
|
16819
|
+
else
|
|
16820
|
+
trap - INT TERM
|
|
16821
|
+
wow_cleanup_dir "$demo_dir"
|
|
16822
|
+
fi
|
|
16823
|
+
echo ""
|
|
16824
|
+
echo "Ready for your repo? loki start"
|
|
16825
|
+
return "$rc"
|
|
16826
|
+
}
|
|
16827
|
+
|
|
16828
|
+
cmd_factory() {
|
|
16829
|
+
if [ "${1:-}" = "--help" ] || [ "${1:-}" = "-h" ]; then
|
|
16830
|
+
echo "loki factory \"<task|prd|issue>\" - same as loki start"
|
|
16831
|
+
echo ""
|
|
16832
|
+
echo "loki start prints the autonomy policy and runs. factory does not change that."
|
|
16833
|
+
echo "It does not write a policy file."
|
|
16834
|
+
echo ""
|
|
16835
|
+
echo "Autonomy levels (unchanged):"
|
|
16836
|
+
echo " propose plan and ask before changing the tree"
|
|
16837
|
+
echo " execute build, verify, seal a receipt, open a PR (default when no policy file)"
|
|
16838
|
+
echo " operate execute, and deploy only when you pass --deploy"
|
|
16839
|
+
echo ""
|
|
16840
|
+
echo "A .loki/policies.json or policies.yaml (repo, or LOKI_DATA_DIR, or ~/.loki) still decides"
|
|
16841
|
+
echo "allow, approval (draft PR) or deny."
|
|
16842
|
+
echo "When the contract cannot be satisfied the run stops with one question (BLOCKED)."
|
|
16843
|
+
echo "The summary still prints outcome, receipt, cost and the next command."
|
|
16844
|
+
echo ""
|
|
16845
|
+
echo "loki start keeps the provider model. Pass --haiku (or --cost lean) to try haiku for"
|
|
16846
|
+
echo "the first implement; a failed check climbs back. --max-cost stays the hard cap."
|
|
16847
|
+
return 0
|
|
16848
|
+
fi
|
|
16849
|
+
exec "$SKILL_DIR/bin/loki" start "$@"
|
|
16850
|
+
}
|
|
16851
|
+
|
|
16493
16852
|
# Demo mode - build a real project from a bundled PRD template
|
|
16494
16853
|
cmd_demo() {
|
|
16495
16854
|
# Handle --help
|
|
@@ -16517,6 +16876,8 @@ cmd_demo() {
|
|
|
16517
16876
|
echo "Examples:"
|
|
16518
16877
|
echo " loki demo --offline # Replay a sample receipt (no spend)"
|
|
16519
16878
|
echo " loki tour # Same as 'loki demo --offline'"
|
|
16879
|
+
echo " loki tour --live # Tiny real task (loki wow); offline sample if no provider"
|
|
16880
|
+
echo " loki wow # Live mini-task, or the offline sample with no key"
|
|
16520
16881
|
echo " loki demo # Build todo app in temp dir"
|
|
16521
16882
|
echo " loki demo --dir ~/demo-project # Build in specific directory"
|
|
16522
16883
|
echo " loki demo --provider codex # Use Codex instead of Claude"
|
|
@@ -22420,6 +22781,9 @@ main() {
|
|
|
22420
22781
|
if declare -f loki_maybe_apply_config_file >/dev/null 2>&1; then
|
|
22421
22782
|
loki_maybe_apply_config_file "$@"
|
|
22422
22783
|
fi
|
|
22784
|
+
# --haiku is opt-in. The dump below shows the levers when the flag is present.
|
|
22785
|
+
loki_apply_haiku_optin "$@"
|
|
22786
|
+
loki_f2p_default "$command" "$@"
|
|
22423
22787
|
# #691: documented observation hook. When LOKI_CONFIG_DUMP=1, print
|
|
22424
22788
|
# the resolved LOKI_* environment (after the config pre-pass AND any
|
|
22425
22789
|
# ambient env) and exit 0 WITHOUT running a build. Lets operators and
|
|
@@ -22476,13 +22840,24 @@ main() {
|
|
|
22476
22840
|
demo)
|
|
22477
22841
|
cmd_demo "$@"
|
|
22478
22842
|
;;
|
|
22843
|
+
wow)
|
|
22844
|
+
cmd_wow "$@"
|
|
22845
|
+
;;
|
|
22846
|
+
factory)
|
|
22847
|
+
cmd_factory "$@"
|
|
22848
|
+
;;
|
|
22479
22849
|
tour)
|
|
22480
22850
|
# Zero-key/zero-spend taste path: an alias for 'demo --offline' that
|
|
22481
22851
|
# replays a bundled real Evidence Receipt. --help routes straight to
|
|
22482
|
-
# the demo help (which documents --offline / tour);
|
|
22483
|
-
# --offline ahead of any user args.
|
|
22852
|
+
# the demo help (which documents --offline / tour); --live is loki wow;
|
|
22853
|
+
# otherwise inject --offline ahead of any user args.
|
|
22484
22854
|
if [ "${1:-}" = "--help" ] || [ "${1:-}" = "-h" ]; then
|
|
22485
22855
|
cmd_demo --help
|
|
22856
|
+
echo " loki tour --live # Tiny real task (same as loki wow)"
|
|
22857
|
+
echo " loki wow # Live mini-task, or this sample with no key"
|
|
22858
|
+
elif [ "${1:-}" = "--live" ]; then
|
|
22859
|
+
shift
|
|
22860
|
+
cmd_wow "$@"
|
|
22486
22861
|
else
|
|
22487
22862
|
cmd_demo --offline "$@"
|
|
22488
22863
|
fi
|
package/autonomy/telemetry.sh
CHANGED
|
@@ -170,7 +170,7 @@ _loki_known_command() {
|
|
|
170
170
|
|audit|bench|checkpoint|ci|cleanup|cluster|cockpit|code\
|
|
171
171
|
|completion|completions|compliance|compound|config|context|control|cost|council|cp\
|
|
172
172
|
|crash|ctx|dashboard|demo|deploy|docker|docs|doctor\
|
|
173
|
-
|dogfood|enterprise|explain|export|failover|github|grill|handoff\
|
|
173
|
+
|dogfood|enterprise|explain|export|factory|failover|github|grill|handoff\
|
|
174
174
|
|heal|help|import|init|internal|issue|kpis|logs\
|
|
175
175
|
|magic|mcp|memory|metrics|migrate|modernize|monitor|next\
|
|
176
176
|
|notify|onboard|open|optimize|otel|own|pause|plan\
|
|
@@ -180,7 +180,7 @@ _loki_known_command() {
|
|
|
180
180
|
|ship|spec|start|state|stats|status|steer|stop\
|
|
181
181
|
|syslog|telemetry|template|test|tour|trigger|trust|trust-metrics\
|
|
182
182
|
|ultracode|update|verify|version|voice|watch|watchdog|web\
|
|
183
|
-
|welcome|why|wiki|worktree|wt)
|
|
183
|
+
|welcome|why|wiki|worktree|wow|wt)
|
|
184
184
|
printf '%s' "$1" ;;
|
|
185
185
|
*)
|
|
186
186
|
printf 'other' ;;
|