loki-mode 11.17.41 → 11.17.43
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 +2 -2
- package/VERSION +1 -1
- package/autonomy/loki +3 -1
- package/autonomy/verify.sh +5 -0
- package/bin/loki +1 -1
- package/completions/_loki +1 -1
- package/completions/loki.bash +16 -0
- package/dashboard/__init__.py +1 -1
- package/docs/CLI-REFERENCE.md +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/docs/v10/BOARD.md +33 -2
- package/docs/v10/FAILURE-CLASSES.md +49 -0
- package/docs/v10/PROGRESS.md +6 -0
- package/loki-ts/dist/loki.js +3 -3
- package/mcp/__init__.py +1 -1
- package/package.json +2 -2
- package/packages/control-plane/dist/server.js +2 -2
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/web-app/dist/assets/{AdminPage-BSR_64u1.js → AdminPage-BKzSXu_j.js} +1 -1
- package/web-app/dist/assets/{Avatar-CnSNZSx6.js → Avatar-DJ7ngKyG.js} +1 -1
- package/web-app/dist/assets/{Badge-C7p_bqIO.js → Badge-DzYByk2v.js} +1 -1
- package/web-app/dist/assets/{Button-5CI0TYxR.js → Button-BxDDHZo6.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-CeiR5rfl.js → CockpitPage-XhjPH9NC.js} +1 -1
- package/web-app/dist/assets/{ComparePage-Cwh3wcqg.js → ComparePage-do4LC1Kw.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-VZcsEDJl.js → ErrorBoundary-Tw_oy-Da.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-Cf5DXTqo.js → EvidenceReceiptPanel-BWlmi-B5.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-C8pxgZhD.js → GitHubIssuesPanel-CuyOWTsQ.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-Dfrm9QTz.js → GitHubPRsPanel-DCCFA4Cg.js} +1 -1
- package/web-app/dist/assets/{HomePage-Be-Hq5wb.js → HomePage-zXruJ694.js} +2 -2
- package/web-app/dist/assets/{LoginPage-DijL2orB.js → LoginPage-D2hTXZIt.js} +1 -1
- package/web-app/dist/assets/{MagicPage-x-KpX3Zk.js → MagicPage-8tcSJtKw.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-uoMG8P0x.js → MetricsPage-BQbmcPiu.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-DmW2a7pG.js → NotFoundPage-VVysOMpk.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-zpARxbll.js → ProjectPage-WU7f9RkJ.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-5dTAn3K7.js → ProjectsPage-DEI8Ha7d.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-ptKy_Tbu.js → SettingsPage-B9NeXoBw.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-BkM5b-6b.js → ShowcasePage-CIRBbxd5.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-BbaZ8aqC.js → SystemSettingsPage-CfuZUU6P.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-CBgDSDWj.js → TeamsPage-DF9nzDjA.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-IdBOifb1.js → TemplatesPage-BFyWWIT4.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-iLcaELwj.js → TerminalOutput-CYSWsLu3.js} +1 -1
- package/web-app/dist/assets/{activity-Di09VZ-C.js → activity-BQ44JhWT.js} +1 -1
- package/web-app/dist/assets/{bell-CuHhohwY.js → bell-CjAfaEDR.js} +1 -1
- package/web-app/dist/assets/{bot-pGvyFisf.js → bot-DgwH21q_.js} +1 -1
- package/web-app/dist/assets/{check-DYPycZns.js → check-CHZWFNwB.js} +1 -1
- package/web-app/dist/assets/{chevron-left-lKRP1pKT.js → chevron-left-B7Etn49H.js} +1 -1
- package/web-app/dist/assets/{circle-alert-D1rDQ9mD.js → circle-alert-nPoVqFm8.js} +1 -1
- package/web-app/dist/assets/{clock-BGhPbAAa.js → clock-C-sLUpGG.js} +1 -1
- package/web-app/dist/assets/{cloud-WsT8-0Fu.js → cloud-D4K7FUJF.js} +1 -1
- package/web-app/dist/assets/{code-xml-DtutBX9b.js → code-xml-BZHY2-WK.js} +1 -1
- package/web-app/dist/assets/{database-LiEeNmyC.js → database-CEj7r6Ao.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-adGlfVLa.js → dollar-sign-DPHUDpsN.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-DY5GkQGM.js → file-code-corner-CboHKdgp.js} +1 -1
- package/web-app/dist/assets/{file-plus-RLd_hPU8.js → file-plus-DsA4DU-n.js} +1 -1
- package/web-app/dist/assets/{globe-CQvcGE8E.js → globe-C7TzpMng.js} +1 -1
- package/web-app/dist/assets/{hammer-BWOWu2Hf.js → hammer-B61u7zMJ.js} +1 -1
- package/web-app/dist/assets/{index-BBV2psih.js → index-cu9_aTCP.js} +3 -3
- package/web-app/dist/assets/{layers-C_cj_ShX.js → layers-D6JO2rbt.js} +1 -1
- package/web-app/dist/assets/{loader-circle-BpyfPEFt.js → loader-circle-CUROrUhG.js} +1 -1
- package/web-app/dist/assets/{lock-Bivqy2kG.js → lock-BEhTudft.js} +1 -1
- package/web-app/dist/assets/{package-DvDJIgWs.js → package-BkeBeiGM.js} +1 -1
- package/web-app/dist/assets/{plus-CVjTmPiU.js → plus-Bv-Q1BYs.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-DPEeU-0s.js → refresh-cw-CeT9llPq.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-DZX_aED8.js → rotate-ccw-aUzPGF5J.js} +1 -1
- package/web-app/dist/assets/{scroll-text-BBMfK4J7.js → scroll-text-DibSs5wF.js} +1 -1
- package/web-app/dist/assets/{server-Bq18pHWE.js → server-DEH19wNA.js} +1 -1
- package/web-app/dist/assets/{shield-alert-Dc5xbnOx.js → shield-alert-CtW0_p0i.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-4nFvjqQ-.js → thumbs-up-BMp9hCP5.js} +1 -1
- package/web-app/dist/assets/{trash-2-SjUKL3ek.js → trash-2-s4Vf7Z8i.js} +1 -1
- package/web-app/dist/assets/{trending-down-B7_1Kuct.js → trending-down-DnMzvTbm.js} +1 -1
- package/web-app/dist/assets/{trending-up-DgRWrCNb.js → trending-up-DnB-6eIb.js} +1 -1
- package/web-app/dist/assets/{upload-Cs07lSfb.js → upload-86CGmwiu.js} +1 -1
- package/web-app/dist/assets/{usePolling-BAUxt1Nu.js → usePolling-BaPZfGcd.js} +1 -1
- package/web-app/dist/assets/{user-DC2T8RYB.js → user-CLepiTkS.js} +1 -1
- package/web-app/dist/index.html +1 -1
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.43
|
|
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
|
|
|
@@ -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.43 | [Autonomi](https://www.autonomi.dev/) flagship product | core skill**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
11.17.
|
|
1
|
+
11.17.43
|
package/autonomy/loki
CHANGED
|
@@ -1855,6 +1855,7 @@ show_help_all() {
|
|
|
1855
1855
|
echo " ultracode \"task\" Run a task as a native Claude Code Dynamic Workflow (opt-in, Claude-only)"
|
|
1856
1856
|
echo " trust [cmd] Visible trust trajectory; 'trust detail' for metrics"
|
|
1857
1857
|
echo " undo <run> [--plan|--dry-run] Plan or apply (LOKI_UNDO=1) an undo of a run; verifies the receipt"
|
|
1858
|
+
echo " undo --list List recent runs with verdict, files changed and age"
|
|
1858
1859
|
echo ""
|
|
1859
1860
|
echo "Observe:"
|
|
1860
1861
|
echo " dashboard [cmd] Operations UI server (start|stop|status|url|open)"
|
|
@@ -1928,6 +1929,7 @@ show_help_all() {
|
|
|
1928
1929
|
echo " loki status [--json] # Current status"
|
|
1929
1930
|
echo " loki report session --efficiency # Token + cost stats"
|
|
1930
1931
|
echo " loki report kpis [--json] # Accuracy + efficiency KPI snapshot"
|
|
1932
|
+
echo " loki report kpis --since 7d # Window KPI totals (Nd or YYYY-MM-DD)"
|
|
1931
1933
|
echo " loki doctor [--json] # System prereq + skill symlinks"
|
|
1932
1934
|
echo " loki logs # Tail recent log output"
|
|
1933
1935
|
echo " loki report export json|markdown|csv|timeline # Export session"
|
|
@@ -19089,7 +19091,7 @@ cmd_verify() {
|
|
|
19089
19091
|
local _pk_arg
|
|
19090
19092
|
for _pk_arg in "$@"; do
|
|
19091
19093
|
case "$_pk_arg" in
|
|
19092
|
-
--pubkey|--pubkey
|
|
19094
|
+
--pubkey|--pubkey=*|--require-exogenous) exec "$_LOKI_SCRIPT_DIR/../bin/loki" verify "$@" ;;
|
|
19093
19095
|
esac
|
|
19094
19096
|
done
|
|
19095
19097
|
# PATH slice: a workspace composite (composite.json, or --seal-composite RUN_DIR) is
|
package/autonomy/verify.sh
CHANGED
|
@@ -2594,6 +2594,11 @@ OPTIONS:
|
|
|
2594
2594
|
no signed issue time, or is more than 300s in the
|
|
2595
2595
|
future. Exits 2 (UNCHECKED). Routed to the engine10
|
|
2596
2596
|
verifier.
|
|
2597
|
+
--require-exogenous
|
|
2598
|
+
With a run receipt: exit 4 when a VERIFIED receipt has
|
|
2599
|
+
no agent-independent passing check or no recorded
|
|
2600
|
+
provenance (or set LOKI_VERIFY_REQUIRE_EXOGENOUS=1).
|
|
2601
|
+
Routed to the engine10 verifier.
|
|
2597
2602
|
-h, --help Show this help.
|
|
2598
2603
|
|
|
2599
2604
|
GATES (deterministic, reproducible by construction):
|
package/bin/loki
CHANGED
|
@@ -556,7 +556,7 @@ case "v10" in
|
|
|
556
556
|
status|verify|dashboard)
|
|
557
557
|
if [ "$1" = "verify" ]; then
|
|
558
558
|
for _pk in "$@"; do
|
|
559
|
-
case "$_pk" in --pubkey|--pubkey
|
|
559
|
+
case "$_pk" in --pubkey|--pubkey=*|--require-exogenous) _e10=1; _e10_hard=1 ;; esac
|
|
560
560
|
done
|
|
561
561
|
unset _pk
|
|
562
562
|
fi
|
package/completions/_loki
CHANGED
|
@@ -305,7 +305,7 @@ function _loki_commands {
|
|
|
305
305
|
'verify-pr:Verify a PR against its linked issue in a sandbox'
|
|
306
306
|
'queue:Overnight issue queue with a morning digest'
|
|
307
307
|
'issues:Run every open issue in a repo and open PRs'
|
|
308
|
-
'undo:Show what undoing a run would do (read-only plan; --dry-run adds the diffstat)'
|
|
308
|
+
'undo:Show what undoing a run would do (read-only plan; --dry-run adds the diffstat; --list shows recent runs)'
|
|
309
309
|
'chat:Interactive chat session (run, attach)'
|
|
310
310
|
'route:Print the engine, provider and model route without running'
|
|
311
311
|
'edit:Make a scoped edit to files'
|
package/completions/loki.bash
CHANGED
|
@@ -274,6 +274,22 @@ _loki_completion() {
|
|
|
274
274
|
_filedir -d
|
|
275
275
|
;;
|
|
276
276
|
|
|
277
|
+
report)
|
|
278
|
+
if [[ "$cur" == -* ]]; then
|
|
279
|
+
COMPREPLY=( $(compgen -W "--json --since --efficiency --help" -- "$cur") )
|
|
280
|
+
return 0
|
|
281
|
+
fi
|
|
282
|
+
COMPREPLY=( $(compgen -W "session metrics cost kpis export share dogfood" -- "$cur") )
|
|
283
|
+
return 0
|
|
284
|
+
;;
|
|
285
|
+
|
|
286
|
+
undo)
|
|
287
|
+
if [[ "$cur" == -* ]]; then
|
|
288
|
+
COMPREPLY=( $(compgen -W "--list --plan --dry-run --help" -- "$cur") )
|
|
289
|
+
return 0
|
|
290
|
+
fi
|
|
291
|
+
;;
|
|
292
|
+
|
|
277
293
|
metrics)
|
|
278
294
|
if [[ "$cur" == -* ]]; then
|
|
279
295
|
COMPREPLY=( $(compgen -W "--json --last --save --share --help" -- "$cur") )
|
package/dashboard/__init__.py
CHANGED
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.17.
|
|
3
|
+
Generated from `loki-ts/src/cli/registry.ts` by `scripts/generate-stale-zero.sh` for v11.17.43. 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 |
|
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.17.
|
|
5
|
+
**Version:** v11.17.43
|
|
6
6
|
|
|
7
7
|
**Engine note:** `loki start` is the primary command. `loki start`, `loki "<task>"`, `loki owner/repo#N` and `loki quick` all run the Loki 10 engine, whatever the flag order or input form (PRD file, issue ref, task or one-word brief). The previous loop runs only on `--engine legacy`, `LOKI_ENGINE=legacy`, or for one call when a flag Loki 10 cannot honor is present. See the [user guide](v10/GUIDE.md) and the [5-minute quickstart](QUICKSTART.md).
|
|
8
8
|
|
package/docs/v10/BOARD.md
CHANGED
|
@@ -1179,8 +1179,39 @@ Source: ~/git/autonomi-dev/research/2026-09-30-adoption/SWARM-PROMPT-ADOPTION.md
|
|
|
1179
1179
|
| TEN-STABILITY-15 | fix: queue add on a corrupt queue file quarantines it and warns instead of silently overwriting every queued item | loki-ts/src/commands/queue.ts, loki-ts/tests/commands/queue.test.ts | MEDIUM | red: a truncated queue.json followed by queue add leaves a file holding only the new item; green: the bad file is renamed to queue.json.corrupt-<ts>, a warning is printed once, the new item is added to a fresh file; cd loki-ts && bunx tsc --noEmit && bun test tests/commands/queue.test.ts | released v11.17.41 | Gap: readQueue returns [] on any JSON error (queue.ts:79-86) and queueAdd then writeQueue overwrites (queue.ts:108-124). Same class as TEN-STABILITY-12 (outbox quarantine at util/outbox.ts:28-33); reuse that pattern and add the row to FAILURE-CLASSES.md. |
|
|
1180
1180
|
| TEN-STABILITY-16 | enhancement: loki start sweeps stale temp files left by a killed atomic write (name.tmp.<deadpid>.<n>) older than 1 hour in the .loki state dirs | loki-ts/src/util/atomic.ts, loki-ts/tests/util/atomic.test.ts | MEDIUM | red: a leftover state.json.tmp.99999.1 with a dead pid stays forever; green: swept when pid is dead and mtime older than 1h, a live pid or fresh file is untouched, only exact tmp names matched; cd loki-ts && bunx tsc --noEmit && bun test tests/util | released (already shipped before the row: loki-ts/src/runner/state.ts:444 sweepOrphanTmpFiles) | Gap: grep -rnE '\.tmp\.' loki-ts/src shows temp names created at util/atomic.ts:89 and run_control.ts:13 with no sweeper anywhere. Never glob outside .loki; reuse processStartTime or kill -0 from util/run_pid.ts for the liveness test; wire from a util/ entry point, not engine10 core. |
|
|
1181
1181
|
| TEN-STABILITY-17 | feature: loki doctor lists orphan runs (a run dir whose owner process died before run.completed) with the resume or undo command for each | loki-ts/src/commands/doctor.ts, loki-ts/tests/commands/doctor.test.ts | MEDIUM | red: doctor ignores a run dir with a dead pid and no run.completed event; green: a warn row names the run id and "loki resume" or "loki undo", live and completed runs produce no row; cd loki-ts && bunx tsc --noEmit && bun test tests/commands/doctor.test.ts | ready@2026-10-17T08:05Z | Gap: runOwnerAlive (util/run_pid.ts:59) is consumed only by util/run_outputs.ts:156; grep -n runOwnerAlive loki-ts/src/commands/doctor.ts returned 0 hits. Warn level only, never fails doctor. Serialize after TEN-DEPLOY-15 (same file). |
|
|
1182
|
-
| TEN-STABILITY-18 | P0 fix-forward: nightly 39016259458 reds still red on main e32ee1b5d (pr_body_golden not-recorded producer util/check_result.ts; sizing wall brief 726 vs cap 616; router_optout_golden wall stage haiku for development; verify.test uv resolution CI-only via Bun.which PATH; test-sigpipe-guard 1737 vs ceiling 1728; help-changelog-drift loki verify --require-exogenous; test-ui-bare-loki exact-match on new control lines; test-local-ci-gitleaks scope) | the failing tests, loki-ts/src/util/check_result.ts, loki-ts/src/engine10/stages/wall.ts, loki-ts/src/engine10/stages/verify.ts, verify help and completions, scripts/local-ci.sh, docs/v10/FAILURE-CLASSES.md | MEDIUM | red: each named test fails on e32ee1b5d; green: cd loki-ts && bun test tests/engine10/pr_body_golden.test.ts tests/engine10/sizing.test.ts tests/engine10/router_optout_golden.test.ts tests/engine10/verify.test.ts tests/util; bash tests/test-sigpipe-guard.sh; bash tests/test-help-changelog-drift.sh; bash tests/test-ui-bare-loki.sh; bash tests/test-local-ci-gitleaks.sh |
|
|
1183
|
-
| TEN-STABILITY-19 | P0 fix-forward: moat P8.ablation-dead-code-not-sealed positive control headline VERIFIED WITH GAPS (expected VERIFIED) and first-run-gate --stub FAILED with dirty tracked tree M sum.js at intake.ts:61 | tests/moat/p8-*.sh or the ablation producer, scripts/first-run-gate.sh, loki-ts/src/engine10/stages/intake.ts only if the honest fix is there | HIGH | red: bash tests/moat/run.sh prints moat suite: FAIL (1 rule failure(s)); bash scripts/first-run-gate.sh --stub fails 7 assertions; green: both exit 0 |
|
|
1182
|
+
| TEN-STABILITY-18 | P0 fix-forward: nightly 39016259458 reds still red on main e32ee1b5d (pr_body_golden not-recorded producer util/check_result.ts; sizing wall brief 726 vs cap 616; router_optout_golden wall stage haiku for development; verify.test uv resolution CI-only via Bun.which PATH; test-sigpipe-guard 1737 vs ceiling 1728; help-changelog-drift loki verify --require-exogenous; test-ui-bare-loki exact-match on new control lines; test-local-ci-gitleaks scope) | the failing tests, loki-ts/src/util/check_result.ts, loki-ts/src/engine10/stages/wall.ts, loki-ts/src/engine10/stages/verify.ts, verify help and completions, scripts/local-ci.sh, docs/v10/FAILURE-CLASSES.md | MEDIUM | red: each named test fails on e32ee1b5d; green: cd loki-ts && bun test tests/engine10/pr_body_golden.test.ts tests/engine10/sizing.test.ts tests/engine10/router_optout_golden.test.ts tests/engine10/verify.test.ts tests/util; bash tests/test-sigpipe-guard.sh; bash tests/test-help-changelog-drift.sh; bash tests/test-ui-bare-loki.sh; bash tests/test-local-ci-gitleaks.sh | released v11.17.42 | Diagnosis 2026-10-17 by nightly diag agent; one FAILURE-CLASSES row per class |
|
|
1183
|
+
| TEN-STABILITY-19 | P0 fix-forward: moat P8.ablation-dead-code-not-sealed positive control headline VERIFIED WITH GAPS (expected VERIFIED) and first-run-gate --stub FAILED with dirty tracked tree M sum.js at intake.ts:61 | tests/moat/p8-*.sh or the ablation producer, scripts/first-run-gate.sh, loki-ts/src/engine10/stages/intake.ts only if the honest fix is there | HIGH | red: bash tests/moat/run.sh prints moat suite: FAIL (1 rule failure(s)); bash scripts/first-run-gate.sh --stub fails 7 assertions; green: both exit 0 | released v11.17.42 | Diagnosis 2026-10-17; never weaken a moat assertion to pass |
|
|
1184
|
+
| TEN-STABILITY-20 | Fix help-changelog-drift red after v11.17.42: list report kpis --since and undo --list in Bun help, autonomy/loki help and both completions | completions/loki.bash, completions/_loki, loki-ts/src help, autonomy/loki, docs/v10/FAILURE-CLASSES.md | LOW | merged 3c4e2fcd9 | released v11.17.43 |
|
|
1185
|
+
| TEN-COST-35 | fix: `loki start --budget-limit=5` (and --provider=, --session-model=, --prd=, --brief=) is accepted by the flag validator then silently ignored, so the default $100 cap and default provider apply; read the `=` form everywhere argVal reads a flag | loki-ts/src/commands/start.ts, loki-ts/tests/commands/start.test.ts | MEDIUM | red: bun test tests/commands/start.test.ts -t "equals form" fails (cap stays default); green: same test passes and `cd loki-ts && bunx tsc --noEmit` exits 0 | ready@2026-10-17T10:00Z | Gap: start.ts:23 argVal matches only exact args via indexOf; start.ts:212 validator splits on "=" so the form is accepted; only --cost and --attempts parse "=" |
|
|
1186
|
+
| TEN-COST-36 | fix: `loki start --budget-limit abc`, `--max-iterations -1`, `--budget-limit 0x` and a trailing value flag with no value are silently dropped so the default cap applies; print one error line naming the flag and exit 2 | loki-ts/src/commands/start.ts, loki-ts/tests/commands/start.test.ts | MEDIUM | red: bun test tests/commands/start.test.ts -t "invalid numeric" fails (exit 0, no message); green: passes, valid values unchanged | ready@2026-10-17T10:00Z | Gap: start.ts:123 posNum returns undefined for non-numeric, zero or negative with no diagnostic; chain after TEN-COST-35 |
|
|
1187
|
+
| TEN-STABILITY-21 | fix: control `--port` with no value or a non-numeric value silently falls back to the default port; reject with a usage line and exit 2 | loki-ts/src/commands/control.ts, loki-ts/tests/commands/control.test.ts | LOW | red: bun test tests/commands/control.test.ts -t "port without value" fails; green: passes and existing control tests stay green | ready@2026-10-17T10:00Z | Gap: control.ts:33 flag() returns args[i+1] unchecked (undefined or the next flag) and callers fall through to the default |
|
|
1188
|
+
| TEN-SECURITY-08 | fix: `loki status <run-id>` and `loki intent show <id>` join the user id into a path with no id check, so `../..` reads an events.jsonl outside .loki/runs; validate against the same RUN_ID_RE as undo and exit 2 | loki-ts/src/commands/run_status.ts, loki-ts/tests/commands/run_status.test.ts | HIGH | red: bun test tests/commands/run_status.test.ts -t "traversal" fails (reads the planted file); green: passes, exit 2 with "invalid run id" | ready@2026-10-17T10:00Z | Gap: run_status.ts:50 eventsPath and :148 readEvents(eventsPath(root, wanted)) take wanted unchecked; undo.ts defines RUN_ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]*$/ (reuse it, do not copy) |
|
|
1189
|
+
| TEN-STABILITY-22 | fix: `loki pause|cancel` prints "requested" for a run whose supervisor pid is dead and targets latestRunId instead of the live run; refuse with "no live run" and exit 1 when run_pid says the owner is gone | loki-ts/src/commands/run_status.ts, loki-ts/tests/commands/run_status.test.ts | MEDIUM | red: bun test tests/commands/run_status.test.ts -t "dead supervisor" fails; green: passes, live-run pause path unchanged | ready@2026-10-17T10:00Z | Gap: run_status.ts:189 runControlVerb never calls runOwnerAlive from util/run_pid.ts; chain after TEN-SECURITY-08 |
|
|
1190
|
+
| TEN-UX-20 | fix: `loki provider frobnicate` prints the help text and exits 0, so scripts and typos look like success; unknown subcommand prints one error line plus help and exits 2 (help, -h, --help stay exit 0) | loki-ts/src/commands/provider.ts, loki-ts/tests/commands/provider.test.ts | LOW | red: bun test tests/commands/provider.test.ts -t "unknown subcommand" fails (exit 0); green: passes, and `bash autonomy/loki provider frobnicate` behavior is checked and the Bun route matches or the bash arm is noted in the PR | ready@2026-10-17T10:00Z | Gap: provider.ts:161 default case returns printProviderHelp() which returns 0 |
|
|
1191
|
+
| TEN-DEPLOY-16 | fix: `loki rollback list --bogus` and `rollback to <id> --bogus` ignore unknown flags, so a mistyped safety flag (for example --dry-run spelled wrong) runs the real rollback; reject unknown flags with exit 2 | loki-ts/src/commands/rollback.ts, loki-ts/tests/commands/rollback.test.ts | MEDIUM | red: bun test tests/commands/rollback.test.ts -t "unknown flag" fails; green: passes, valid invocations unchanged | ready@2026-10-17T10:00Z | Gap: rollback.ts:120 rejects only unknown subcommands; no flag check on to, latest or list |
|
|
1192
|
+
| TEN-COST-37 | fix: a set but unparseable LOKI_BUDGET_LIMIT (for example "5usd") or loki.yaml budgets.per_run is skipped without a warning and the $100 default silently applies; return the existing {error} form so the run refuses to start (0 stays a valid no-cap value) | loki-ts/src/e10ext/budget_cap.ts, loki-ts/tests/engine10/budget_cap.test.ts | MEDIUM | red: bun test tests/engine10/budget_cap.test.ts -t "unparseable" fails; green: passes, all existing cases green, net line change in engine10 core is zero (e10ext is outside it) | ready@2026-10-17T10:00Z | Gap: budget_cap.ts:20 resolveCap falls through on NaN for env and yaml sources with no error or note |
|
|
1193
|
+
| TEN-UX-21 | fix: run summary color ignores the NO_COLOR convention inconsistently: useColor treats NO_COLOR="" as set (disables color) while util/colors.ts treats empty as unset, and neither honors TERM=dumb; make both read one rule (non-empty NO_COLOR or TERM=dumb disables) | loki-ts/src/util/run_summary.ts, loki-ts/src/util/colors.ts, loki-ts/tests/util/run_summary.test.ts | LOW | red: bun test tests/util/run_summary.test.ts -t "NO_COLOR empty" fails; green: passes and `bun test tests/util` stays green | ready@2026-10-17T10:00Z | Gap: run_summary.ts:75 `env.NO_COLOR === undefined` vs colors.ts:9 `.length > 0`; grep TERM in both files returns 0 hits |
|
|
1194
|
+
| TEN-STABILITY-23 | fix: LOKI_E10_DASHBOARD_PORT="abc", "" or 70000 reaches Bun.serve as NaN, 0 (random port) or out of range; validate 1-65535, else print the bad value and fall back to the default port with a one-line note | loki-ts/src/runner/engine10_dashboard.ts, loki-ts/tests/engine10/dashboard_entry.test.ts | LOW | red: bun test tests/engine10/dashboard_entry.test.ts -t "bad port env" fails; green: passes, default behavior unchanged | ready@2026-10-17T10:00Z | Gap: engine10_dashboard.ts:330 `Number(process.env["LOKI_E10_DASHBOARD_PORT"] ?? DEFAULT_PORT)` has no range or NaN check |
|
|
1195
|
+
| TEN-QUALITY-19 | fix: two different long tasks that share their first 40 slug characters map to one .loki/specs/<slug>.md and one spec-<slug> run dir, so the second task fails with "spec exists" or reuses the first task's edited spec; append a short task hash when the slug was truncated | loki-ts/src/util/spec_file.ts, loki-ts/tests/engine10/spec_first_intent.test.ts | MEDIUM | red: bun test tests/engine10/spec_first_intent.test.ts -t "long task collision" fails; green: passes, short-task slugs unchanged byte for byte | ready@2026-10-17T10:00Z | Gap: spec_file.ts:29 slugify slices to 40 chars with no disambiguator; generateSpec uses it for both the path and the run dir |
|
|
1196
|
+
| TEN-UX-22 | fix: `loki memory brief --task` with no value silently briefs for an empty task; print usage and exit 2 | loki-ts/src/commands/memory.ts, loki-ts/tests/commands/memory.test.ts | LOW | red: bun test tests/commands/memory.test.ts -t "brief without task" fails; green: passes, `brief --task "x"` output unchanged | ready@2026-10-17T10:00Z | Gap: memory.ts:123 `argv[i + 1] ?? ""` accepts a missing value |
|
|
1197
|
+
| TEN-QUALITY-20 | fix: `loki wiki show architecture modules` silently shows only the last section named; reject a second positional with a usage error and exit 1 | loki-ts/src/commands/wiki.ts, loki-ts/tests/commands/wiki.test.ts | LOW | red: bun test tests/commands/wiki.test.ts -t "two sections" fails; green: passes, single section output unchanged | ready@2026-10-17T10:00Z | Gap: wiki.ts:59 `section = a` overwrites on each positional |
|
|
1198
|
+
| TEN-ADOPTION-16 | feature: `--json` for the control status verb so scripts can read running, pid, port and url without parsing text | loki-ts/src/commands/control.ts, loki-ts/tests/commands/control.test.ts | LOW | red: bun test tests/commands/control.test.ts -t "status json" fails; green: passes, text output byte identical | ready@2026-10-17T10:00Z | Gap: grep -c '"--json"' loki-ts/src/commands/control.ts returns 0; chain after TEN-STABILITY-21 |
|
|
1199
|
+
| TEN-ADOPTION-17 | feature: `loki provider list --json` printing name, tier, installed and version per provider for CI and editor integrations | loki-ts/src/commands/provider.ts, loki-ts/tests/commands/provider.test.ts | LOW | red: bun test tests/commands/provider.test.ts -t "list json" fails; green: passes, plain `provider list` unchanged | ready@2026-10-17T10:00Z | Gap: provider.ts has a single "--json" mention and none on the list arm; chain after TEN-UX-20 |
|
|
1200
|
+
| TEN-DEPLOY-17 | feature: `loki rollback list --json` so deploy automation can pick a rollback target without scraping text | loki-ts/src/commands/rollback.ts, loki-ts/tests/commands/rollback.test.ts | LOW | red: bun test tests/commands/rollback.test.ts -t "list json" fails; green: passes, text output byte identical | ready@2026-10-17T10:00Z | Gap: grep -c '"--json"' loki-ts/src/commands/rollback.ts returns 0; chain after TEN-DEPLOY-16 |
|
|
1201
|
+
| TEN-ADOPTION-18 | feature: `loki version --json` printing {version, runtime, install_path}; plain `loki version` output stays byte identical to bash | loki-ts/src/commands/version.ts, loki-ts/tests/commands/version.test.ts | LOW | red: bun test tests/commands/version.test.ts -t "version json" fails; green: passes including the existing byte parity test | ready@2026-10-17T10:00Z | Gap: version.ts:12 lines, runVersion() takes no args and the file has no "--json" |
|
|
1202
|
+
| TEN-ADOPTION-19 | feature: `loki crash list --json` (and `crash --json`) emitting id, captured_at, error_class, fingerprint for tooling | loki-ts/src/commands/crash.ts, loki-ts/tests/commands/crash.test.ts | LOW | red: bun test tests/commands/crash.test.ts -t "list json" fails; green: passes, text list unchanged | ready@2026-10-17T10:00Z | Gap: crash.ts listCrashes prints a padded table only; grep -c '"--json"' returns 0 |
|
|
1203
|
+
| TEN-GATES-21 | feature: `loki verify-pr <ref> --json` printing the verify-pr-result.json verdict object on stdout (the file is already written) so CI can gate on it without reading disk | loki-ts/src/commands/verify_pr.ts, loki-ts/tests/commands/verify_pr.test.ts | MEDIUM | red: bun test tests/commands/verify_pr.test.ts -t "json stdout" fails; green: passes, exit codes 0/2/4 unchanged | ready@2026-10-17T10:00Z | Gap: verify_pr.ts runVerifyPr handles only --out and --help and treats --json as an extra positional (usage error, exit 2) |
|
|
1204
|
+
| TEN-ADOPTION-20 | feature: `loki memory list --json` returning the pattern, mistake and success counts and learnings path | loki-ts/src/commands/memory.ts, loki-ts/tests/commands/memory.test.ts | LOW | red: bun test tests/commands/memory.test.ts -t "list json" fails; green: passes, text output unchanged | ready@2026-10-17T10:00Z | Gap: memory.ts runMemoryList() takes no args; only `lessons` has --json; chain after TEN-UX-22 |
|
|
1205
|
+
| TEN-SECURITY-09 | enhancement: SARIF secret scan misses hyphenated and common vendor keys (sk-ant-api03-..., sk-proj-..., npm_..., sk_live_..., JWT); extend SECRET_PATTERNS with one fixture each and a no-false-positive fixture | loki-ts/src/commands/export_sarif.ts, loki-ts/tests/commands/export_sarif.test.ts | HIGH | red: bun test tests/commands/export_sarif.test.ts -t "vendor keys" fails (0 findings); green: passes and clean fixtures still report 0 | ready@2026-10-17T10:00Z | Gap: export_sarif.ts:11 `openai-style-key: /sk-[A-Za-z0-9]{20,}/` stops at the first hyphen so sk-ant-api03-XXXX is not matched; no npm_, Stripe or JWT pattern |
|
|
1206
|
+
| TEN-SECURITY-10 | enhancement: redact() leaves SendGrid (SG.), Twilio (SK + 32 hex), Docker (dckr_pat_), DigitalOcean (dop_v1_) and Google OAuth (ya29.) tokens in logs and receipts; add anchored patterns with a positive and a near-miss fixture each | loki-ts/src/util/redact.ts, loki-ts/tests/util/redact.test.ts | HIGH | red: bun test tests/util/redact.test.ts -t "vendor tokens" fails; green: passes, existing redact tests and `bun test tests/util` green | ready@2026-10-17T10:00Z | Gap: grep -n 'SG\\.' loki-ts/src/util/redact.ts returns 0 hits; same for dckr_pat_, dop_v1_, ya29 |
|
|
1207
|
+
| TEN-ADOPTION-21 | enhancement: update nudge ignores LOKI_NO_UPDATE_CHECK=true and always suggests `bun install -g loki-mode` even for npm or brew installs; accept 1/true/yes and pick the hint from the install path | loki-ts/src/util/update_check.ts, loki-ts/tests/util/update_check.test.ts | LOW | red: bun test tests/util/update_check.test.ts -t "opt out true" fails; green: passes, default hint unchanged for bun installs | ready@2026-10-17T10:00Z | Gap: update_check.ts:62 `=== "1"` only; :286 hint string is fixed |
|
|
1208
|
+
| TEN-STABILITY-24 | enhancement: provider failover does not recognize HTTP 529, insufficient_quota, "quota exceeded", RESOURCE_EXHAUSTED or ETIMEDOUT, so those provider failures stall instead of failing over; extend RATE_LIMIT and OUTAGE with a fixture per marker and a non-match for plain app text | loki-ts/src/runner/provider_failover.ts, loki-ts/tests/engine10/failover.test.ts | MEDIUM | red: bun test tests/engine10/failover.test.ts -t "529 and quota" fails; green: passes, existing failover and failover_receipt tests green | ready@2026-10-17T10:00Z | Gap: provider_failover.ts:18-19 RATE_LIMIT/OUTAGE list 429 and 502-504 only |
|
|
1209
|
+
| TEN-QUALITY-21 | enhancement: runner error classifier does not recognize the unittest load failure `ImportError: Failed to import test module`, so a broken test module reads as a code failure instead of a load error; add the pattern with a fixture | loki-ts/src/runner/runner_errors.ts, loki-ts/tests/engine10/runner_errors.test.ts | LOW | red: bun test tests/engine10/runner_errors.test.ts -t "unittest import" fails; green: passes, existing patterns unchanged | ready@2026-10-17T10:00Z | Gap: runner_errors.ts:24 LOAD_PATTERNS has no unittest "Failed to import test module" entry |
|
|
1210
|
+
| TEN-DEPLOY-18 | enhancement: `loki rollback deploy` knows only vercel, fly, netlify and wrangler; add heroku (`heroku releases:rollback`), railway and render manual notes, and a gcloud run revisions hint, each read only (never run) | loki-ts/src/commands/rollback.ts, loki-ts/tests/commands/rollback.test.ts | LOW | red: bun test tests/commands/rollback.test.ts -t "more providers" fails (prints "No rollback command known"); green: passes, existing four unchanged | ready@2026-10-17T10:00Z | Gap: rollback.ts:173 DEPLOY_ROLLBACKS has four prefixes; chain after TEN-DEPLOY-17 |
|
|
1211
|
+
| TEN-COST-38 | enhancement: retry classifier treats OpenAI's "You exceeded your current quota" and Gemini RESOURCE_EXHAUSTED billing text as retryable, burning retries (and cost) on an account that is out of funds; add to quota_exhausted with a fixture and keep rate limit wording transient | loki-ts/src/runner/retry_class.ts, loki-ts/tests/runner/retry_class.test.ts | MEDIUM | red: bun test tests/runner/retry_class.test.ts -t "exceeded current quota" fails; green: passes, TRANSIENT_OVERRIDE cases unchanged | ready@2026-10-17T10:00Z | Gap: retry_class.ts:53 quota_exhausted matches insufficient quota/credit/funds and billing only |
|
|
1212
|
+
| TEN-STABILITY-25 | enhancement: retry classifier lacks HTTP 529 (Anthropic overloaded status) and "bad gateway"/"gateway timeout" words in TRANSIENT_OVERRIDE, so a 529 body that also carries permanent-looking text can be classed non-retryable | loki-ts/src/runner/retry_class.ts, loki-ts/tests/runner/retry_class.test.ts | MEDIUM | red: bun test tests/runner/retry_class.test.ts -t "529" fails; green: passes | ready@2026-10-17T10:00Z | Gap: retry_class.ts:61 lists 502, 503, 504 but not 529; chain after TEN-COST-38 |
|
|
1213
|
+
| TEN-SPEED-09 | enhancement: unit mode silently drops its cost cap when LOKI_UNIT_USD_PER_MTOK is invalid (NaN, 0, negative); emit a NOT PROVEN style note so the user sees the cap was not applied, never loosen the existing cap | loki-ts/src/features/speed/unit_mode.ts, loki-ts/tests/e10ext/unit_mode.test.ts | MEDIUM | red: bun test tests/e10ext/unit_mode.test.ts -t "invalid rate note" fails; green: passes, valid rate output byte identical | ready@2026-10-17T10:00Z | Gap: unit_mode.ts:83 returns the existing cap or {} for a non-finite rate with no note; unit_mode.ts:107 parses Number(env) unchecked |
|
|
1214
|
+
| TEN-UX-23 | fix: `loki crash show <id> extra` and `crash submit <id> extra` silently ignore extra args, and `crash list --foo` lists anyway; reject extra args with a usage line and exit 2 | loki-ts/src/commands/crash.ts, loki-ts/tests/commands/crash.test.ts | LOW | red: bun test tests/commands/crash.test.ts -t "extra args" fails; green: passes, single-arg forms unchanged | ready@2026-10-17T10:00Z | Gap: crash.ts runCrash passes argv[1] only and ignores the rest; chain after TEN-ADOPTION-19 |
|
|
1184
1215
|
| TEN-SECURITY-04 | fix: redactSecrets also strips GitLab (glpat-), npm (npm_), Hugging Face (hf_), Stripe (sk_live_, rk_live_) tokens and PEM private key blocks | loki-ts/src/util/redact.ts, loki-ts/tests/util/redact.test.ts | HIGH | red: each of the five token shapes and a -----BEGIN PRIVATE KEY----- block survive redactSecrets; green: all replaced with [REDACTED:...] markers, existing rules and ordering unchanged; cd loki-ts && bunx tsc --noEmit && bun test tests/util/redact.test.ts | released v11.17.40 | Gap: redact.ts RULES (lines 3-14) cover Anthropic, GitHub, Slack, AWS, JWT, Google, OpenAI, Bearer, URL userinfo; grep -rnE 'glpat or npm_ or hf_ or BEGIN [A-Z ]*PRIVATE or sk_live' loki-ts/src/util/redact.ts returned 0 hits (export_sarif.ts:18 and contrib/ai_bom.ts:83 know the shapes but are not the redactor). Specific rules before generic, keep ReDoS-safe quantifiers. |
|
|
1185
1216
|
| TEN-SECURITY-05 | enhancement: redactSecrets strips secret query parameters (token, access_token, api_key, apikey, password, secret, sig) from URLs in logged and receipted output | loki-ts/src/util/redact.ts, loki-ts/tests/util/redact.test.ts | HIGH | red: https://h/x?access_token=abc123 survives; green: value replaced, parameter name and other params kept, non-secret params untouched; cd loki-ts && bunx tsc --noEmit && bun test tests/util/redact.test.ts | released v11.17.41 | Gap: TEN-SECURITY-02 covers URL userinfo and Authorization only (redact.ts:12-13); grep -nE 'access_token or api_key or \?' loki-ts/src/util/redact.ts returned 0 query-string rules. Serialize after TEN-SECURITY-04 (same two files). |
|
|
1186
1217
|
| TEN-SECURITY-06 | feature: secure-scan rule 6 flags disabled TLS verification in committed code (verify=False, rejectUnauthorized: false, InsecureSkipVerify: true, NODE_TLS_REJECT_UNAUTHORIZED=0) | autonomy/lib/secure-scan.py, tests/test-secure-scan.sh | HIGH | red: a fixture with requests.get(url, verify=False) scans clean; green: finding rule tls-verify-disabled with file and line, test and fixture paths and comments excluded like rule 4; bash tests/test-secure-scan.sh | released v11.17.41 | Gap: secure-scan.py has rules 1-5 only (rule comments at lines 93, 105, 193, 238, 345); grep -nE 'verify=False or rejectUnauthorized or InsecureSkipVerify or NODE_TLS' autonomy/lib/secure-scan.py returned 0 hits. Bump RULES_VERSION (line 49). Serialize after TEN-GATES-20 and before TEN-SECURITY-07. |
|
|
@@ -1040,3 +1040,52 @@ L0 review rule (ENGINE-LAWS.md L0): a fix that adds an `if` or a regex about the
|
|
|
1040
1040
|
- Siblings: util/outbox.ts runOnce (TEN-STABILITY-12, already quarantines); queue run reads the queue and returns "queue is empty" without writing, so it cannot overwrite; its end-of-run writeQueue only follows a successful read.
|
|
1041
1041
|
- Mechanism: queueAdd calls quarantineCorruptQueue, which renames the bad file to issue-queue.json.corrupt-<ts> and warns once on stderr before the read.
|
|
1042
1042
|
- Fixture: loki-ts/tests/commands/queue.test.ts "add on a corrupt queue file quarantines it".
|
|
1043
|
+
|
|
1044
|
+
## FC-TEN-STABILITY-18a Test pins a literal that an intentional change moved, and the pin is not updated in the same slice (STALE-PIN-AFTER-INTENT)
|
|
1045
|
+
- User-visible vs raw: raw (test infrastructure). Nightly 39016259458 stayed red on main e32ee1b5d: pr_body_golden producer registry (util/check_result.ts moved the gate line there, TEN-STABILITY-13), sizing wall brief cap (710 measured vs 600; TEN-COST-14 output budget plus TEN-QUALITY-14 negative-case sentence), router_optout_golden (TEN-COST-11 haiku-first Wall), test-ui-bare-loki (TEN-UX-10 next-step lines), test-local-ci-gitleaks (TEN-SEC-GITLEAKS-01-F1 first-parent log-opts).
|
|
1046
|
+
- Law broken: a slice that changes an asserted surface owns the guards that assert it; green on the slice branch is not green on main when the change landed after the pin.
|
|
1047
|
+
- Siblings: the five pins above (all fixed). The sizing cap now records its measured number; the router golden pins LOKI_E10_WALL_FIRST=0 so it isolates router behavior (wall.test.ts owns haiku-first).
|
|
1048
|
+
- Mechanism: each guard names the owning change in a comment and asserts the intended new shape (first line plus next-step lines; the exact log-opts string), never a weaker match.
|
|
1049
|
+
- Fixture: tests/test-ui-bare-loki.sh "the URL is followed by the start and stop next-step lines"; tests/test-local-ci-gitleaks.sh exact log-opts grep and live invocation mirror.
|
|
1050
|
+
|
|
1051
|
+
## FC-TEN-STABILITY-18b Bun.which reads the PATH captured at process start, so a test or caller that mutates process.env.PATH is ignored (BUN-WHICH-STALE-PATH)
|
|
1052
|
+
- User-visible vs raw: raw (CI only). verify.test.ts TEN-QUALITY-11 cases passed on a machine with uv installed and failed in CI without it: resolveTool asked Bun.which("uv") and never saw the fake uv prepended to process.env.PATH.
|
|
1053
|
+
- Law broken: tool resolution must use the same PATH the child process will receive.
|
|
1054
|
+
- Siblings: verify.ts resolveTool (fixed, both uv and fallback lookups); provider_failover.ts defaultInstalled, deep.ts:104 and modernize/lang/java.ts:159 call Bun.which without the live PATH when no path option is given (named, not changed: production PATH is fixed at start, no test mutates it).
|
|
1055
|
+
- Mechanism: resolveTool's onPath helper passes {PATH: process.env.PATH}.
|
|
1056
|
+
- Fixture: verify.test.ts TEN-QUALITY-11 cases, run with PATH=/usr/bin:/bin plus the bun directory (no uv): red before the fix (2 fail), green after.
|
|
1057
|
+
|
|
1058
|
+
## FC-TEN-STABILITY-18c A verify flag exists in the engine10 verifier and completions but the dispatcher rejects it and help omits it (VERIFY-FLAG-NOT-ROUTED)
|
|
1059
|
+
- User-visible vs raw: user-visible. `loki verify --require-exogenous` (the CHANGELOG form) printed "[verify][error] unknown option" from the legacy verifier, and `loki verify --help` did not list the flag.
|
|
1060
|
+
- Law broken: a documented flag must reach the implementation that owns it, and its help must list it.
|
|
1061
|
+
- Siblings: --allow-unsigned and --export-dsse also lack a flag-first route in bin/loki (they work after a run id or receipt path); named, not changed here.
|
|
1062
|
+
- Mechanism: bin/loki and autonomy/loki cmd_verify route --require-exogenous to engine10 like --pubkey; autonomy/verify.sh help lists it.
|
|
1063
|
+
- Fixture: tests/test-help-changelog-drift.sh (flag in help); `bash bin/loki verify --require-exogenous` now reaches engine10 ("no runs found") instead of the unknown-option error.
|
|
1064
|
+
|
|
1065
|
+
## FC-TEN-STABILITY-18d The legacy echo-into-grep-q ratchet is breached by new tests and the ceiling is the only guard (SIGPIPE-RATCHET-BREACH)
|
|
1066
|
+
- User-visible vs raw: raw (test infrastructure). tests/test-sigpipe-guard.sh counted 1737 legacy forms against a ceiling of 1728.
|
|
1067
|
+
- Law broken: the ceiling is lowered when a suite is converted, never raised (the guard's own header).
|
|
1068
|
+
- Siblings: 15 forms converted in test-next-resume-agree.sh (7), test-security-audit-config.sh (6) and test-doctor-ux.sh (2); the ceiling now equals the new count, 1722. Large holders remain (test-v10-pulse.sh 321, test-deploy-receipt-gate.sh 38).
|
|
1069
|
+
- Mechanism: grep -q PATTERN <<<"$var" here-string form.
|
|
1070
|
+
- Fixture: tests/test-sigpipe-guard.sh; SIGPIPE_GUARD_CEILING=1721 turns it red (count 1722 exceeds ceiling 1721).
|
|
1071
|
+
|
|
1072
|
+
## FC-TEN-STABILITY-19a A headline policy change silently disarmed a moat positive control (MOAT-CONTROL-POLICY-DRIFT)
|
|
1073
|
+
- User-visible vs raw: raw (moat suite). `bash tests/moat/run.sh` printed "moat suite: FAIL (1 rule failure(s))": P8.ablation-dead-code-not-sealed got "positive control: load-bearing fixture headline=VERIFIED WITH GAPS, expected VERIFIED". The raw cause was TEN-GATES-10 (c6796b75b, D104): VERIFIED now needs one agent-independent fact beside the agent's suite, and the P8 fixture recorded only the suite (build marked not applicable), so every P8 fixture got an exogenous_evidence gap. The dead-code assertion "headline is not VERIFIED" then held for the wrong reason: removing the not_load_bearing rule from _compute_headline no longer turned it red.
|
|
1074
|
+
- Law broken: a negative assertion is evidence only while its positive control reaches the green state under the CURRENT headline rules; a headline rule change must re-green every moat control it touches.
|
|
1075
|
+
- Siblings: tests/test-proof-ablation-headline.sh (passes; it pins facts.ablation, not the headline); tests/test_proof_generator.py (updated by TEN-GATES-10 itself); P1-P7 and P9 were green on the same run, so no other moat control reads a suite-only VERIFIED.
|
|
1076
|
+
- Mechanism: the P8 fixture records a real build fact (byte-compiling every source file, exit code recorded, no .pyc written) so the control meets D104; the moat rule and the generator are unchanged.
|
|
1077
|
+
- Fixture: tests/moat/p8-load-bearing-proof.sh. Red with the build exit code forced to 1 (control headline=NOT VERIFIED), and red with the generator's not_load_bearing check mutated ("headline is VERIFIED although the checks pass with the change no-oped"), which was undetectable before this fix.
|
|
1078
|
+
|
|
1079
|
+
## FC-TEN-STABILITY-19b The first-run gate stub treated the login probe as a work session (STUB-AUTH-STATUS-SILENT recurrence)
|
|
1080
|
+
- User-visible vs raw: raw (release gate). `bash scripts/first-run-gate.sh --stub` failed 7 assertions, all from "Reason: dirty tracked tree: M sum.js" at intake.ts:61, plus a python FileNotFoundError traceback from the cost-non-null probe. The engine preflight (TEN-UX-01, 08a8ae052) runs `claude auth status` in the repo before Intake; the gate's heredoc stub short-circuited only --help/--version, so the probe applied the sum.js fix and Intake refused the dirty tree. The real CLI's auth status is read-only, so users never saw this.
|
|
1081
|
+
- Law broken: same as FC-TEN-STABILITY-09: a stub provider must honour every CLI call the engine makes before a session.
|
|
1082
|
+
- Siblings: FC-TEN-STABILITY-09 fixed the loki-ts/tests stubs but not scripts/first-run-gate.sh (fixed here). scripts/b9-scoreboard.sh already answers auth. tests/test-quick-config-safety.sh, test-quick-receipt-order.sh, test-quick-artifacts.sh, test-json-schemas.sh and test-usage-governor.sh all pass on this base (their stubs do not edit the tree on the probe).
|
|
1083
|
+
- Mechanism: the gate stub answers `auth status` with {"loggedIn": true}, no side effects; the cost-non-null probe reports an unreadable run record as a FAIL line instead of a traceback.
|
|
1084
|
+
- Fixture: loki-ts/tests/engine10/e2e.test.ts "every engine10 stub claude answers claude auth status as logged in" now also pins the first-run gate stub (red with the stub line removed); the gate itself returns to 7 failures with that line removed.
|
|
1085
|
+
|
|
1086
|
+
## FC-TEN-STABILITY-20 A slice adds a CLI flag in the Bun route and CHANGELOG but not in the help-drift-checked help or completions (HELP-FLAG-DRIFT)
|
|
1087
|
+
- User-visible vs raw: user-visible. `loki report kpis --since` and `loki undo --list` (v11.17.40) worked but were absent from `loki help` and Tab completion, so tests/test-help-changelog-drift.sh was red on 3 lines.
|
|
1088
|
+
- Law broken: a documented flag must appear in the help output for its command and in completions/loki.bash.
|
|
1089
|
+
- Siblings: swept the other newest-window invocations (proof list --json, proof share --dry-run, queue add, start --help, status --probe/--json); all already pass. completions/_loki carries no per-flag lists for report or undo; its undo description now names --list.
|
|
1090
|
+
- Mechanism: autonomy/loki help text lists both flags; completions/loki.bash gains report and undo cases. The drift test already guards both.
|
|
1091
|
+
- Fixture: tests/test-help-changelog-drift.sh (22 passed, 0 failed); removing the `undo --list` help line turns it red.
|
package/docs/v10/PROGRESS.md
CHANGED
|
@@ -2503,3 +2503,9 @@ v11.17.21 published (Release success on 462fbc40a; npm latest 11.17.21, next 11.
|
|
|
2503
2503
|
|
|
2504
2504
|
## 2026-10-17T09:37Z (CoS) v11.17.41
|
|
2505
2505
|
- v11.17.41: wave AJ, 9 of 9 slices approved and merged cleanly; tests/util plus budget and L0 guards 446 pass 0 fail, tsc clean outside control-plane. Follow-ups noted by reviewers: doctor JSON path still serial, help-changelog-drift red (TEN-STABILITY-18 owns it).
|
|
2506
|
+
|
|
2507
|
+
## 2026-10-17T09:41Z (CoS) v11.17.42
|
|
2508
|
+
- v11.17.42: TEN-STABILITY-18 and TEN-STABILITY-19 merged; FAILURE-CLASSES append conflicts resolved as union. Results: tests/util plus pr_body_golden, sizing, router_optout_golden, verify, budget and l0 guards 538 pass 0 fail. sigpipe, ui-bare and local-ci-gitleaks rc 0; first-run-gate --stub 0 assertions failed. help-changelog-drift still red on new v11.17.40 flags (report --since, undo --list); TEN-STABILITY-20 dispatched.
|
|
2509
|
+
|
|
2510
|
+
## 2026-10-17T09:49Z (CoS) v11.17.43
|
|
2511
|
+
- Released TEN-STABILITY-20 (help/completion drift fix-forward). Board refilled with 30 TEN rows for wave AL (fc36b4548).
|
package/loki-ts/dist/loki.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var rw0=Object.create;var{getPrototypeOf:tw0,defineProperty:OW,getOwnPropertyNames:vd,getOwnPropertyDescriptor:ew0}=Object,hd=Object.prototype.hasOwnProperty;function fd(Z){return this[Z]}var Z_0,$_0,J_0=(Z,$,J)=>{var X=Z!=null&&typeof Z==="object";if(X){var Y=$?Z_0??=new WeakMap:$_0??=new WeakMap,z=Y.get(Z);if(z)return z}J=Z!=null?rw0(tw0(Z)):{};let Q=$||!Z||!Z.__esModule?OW(J,"default",{value:Z,enumerable:!0}):J;for(let W of vd(Z))if(!hd.call(Q,W))OW(Q,W,{get:fd.bind(Z,W),enumerable:!0});if(X)Y.set(Z,Q);return Q},X_0=(Z)=>{var $=(yd??=new WeakMap).get(Z),J;if($)return $;if($=OW({},"__esModule",{value:!0}),Z&&typeof Z==="object"||typeof Z==="function"){for(var X of vd(Z))if(!hd.call($,X))OW($,X,{get:fd.bind(Z,X),enumerable:!(J=ew0(Z,X))||J.enumerable})}return yd.set(Z,$),$},yd,RB=(Z,$)=>()=>($||Z(($={exports:{}}).exports,$),$.exports);var Y_0=(Z)=>Z;function z_0(Z,$){this[Z]=Y_0.bind(null,$)}var O0=(Z,$)=>{for(var J in $)OW(Z,J,{get:$[J],enumerable:!0,configurable:!0,set:z_0.bind($,J)})};var S=(Z,$)=>()=>(Z&&($=Z(Z=0)),$);var m9=import.meta.require;var md={};O0(md,{lokiDir:()=>P0,homeLokiDir:()=>Z2,findRepoRootForVersion:()=>tT,REPO_ROOT:()=>j0});import{resolve as sZ,dirname as rT}from"path";import{fileURLToPath as Q_0}from"url";import{existsSync as EB}from"fs";import{homedir as W_0}from"os";function K_0(){let Z=gd;for(let $=0;$<6;$++){if(EB(sZ(Z,"VERSION"))&&EB(sZ(Z,"autonomy/run.sh")))return Z;let J=rT(Z);if(J===Z)break;Z=J}return sZ(gd,"..","..","..")}function tT(Z){let $=Z;for(let J=0;J<6;J++){if(EB(sZ($,"VERSION"))&&EB(sZ($,"autonomy/run.sh")))return $;let X=rT($);if(X===$)break;$=X}return sZ(Z,"..","..","..")}function P0(){return process.env.LOKI_DIR??sZ(process.cwd(),".loki")}function Z2(){return sZ(W_0(),".loki")}var gd,j0;var n0=S(()=>{gd=rT(Q_0(import.meta.url));j0=K_0()});import{readFileSync as V_0}from"fs";import{resolve as G_0,dirname as H_0}from"path";import{fileURLToPath as q_0}from"url";function Y6(){if(Z1!==null)return Z1;let Z="11.17.
|
|
2
|
+
var rw0=Object.create;var{getPrototypeOf:tw0,defineProperty:OW,getOwnPropertyNames:vd,getOwnPropertyDescriptor:ew0}=Object,hd=Object.prototype.hasOwnProperty;function fd(Z){return this[Z]}var Z_0,$_0,J_0=(Z,$,J)=>{var X=Z!=null&&typeof Z==="object";if(X){var Y=$?Z_0??=new WeakMap:$_0??=new WeakMap,z=Y.get(Z);if(z)return z}J=Z!=null?rw0(tw0(Z)):{};let Q=$||!Z||!Z.__esModule?OW(J,"default",{value:Z,enumerable:!0}):J;for(let W of vd(Z))if(!hd.call(Q,W))OW(Q,W,{get:fd.bind(Z,W),enumerable:!0});if(X)Y.set(Z,Q);return Q},X_0=(Z)=>{var $=(yd??=new WeakMap).get(Z),J;if($)return $;if($=OW({},"__esModule",{value:!0}),Z&&typeof Z==="object"||typeof Z==="function"){for(var X of vd(Z))if(!hd.call($,X))OW($,X,{get:fd.bind(Z,X),enumerable:!(J=ew0(Z,X))||J.enumerable})}return yd.set(Z,$),$},yd,RB=(Z,$)=>()=>($||Z(($={exports:{}}).exports,$),$.exports);var Y_0=(Z)=>Z;function z_0(Z,$){this[Z]=Y_0.bind(null,$)}var O0=(Z,$)=>{for(var J in $)OW(Z,J,{get:$[J],enumerable:!0,configurable:!0,set:z_0.bind($,J)})};var S=(Z,$)=>()=>(Z&&($=Z(Z=0)),$);var m9=import.meta.require;var md={};O0(md,{lokiDir:()=>P0,homeLokiDir:()=>Z2,findRepoRootForVersion:()=>tT,REPO_ROOT:()=>j0});import{resolve as sZ,dirname as rT}from"path";import{fileURLToPath as Q_0}from"url";import{existsSync as EB}from"fs";import{homedir as W_0}from"os";function K_0(){let Z=gd;for(let $=0;$<6;$++){if(EB(sZ(Z,"VERSION"))&&EB(sZ(Z,"autonomy/run.sh")))return Z;let J=rT(Z);if(J===Z)break;Z=J}return sZ(gd,"..","..","..")}function tT(Z){let $=Z;for(let J=0;J<6;J++){if(EB(sZ($,"VERSION"))&&EB(sZ($,"autonomy/run.sh")))return $;let X=rT($);if(X===$)break;$=X}return sZ(Z,"..","..","..")}function P0(){return process.env.LOKI_DIR??sZ(process.cwd(),".loki")}function Z2(){return sZ(W_0(),".loki")}var gd,j0;var n0=S(()=>{gd=rT(Q_0(import.meta.url));j0=K_0()});import{readFileSync as V_0}from"fs";import{resolve as G_0,dirname as H_0}from"path";import{fileURLToPath as q_0}from"url";function Y6(){if(Z1!==null)return Z1;let Z="11.17.43";if(typeof Z==="string"&&Z.length>0)return Z1=Z,Z1;try{let $=H_0(q_0(import.meta.url)),J=tT($);Z1=V_0(G_0(J,"VERSION"),"utf-8").trim()}catch{Z1="unknown"}return Z1}var Z1=null;var rZ=S(()=>{n0()});import{mkdirSync as ud,readFileSync as ZP,realpathSync as U_0,statSync as B_0,writeFileSync as pd}from"fs";import{dirname as AW,join as eT,resolve as cd}from"path";function A_0(){return cd(Z2(),"cache","update-check.json")}function tZ(Z){let $=/^(\d+)\.(\d+)\.(\d+)$/.exec(Z.trim());if(!$)return null;return[Number($[1]),Number($[2]),Number($[3])]}function LW(Z,$){let J=tZ(Z),X=tZ($);if(!J||!X)return!1;let[Y,z,Q]=J,[W,K,V]=X;if(Y!==W)return Y>W;if(z!==K)return z>K;return Q>V}function dd(){if(process.env.LOKI_NO_UPDATE_CHECK==="1")return!0;if(process.env.CI)return!0;if(!process.stdout.isTTY)return!0;return!1}function L_0(Z){try{let $=ZP(Z,"utf-8"),J=JSON.parse($);if(typeof J.checkedAt==="number"&&typeof J.latest==="string"&&tZ(J.latest)!==null)return{checkedAt:J.checkedAt,latest:J.latest}}catch{}return null}function j_0(Z,$){try{ud(AW(Z),{recursive:!0}),pd(Z,JSON.stringify($),"utf-8")}catch{}}async function F_0(){try{let Z=await fetch(N_0,{signal:AbortSignal.timeout(O_0),headers:{accept:"application/json"}});if(!Z.ok)return null;let $=await Z.json();if(typeof $.version==="string"&&tZ($.version)!==null)return $.version}catch{}return null}async function C_0(Z=Date.now(),$=F_0,J=A_0()){let X=L_0(J);if(X&&Z-X.checkedAt<M_0)return X.latest;let Y=await $();if(Y===null)return null;return j_0(J,{checkedAt:Z,latest:Y}),Y}function I_0(Z,$=process.env){if(tZ(Z)===null)return null;let X=$.PATH;if(!X)return null;let Y=new Set;for(let z of X.split(":")){if(!z)continue;let Q=eT(z,"loki"),W;try{B_0(Q),W=U_0(Q)}catch{continue}if(Y.has(W))continue;Y.add(W);try{let K=eT(AW(AW(W)),"package.json"),V=JSON.parse(ZP(K,"utf8")).version;if(typeof V!=="string")continue;if(LW(V,Z))return{path:Q,version:V}}catch{continue}}return null}function T_0(){return cd(Z2(),"cache","last-seen-version.json")}function P_0(Z,$={}){try{if(dd())return!1;if(tZ(Z)===null)return!1;let J=$.seenFile??T_0(),X=null;try{let z=JSON.parse(ZP(J,"utf-8")).version;if(typeof z==="string"&&tZ(z)!==null)X=z}catch{}if(X!==null&&!LW(Z,X))return!1;try{ud(AW(J),{recursive:!0}),pd(J,JSON.stringify({version:Z}),"utf-8")}catch{return!1}if(X===null)return!1;return($.write??((z)=>process.stderr.write(z)))(`Loki Mode upgraded ${X} -> ${Z}. What is new: https://github.com/asklokesh/loki-mode/releases/tag/v${Z}
|
|
3
3
|
`),!0}catch{return!1}}async function ld(Z,$={}){try{if(dd())return;if(tZ(Z)===null)return;let J=$.write??((z)=>process.stderr.write(z));P_0(Z,{write:J,...$.cacheFile?{seenFile:eT(AW($.cacheFile),"last-seen-version.json")}:{}});let X=I_0(Z,$.env??process.env);if(X!==null){J(`Loki Mode ${X.version} is installed but not the one running (you are running ${Z}).
|
|
4
4
|
Another loki earlier on PATH is winning. Newer copy: ${X.path}
|
|
5
5
|
Run \`which -a loki\` to see the order, then remove or re-point the earlier entry.
|
|
@@ -744,7 +744,7 @@ ${G.stderr}`,U=G.exitCode===0?void 0:await Dz({repoDir:Z.repoDir,baseSha:Z.baseS
|
|
|
744
744
|
`).map((O)=>O.trim()).filter(Boolean),N=H.findings.filter((O)=>String(O.severity).toUpperCase()==="HIGH");if(G.exitCode===3)q.push("secret-scan.sh failed to load");if(!H.ok)q.push(H.error??"secure-scan failed");if(B.length>0)U.push(`secret match: ${B.join(", ")}`);if(N.length>0)U.push(`secure-scan: ${N.map((O)=>`${O.rule}: ${O.file}:${O.line}`).join(", ")}`);let M=U.length>0?"fail":q.length>0?"not_run":"pass";if(X.push({name:"security scan",cmd:"secret-scan.sh + secure-scan.py",result:M,duration_s:(Date.now()-V)/1000,...M==="pass"?{}:{reason:(M==="fail"?U:q).join("; ")}}),M==="not_run")Y.add(`not run: security scan (${q.join("; ")})`)}function Yc8(Z,$){return["comment",Z,$]}function zc8(Z,$,J){let X=[`## Loki deep verify: ${J}`,"","### Checks"];return X.push(...Z.length?Z.map((Y)=>`- ${Y.result}: ${Y.name}${Y.reason?` (${Y.reason})`:""}`):["- none"]),X.push("","### NOT PROVEN",...$.length?$.map((Y)=>`- ${Y}`):["- none"]),`${X.join(`
|
|
745
745
|
`)}
|
|
746
746
|
`}async function Qc8(Z,$,J,X,Y){let z=[],Q=Z.pinnedOrigin;if(!Q)return z.push("push refused: no pinned origin (Rule of Two)"),z;let W=$.pushScriptPath??QW0,K={...process.env,...$.pushExtraEnv,_LOKI_ORIGIN_PINNED:"1",_LOKI_PINNED_ORIGIN:Q},V=Z.outputs().pr?.pr_url,G=V?rp8.exec(V)?.[1]:void 0;if(G){ib(Z.runDir,{recursive:!0});let q=Z4(Z.runDir,"deep-comment.md");ob(q,zc8(J,X,Y),"utf8");let U=await y0(["bash",W,...Yc8(G,q)],{cwd:Z.repoDir,env:K,timeoutMs:30000});if(U.exitCode!==0)z.push(`deep comment not posted (engine10-push.sh exit ${U.exitCode})`)}else z.push("deep comment not posted (no PR number)");let H=(await G9(Z.repoDir,["rev-parse","HEAD"],{timeoutMs:1e4})).stdout.trim();if(tp8.test(H)){let q={cmd:"status",sha:H,state:Y,description:`Loki 10 deep verify: ${Y}`},U=await y0(["bash",W,...i2(q)],{cwd:Z.repoDir,env:K,timeoutMs:30000});if(U.exitCode!==0)z.push(`loki/deep-verify status not set (engine10-push.sh exit ${U.exitCode})`)}else z.push("loki/deep-verify status not set (HEAD sha not resolvable)");return z}async function VW0(Z,$,J={}){if($.aborted)return{status:"failed",data:{},reason:"aborted before deep verify started"};try{qj(J.env??process.env)}catch(N){return{status:"failed",data:{},reason:N.message}}let X;try{X=FZ(Z.repoDir,Z.baseSha)}catch(N){return{status:"failed",data:{},reason:`git diff against base failed: ${N.message}`}}let Y=[],z=new Set;await KW0(Z,$,J,Y,z),await Zc8(Z,J,Y,z),await $c8(Z,X,Z.baseSha,$,J,Y,z),await Xc8(Z,X,J,Y,z);let Q=Y.some((N)=>N.result==="fail")?"failure":"success",W=[...z],K=Z.outputs().seal,V={schema:"loki.v10.receipt-addendum/1",run_id:Z.runId,base_receipt_sha256:K?.receipt_sha256??null,checks:Y,not_proven:W,status_state:Q},G=L7(n5(V)),H=h4(`${Z.runId}-deep`,G),q={...V,addendum_sha256:G,verification:{jwt:H.jwt,kid:H.kid}};ib(Z.runDir,{recursive:!0}),ob(Z4(Z.runDir,"receipt-addendum-1.json"),JSON.stringify(q,null,2)+`
|
|
747
|
-
`);let U=await Qc8(Z,J,Y,W,Q),B=[...W,...U];return Z.emit("deep.completed","deep",{checks:Y,status_state:Q,addendum_sha256:G}),{status:"completed",data:{checks:Y,addendum_sha256:G,status_state:Q,not_proven:B}}}var QW0,WW0,np8=400000,sp8=600,ZW0=300000,rp8,tp8,ep8,GW0,Wc8;var sb=S(()=>{Pb();dL();O9();uL();ab();f4();pG();eQ0();A6();KG();r9();$Z();x0();QW0=new URL("../../../../autonomy/lib/engine10-push.sh",import.meta.url).pathname,WW0=new URL("../../../../autonomy/lib/secret-scan.sh",import.meta.url).pathname,rp8=/\/pull\/(\d+)$/,tp8=/^[0-9a-f]{40}$/,ep8={pytest:{cmd:"python",args:["-m","pytest","-q"]},vitest:{cmd:"npx",args:["vitest","run"]},jest:{cmd:"npx",args:["jest"]},bun:{cmd:"bun",args:["test"]},node:{cmd:"node",args:["--test"]},npm:{cmd:"npm",args:["test","--silent"]},go:{cmd:"go",args:["test","-json","./..."]},cargo:{cmd:"cargo",args:["test"]}};GW0={name:"deep",...y9.deep,run:(Z,$)=>VW0(Z,$,{council:zW0(Z.sessions)})},Wc8=GW0});var LW0={};O0(LW0,{verifyStage:()=>AW0,testConfigChanged:()=>hL,testCheckName:()=>J$,stage:()=>Oc8,skipped:()=>qG,runnerCmd:()=>BW0,runLintChecks:()=>OW0,runCheck:()=>v4,ran:()=>HG,firstError:()=>MW0,commandFor:()=>TZ,changedFiles:()=>FZ});import{existsSync as iG,mkdtempSync as Kc8,realpathSync as HW0,rmSync as Vc8}from"fs";import{tmpdir as Gc8}from"os";import{dirname as Hc8,isAbsolute as qW0,join as PZ,relative as eb}from"path";function UW0(Z,$,J,X=J){let Y=(
|
|
747
|
+
`);let U=await Qc8(Z,J,Y,W,Q),B=[...W,...U];return Z.emit("deep.completed","deep",{checks:Y,status_state:Q,addendum_sha256:G}),{status:"completed",data:{checks:Y,addendum_sha256:G,status_state:Q,not_proven:B}}}var QW0,WW0,np8=400000,sp8=600,ZW0=300000,rp8,tp8,ep8,GW0,Wc8;var sb=S(()=>{Pb();dL();O9();uL();ab();f4();pG();eQ0();A6();KG();r9();$Z();x0();QW0=new URL("../../../../autonomy/lib/engine10-push.sh",import.meta.url).pathname,WW0=new URL("../../../../autonomy/lib/secret-scan.sh",import.meta.url).pathname,rp8=/\/pull\/(\d+)$/,tp8=/^[0-9a-f]{40}$/,ep8={pytest:{cmd:"python",args:["-m","pytest","-q"]},vitest:{cmd:"npx",args:["vitest","run"]},jest:{cmd:"npx",args:["jest"]},bun:{cmd:"bun",args:["test"]},node:{cmd:"node",args:["--test"]},npm:{cmd:"npm",args:["test","--silent"]},go:{cmd:"go",args:["test","-json","./..."]},cargo:{cmd:"cargo",args:["test"]}};GW0={name:"deep",...y9.deep,run:(Z,$)=>VW0(Z,$,{council:zW0(Z.sessions)})},Wc8=GW0});var LW0={};O0(LW0,{verifyStage:()=>AW0,testConfigChanged:()=>hL,testCheckName:()=>J$,stage:()=>Oc8,skipped:()=>qG,runnerCmd:()=>BW0,runLintChecks:()=>OW0,runCheck:()=>v4,ran:()=>HG,firstError:()=>MW0,commandFor:()=>TZ,changedFiles:()=>FZ});import{existsSync as iG,mkdtempSync as Kc8,realpathSync as HW0,rmSync as Vc8}from"fs";import{tmpdir as Gc8}from"os";import{dirname as Hc8,isAbsolute as qW0,join as PZ,relative as eb}from"path";function UW0(Z,$,J,X=J){let Y=(K)=>{try{let V=eb(HW0(Z),HW0(K));return V!==""&&!V.startsWith("..")&&!qW0(V)}catch{return!1}},z=process.env.VIRTUAL_ENV,Q=(K)=>Bun.which(K,{PATH:process.env.PATH??""}),W=[PZ(Z,".venv","bin",$),PZ(Z,"venv","bin",$),...z&&Y(z)?[PZ(z,"bin",$)]:[]].find(iG);return W?[W,"project",[]]:iG(PZ(Z,"uv.lock"))&&Q("uv")?["uv","project",["run","--",$]]:[Q(J)?J:X,"system",[]]}function BW0(Z,$){switch(Z.runner){case"pytest":{let[J,X,Y]=UW0($,"python","python3","python");return[J,[...Y,"-m","pytest","-q",Z.path],X]}case"vitest":return["npx",["vitest","run",Z.path]];case"jest":return["npx",["jest",Z.path]];case"bun":return["bun",["test",Z.path]];case"node":return["node",["--test",`./${Z.path}`]];case"npm":return["npm",["test","--silent"]];case"go":return["go",["test","-json",`./${Hc8(Z.path)}`]];case"cargo":return["cargo",["test"]]}}function TZ(Z,$,J){let X=wx(J,$,Z.path),[Y,z,Q]=BW0(X?{runner:Z.runner,path:X.file}:Z,$);return{cwd:X?.cwd??$,cmd:Y,args:z,argv:[Y,...z],...Q?{interpreter:Q}:{},pkgRoot:X?.root??"."}}async function Uj(Z,$,J,X,Y){if(!Bun.which(Z,{PATH:Y.path??process.env.PATH??""}))return{ok:!1,missing:!0,cut:!1,out:""};let z=AbortSignal.timeout(Y.timeoutMs??Zy),Q=Bun.spawn([Z,...$],{cwd:J,stdin:Y.stdin!==void 0?Buffer.from(Y.stdin):"ignore",stdout:"pipe",stderr:"pipe",signal:AbortSignal.any([X,z]),env:Y.path?{...O6(),PATH:Y.path}:O6()}),W="",K=[Q.stdout,Q.stderr].map((q)=>q.getReader()),V=K.map(async(q)=>{let U=new TextDecoder;for(;;){let B=await q.read().catch(()=>({done:!0,value:void 0}));if(B.done)return;W=(W+U.decode(B.value,{stream:!0})).slice(-65536)}}),G=await Q.exited;await Promise.race([Promise.all(V),new Promise((q)=>setTimeout(q,300))]),K.forEach((q)=>q.cancel().catch(()=>{}));let H=z.aborted||X.aborted;return{ok:G===0&&!H,missing:!1,cut:H,out:H?"":i5(W)}}function MW0(Z){let $=(Y)=>{try{let z=JSON.parse(Y);return typeof z.Action==="string"?z.Action==="output"||z.Action==="build-output"?z.Output??"":"":Y}catch{return Y}},J=Z.slice(-65536).split(`
|
|
748
748
|
`).map((Y)=>(Y.startsWith("{")?$(Y):Y).trim()).filter(Boolean);return(J.find((Y)=>/^(FAILED\s|\u25cf\s.*\u203a|not ok\s|_{3,}\s.+\s_{3,}$)/.test(Y))??J.find((Y)=>/^[\w./-]+\.go:\d+:\d+: \S/.test(Y))??J.find((Y)=>/fail|error/i.test(Y)&&!/^(=|\u2713|ok\b|PASS)/.test(Y))??"").replace(/\d{4}-\d\d-\d\dT[\d:.]+Z?/g,"").replace(/(^|\s)\/(?:[\w.@-]+\/)*[\w.@-]+/g,"$1<path>").replace(/:\d+(?::\d+)?/g,"").replace(/\[?\d+(?:\.\d+)?m?s\]?/g,"").replace(/\s+/g," ").slice(0,160)}async function v4(Z,$,J,X,Y,z,Q={}){let W=Date.now(),K=[J,...X].join(" "),V=Q.kind??"test",G=Q.cwd??Z.repoDir,H=async(O)=>{let L=zJ({kind:V,ok:O.ok,cut:O.cut,missing:O.missing,out:O.out,...Cz(J,X),path:/\.[cm]?[jt]s$/.test(X[X.length-1]??"")?X[X.length-1]:void 0}),j=V==="test"&&!O.ok&&!O.cut&&!O.missing?await Dz({repoDir:Z.repoDir,baseSha:Z.baseSha,out:O.out,cmd:J,args:X,signal:Y,cwd:G,protect:Q.protect,...Q.path?{env:{PATH:Q.path}}:{}}):void 0;if(j)L={result:"not_run",reason:j,owner:"harness"};if(!j&&V==="static"&&!O.ok&&!O.cut&&!O.missing&&Q.wall?.size&&Cz0(O.out,G,Z.repoDir,Q.wall))L={result:"not_run",reason:Fz0,owner:"harness"};let F=O.missing?`${J} not found on PATH`:O.cut?Y.aborted?"aborted":`timed out after ${(Q.timeoutMs??Zy)/1000}s`:L.reason;return{...L,...F?{reason:F}:{}}},q=await Uj(J,X,G,Y,Q),U=await H(q),B=U.result;if(U.result==="fail")q=await Uj(J,X,G,Y,Q),U=await H(q),B=U.result==="not_run"?"not_run":U.result==="pass"?"flaky":"fail";let N=U.reason,M={name:$,cmd:K,result:B,duration_s:(Date.now()-W)/1000,...B==="fail"?{first_error:MW0(q.out),ids:jZ(q.out)}:B==="pass"&&V==="test"?{n:U.n??0,sk:qG(q.out)}:{},...N?{reason:N}:{},...U.owner?{owner:"harness"}:{},...Q.interpreter?{interpreter:Q.interpreter}:{}};if(B==="fail"&&!Q.opaque&&!$$(M))NW0.set(M,tJ0(q.out,Z.repoDir));if(z.push(M),Q.opaque&&M.result!=="pass"&&M.reason)Ob(Z.runDir,{check:$,result:M.result,reason:M.reason});return Z.emit("test.result","verify",Q.opaque?{...tb(M)}:{...M}),M}async function Bc8(Z,$,J,X,Y,z,Q,W){let K={ids:[],names:[],weak:[],cnt:{}},V=J.flatMap((B)=>{let N=X.find((M)=>J$(M)===B.name);return N?[{c:B,t:N}]:[]}),G=V.filter(({t:B})=>!Y.includes(B.path)),H=V.filter(({c:B})=>Q.has(B.name)&&B.result==="pass");if(!(G.some(({c:B})=>B.result==="fail"&&B.ids?.length)||H.length)||W.aborted)return K;let q=Kc8(PZ(Gc8(),"e10-base-")),U=(B)=>{J0(Z.repoDir,B,{stdio:"ignore",repoDrivers:!0})};try{U(["-c","core.hooksPath=/dev/null","worktree","add","--detach",q,Z.baseSha]);let B=new Map;for(let{c:M,t:O}of new Set([...G,...H])){let L=TZ(O,q,$),j=await Uj(L.cmd,L.args,L.cwd,W,{}),F=!j.ok&&!j.cut?jZ(j.out):[];B.set(M,{red:F,n:HG(j.out)??pJ0(j.out),sk:qG(j.out)})}K.weak=H.filter(({c:M})=>(M.sk??0)>B.get(M).sk||(M.n??0)<B.get(M).n).map(({c:M})=>M.name);for(let{c:M}of H)K.cnt[M.name]={b:{run:B.get(M).n,skipped:B.get(M).sk},h:{run:M.n??0,skipped:M.sk??0}};if(J.some((M)=>z.has(M.name)&&M.result==="pass")||H.some(({c:M})=>!K.weak.includes(M.name)&&B.get(M).red.length>0&&(M.n??0)>=B.get(M).n)){for(let{c:M}of G)if(!Q.has(M.name)&&M.result==="fail"&&M.ids?.length&&M.ids.every((O)=>B.get(M).red.includes(O)))K.names.push(M.name),K.ids.push(...M.ids)}}catch{}finally{try{U(["worktree","remove","--force",q])}catch{}Vc8(q,{recursive:!0,force:!0});try{U(["worktree","prune"])}catch{}}return K}function Nc8(Z){return iG(PZ(Z,"scripts","select-tests.sh"))}async function OW0(Z,$,J,X,Y={}){let{api:z,...Q}=Y;Y=Q;let W=[],K=$.filter((G)=>G.endsWith(".py"));if(K.length){let[G,H,q]=UW0(Z.repoDir,"ruff","ruff"),U=await v4(Z,"lint:ruff",G,[...q,"check","--output-format=concise",...K],J,X,{...Y,interpreter:H,kind:"static"});if(await rb(Z,J,U,"ruff",G,[...q,"check"],Z.repoDir,K,Y))W.push(U.name)}let V=$.filter((G)=>G.endsWith(".sh"));if(V.length){await v4(Z,"lint:bash-n","bash",["-c",'for f in "$@"; do bash -n "$f" || exit 1; done',"_",...V],J,X,{...Y,kind:"static"});let G=await v4(Z,"lint:shellcheck","shellcheck",V,J,X,{...Y,kind:"static"});if(await rb(Z,J,G,"shellcheck","shellcheck",[],Z.repoDir,V,Y))W.push(G.name)}for(let G of W10(z,Z.repoDir,$.filter((H)=>/\.(ts|tsx|js|jsx)$/.test(H)))){let H=G.root==="."?"":`:${G.root}`,q=G.root==="."?Y:{...Y,cwd:G.cwd};if(iG(PZ(G.cwd,"tsconfig.json")))await v4(Z,`lint:tsc${H}`,"npx",["tsc","--noEmit","-p","."],J,X,{...q,kind:"static"});if(Mc8.some((U)=>iG(PZ(G.cwd,U)))){let U=await v4(Z,`lint:eslint${H}`,"npx",["eslint",...G.rel],J,X,{...q,kind:"static"});if(await rb(Z,J,U,"eslint","npx",["eslint"],G.cwd,G.rel,q))W.push(U.name)}}return W}var Zy=60000,NW0,$$=(Z)=>Mb(Z.name),tb=(Z)=>({name:"holdout",cmd:"holdout",result:Z.result,duration_s:Z.duration_s,...Z.n!==void 0?{n:Z.n}:{},...Z.sk!==void 0?{sk:Z.sk}:{},...Z.owner?{owner:Z.owner,reason:"holdout infrastructure failure"}:{}}),J$=(Z)=>`${Z.runner}:${Z.path}`,qc8=(Z)=>[...new Map(Z.map(($)=>[`${$.runner}:${$.path}`,$])).values()],Uc8,Mc8,rb=(Z,$,J,X,Y,z,Q,W,K)=>J.result!=="fail"||$.aborted?Promise.resolve(!1):RS(X,z,W,{run:async(V,G)=>{if($.aborted)return null;let H=await Uj(Y,V,Q,AbortSignal.any([$,AbortSignal.timeout(K.timeoutMs??Zy)]),{...K,...G!==void 0?{stdin:G}:{}});return H.missing||H.cut?null:H},base:(V)=>{try{return J0(Z.repoDir,["show",`${Z.baseSha}:${eb(Z.repoDir,PZ(Q,V))}`],{stdio:["ignore","pipe","ignore"]})}catch{return null}}}),AW0,Oc8;var pG=S(()=>{xx();fL();Fb();KG();Cb();uL();Y7();I2();A6();Iz0();kG();r9();C2();x0();o3();A6();A6();fL();NW0=new WeakMap,Uc8=/\.(?:[cm]?[jt]sx?|py|go)$/;Mc8=[".eslintrc",".eslintrc.json",".eslintrc.js",".eslintrc.cjs","eslint.config.js","eslint.config.mjs","eslint.config.cjs"];AW0={name:"verify",targetS:y9.verify.targetS,limitS:y9.verify.limitS,async run(Z,$){let J;try{J=FZ(Z.repoDir,Z.baseSha)}catch(f){return{status:"failed",data:{},reason:`git diff against base failed: ${f.message}`}}if(J.length===0){if(Z.outputs().implement?.exit==="already_done")return{status:"completed",data:{already_satisfied:!0,checks:[],flaky:[],failures_grouped:[],changed_files:[]}};return{status:"failed",data:{changed_files:[]},reason:"empty diff without an already_done marker"}}let X=(()=>{try{let f=nJ0(sJ0(Z.repoDir,Z.baseSha));return US(Z.repoDir,f),f}catch{return null}})(),Y=[],z=H5(Z.repoDir),Q=await Z.tests.detect(Z.repoDir),W=Z.tests.impacted(Q,J),K=Q.tests.filter((f)=>J.includes(f.path)),V=Z.outputs().wall??{},G=new Set((V.files??[]).map((f)=>qW0(f.path)?eb(Z.repoDir,f.path):f.path)),H=Q.tests.filter((f)=>G.has(f.path)),q=Z.outputs().intake,U=Z.tests.impacted(Q,Gz(q?.task??"",t7(q?.repomap_ref))),B=Nz0(qc8([...W,...K,...H,...U]),Z.outputs().verify?.checks),N=B10(Q);if(N.length)Z.emit("test.scoped_out","verify",{tests:N});for(let f of B){if($.aborted)break;let a=TZ(f,Z.repoDir,z);await v4(Z,J$(f),a.cmd,a.args,$,Y,{...a.interpreter?{interpreter:a.interpreter}:{},protect:[...H,...U].includes(f),...a.pkgRoot!=="."?{cwd:a.cwd}:{}})}let M=V.holdout_dir?Yz0(V.holdout_dir,Z.repoDir):null;try{for(let[f,a]of(M?.tests??[]).entries()){if($.aborted)break;let g=a,u=TZ(g,Z.repoDir,z);await v4(Z,`holdout:${f+1}`,u.cmd,u.args,$,Y,{...u.interpreter?{interpreter:u.interpreter}:{},protect:!0,opaque:!0,...u.pkgRoot!=="."?{cwd:u.cwd}:{}})}}finally{M?.cleanup()}if(M?.missing.length){for(let a of M.missing)Ob(Z.runDir,{check:"holdout:store",result:"not_run",reason:a});let f={name:"holdout:store",cmd:"holdout",result:"not_run",duration_s:0,reason:"holdout store unavailable",owner:"harness"};Y.push(f),Z.emit("test.result","verify",{...tb(f)})}let O=new Set([...[...H,...U].map(J$),...Y.filter($$).map((f)=>f.name)]),L=await Bc8(Z,z,Y,B,J,new Set(H.map(J$)),new Set(U.map(J$)),$),j=KL(Z.repoDir,Z.baseSha,Y.filter((f)=>f.result==="fail"&&!L.names.includes(f.name)).map((f)=>({name:f.name,ids:f.ids,eligible:!O.has(f.name)&&!J.includes(f.name.slice(f.name.indexOf(":")+1))})));if(j.introducedChecks=[...new Set(j.introducedChecks.map((f)=>Mb(f)?"holdout":f))],L.names.push(...j.preExistingChecks),L.ids.push(...j.preExistingIds),!$.aborted){let f=await OW0(Z,J,$,Y,{api:z,wall:G});if(L.names.push(...f),f.length)j.line=[j.line,`baseline: ${f.join(", ")} static diagnostics already on base (not blocking)`].filter(Boolean).join("; ");if(Nc8(Z.repoDir))await v4(Z,"select-tests","bash",["scripts/select-tests.sh","--files","-","--run"],$,Y,{kind:"static",stdin:J.join(`
|
|
749
749
|
`)+`
|
|
750
750
|
`})}let F=new Set;if(X&&X.tier!=="low"&&!$.aborted){let{runFullSuite:f}=await Promise.resolve().then(() => (sb(),nb)),a=[];await f(Z,$,{},a,F);for(let u of a){let o={name:u.name,cmd:u.cmd,result:u.result,duration_s:u.duration_s,...u.reason?{reason:u.reason}:{}};Y.push(o),Z.emit("test.result","verify",{...o})}let g=PS(Z.repoDir,Z.baseSha,a,Y.filter((u)=>u.result==="fail"&&!L.names.includes(u.name)).flatMap((u)=>u.ids??[]),J);if(L.names.push(...g.preExistingChecks),L.ids.push(...g.preExistingIds),j.introducedChecks.push(...g.introducedChecks),j.line=[j.line,g.line].filter(Boolean).join("; ")||null,a.some((u)=>u.result==="pass"||u.result==="fail"))X=iJ0(X,["full test command","full suite"]),US(Z.repoDir,X)}let I=hL(Z.repoDir,Z.baseSha,J),T=(f)=>Z.tests.impacted(Q,[f]).some((a)=>Y.some((g)=>g.name===J$(a)&&UG([g]))),C=J.filter((f)=>Uc8.test(f)&&!e7(f)&&!G.has(f)&&!I.includes(f)&&!T(f)),R=Y.filter((f)=>f.result==="flaky").map((f)=>$$(f)?"holdout":f.name),D=rJ0,P=Y.filter((f)=>f.result==="fail"&&!L.names.includes(f.name)&&!$$(f)).map((f)=>{let a=$$(f)?"":BS(NW0.get(f)??"",Math.max(0,D));return D-=Buffer.byteLength(a),{signature:f.first_error?`${f.name} ${f.first_error}`:f.name,count:1,sample:a?`${f.cmd}
|
|
@@ -3074,4 +3074,4 @@ Unknown commands exit 2 with a suggestion; run 'loki help' for the full list.
|
|
|
3074
3074
|
`);{let{suggestCommand:X}=await Promise.resolve().then(() => (Ld(),Lw0)),Y=$===void 0?void 0:X($);if(Y)process.stderr.write(`Did you mean 'loki ${Y}'?
|
|
3075
3075
|
`)}return process.stderr.write(cw0),2}}wM0();var dw0=()=>globalThis[Symbol.for("loki.ownsStopSignals")]===!0;process.on("SIGINT",()=>{if(!dw0())process.exit(130)});process.on("SIGTERM",()=>{if(!dw0())process.exit(143)});var jz9=await Lz9(Bun.argv.slice(2));process.exit(jz9);
|
|
3076
3076
|
|
|
3077
|
-
//# debugId=
|
|
3077
|
+
//# debugId=35B74351AA5AE08155494EA753BC8627
|
package/mcp/__init__.py
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "loki-mode",
|
|
3
3
|
"mcpName": "io.github.asklokesh/loki-mode",
|
|
4
|
-
"version": "11.17.
|
|
4
|
+
"version": "11.17.43",
|
|
5
5
|
"description": "An autonomous software factory that knows what it is supposed to deliver, and proves it did.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"agent",
|
|
@@ -158,5 +158,5 @@
|
|
|
158
158
|
"dependencies": {
|
|
159
159
|
"@resvg/resvg-wasm": "^2.6.2"
|
|
160
160
|
},
|
|
161
|
-
"gitHead": "
|
|
161
|
+
"gitHead": "e0adb90851f7fd1163369a17869bd8e1a7db5a68"
|
|
162
162
|
}
|
|
@@ -14009,9 +14009,9 @@ function resolveTool(repoDir, bin, fallback, lastResort = fallback) {
|
|
|
14009
14009
|
return false;
|
|
14010
14010
|
}
|
|
14011
14011
|
};
|
|
14012
|
-
const venvEnv = process.env["VIRTUAL_ENV"];
|
|
14012
|
+
const venvEnv = process.env["VIRTUAL_ENV"], onPath = (b) => Bun.which(b, { PATH: process.env["PATH"] ?? "" });
|
|
14013
14013
|
const project = [join56(repoDir, ".venv", "bin", bin), join56(repoDir, "venv", "bin", bin), ...venvEnv && inRepo(venvEnv) ? [join56(venvEnv, "bin", bin)] : []].find(existsSync36);
|
|
14014
|
-
return project ? [project, "project", []] : existsSync36(join56(repoDir, "uv.lock")) &&
|
|
14014
|
+
return project ? [project, "project", []] : existsSync36(join56(repoDir, "uv.lock")) && onPath("uv") ? ["uv", "project", ["run", "--", bin]] : [onPath(fallback) ? fallback : lastResort, "system", []];
|
|
14015
14015
|
}
|
|
14016
14016
|
function runnerCmd(t, repoDir) {
|
|
14017
14017
|
switch (t.runner) {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
|
|
3
3
|
"name": "loki-mode",
|
|
4
4
|
"displayName": "Loki Mode",
|
|
5
|
-
"version": "11.17.
|
|
5
|
+
"version": "11.17.43",
|
|
6
6
|
"description": "Autonomous spec-to-product build system with a built-in trust layer (RARV-C closure loop, 8 quality gates, completion council). Ships Loki's spec-hardening, drift-detection, and deterministic PR verification commands plus the Loki MCP server.",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "Autonomi",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{c as L,r as x,j as e,w as re,Z as ne,m as le,h as ie,p as P,F as ye,U as I,X as ce,L as de,x as oe,M as Ae,T as Z,S as we,l as xe,k as me,y as Ce,E as Fe,a0 as Se,a as U,a2 as he}from"./index-
|
|
1
|
+
import{c as L,r as x,j as e,w as re,Z as ne,m as le,h as ie,p as P,F as ye,U as I,X as ce,L as de,x as oe,M as Ae,T as Z,S as we,l as xe,k as me,y as Ce,E as Fe,a0 as Se,a as U,a2 as he}from"./index-cu9_aTCP.js";import{B as C}from"./Button-BxDDHZo6.js";import{T as $e}from"./trending-up-DnB-6eIb.js";import{C as z}from"./clock-C-sLUpGG.js";import{A as Be,U as ue,M as De}from"./Avatar-DJ7ngKyG.js";import{A as J}from"./activity-BQ44JhWT.js";import{R as pe}from"./refresh-cw-CeT9llPq.js";import{G as ze}from"./globe-C7TzpMng.js";import{C as Le}from"./chevron-left-B7Etn49H.js";import{C as je}from"./check-CHZWFNwB.js";import{D as Y}from"./dollar-sign-DPHUDpsN.js";import{U as Te}from"./user-CLepiTkS.js";import{D as Me}from"./database-CEj7r6Ao.js";import{L as Ue}from"./lock-BEhTudft.js";import{S as Re}from"./scroll-text-DibSs5wF.js";import{S as Ie}from"./shield-alert-CtW0_p0i.js";/**
|
|
2
2
|
* @license lucide-react v0.577.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{j as e}from"./index-
|
|
1
|
+
import{j as e}from"./index-cu9_aTCP.js";import{C as r}from"./clock-C-sLUpGG.js";import{C as a}from"./circle-alert-nPoVqFm8.js";import{C as l}from"./check-CHZWFNwB.js";const i={completed:"bg-[#1FC5A8]/10 text-[#1FC5A8]",running:"bg-[#553DE9]/10 text-[#553DE9]",failed:"bg-[#C45B5B]/10 text-[#C45B5B]",started:"bg-[#D4A03C]/10 text-[#D4A03C]",empty:"bg-[#F8F4F0] text-[#6B6960]",version:"bg-[#553DE9]/10 text-[#553DE9]"};function o({status:t}){switch(t){case"completed":return e.jsx(l,{size:12});case"running":return e.jsxs("span",{className:"relative flex h-2 w-2",children:[e.jsx("span",{className:"animate-ping motion-reduce:animate-none absolute inline-flex h-full w-full rounded-full bg-current opacity-75"}),e.jsx("span",{className:"relative inline-flex rounded-full h-2 w-2 bg-current"})]});case"failed":return e.jsx(a,{size:12});case"started":return e.jsx(r,{size:12});default:return null}}function f({status:t,children:n,className:s=""}){return e.jsxs("span",{className:["inline-flex items-center gap-1 rounded-btn px-2.5 py-0.5 text-xs font-semibold",i[t],s].filter(Boolean).join(" "),children:[e.jsx(o,{status:t}),n]})}export{f as B};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as p,j as t}from"./index-
|
|
1
|
+
import{r as p,j as t}from"./index-cu9_aTCP.js";const m={primary:"bg-[#553DE9] text-white hover:bg-[#4432c4] shadow-button rounded-btn",secondary:"border border-[#553DE9] text-[#553DE9] hover:bg-[#E8E4FD] bg-transparent rounded-btn",ghost:"text-[#36342E] hover:bg-[#F8F4F0] rounded-btn",danger:"bg-[#C45B5B]/10 text-[#C45B5B] border border-[#C45B5B]/20 hover:bg-[#C45B5B]/20 rounded-btn"},b={sm:"px-3 py-1.5 text-xs",md:"px-4 py-2 text-sm",lg:"px-6 py-3 text-base"},u={sm:14,md:16,lg:18};function h({size:e}){return t.jsxs("svg",{className:"animate-spin",width:e,height:e,viewBox:"0 0 24 24",fill:"none",children:[t.jsx("circle",{className:"opacity-25",cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"4"}),t.jsx("path",{className:"opacity-75",fill:"currentColor",d:"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"})]})}const B=p.forwardRef(({variant:e="primary",size:o="md",icon:n,iconRight:i,loading:r=!1,disabled:a,className:c="",children:l,...x},d)=>{const s=u[o];return t.jsxs("button",{ref:d,disabled:a||r,className:["inline-flex items-center justify-center gap-2 font-medium transition-colors",m[e],b[o],(a||r)&&"opacity-60 cursor-not-allowed",c].filter(Boolean).join(" "),...x,children:[r?t.jsx(h,{size:s}):n?t.jsx(n,{size:s}):null,l,i&&!r&&t.jsx(i,{size:s})]})});B.displayName="Button";export{B};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{c as $,r as l,j as e,G as we,Q as Se,F as Ce,h as Re,T as U,Z as Ee,a as S,V as Me,S as $e,Y as Te,X as Pe,P as ie,i as Ae,g as ze,C as Ie,l as Le,N as I,J as _e,K as De,O as Fe,u as Oe}from"./index-
|
|
1
|
+
import{c as $,r as l,j as e,G as we,Q as Se,F as Ce,h as Re,T as U,Z as Ee,a as S,V as Me,S as $e,Y as Te,X as Pe,P as ie,i as Ae,g as ze,C as Ie,l as Le,N as I,J as _e,K as De,O as Fe,u as Oe}from"./index-cu9_aTCP.js";import{P as K,S as He,E as Be}from"./ErrorBoundary-Tw_oy-Da.js";import{C as qe,F as Ge,M as Ue,H as Ke,a as We,G as Ve,T as Qe}from"./thumbs-up-BMp9hCP5.js";import{C as oe}from"./check-CHZWFNwB.js";import{C as Ye}from"./clock-C-sLUpGG.js";import{D as Xe}from"./dollar-sign-DPHUDpsN.js";import{U as Ze}from"./upload-86CGmwiu.js";import{L as V}from"./loader-circle-CUROrUhG.js";/**
|
|
2
2
|
* @license lucide-react v0.577.0 - ISC
|
|
3
3
|
*
|
|
4
4
|
* This source code is licensed under the ISC license.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{r as o,j as e}from"./index-BBV2psih.js";function f({value:r,prefix:t="",suffix:s=""}){const[u,n]=o.useState(0),c=o.useRef(0);return o.useEffect(()=>{const a=c.current,h=r-a;if(h===0)return;const i=600,d=performance.now();function l(b){const v=b-d,m=Math.min(v/i,1),N=1-Math.pow(1-m,3),p=Math.round(a+h*N);n(p),c.current=p,m<1&&requestAnimationFrame(l)}requestAnimationFrame(l)},[r]),e.jsxs("span",{className:"tabular-nums",children:[t,u.toLocaleString(),s]})}function g(){const[r,t]=o.useState(5),[s,u]=o.useState(30),[n,c]=o.useState(75),a=.4,i=Math.round(r*s*a*4.33),d=Math.round(i*n);return e.jsxs("div",{className:"bg-white border border-[#ECEAE3] rounded-xl p-6 shadow-sm",children:[e.jsx("h3",{className:"text-lg font-bold text-[#36342E] mb-1",children:"ROI Calculator"}),e.jsx("p",{className:"text-sm text-[#6B6960] mb-6",children:"Estimate how much your team could save with autonomous development."}),e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("label",{className:"text-sm font-medium text-[#36342E]",children:"Team size"}),e.jsxs("span",{className:"text-sm font-semibold text-[#553DE9] tabular-nums",children:[r," developers"]})]}),e.jsx("input",{type:"range",min:1,max:50,value:r,onChange:l=>t(Number(l.target.value)),className:"w-full h-2 bg-[#ECEAE3] rounded-full appearance-none cursor-pointer accent-[#553DE9]"}),e.jsxs("div",{className:"flex justify-between text-xs text-[#939084] mt-1",children:[e.jsx("span",{children:"1"}),e.jsx("span",{children:"50"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("label",{className:"text-sm font-medium text-[#36342E]",children:"Hours coding per week"}),e.jsxs("span",{className:"text-sm font-semibold text-[#553DE9] tabular-nums",children:[s,"h"]})]}),e.jsx("input",{type:"range",min:5,max:60,value:s,onChange:l=>u(Number(l.target.value)),className:"w-full h-2 bg-[#ECEAE3] rounded-full appearance-none cursor-pointer accent-[#553DE9]"}),e.jsxs("div",{className:"flex justify-between text-xs text-[#939084] mt-1",children:[e.jsx("span",{children:"5h"}),e.jsx("span",{children:"60h"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("label",{className:"text-sm font-medium text-[#36342E]",children:"Average hourly rate"}),e.jsxs("span",{className:"text-sm font-semibold text-[#553DE9] tabular-nums",children:["$",n,"/hr"]})]}),e.jsx("input",{type:"range",min:25,max:250,step:5,value:n,onChange:l=>c(Number(l.target.value)),className:"w-full h-2 bg-[#ECEAE3] rounded-full appearance-none cursor-pointer accent-[#553DE9]"}),e.jsxs("div",{className:"flex justify-between text-xs text-[#939084] mt-1",children:[e.jsx("span",{children:"$25"}),e.jsx("span",{children:"$250"})]})]})]}),e.jsxs("div",{className:"mt-6 pt-6 border-t border-[#ECEAE3]",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4 text-center",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-2xl font-bold text-[#553DE9]",children:e.jsx(f,{value:i,suffix:"h"})}),e.jsx("div",{className:"text-xs text-[#6B6960] mt-1",children:"Est. hours saved / month"})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-2xl font-bold text-[#1FC5A8]",children:e.jsx(f,{value:d,prefix:"$"})}),e.jsx("div",{className:"text-xs text-[#6B6960] mt-1",children:"Est. cost saved / month"})]})]}),e.jsxs("div",{className:"mt-4 p-3 rounded-lg bg-[#553DE9]/5 border border-[#553DE9]/10",children:[e.jsxs("p",{className:"text-sm text-[#36342E] text-center",children:["If Loki Mode saved ",Math.round(a*100),"% of coding time, your team could save"," ",e.jsxs("span",{className:"font-bold text-[#553DE9]",children:[i.toLocaleString()," hours"]})," ","and"," ",e.jsxs("span",{className:"font-bold text-[#1FC5A8]",children:["$",d.toLocaleString()]})," ","per month."]}),e.jsxs("p",{className:"mt-2 text-xs text-[#6B6960] text-center",children:["The ",Math.round(a*100),"% is an assumption, not a measurement. Model and API spend is not included."]})]})]})]})}const j=[{feature:"Claude (Opus/Sonnet/Haiku)",category:"AI Models",lokiMode:!0,boltNew:!1,replit:!1,lovable:!0},{feature:"GPT-4o / Codex",category:"AI Models",lokiMode:!0,boltNew:!0,replit:!0,lovable:!1},{feature:"5-provider auto-failover",category:"AI Models",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"8 automated quality gates",category:"Quality",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"Blind 3-reviewer code review",category:"Quality",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"Anti-sycophancy checks",category:"Quality",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"Automated test generation",category:"Quality",lokiMode:!0,boltNew:!1,replit:"Partial",lovable:!1},{feature:"Docker container generation",category:"Deployment",lokiMode:!0,boltNew:!1,replit:!0,lovable:!1},{feature:"CI/CD pipeline generation",category:"Deployment",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"One-click cloud deploy",category:"Deployment",lokiMode:"Planned",boltNew:!0,replit:!0,lovable:!0},{feature:"Self-hosted (your keys)",category:"Cost",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"Free tier available",category:"Cost",lokiMode:"Source-available (BUSL-1.1)",boltNew:!0,replit:!0,lovable:!0},{feature:"No vendor lock-in",category:"Cost",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"SSO / OIDC authentication",category:"Enterprise",lokiMode:!0,boltNew:!1,replit:!0,lovable:!1},{feature:"RBAC access control",category:"Enterprise",lokiMode:!0,boltNew:!1,replit:!0,lovable:!1},{feature:"Audit logging",category:"Enterprise",lokiMode:!0,boltNew:!1,replit:!0,lovable:!1},{feature:"Air-gapped deployment",category:"Enterprise",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1}];function y(){return e.jsx("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",className:"text-[#1FC5A8]",children:e.jsx("path",{d:"M20 6L9 17l-5-5",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function w(){return e.jsx("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",className:"text-[#C45B5B]/40",children:e.jsx("path",{d:"M18 6L6 18M6 6l12 12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}function x({value:r}){return typeof r=="string"?e.jsx("span",{className:"text-xs text-[#6B6960] font-medium",children:r}):r?e.jsx(y,{}):e.jsx(w,{})}const k=[{title:"Full Autonomy",description:"Describe what you want. Loki Mode handles planning, coding, testing, and verification automatically.",icon:e.jsx("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",className:"text-[#553DE9]",children:e.jsx("path",{d:"M13 2L3 14h9l-1 8 10-12h-9l1-8z",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})},{title:"Production Quality",description:"8 quality gates, blind code review, and anti-sycophancy checks ensure code that actually works.",icon:e.jsx("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",className:"text-[#1FC5A8]",children:e.jsx("path",{d:"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})},{title:"Your Infrastructure",description:"Self-hosted, source-available (BUSL-1.1), no data leaves your network. Use your own API keys across 5 providers.",icon:e.jsxs("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",className:"text-[#2F71E3]",children:[e.jsx("rect",{x:"2",y:"2",width:"20",height:"8",rx:"2",stroke:"currentColor",strokeWidth:"2"}),e.jsx("rect",{x:"2",y:"14",width:"20",height:"8",rx:"2",stroke:"currentColor",strokeWidth:"2"}),e.jsx("circle",{cx:"6",cy:"6",r:"1",fill:"currentColor"}),e.jsx("circle",{cx:"6",cy:"18",r:"1",fill:"currentColor"})]})},{title:"Built for Teams",description:"Enterprise auth, RBAC, audit logs, and parallel workflows for teams of any size.",icon:e.jsxs("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",className:"text-[#E93D82]",children:[e.jsx("path",{d:"M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"}),e.jsx("circle",{cx:"9",cy:"7",r:"4",stroke:"currentColor",strokeWidth:"2"}),e.jsx("path",{d:"M23 21v-2a4 4 0 00-3-3.87M16 3.13a4 4 0 010 7.75",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})]})}];function C(){const r=[...new Set(j.map(t=>t.category))];return e.jsx("div",{className:"min-h-screen bg-[#FAF9F6]",children:e.jsxs("div",{className:"max-w-6xl mx-auto px-6 py-8",children:[e.jsxs("div",{className:"mb-8",children:[e.jsx("h1",{className:"text-2xl font-bold text-[#36342E]",children:"Compare"}),e.jsx("p",{className:"text-[#6B6960] mt-1",children:"See how Loki Mode stacks up against other AI development platforms."})]}),e.jsx("div",{className:"bg-white border border-[#ECEAE3] rounded-xl overflow-hidden shadow-sm",children:e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-[#ECEAE3]",children:[e.jsx("th",{className:"text-left px-4 py-3 font-medium text-[#6B6960] w-[240px]",children:"Feature"}),e.jsx("th",{className:"text-center px-4 py-3 font-bold text-[#553DE9] bg-[#553DE9]/5 w-[130px]",children:"Loki Mode"}),e.jsx("th",{className:"text-center px-4 py-3 font-medium text-[#6B6960] w-[130px]",children:"bolt.new"}),e.jsx("th",{className:"text-center px-4 py-3 font-medium text-[#6B6960] w-[130px]",children:"Replit"}),e.jsx("th",{className:"text-center px-4 py-3 font-medium text-[#6B6960] w-[130px]",children:"Lovable"})]})}),e.jsx("tbody",{children:r.map(t=>e.jsxs(e.Fragment,{children:[e.jsx("tr",{className:"bg-[#FAF9F6]",children:e.jsx("td",{colSpan:5,className:"px-4 py-2 text-xs font-bold text-[#939084] uppercase tracking-wider",children:t})},`cat-${t}`),j.filter(s=>s.category===t).map(s=>e.jsxs("tr",{className:"border-b border-[#ECEAE3] last:border-b-0",children:[e.jsx("td",{className:"px-4 py-2.5 text-[#36342E]",children:s.feature}),e.jsx("td",{className:"px-4 py-2.5 text-center bg-[#553DE9]/5",children:e.jsx("div",{className:"flex justify-center",children:e.jsx(x,{value:s.lokiMode})})}),e.jsx("td",{className:"px-4 py-2.5 text-center",children:e.jsx("div",{className:"flex justify-center",children:e.jsx(x,{value:s.boltNew})})}),e.jsx("td",{className:"px-4 py-2.5 text-center",children:e.jsx("div",{className:"flex justify-center",children:e.jsx(x,{value:s.replit})})}),e.jsx("td",{className:"px-4 py-2.5 text-center",children:e.jsx("div",{className:"flex justify-center",children:e.jsx(x,{value:s.lovable})})})]},s.feature))]}))})]})})}),e.jsxs("div",{className:"mt-12",children:[e.jsx("h2",{className:"text-xl font-bold text-[#36342E] mb-6",children:"Why developers choose Loki Mode"}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-5",children:k.map(t=>e.jsxs("div",{className:"bg-white border border-[#ECEAE3] rounded-xl p-5 shadow-sm hover:shadow-md transition-shadow",children:[e.jsx("div",{className:"mb-3",children:t.icon}),e.jsx("h3",{className:"text-base font-bold text-[#36342E] mb-1",children:t.title}),e.jsx("p",{className:"text-sm text-[#6B6960]",children:t.description})]},t.title))})]}),e.jsx("div",{className:"mt-12 max-w-xl mx-auto",children:e.jsx(g,{})})]})})}export{C as default};
|
|
1
|
+
import{r as o,j as e}from"./index-cu9_aTCP.js";function f({value:r,prefix:t="",suffix:s=""}){const[u,n]=o.useState(0),c=o.useRef(0);return o.useEffect(()=>{const a=c.current,h=r-a;if(h===0)return;const i=600,d=performance.now();function l(b){const v=b-d,m=Math.min(v/i,1),N=1-Math.pow(1-m,3),p=Math.round(a+h*N);n(p),c.current=p,m<1&&requestAnimationFrame(l)}requestAnimationFrame(l)},[r]),e.jsxs("span",{className:"tabular-nums",children:[t,u.toLocaleString(),s]})}function g(){const[r,t]=o.useState(5),[s,u]=o.useState(30),[n,c]=o.useState(75),a=.4,i=Math.round(r*s*a*4.33),d=Math.round(i*n);return e.jsxs("div",{className:"bg-white border border-[#ECEAE3] rounded-xl p-6 shadow-sm",children:[e.jsx("h3",{className:"text-lg font-bold text-[#36342E] mb-1",children:"ROI Calculator"}),e.jsx("p",{className:"text-sm text-[#6B6960] mb-6",children:"Estimate how much your team could save with autonomous development."}),e.jsxs("div",{className:"space-y-5",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("label",{className:"text-sm font-medium text-[#36342E]",children:"Team size"}),e.jsxs("span",{className:"text-sm font-semibold text-[#553DE9] tabular-nums",children:[r," developers"]})]}),e.jsx("input",{type:"range",min:1,max:50,value:r,onChange:l=>t(Number(l.target.value)),className:"w-full h-2 bg-[#ECEAE3] rounded-full appearance-none cursor-pointer accent-[#553DE9]"}),e.jsxs("div",{className:"flex justify-between text-xs text-[#939084] mt-1",children:[e.jsx("span",{children:"1"}),e.jsx("span",{children:"50"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("label",{className:"text-sm font-medium text-[#36342E]",children:"Hours coding per week"}),e.jsxs("span",{className:"text-sm font-semibold text-[#553DE9] tabular-nums",children:[s,"h"]})]}),e.jsx("input",{type:"range",min:5,max:60,value:s,onChange:l=>u(Number(l.target.value)),className:"w-full h-2 bg-[#ECEAE3] rounded-full appearance-none cursor-pointer accent-[#553DE9]"}),e.jsxs("div",{className:"flex justify-between text-xs text-[#939084] mt-1",children:[e.jsx("span",{children:"5h"}),e.jsx("span",{children:"60h"})]})]}),e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsx("label",{className:"text-sm font-medium text-[#36342E]",children:"Average hourly rate"}),e.jsxs("span",{className:"text-sm font-semibold text-[#553DE9] tabular-nums",children:["$",n,"/hr"]})]}),e.jsx("input",{type:"range",min:25,max:250,step:5,value:n,onChange:l=>c(Number(l.target.value)),className:"w-full h-2 bg-[#ECEAE3] rounded-full appearance-none cursor-pointer accent-[#553DE9]"}),e.jsxs("div",{className:"flex justify-between text-xs text-[#939084] mt-1",children:[e.jsx("span",{children:"$25"}),e.jsx("span",{children:"$250"})]})]})]}),e.jsxs("div",{className:"mt-6 pt-6 border-t border-[#ECEAE3]",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-4 text-center",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-2xl font-bold text-[#553DE9]",children:e.jsx(f,{value:i,suffix:"h"})}),e.jsx("div",{className:"text-xs text-[#6B6960] mt-1",children:"Est. hours saved / month"})]}),e.jsxs("div",{children:[e.jsx("div",{className:"text-2xl font-bold text-[#1FC5A8]",children:e.jsx(f,{value:d,prefix:"$"})}),e.jsx("div",{className:"text-xs text-[#6B6960] mt-1",children:"Est. cost saved / month"})]})]}),e.jsxs("div",{className:"mt-4 p-3 rounded-lg bg-[#553DE9]/5 border border-[#553DE9]/10",children:[e.jsxs("p",{className:"text-sm text-[#36342E] text-center",children:["If Loki Mode saved ",Math.round(a*100),"% of coding time, your team could save"," ",e.jsxs("span",{className:"font-bold text-[#553DE9]",children:[i.toLocaleString()," hours"]})," ","and"," ",e.jsxs("span",{className:"font-bold text-[#1FC5A8]",children:["$",d.toLocaleString()]})," ","per month."]}),e.jsxs("p",{className:"mt-2 text-xs text-[#6B6960] text-center",children:["The ",Math.round(a*100),"% is an assumption, not a measurement. Model and API spend is not included."]})]})]})]})}const j=[{feature:"Claude (Opus/Sonnet/Haiku)",category:"AI Models",lokiMode:!0,boltNew:!1,replit:!1,lovable:!0},{feature:"GPT-4o / Codex",category:"AI Models",lokiMode:!0,boltNew:!0,replit:!0,lovable:!1},{feature:"5-provider auto-failover",category:"AI Models",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"8 automated quality gates",category:"Quality",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"Blind 3-reviewer code review",category:"Quality",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"Anti-sycophancy checks",category:"Quality",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"Automated test generation",category:"Quality",lokiMode:!0,boltNew:!1,replit:"Partial",lovable:!1},{feature:"Docker container generation",category:"Deployment",lokiMode:!0,boltNew:!1,replit:!0,lovable:!1},{feature:"CI/CD pipeline generation",category:"Deployment",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"One-click cloud deploy",category:"Deployment",lokiMode:"Planned",boltNew:!0,replit:!0,lovable:!0},{feature:"Self-hosted (your keys)",category:"Cost",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"Free tier available",category:"Cost",lokiMode:"Source-available (BUSL-1.1)",boltNew:!0,replit:!0,lovable:!0},{feature:"No vendor lock-in",category:"Cost",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1},{feature:"SSO / OIDC authentication",category:"Enterprise",lokiMode:!0,boltNew:!1,replit:!0,lovable:!1},{feature:"RBAC access control",category:"Enterprise",lokiMode:!0,boltNew:!1,replit:!0,lovable:!1},{feature:"Audit logging",category:"Enterprise",lokiMode:!0,boltNew:!1,replit:!0,lovable:!1},{feature:"Air-gapped deployment",category:"Enterprise",lokiMode:!0,boltNew:!1,replit:!1,lovable:!1}];function y(){return e.jsx("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",className:"text-[#1FC5A8]",children:e.jsx("path",{d:"M20 6L9 17l-5-5",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function w(){return e.jsx("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",className:"text-[#C45B5B]/40",children:e.jsx("path",{d:"M18 6L6 18M6 6l12 12",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})}function x({value:r}){return typeof r=="string"?e.jsx("span",{className:"text-xs text-[#6B6960] font-medium",children:r}):r?e.jsx(y,{}):e.jsx(w,{})}const k=[{title:"Full Autonomy",description:"Describe what you want. Loki Mode handles planning, coding, testing, and verification automatically.",icon:e.jsx("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",className:"text-[#553DE9]",children:e.jsx("path",{d:"M13 2L3 14h9l-1 8 10-12h-9l1-8z",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})},{title:"Production Quality",description:"8 quality gates, blind code review, and anti-sycophancy checks ensure code that actually works.",icon:e.jsx("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",className:"text-[#1FC5A8]",children:e.jsx("path",{d:"M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})})},{title:"Your Infrastructure",description:"Self-hosted, source-available (BUSL-1.1), no data leaves your network. Use your own API keys across 5 providers.",icon:e.jsxs("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",className:"text-[#2F71E3]",children:[e.jsx("rect",{x:"2",y:"2",width:"20",height:"8",rx:"2",stroke:"currentColor",strokeWidth:"2"}),e.jsx("rect",{x:"2",y:"14",width:"20",height:"8",rx:"2",stroke:"currentColor",strokeWidth:"2"}),e.jsx("circle",{cx:"6",cy:"6",r:"1",fill:"currentColor"}),e.jsx("circle",{cx:"6",cy:"18",r:"1",fill:"currentColor"})]})},{title:"Built for Teams",description:"Enterprise auth, RBAC, audit logs, and parallel workflows for teams of any size.",icon:e.jsxs("svg",{width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",className:"text-[#E93D82]",children:[e.jsx("path",{d:"M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"}),e.jsx("circle",{cx:"9",cy:"7",r:"4",stroke:"currentColor",strokeWidth:"2"}),e.jsx("path",{d:"M23 21v-2a4 4 0 00-3-3.87M16 3.13a4 4 0 010 7.75",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round"})]})}];function C(){const r=[...new Set(j.map(t=>t.category))];return e.jsx("div",{className:"min-h-screen bg-[#FAF9F6]",children:e.jsxs("div",{className:"max-w-6xl mx-auto px-6 py-8",children:[e.jsxs("div",{className:"mb-8",children:[e.jsx("h1",{className:"text-2xl font-bold text-[#36342E]",children:"Compare"}),e.jsx("p",{className:"text-[#6B6960] mt-1",children:"See how Loki Mode stacks up against other AI development platforms."})]}),e.jsx("div",{className:"bg-white border border-[#ECEAE3] rounded-xl overflow-hidden shadow-sm",children:e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-sm",children:[e.jsx("thead",{children:e.jsxs("tr",{className:"border-b border-[#ECEAE3]",children:[e.jsx("th",{className:"text-left px-4 py-3 font-medium text-[#6B6960] w-[240px]",children:"Feature"}),e.jsx("th",{className:"text-center px-4 py-3 font-bold text-[#553DE9] bg-[#553DE9]/5 w-[130px]",children:"Loki Mode"}),e.jsx("th",{className:"text-center px-4 py-3 font-medium text-[#6B6960] w-[130px]",children:"bolt.new"}),e.jsx("th",{className:"text-center px-4 py-3 font-medium text-[#6B6960] w-[130px]",children:"Replit"}),e.jsx("th",{className:"text-center px-4 py-3 font-medium text-[#6B6960] w-[130px]",children:"Lovable"})]})}),e.jsx("tbody",{children:r.map(t=>e.jsxs(e.Fragment,{children:[e.jsx("tr",{className:"bg-[#FAF9F6]",children:e.jsx("td",{colSpan:5,className:"px-4 py-2 text-xs font-bold text-[#939084] uppercase tracking-wider",children:t})},`cat-${t}`),j.filter(s=>s.category===t).map(s=>e.jsxs("tr",{className:"border-b border-[#ECEAE3] last:border-b-0",children:[e.jsx("td",{className:"px-4 py-2.5 text-[#36342E]",children:s.feature}),e.jsx("td",{className:"px-4 py-2.5 text-center bg-[#553DE9]/5",children:e.jsx("div",{className:"flex justify-center",children:e.jsx(x,{value:s.lokiMode})})}),e.jsx("td",{className:"px-4 py-2.5 text-center",children:e.jsx("div",{className:"flex justify-center",children:e.jsx(x,{value:s.boltNew})})}),e.jsx("td",{className:"px-4 py-2.5 text-center",children:e.jsx("div",{className:"flex justify-center",children:e.jsx(x,{value:s.replit})})}),e.jsx("td",{className:"px-4 py-2.5 text-center",children:e.jsx("div",{className:"flex justify-center",children:e.jsx(x,{value:s.lovable})})})]},s.feature))]}))})]})})}),e.jsxs("div",{className:"mt-12",children:[e.jsx("h2",{className:"text-xl font-bold text-[#36342E] mb-6",children:"Why developers choose Loki Mode"}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-5",children:k.map(t=>e.jsxs("div",{className:"bg-white border border-[#ECEAE3] rounded-xl p-5 shadow-sm hover:shadow-md transition-shadow",children:[e.jsx("div",{className:"mb-3",children:t.icon}),e.jsx("h3",{className:"text-base font-bold text-[#36342E] mb-1",children:t.title}),e.jsx("p",{className:"text-sm text-[#6B6960]",children:t.description})]},t.title))})]}),e.jsx("div",{className:"mt-12 max-w-xl mx-auto",children:e.jsx(g,{})})]})})}export{C as default};
|