loki-mode 9.49.3 → 9.49.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/loki-issue-to-pr.yml +1 -1
- package/README.md +2 -2
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/lib/proof-verify.py +4 -2
- package/dashboard/__init__.py +1 -1
- package/dashboard/server.py +21 -8
- package/docs/INSTALLATION.md +1 -1
- package/docs/P0-SWEEP-PLAN.md +1 -1
- package/docs/cursor-comparison.md +1 -1
- package/loki-ts/dist/loki.js +240 -240
- package/mcp/__init__.py +1 -1
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/skills/quality-gates.md +1 -1
- package/web-app/dist/assets/{AdminPage-BA6etdwL.js → AdminPage-y6_b2Xo4.js} +1 -1
- package/web-app/dist/assets/{Avatar-CAtbcD23.js → Avatar-BFPkXhIJ.js} +1 -1
- package/web-app/dist/assets/{Badge-sb_JbKl0.js → Badge-BF3mhT57.js} +1 -1
- package/web-app/dist/assets/{Button-BamXbIWa.js → Button-BDp9aJ9q.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-CUYizBtG.js → CockpitPage-5TKICCoA.js} +1 -1
- package/web-app/dist/assets/{ComparePage-BnmNTggM.js → ComparePage-BSuNsUHy.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-BjX4_KOW.js → ErrorBoundary-ut3wrUmu.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-Bq6pmNUw.js → EvidenceReceiptPanel-CcaBwEI-.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-DD8c6RVj.js → GitHubIssuesPanel-DJeYgzAa.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-4NawTXRl.js → GitHubPRsPanel-DurZgSaj.js} +1 -1
- package/web-app/dist/assets/{HomePage-DTREi8OE.js → HomePage-Bs451LAy.js} +1 -1
- package/web-app/dist/assets/{LoginPage-DavfeQxC.js → LoginPage-HeRGJeZy.js} +1 -1
- package/web-app/dist/assets/{MagicPage-BIbTFlwh.js → MagicPage-CUKrqsZs.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-Cn3UPKpU.js → MetricsPage-DvY1csgz.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-BVs_nuBv.js → NotFoundPage-BZDZ-B77.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-CLplvOHe.js → ProjectPage-CqHkEZkl.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-BBFzBBG_.js → ProjectsPage-CLvCK1Y8.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-WPsJ_K9r.js → SettingsPage-DP7OmdwP.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-ZaLaJl5J.js → ShowcasePage-BGS2jTGH.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-CCORP-uG.js → SystemSettingsPage-P_rlLh0x.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-B6IGT_K2.js → TeamsPage-DxtBDcBC.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-RrYYC3CM.js → TemplatesPage-5e-faH3W.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-CeTvKnkl.js → TerminalOutput-togzv9Zl.js} +1 -1
- package/web-app/dist/assets/{activity-CySdOdDP.js → activity-Dreyb_Kr.js} +1 -1
- package/web-app/dist/assets/{bell-BHdr5yat.js → bell-DWH0drES.js} +1 -1
- package/web-app/dist/assets/{bot-BaB4q_4m.js → bot-78MoCuDl.js} +1 -1
- package/web-app/dist/assets/{check-BAgbzVrK.js → check-ikfylPst.js} +1 -1
- package/web-app/dist/assets/{chevron-left-CrVUY29C.js → chevron-left-DXUqkd8J.js} +1 -1
- package/web-app/dist/assets/{circle-alert-YrWgH49w.js → circle-alert-Da74VO8P.js} +1 -1
- package/web-app/dist/assets/{clock-DN8LAN-0.js → clock-mlGCFq8l.js} +1 -1
- package/web-app/dist/assets/{cloud-D6C4b1KY.js → cloud-B_Y5ZrIO.js} +1 -1
- package/web-app/dist/assets/{code-xml-xBWyKfux.js → code-xml-Bbom7YWV.js} +1 -1
- package/web-app/dist/assets/{database-BYqcS6kn.js → database-CLcofiVp.js} +1 -1
- package/web-app/dist/assets/{dollar-sign--WOh4k_m.js → dollar-sign-C5mkjXIM.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-B0rLPjW1.js → file-code-corner-CVrkaOQP.js} +1 -1
- package/web-app/dist/assets/{file-plus-BNhUQ1TQ.js → file-plus-BV9240gX.js} +1 -1
- package/web-app/dist/assets/{folder-open-DliiOgFl.js → folder-open-D_6yV78G.js} +1 -1
- package/web-app/dist/assets/{globe-BV-hx0u_.js → globe-aZ0Zso4I.js} +1 -1
- package/web-app/dist/assets/{hammer-DhmP4GLw.js → hammer-EgOQNukG.js} +1 -1
- package/web-app/dist/assets/index-BSgmPwC0.css +1 -0
- package/web-app/dist/assets/{index-x0TESFYr.js → index-DvZ0Kk2x.js} +2 -2
- package/web-app/dist/assets/{layers-DXWDMSYj.js → layers-BOVKmepE.js} +1 -1
- package/web-app/dist/assets/{lightbulb-PBw6hhLS.js → lightbulb-DdASgqOG.js} +1 -1
- package/web-app/dist/assets/{loader-circle-B7KiGAVU.js → loader-circle-0K8yLgHl.js} +1 -1
- package/web-app/dist/assets/{lock-BUTRYdDQ.js → lock-XzlDMy8M.js} +1 -1
- package/web-app/dist/assets/{mail-DaLiNrPb.js → mail-COu670_W.js} +1 -1
- package/web-app/dist/assets/{minus-DB_hlGEk.js → minus-bQpUt9ff.js} +1 -1
- package/web-app/dist/assets/{package-CymmXoiQ.js → package-BtXTKusI.js} +1 -1
- package/web-app/dist/assets/{plus-Cp4AO4I2.js → plus-PxeiD8ju.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-ygYTmZTE.js → refresh-cw-CjqzYczt.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-Ba3QxM9K.js → rotate-ccw-CY0os4DH.js} +1 -1
- package/web-app/dist/assets/{save-DPm96BnR.js → save-v8qep5cY.js} +1 -1
- package/web-app/dist/assets/{server-BapOz_vf.js → server-pIIs9vNp.js} +1 -1
- package/web-app/dist/assets/{shield-alert-DYzfVqWS.js → shield-alert-CsDqKXwA.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-DxOTplej.js → thumbs-up-CAh3HVzH.js} +1 -1
- package/web-app/dist/assets/{trash-2-Br8dh_6B.js → trash-2-Dt6urTyY.js} +1 -1
- package/web-app/dist/assets/{trending-down-CxSP6MU3.js → trending-down-DrtBd_C9.js} +1 -1
- package/web-app/dist/assets/{trending-up-CXx0ywZb.js → trending-up-D-DbCHXm.js} +1 -1
- package/web-app/dist/assets/{upload-CpEO3qNc.js → upload-D4l6DCOt.js} +1 -1
- package/web-app/dist/assets/{usePolling-BuzXwjmC.js → usePolling-D0aoTX80.js} +1 -1
- package/web-app/dist/assets/{user-DUUYT47B.js → user-BQf_XJO_.js} +1 -1
- package/web-app/dist/index.html +2 -2
- package/web-app/dist/assets/index-D98GzaW8.css +0 -1
|
@@ -61,7 +61,7 @@ jobs:
|
|
|
61
61
|
# Pinned to a TAG, not @main. A moving ref would hand every user
|
|
62
62
|
# whatever main holds at the moment their issue is labeled, including a
|
|
63
63
|
# half-landed release. Bump this line deliberately.
|
|
64
|
-
uses: asklokesh/loki-mode/.github/actions/issue-to-pr@v9.49.
|
|
64
|
+
uses: asklokesh/loki-mode/.github/actions/issue-to-pr@v9.49.4
|
|
65
65
|
env:
|
|
66
66
|
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
|
67
67
|
with:
|
package/README.md
CHANGED
|
@@ -532,14 +532,14 @@ Required:
|
|
|
532
532
|
|
|
533
533
|
- An agent provider CLI: [Claude Code](https://docs.claude.com/en/docs/claude-code) (`claude`, Tier 1, recommended and E2E-verified - the provider Loki Mode is built for). Cline, Codex, Aider, and opencode are supported as experimental providers (wiring in place; not yet E2E-verified by us). Loki cannot run a build without one of these installed and authenticated.
|
|
534
534
|
- Python 3.10+ (`python3`) for the dashboard, memory system, and orchestration helpers.
|
|
535
|
+
- Node.js 18+ (`node`) for the npm install path and the bundled runtime.
|
|
536
|
+
- `jq` for the JSON that the shell flows and the quality gates parse.
|
|
535
537
|
- Git 2.x (`git`) for checkpoints and worktrees.
|
|
536
538
|
- `curl` for installation and network calls.
|
|
537
539
|
|
|
538
540
|
Recommended:
|
|
539
541
|
|
|
540
542
|
- Bun 1.3.0+ (`bun`) for the fast runtime (the recommended install path above installs it).
|
|
541
|
-
- Node.js 18+ and npm if you install via npm instead of Bun.
|
|
542
|
-
- `jq` for nicer JSON handling in shell flows.
|
|
543
543
|
- Docker if you want Loki's App Runner to run containerized projects, or to run Loki itself from the published image.
|
|
544
544
|
|
|
545
545
|
You also need credentials for whichever provider you use (for Claude Code, an authenticated `claude` login or `ANTHROPIC_API_KEY`). `loki doctor` flags a missing or unauthenticated provider as the first thing to fix.
|
package/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: loki-mode
|
|
|
3
3
|
description: Autonomous spec-driven build system with a built-in trust layer. It does not call work done until it is verified (RARV-C closure loop, 8 quality gates, completion council, verified-completion evidence gate). Triggers on "Loki Mode". Takes a spec (PRD, GitHub issue, OpenAPI doc, etc.) to deployed product with minimal human intervention. Provider-agnostic. Requires --dangerously-skip-permissions flag.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Loki Mode v9.49.
|
|
6
|
+
# Loki Mode v9.49.4
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
@@ -470,4 +470,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
|
|
|
470
470
|
|
|
471
471
|
---
|
|
472
472
|
|
|
473
|
-
**v9.49.
|
|
473
|
+
**v9.49.4 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
9.49.
|
|
1
|
+
9.49.4
|
|
@@ -324,7 +324,8 @@ def _compute_headline(facts, degraded):
|
|
|
324
324
|
or tests.get("status") == "failed"
|
|
325
325
|
or build.get("status") == "failed"
|
|
326
326
|
or any(g.get("status") == "failed"
|
|
327
|
-
for g in (facts.get("quality_gates") or [])
|
|
327
|
+
for g in (facts.get("quality_gates") or [])
|
|
328
|
+
if _is_exogenous(g))
|
|
328
329
|
or sec_high
|
|
329
330
|
or fn_failed
|
|
330
331
|
)
|
|
@@ -342,7 +343,8 @@ def _compute_headline(facts, degraded):
|
|
|
342
343
|
tests.get("status") == "verified"
|
|
343
344
|
or build.get("status") == "verified"
|
|
344
345
|
or any(g.get("status") == "passed"
|
|
345
|
-
for g in (facts.get("quality_gates") or [])
|
|
346
|
+
for g in (facts.get("quality_gates") or [])
|
|
347
|
+
if _is_exogenous(g))
|
|
346
348
|
)
|
|
347
349
|
if any_verified and degraded:
|
|
348
350
|
return "VERIFIED WITH GAPS"
|
package/dashboard/__init__.py
CHANGED
package/dashboard/server.py
CHANGED
|
@@ -261,16 +261,16 @@ def _real_client_host(request: Request):
|
|
|
261
261
|
client = getattr(request, "client", None)
|
|
262
262
|
host = getattr(client, "host", None) if client else None
|
|
263
263
|
if host is None:
|
|
264
|
-
return None
|
|
264
|
+
return None, False
|
|
265
265
|
if host in _trusted_proxies():
|
|
266
266
|
fwd = request.headers.get("x-forwarded-for", "")
|
|
267
267
|
first = fwd.split(",")[0].strip()
|
|
268
268
|
if first:
|
|
269
|
-
return first
|
|
270
|
-
return host
|
|
269
|
+
return first, True
|
|
270
|
+
return host, False
|
|
271
271
|
|
|
272
272
|
|
|
273
|
-
def _is_local_caller(host) -> bool:
|
|
273
|
+
def _is_local_caller(host, from_forwarded: bool = False) -> bool:
|
|
274
274
|
"""True only for a caller we can positively identify as non-routable.
|
|
275
275
|
|
|
276
276
|
A peer that is not an IP literal (ASGI test transports report
|
|
@@ -285,7 +285,18 @@ def _is_local_caller(host) -> bool:
|
|
|
285
285
|
try:
|
|
286
286
|
return ipaddress.ip_address(host).is_loopback
|
|
287
287
|
except ValueError:
|
|
288
|
-
|
|
288
|
+
# A DIRECT peer that is not an IP literal is genuinely local: ASGI test
|
|
289
|
+
# transports report "testclient" and UDS transports report names, and
|
|
290
|
+
# refusing those closes no hole while breaking 17 tests.
|
|
291
|
+
#
|
|
292
|
+
# A FORWARDED value is different in kind. It arrived inside a request
|
|
293
|
+
# header, so treating an unparseable one as local lets any caller behind
|
|
294
|
+
# a trusted proxy pass the local check by sending a non-IP token.
|
|
295
|
+
# Measured: with LOKI_TRUSTED_PROXIES set, "not-an-ip", "unknown" and
|
|
296
|
+
# "testclient" all returned local, while an empty value correctly did
|
|
297
|
+
# not. "unknown" is a literal some proxies emit when the client address
|
|
298
|
+
# is unavailable, so this is reachable without an attacker choosing it.
|
|
299
|
+
return not from_forwarded
|
|
289
300
|
|
|
290
301
|
|
|
291
302
|
def require_local_or_authenticated(request: Request) -> None:
|
|
@@ -316,13 +327,13 @@ def require_local_or_authenticated(request: Request) -> None:
|
|
|
316
327
|
"""
|
|
317
328
|
if auth.ENTERPRISE_AUTH_ENABLED or auth.OIDC_ENABLED:
|
|
318
329
|
return
|
|
319
|
-
host = _real_client_host(request)
|
|
330
|
+
host, host_from_forwarded = _real_client_host(request)
|
|
320
331
|
if host is None:
|
|
321
332
|
raise HTTPException(
|
|
322
333
|
status_code=403,
|
|
323
334
|
detail="control requires an identifiable client; enable "
|
|
324
335
|
"LOKI_ENTERPRISE_AUTH to allow remote access")
|
|
325
|
-
if _is_local_caller(host):
|
|
336
|
+
if _is_local_caller(host, host_from_forwarded):
|
|
326
337
|
return
|
|
327
338
|
raise HTTPException(
|
|
328
339
|
status_code=403,
|
|
@@ -1211,14 +1222,16 @@ class WebSocketBoundaryMiddleware:
|
|
|
1211
1222
|
if not (auth.ENTERPRISE_AUTH_ENABLED or auth.OIDC_ENABLED):
|
|
1212
1223
|
client = scope.get("client")
|
|
1213
1224
|
host = client[0] if client else None
|
|
1225
|
+
host_from_forwarded = False
|
|
1214
1226
|
if host in _trusted_proxies():
|
|
1215
1227
|
for raw_name, raw_value in scope.get("headers", []):
|
|
1216
1228
|
if raw_name == b"x-forwarded-for":
|
|
1217
1229
|
first = raw_value.decode("latin-1").split(",")[0].strip()
|
|
1218
1230
|
if first:
|
|
1219
1231
|
host = first
|
|
1232
|
+
host_from_forwarded = True
|
|
1220
1233
|
break
|
|
1221
|
-
if not _is_local_caller(host):
|
|
1234
|
+
if not _is_local_caller(host, host_from_forwarded):
|
|
1222
1235
|
# 1008 = policy violation. Closing with a code beats an
|
|
1223
1236
|
# accept-then-drop, which reads to a client as a flaky network.
|
|
1224
1237
|
await send({"type": "websocket.close", "code": 1008})
|
package/docs/INSTALLATION.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The flagship product of [Autonomi](https://www.autonomi.dev/). Loki Mode is a spec-driven autonomous builder with a built-in trust layer that takes any spec to a deployed product and verifies completion with evidence (quality gates plus a completion council), not just a "done" claim. Complete installation instructions for all platforms and use cases.
|
|
4
4
|
|
|
5
|
-
**Version:** v9.49.
|
|
5
|
+
**Version:** v9.49.4
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
package/docs/P0-SWEEP-PLAN.md
CHANGED
|
@@ -42,7 +42,7 @@ Honest count after this sweep: 8 gates.
|
|
|
42
42
|
| 5 | Mock Integrity Detector | enforce_mock_integrity -> tests/detect-mock-problems.sh | Yes (HIGH blocks) | LOKI_GATE_MOCK=false |
|
|
43
43
|
| 6 | Test Mutation Detector | enforce_mutation_integrity -> tests/detect-test-mutations.sh | Yes (HIGH blocks) | LOKI_GATE_MUTATION=false |
|
|
44
44
|
| 7 | Documentation Coverage | run_doc_quality_gate (run.sh:7388) | Yes | LOKI_GATE_DOC_COVERAGE=false |
|
|
45
|
-
| 8 | Magic Modules Debate | run_magic_debate_gate (run.sh:7495) | Yes (BLOCK sev) | LOKI_GATE_MAGIC_DEBATE=false |
|
|
45
|
+
| 8 | Magic Modules Debate | run_magic_debate_gate (run.sh:7495) | No, advisory by default. NOTE added 2026-09-13: this row said "Yes (BLOCK sev)" and that was never true on either route; bash enforces only with LOKI_GATE_MAGIC_DEBATE_BLOCKING=true and Bun self-skips unless LOKI_GATE_MAGIC_DEBATE="true". Line numbers in this document are as grep-verified in June 2026 and are left unchanged. | LOKI_GATE_MAGIC_DEBATE=false |
|
|
46
46
|
|
|
47
47
|
Conditional auditor (documented separately, NOT numbered): Backward-Compatibility
|
|
48
48
|
/ legacy-healing-auditor (healing mode only). Removed: Input/Output Guardrails.
|
|
@@ -76,7 +76,7 @@ velocity_quality_balance:
|
|
|
76
76
|
5. Mock Integrity Detector - HIGH blocks
|
|
77
77
|
6. Test Mutation Detector - HIGH blocks
|
|
78
78
|
7. Documentation Coverage
|
|
79
|
-
8. Magic Modules Debate -
|
|
79
|
+
8. Magic Modules Debate - advisory by default on both routes (bash needs LOKI_GATE_MAGIC_DEBATE_BLOCKING=true; Bun self-skips unless LOKI_GATE_MAGIC_DEBATE="true")
|
|
80
80
|
|
|
81
81
|
Conditional auditor (not numbered): backward-compatibility / legacy-healing-auditor (healing mode only).
|
|
82
82
|
|