loki-mode 7.5.9 → 7.5.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -5
- package/SKILL.md +28 -12
- package/VERSION +1 -1
- package/autonomy/run.sh +33 -3
- package/dashboard/__init__.py +1 -1
- package/dashboard/server.py +1 -1
- package/dashboard/static/index.html +9 -9
- package/docs/COMPARISON.md +6 -6
- package/docs/INSTALLATION.md +32 -22
- package/docs/cursor-comparison.md +6 -6
- package/events/emit.sh +76 -0
- package/loki-ts/dist/loki.js +2 -2
- package/loki-ts/package.json +2 -1
- package/mcp/__init__.py +1 -1
- package/memory/retrieval.py +52 -7
- package/memory/storage.py +9 -0
- package/package.json +5 -5
- package/skills/healing.md +12 -0
- package/skills/quality-gates.md +10 -0
- package/web-app/requirements.txt +3 -0
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
|
|
3
|
-
# Loki Mode
|
|
3
|
+
# Loki Mode aka Autonomi
|
|
4
4
|
|
|
5
5
|
### Build the future, faster.
|
|
6
6
|
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
21
|
-
> **How it works:**
|
|
21
|
+
> **How it works:** Drop a spec -- a PRD, GitHub issue, OpenAPI/JSON/YAML, or one-line brief. Loki Mode classifies complexity (`run.sh:detect_complexity()`), assembles an agent team from 41 specialized types across 8 swarms, and runs autonomous RARV cycles (Reason - Act - Reflect - Verify, see `run.sh:run_autonomous()`) with 11 quality gates (see `skills/quality-gates.md`). Code is not "done" until it passes automated verification. Output is a Git repo with source, tests, configs, and audit logs.
|
|
22
22
|
|
|
23
23
|
---
|
|
24
24
|
|
|
@@ -49,7 +49,9 @@ bun install -g loki-mode
|
|
|
49
49
|
loki doctor # verify environment
|
|
50
50
|
loki init my-app --template simple-todo-app
|
|
51
51
|
cd my-app
|
|
52
|
-
loki start prd.md # autonomous build
|
|
52
|
+
loki start prd.md # autonomous build from a Markdown PRD
|
|
53
|
+
loki start owner/repo#123 # ...or a GitHub issue
|
|
54
|
+
loki start ./openapi.yaml # ...or an OpenAPI/YAML spec
|
|
53
55
|
```
|
|
54
56
|
|
|
55
57
|
Or skip scaffolding and go straight to a quick task:
|
|
@@ -64,7 +66,7 @@ loki quick "build a landing page with a signup form"
|
|
|
64
66
|
|--------|---------|-------|
|
|
65
67
|
| **Bun (recommended)** | `bun install -g loki-mode` | Fastest. v8 will be Bun-only. |
|
|
66
68
|
| **Homebrew** | `brew tap asklokesh/tap && brew install loki-mode` | Auto-installs Bun as a dep |
|
|
67
|
-
| **Docker** | `docker pull asklokesh/loki-mode:7.5.
|
|
69
|
+
| **Docker** | `docker pull asklokesh/loki-mode:7.5.11 && docker run --rm asklokesh/loki-mode:7.5.11 start prd.md` | Bun pre-installed in image |
|
|
68
70
|
| **npm (compat)** | `npm install -g loki-mode` | Works without Bun (bash fallback). Migrate any time with `loki self-update --to bun`. |
|
|
69
71
|
|
|
70
72
|
**Upgrading:**
|
|
@@ -124,7 +126,7 @@ The next major release sunsets the Bash runtime entirely. There is no firm calen
|
|
|
124
126
|
| Method | Command |
|
|
125
127
|
|--------|---------|
|
|
126
128
|
| **Homebrew** | `brew tap asklokesh/tap && brew install loki-mode` |
|
|
127
|
-
| **Docker** | `docker pull asklokesh/loki-mode:7.5.
|
|
129
|
+
| **Docker** | `docker pull asklokesh/loki-mode:7.5.11` |
|
|
128
130
|
| **Inside Claude Code** | `claude --dangerously-skip-permissions` then type "Loki Mode" |
|
|
129
131
|
| **Git clone** | `git clone https://github.com/asklokesh/loki-mode.git` |
|
|
130
132
|
|
|
@@ -132,6 +134,29 @@ See the full [Installation Guide](docs/INSTALLATION.md).
|
|
|
132
134
|
|
|
133
135
|
</details>
|
|
134
136
|
|
|
137
|
+
<details>
|
|
138
|
+
<summary><strong>Supported spec formats</strong></summary>
|
|
139
|
+
|
|
140
|
+
A "spec" is whatever you hand `loki start`. Loki auto-detects the format and normalises it before the RARV loop. A Markdown PRD is one form of spec; the table below lists every input the v7.5.11 CLI accepts.
|
|
141
|
+
|
|
142
|
+
| Format | Example | Notes |
|
|
143
|
+
|--------|---------|-------|
|
|
144
|
+
| Markdown PRD | `loki start ./prd.md` | Canonical form. Headings become section anchors. |
|
|
145
|
+
| JSON spec | `loki start ./spec.json` | Free-form JSON; keys surfaced to agents. |
|
|
146
|
+
| YAML spec | `loki start ./openapi.yaml` | OpenAPI / AsyncAPI / plain YAML all accepted. |
|
|
147
|
+
| Plain text brief | `loki start ./brief.txt` | One-paragraph briefs work; complexity auto-detects to "simple". |
|
|
148
|
+
| GitHub issue URL | `loki start https://github.com/owner/repo/issues/42` | Title + body + labels become the spec. |
|
|
149
|
+
| GitHub shorthand | `loki start owner/repo#42` | Same as above, shorter. |
|
|
150
|
+
| Jira ticket key | `loki start PROJ-456` | Requires `JIRA_BASE_URL` + `JIRA_TOKEN` env vars. |
|
|
151
|
+
| GitLab / Azure DevOps URL | `loki start https://gitlab.com/group/proj/-/issues/7` | GitLab and Azure DevOps issue URLs both supported. |
|
|
152
|
+
| Bare issue number | `loki start #123` or `loki start 123` | Resolved against the current repo's `origin` remote. |
|
|
153
|
+
| OpenSpec change directory | `loki start --openspec ./openspec/change-001` | Reads OpenSpec change manifest + delta files. |
|
|
154
|
+
| Auto-detect (no input) | `loki start` | Picks up `./prd.md`, `./spec.{json,yaml,yml}`, or `./SPEC.md` from cwd. |
|
|
155
|
+
|
|
156
|
+
All formats land in the same RARV pipeline and pass the same 11 quality gates (`skills/quality-gates.md`).
|
|
157
|
+
|
|
158
|
+
</details>
|
|
159
|
+
|
|
135
160
|
---
|
|
136
161
|
|
|
137
162
|
## What You Can Build
|
package/SKILL.md
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: loki-mode
|
|
3
|
-
description: Multi-agent autonomous startup system. Triggers on "Loki Mode". Takes PRD to deployed product with minimal human intervention. Requires --dangerously-skip-permissions flag.
|
|
3
|
+
description: Multi-agent autonomous startup system. Triggers on "Loki Mode". Takes a spec (PRD, GitHub issue, OpenAPI doc, etc.) to deployed product with minimal human intervention. Requires --dangerously-skip-permissions flag.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Loki Mode v7.5.
|
|
6
|
+
# Loki Mode v7.5.11
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
10
|
+
**Spec in, product out.** A "spec" is whatever describes the work: a Markdown PRD, a GitHub issue, an OpenAPI doc, a Jira ticket -- a PRD is one form of spec.
|
|
11
|
+
|
|
10
12
|
**Multi-provider (stable since v5.0.0):** Claude/Codex/Gemini/Cline/Aider with abstract model tiers and degraded mode for non-Claude providers. See `skills/providers.md`. **Current track (v7.5.x):** Phase 1 RARV-C closure -- real provider judges, gate-failure flock, synthetic PRD e2e, status `--json`, dead code cleanup.
|
|
11
13
|
|
|
12
14
|
**Runtime migration in progress:** A bash-to-Bun migration is underway on the `feat/bun-migration` branch. The first phase (shipped in v7.3.0) routes a small set of read-only commands -- `version`, `status`, `stats`, `doctor`, `provider show/list`, `memory list/index` -- through a Bun runtime via `bin/loki`. Every other command remains on the Bash runtime (`autonomy/loki`). Rollback is available with `LOKI_LEGACY_BASH=1`. See `UPGRADING.md` and `docs/architecture/ADR-001-runtime-migration.md` for the full plan.
|
|
@@ -89,11 +91,11 @@ These rules guide autonomous operation. Test results and code quality always tak
|
|
|
89
91
|
|
|
90
92
|
## Model Selection
|
|
91
93
|
|
|
92
|
-
**Default since v5.3.0 (reaffirmed in v7.5.
|
|
94
|
+
**Default since v5.3.0 (reaffirmed in v7.5.11):** Haiku disabled for quality. Use `--allow-haiku` or `LOKI_ALLOW_HAIKU=true` to enable.
|
|
93
95
|
|
|
94
96
|
| Task Type | Tier | Claude (default) | Claude (--allow-haiku) | Codex (GPT-5.3) | Gemini |
|
|
95
97
|
|-----------|------|------------------|------------------------|------------------|--------|
|
|
96
|
-
|
|
|
98
|
+
| Spec analysis, architecture, system design | **planning** | opus | opus | effort=xhigh | thinking=high |
|
|
97
99
|
| Feature implementation, complex bugs | **development** | opus | sonnet | effort=high | thinking=medium |
|
|
98
100
|
| Code review (planned: 3 parallel reviewers) | **development** | opus | sonnet | effort=high | thinking=medium |
|
|
99
101
|
| Integration tests, E2E, deployment | **development** | opus | sonnet | effort=high | thinking=medium |
|
|
@@ -113,7 +115,7 @@ These rules guide autonomous operation. Test results and code quality always tak
|
|
|
113
115
|
|
|
114
116
|
```
|
|
115
117
|
BOOTSTRAP ──[project initialized]──> DISCOVERY
|
|
116
|
-
DISCOVERY ──[
|
|
118
|
+
DISCOVERY ──[spec analyzed, requirements clear]──> ARCHITECTURE
|
|
117
119
|
ARCHITECTURE ──[design approved, specs written]──> DEEPEN_PLAN (standard/complex only)
|
|
118
120
|
DEEPEN_PLAN ──[plan enhanced by 4 research agents]──> INFRASTRUCTURE
|
|
119
121
|
INFRASTRUCTURE ──[cloud/DB ready]──> DEVELOPMENT
|
|
@@ -187,20 +189,21 @@ This protocol governs **skill module** loading -- task-scoped instruction files
|
|
|
187
189
|
|
|
188
190
|
## Invocation
|
|
189
191
|
|
|
190
|
-
**Unified entry point (v6.84.0):** `loki start` auto-detects whether the input is a PRD file, an issue URL,
|
|
192
|
+
**Unified entry point (v6.84.0):** `loki start [SPEC|ISSUE-REF]` auto-detects whether the input is a PRD file, an issue URL, an issue number, or another spec format (e.g. OpenAPI). No need to pick between `loki start` and `loki run` -- the single command handles all cases.
|
|
191
193
|
|
|
192
194
|
```bash
|
|
193
195
|
# Standard mode (Claude - full features)
|
|
194
196
|
claude --dangerously-skip-permissions
|
|
195
|
-
# Then say: "Loki Mode" or "Loki Mode with
|
|
197
|
+
# Then say: "Loki Mode" or "Loki Mode with spec at path/to/spec" (PRD .md/.json, OpenAPI .yaml, etc.)
|
|
196
198
|
|
|
197
199
|
# Unified `loki start` -- one command, auto-detected mode
|
|
198
|
-
loki start # no arg: analyze current dir, auto-generate
|
|
199
|
-
loki start ./prd.md # PRD mode (.md/.json/.txt/.yaml)
|
|
200
|
+
loki start # no arg: analyze current dir, auto-generate spec
|
|
201
|
+
loki start ./prd.md # PRD mode (.md/.json/.txt/.yaml) -- a PRD is one form of spec
|
|
202
|
+
loki start ./openapi.yaml # SPEC mode (OpenAPI doc treated as the spec)
|
|
203
|
+
loki start owner/repo#123 # ISSUE mode (GitHub specific repo)
|
|
200
204
|
loki start https://github.com/o/r/issues/42 # ISSUE mode (GitHub URL)
|
|
201
205
|
loki start 123 # ISSUE mode (GitHub issue in current repo)
|
|
202
206
|
loki start PROJ-456 # ISSUE mode (Jira)
|
|
203
|
-
loki start owner/repo#789 # ISSUE mode (GitHub specific repo)
|
|
204
207
|
loki start --prd ./prd.md # Explicit PRD mode (overrides detection)
|
|
205
208
|
loki start --issue 123 # Explicit issue mode (overrides detection)
|
|
206
209
|
|
|
@@ -330,6 +333,19 @@ See `references/core-workflow.md` for the full RARV-C contract.
|
|
|
330
333
|
|
|
331
334
|
---
|
|
332
335
|
|
|
336
|
+
## Concurrency and Security Hardening (v7.5.7 - v7.5.11)
|
|
337
|
+
|
|
338
|
+
Three back-to-back patches closed cross-process and security gaps. No user-facing behavior change on the default flow; verify via the cited paths.
|
|
339
|
+
|
|
340
|
+
- **Cross-process file locks** on append-or-rewrite state, so parallel runs / dashboard / MCP do not corrupt shared files: gate counter (`autonomy/run.sh` gate-counter writes), task queues (`autonomy/run.sh` queue read-modify-write), checkpoint index (`autonomy/run.sh` checkpoint index updates), `events.jsonl` append (event emission paths in `events/emit.sh` and `autonomy/run.sh`), human intervention signal files (`autonomy/run.sh:check_human_intervention()` at line ~8059 / 7897 per state-machine doc).
|
|
341
|
+
- **MCP path validation** -- file/path arguments to `mcp/server.py` tools are normalized and rejected if they escape the project root (path-traversal fix from v7.5.8).
|
|
342
|
+
- **Dashboard auth** now required on `/api/memory/*`, `/api/learning/*`, and `/api/status` in `dashboard/server.py` (previously unauthenticated read paths).
|
|
343
|
+
- **Bash quoting hardening** across `autonomy/run.sh` and `autonomy/loki` -- variable expansions inside command substitution and `[ ]` tests quoted to prevent word-splitting on paths with spaces.
|
|
344
|
+
|
|
345
|
+
See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.11] for the per-fix list and reviewer sign-off.
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
333
349
|
## Implemented Features
|
|
334
350
|
|
|
335
351
|
| Feature | Added | Notes |
|
|
@@ -342,7 +358,7 @@ See `references/core-workflow.md` for the full RARV-C contract.
|
|
|
342
358
|
| Notification Triggers | v5.40.0 | `GET/PUT /api/notifications/triggers` |
|
|
343
359
|
| GitHub integration | v5.42.2 | Import, sync-back, PR creation, export. CLI: `loki github`, API: `/api/github/*` |
|
|
344
360
|
| Legacy System Healing | v6.67.0 | `loki heal <path>` -- friction-as-semantics, characterization tests |
|
|
345
|
-
| Unified `loki start` | v6.84.0 | Auto-detects PRD vs issue input |
|
|
361
|
+
| Unified `loki start` | v6.84.0 | Auto-detects spec (PRD, OpenAPI, etc.) vs issue input |
|
|
346
362
|
| Managed Agents (memory mirror) | v7.2.0 | Opt-in via `LOKI_MANAGED_AGENTS` -- see Managed Agents section |
|
|
347
363
|
| Bun runtime (Phase 1) | v7.3.0 | Read-only commands routed through `bin/loki`; `LOKI_LEGACY_BASH=1` to revert |
|
|
348
364
|
| Phase 1 RARV-C closure | v7.5.x | Findings injection, real judges, auto-learnings, handoff.md |
|
|
@@ -365,4 +381,4 @@ See `references/core-workflow.md` for the full RARV-C contract.
|
|
|
365
381
|
|
|
366
382
|
---
|
|
367
383
|
|
|
368
|
-
**v7.5.
|
|
384
|
+
**v7.5.11 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
7.5.
|
|
1
|
+
7.5.11
|
package/autonomy/run.sh
CHANGED
|
@@ -477,6 +477,18 @@ parse_yaml_with_yq() {
|
|
|
477
477
|
load_config_file
|
|
478
478
|
|
|
479
479
|
# Load JSON settings from loki config set (v6.0.0)
|
|
480
|
+
#
|
|
481
|
+
# SECURITY NOTE (v7.5.10, L12#2 audit): The eval below is intentional and safe.
|
|
482
|
+
# The Python script's output is constrained to a fixed template:
|
|
483
|
+
# [ -z "${VAR:-}" ] && export VAR=<value>
|
|
484
|
+
# where:
|
|
485
|
+
# - VAR is a hardcoded env var name from the `mapping` dict (NOT user-controlled).
|
|
486
|
+
# - <value> is produced by shlex.quote(), which emits POSIX-shell-safe single-
|
|
487
|
+
# quoted strings even for adversarial input (e.g. quotes, semicolons, $()).
|
|
488
|
+
# - Non-string values from settings.json are skipped (isinstance check).
|
|
489
|
+
# Therefore no user-controlled bytes can break out of the quoted value or alter
|
|
490
|
+
# the surrounding shell syntax. Do NOT remove the shlex.quote() call or relax
|
|
491
|
+
# the isinstance(val, str) guard without re-auditing this eval.
|
|
480
492
|
_load_json_settings() {
|
|
481
493
|
local settings_file="${TARGET_DIR:-.}/.loki/config/settings.json"
|
|
482
494
|
[ -f "$settings_file" ] || return 0
|
|
@@ -7100,13 +7112,31 @@ rollback_to_checkpoint() {
|
|
|
7100
7112
|
done
|
|
7101
7113
|
|
|
7102
7114
|
# Log the rollback (use python3 for safe JSON serialization)
|
|
7103
|
-
|
|
7115
|
+
# v7.5.10: route through safe_append_event_jsonl() so parallel-worktree
|
|
7116
|
+
# rollbacks cannot interleave partial JSONL lines (POSIX append is
|
|
7117
|
+
# only atomic for <PIPE_BUF and not all platforms honor it).
|
|
7118
|
+
local timestamp rb_event
|
|
7104
7119
|
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
7105
|
-
_RB_CPID="$checkpoint_id" _RB_SHA="$git_sha" _RB_TS="$timestamp" \
|
|
7120
|
+
rb_event=$(_RB_CPID="$checkpoint_id" _RB_SHA="$git_sha" _RB_TS="$timestamp" \
|
|
7106
7121
|
python3 -c "
|
|
7107
7122
|
import json,os
|
|
7108
7123
|
print(json.dumps({'event':'rollback','checkpoint':os.environ['_RB_CPID'],'git_sha':os.environ['_RB_SHA'],'timestamp':os.environ['_RB_TS']}))
|
|
7109
|
-
"
|
|
7124
|
+
" 2>/dev/null) || rb_event=""
|
|
7125
|
+
if [ -n "$rb_event" ]; then
|
|
7126
|
+
# Source the emit lib once per call to get safe_append_event_jsonl.
|
|
7127
|
+
# Lib-only mode skips the emit script's normal CLI execution.
|
|
7128
|
+
# shellcheck disable=SC1091
|
|
7129
|
+
if [ -z "${_LOKI_EMIT_LIB_LOADED:-}" ]; then
|
|
7130
|
+
LOKI_EMIT_LIB_ONLY=1 . "$(dirname "${BASH_SOURCE[0]}")/../events/emit.sh" 2>/dev/null \
|
|
7131
|
+
&& _LOKI_EMIT_LIB_LOADED=1
|
|
7132
|
+
fi
|
|
7133
|
+
if declare -f safe_append_event_jsonl >/dev/null 2>&1; then
|
|
7134
|
+
safe_append_event_jsonl ".loki/events.jsonl" "$rb_event" 2>/dev/null || true
|
|
7135
|
+
else
|
|
7136
|
+
# Last-resort fallback: bare append (preserves prior behavior).
|
|
7137
|
+
printf '%s\n' "$rb_event" >> ".loki/events.jsonl" 2>/dev/null || true
|
|
7138
|
+
fi
|
|
7139
|
+
fi
|
|
7110
7140
|
|
|
7111
7141
|
log_info "State files restored from checkpoint: ${checkpoint_id}"
|
|
7112
7142
|
|
package/dashboard/__init__.py
CHANGED
package/dashboard/server.py
CHANGED
|
@@ -740,7 +740,7 @@ async def agent_card() -> dict:
|
|
|
740
740
|
|
|
741
741
|
|
|
742
742
|
# Status endpoint - reads from .loki/ flat files (primary) + DB (fallback)
|
|
743
|
-
@app.get("/api/status", response_model=StatusResponse)
|
|
743
|
+
@app.get("/api/status", response_model=StatusResponse, dependencies=[Depends(auth.require_scope("read"))])
|
|
744
744
|
async def get_status() -> StatusResponse:
|
|
745
745
|
"""Get system status from .loki/ session files."""
|
|
746
746
|
loki_dir = _get_loki_dir()
|
|
@@ -527,7 +527,7 @@
|
|
|
527
527
|
</button>
|
|
528
528
|
<button class="nav-link" data-section="prd-checklist" id="nav-prd-checklist">
|
|
529
529
|
<svg viewBox="0 0 24 24"><path d="M9 11l3 3L22 4"/><path d="M21 12v7a2 2 0 01-2 2H5a2 2 0 01-2-2V5a2 2 0 012-2h11"/></svg>
|
|
530
|
-
|
|
530
|
+
Spec Checklist
|
|
531
531
|
</button>
|
|
532
532
|
<button class="nav-link" data-section="app-runner" id="nav-app-runner">
|
|
533
533
|
<svg viewBox="0 0 24 24"><polygon points="5 3 19 12 5 21 5 3"/></svg>
|
|
@@ -618,10 +618,10 @@
|
|
|
618
618
|
</div>
|
|
619
619
|
</div>
|
|
620
620
|
|
|
621
|
-
<!--
|
|
621
|
+
<!-- Spec Checklist -->
|
|
622
622
|
<div class="section-page" id="page-prd-checklist">
|
|
623
623
|
<div class="section-page-header">
|
|
624
|
-
<h2 class="section-page-title">
|
|
624
|
+
<h2 class="section-page-title">Spec Checklist</h2>
|
|
625
625
|
</div>
|
|
626
626
|
<loki-checklist-viewer id="checklist-viewer"></loki-checklist-viewer>
|
|
627
627
|
</div>
|
|
@@ -715,7 +715,7 @@
|
|
|
715
715
|
<div class="shortcuts-group-title">Navigation</div>
|
|
716
716
|
<div class="shortcut-row"><span class="shortcut-desc">Overview</span><span class="shortcut-keys"><kbd class="shortcut-key">1</kbd></span></div>
|
|
717
717
|
<div class="shortcut-row"><span class="shortcut-desc">Insights</span><span class="shortcut-keys"><kbd class="shortcut-key">2</kbd></span></div>
|
|
718
|
-
<div class="shortcut-row"><span class="shortcut-desc">
|
|
718
|
+
<div class="shortcut-row"><span class="shortcut-desc">Spec Checklist</span><span class="shortcut-keys"><kbd class="shortcut-key">3</kbd></span></div>
|
|
719
719
|
<div class="shortcut-row"><span class="shortcut-desc">App Runner</span><span class="shortcut-keys"><kbd class="shortcut-key">4</kbd></span></div>
|
|
720
720
|
<div class="shortcut-row"><span class="shortcut-desc">Council</span><span class="shortcut-keys"><kbd class="shortcut-key">5</kbd></span></div>
|
|
721
721
|
<div class="shortcut-row"><span class="shortcut-desc">Quality</span><span class="shortcut-keys"><kbd class="shortcut-key">6</kbd></span></div>
|
|
@@ -1267,12 +1267,12 @@ var LokiDashboard=(()=>{var xt=Object.defineProperty;var Qt=Object.getOwnPropert
|
|
|
1267
1267
|
</div>
|
|
1268
1268
|
`}_renderChecklistCard(){let t=this._checklistSummary;if(!t||!t.total)return`
|
|
1269
1269
|
<div class="overview-card">
|
|
1270
|
-
<div class="card-label">
|
|
1271
|
-
<div class="card-value small-text">${this._data.status==="running"||this._data.status==="autonomous"?"Analyzing
|
|
1270
|
+
<div class="card-label">Spec Progress</div>
|
|
1271
|
+
<div class="card-value small-text">${this._data.status==="running"||this._data.status==="autonomous"?"Analyzing spec...":"No checklist"}</div>
|
|
1272
1272
|
</div>
|
|
1273
1273
|
`;let e=Math.round(t.verified/t.total*100),i=t.failing>0?"var(--loki-yellow, #f59e0b)":"var(--loki-green, #22c55e)";return`
|
|
1274
1274
|
<div class="overview-card">
|
|
1275
|
-
<div class="card-label">
|
|
1275
|
+
<div class="card-label">Spec Progress</div>
|
|
1276
1276
|
<div class="card-value small-text">${t.verified}/${t.total} (${e}%)</div>
|
|
1277
1277
|
<div class="mini-progress" style="margin-top:4px;height:4px;background:var(--loki-bg-secondary,#e4e4e7);border-radius:2px;overflow:hidden;">
|
|
1278
1278
|
<div style="width:${e}%;height:100%;background:${i};transition:width 0.3s;"></div>
|
|
@@ -5572,7 +5572,7 @@ var LokiDashboard=(()=>{var xt=Object.defineProperty;var Qt=Object.getOwnPropert
|
|
|
5572
5572
|
<style>${this.getBaseStyles()}${this._getStyles()}</style>
|
|
5573
5573
|
<div class="checklist-viewer">
|
|
5574
5574
|
<div class="checklist-header">
|
|
5575
|
-
<h2 class="title">
|
|
5575
|
+
<h2 class="title">Spec Checklist</h2>
|
|
5576
5576
|
${i?this._renderBadges(e.summary):""}
|
|
5577
5577
|
</div>
|
|
5578
5578
|
${i?this._renderGateBanner():""}
|
|
@@ -5623,7 +5623,7 @@ var LokiDashboard=(()=>{var xt=Object.defineProperty;var Qt=Object.getOwnPropert
|
|
|
5623
5623
|
`}).join(""):'<div class="item" style="color:var(--loki-text-muted)">No items</div>'}_renderEmpty(){return`
|
|
5624
5624
|
<div class="empty-state">
|
|
5625
5625
|
<p><strong>No checklist data yet.</strong></p>
|
|
5626
|
-
<p class="hint">The
|
|
5626
|
+
<p class="hint">The spec checklist is generated during the first iteration. Start a session with <code>loki start ./spec.md</code> (PRD files also accepted) -- groups and items will appear here as the session progresses and can be expanded for details.</p>
|
|
5627
5627
|
</div>
|
|
5628
5628
|
`}_attachEventListeners(){let t=this.shadowRoot;t&&(t.querySelectorAll(".category-header[data-category]").forEach(e=>{e.addEventListener("click",()=>this._toggleCategory(e.dataset.category))}),t.querySelectorAll("button[data-waive-id]").forEach(e=>{e.addEventListener("click",i=>{i.stopPropagation(),this._waiveItem(e.dataset.waiveId)})}),t.querySelectorAll("button[data-unwaive-id]").forEach(e=>{e.addEventListener("click",i=>{i.stopPropagation(),this._unwaiveItem(e.dataset.unwaiveId)})}))}_escapeHtml(t){return t?String(t).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,"""):""}};customElements.define("loki-checklist-viewer",Y);var Nt={not_initialized:{color:"var(--loki-text-muted, #71717a)",label:"Not Started",pulse:!1},starting:{color:"var(--loki-yellow, #ca8a04)",label:"Starting...",pulse:!0},running:{color:"var(--loki-green, #16a34a)",label:"Running",pulse:!0},stale:{color:"var(--loki-yellow, #ca8a04)",label:"Stale",pulse:!1},completed:{color:"var(--loki-text-muted, #a1a1aa)",label:"Completed",pulse:!1},failed:{color:"var(--loki-red, #dc2626)",label:"Failed",pulse:!1},crashed:{color:"var(--loki-red, #dc2626)",label:"Crashed",pulse:!1},stopped:{color:"var(--loki-text-muted, #a1a1aa)",label:"Stopped",pulse:!1},unknown:{color:"var(--loki-text-muted, #71717a)",label:"Unknown",pulse:!1}},W=class extends u{static get observedAttributes(){return["api-url","theme"]}constructor(){super(),this._loading=!1,this._error=null,this._api=null,this._pollInterval=null,this._status=null,this._logs=[],this._lastDataHash=null,this._lastLogsHash=null}connectedCallback(){super.connectedCallback(),this._setupApi(),this._loadData(),this._startPolling()}disconnectedCallback(){super.disconnectedCallback(),this._stopPolling()}attributeChangedCallback(t,e,i){e!==i&&(t==="api-url"&&this._api&&(this._api.baseUrl=i,this._loadData()),t==="theme"&&this._applyTheme())}_setupApi(){let t=this.getAttribute("api-url")||window.location.origin;this._api=g({baseUrl:t})}_startPolling(){this._pollInterval=setInterval(()=>this._loadData(),3e3),this._visibilityHandler=()=>{document.hidden?this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null):this._pollInterval||(this._loadData(),this._pollInterval=setInterval(()=>this._loadData(),3e3))},document.addEventListener("visibilitychange",this._visibilityHandler)}_stopPolling(){this._pollInterval&&(clearInterval(this._pollInterval),this._pollInterval=null),this._visibilityHandler&&(document.removeEventListener("visibilitychange",this._visibilityHandler),this._visibilityHandler=null)}async _loadData(){try{let[t,e]=await Promise.all([this._api.getAppRunnerStatus(),this._api.getAppRunnerLogs()]),i=JSON.stringify({status:t?.status,port:t?.port,restarts:t?.restart_count,url:t?.url}),a=JSON.stringify(e?.lines?.slice(-5)||[]),s=a!==this._lastLogsHash;if(i===this._lastDataHash&&!s)return;this._lastDataHash=i,this._lastLogsHash=a,this._status=t,this._logs=e?.lines||[],this._error=null,this.render(),this._scrollLogsToBottom()}catch(t){this._error||(this._error=`Failed to load app status: ${t.message}`,this.render())}}_scrollLogsToBottom(){let t=this.shadowRoot;if(!t)return;let e=t.querySelector(".log-area");e&&(e.scrollTop=e.scrollHeight)}async _handleRestart(){try{await this._api.restartApp(),this._loadData()}catch(t){this._error=`Restart failed: ${t.message}`,this.render()}}async _handleStop(){try{await this._api.stopApp(),this._loadData()}catch(t){this._error=`Stop failed: ${t.message}`,this.render()}}_formatUptime(t){if(!t)return"--";let e=new Date(t),a=Math.floor((new Date-e)/1e3);if(a<60)return`${a}s`;if(a<3600)return`${Math.floor(a/60)}m ${a%60}s`;let s=Math.floor(a/3600),r=Math.floor(a%3600/60);return`${s}h ${r}m`}_isValidUrl(t){if(!t)return!1;try{let e=new URL(t);return e.protocol==="http:"||e.protocol==="https:"}catch{return!1}}_getStyles(){return`
|
|
5629
5629
|
.app-status {
|
package/docs/COMPARISON.md
CHANGED
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
|---------|--------------|-----------|-----------|------------|----------|-----------------|--------------|--------------|
|
|
38
38
|
| **Code Review** | 3 blind reviewers + devil's advocate | Basic | Basic | BugBot PR | Property-based | Artifacts | Doc/Review | Basic |
|
|
39
39
|
| **Anti-Sycophancy** | Yes (CONSENSAGENT) | No | No | No | No | No | No | No |
|
|
40
|
-
| **Quality Gates** |
|
|
40
|
+
| **Quality Gates** | 11 gates + PBT | Basic | Sandbox | Tests | Spec validation | Artifact checks | Tests | Permissions |
|
|
41
41
|
| **Constitutional AI** | Yes (principles) | No | Refusal training | No | No | No | No | No |
|
|
42
42
|
|
|
43
43
|
---
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
| Feature | **Loki Mode** | **Devin** | **Codex** | **Cursor** | **Kiro** | **Antigravity** | **Amazon Q** | **OpenCode** |
|
|
48
48
|
|---------|--------------|-----------|-----------|------------|----------|-----------------|--------------|--------------|
|
|
49
49
|
| **Spec-First** | OpenAPI-first | Natural lang | Natural lang | Natural lang | requirements.md, design.md, tasks.md | Natural lang | Natural lang | AGENTS.md |
|
|
50
|
-
| **PRD
|
|
50
|
+
| **Spec Support (PRD / issue / YAML)** | Native parsing across all three | Ticket-based | Issue-based | No | Native specs | No | Issue-based | No |
|
|
51
51
|
| **Design Docs** | Auto-generates | No | No | No | Yes (design.md) | Artifacts | Yes | No |
|
|
52
52
|
|
|
53
53
|
---
|
|
@@ -207,7 +207,7 @@
|
|
|
207
207
|
| **Skills** | Progressive disclosure | 6 slash commands | N/A | 129 skills | N/A | 35 skills | Memory focus |
|
|
208
208
|
| **Multi-Provider** | Yes (Claude/Codex/Gemini) | 3 CLIs (separate) | No | No | No | No | No |
|
|
209
209
|
| **Memory System** | 3-tier (episodic/semantic/procedural) | None | N/A | N/A | Hybrid | N/A | SQLite+FTS5 |
|
|
210
|
-
| **Quality Gates** |
|
|
210
|
+
| **Quality Gates** | 11 gates + Completion Council | User verify only | Two-Stage Review | N/A | Consensus | Tiered | N/A |
|
|
211
211
|
| **Context Mgmt** | Standard | Fresh per task (core innovation) | Fresh per task | N/A | N/A | N/A | Progressive |
|
|
212
212
|
| **Autonomy** | High (minimal human) | Semi (checkpoints) | Human-guided | Human-guided | Orchestrated | Human-guided | N/A |
|
|
213
213
|
|
|
@@ -232,7 +232,7 @@ These are patterns from competing projects that are **practically and scientific
|
|
|
232
232
|
|----------|---------|-------------------------|
|
|
233
233
|
| **Multi-Provider Support** | Only skill supporting Claude, Codex, and Gemini with graceful degradation | All 8 competitors are Claude-only |
|
|
234
234
|
| **RARV Cycle** | Reason-Act-Reflect-Verify is more rigorous than Plan-Execute | Most use simple Plan-Execute |
|
|
235
|
-
| **
|
|
235
|
+
| **11-Gate Quality System** | Static analysis + 3 reviewers + devil's advocate + anti-sycophancy + severity blocking + coverage + debate + backward-compat (healing) + Phase 1 closure | Superpowers has 2-stage, others have less |
|
|
236
236
|
| **Constitutional AI Integration** | Principles-based self-critique from Anthropic research | None have this |
|
|
237
237
|
| **Anti-Sycophancy (CONSENSAGENT)** | Blind review + devil's advocate prevents groupthink | None have this |
|
|
238
238
|
| **Provider Abstraction Layer** | Clean degradation from full-featured to sequential-only | Claude-only projects can't degrade |
|
|
@@ -342,7 +342,7 @@ Tiered agent architecture with explicit escalation:
|
|
|
342
342
|
|
|
343
343
|
| Agent | Killer Feature |
|
|
344
344
|
|-------|---------------|
|
|
345
|
-
| **Loki Mode** | Minimal-human-intervention full SDLC, 41 agents in 8 swarms, Constitutional AI, anti-sycophancy, cross-project learning, code transformation, property-based testing |
|
|
345
|
+
| **Loki Mode** | Minimal-human-intervention full SDLC from any spec (PRD, GitHub issue, or YAML), 41 agents in 8 swarms, Constitutional AI, anti-sycophancy, cross-project learning, code transformation, property-based testing |
|
|
346
346
|
| **Devin** | Full software engineer persona, Slack integration, 67% PR merge rate |
|
|
347
347
|
| **OpenAI Codex** | Skills marketplace, $skill-creator, GPT-5.2-Codex, secure sandbox |
|
|
348
348
|
| **Cursor** | 8 parallel agents, BugBot, Memories, $10B valuation, Composer model (250 tok/s) |
|
|
@@ -359,7 +359,7 @@ Tiered agent architecture with explicit escalation:
|
|
|
359
359
|
|-----------|-------------------|
|
|
360
360
|
| **Autonomy** | Designed for high autonomy with minimal human intervention |
|
|
361
361
|
| **Multi-Agent** | 41 specialized agents in 8 swarms vs 1-8 in competitors |
|
|
362
|
-
| **Quality** |
|
|
362
|
+
| **Quality** | 11 gates + blind review + devil's advocate + property-based testing |
|
|
363
363
|
| **Research** | 10+ academic papers integrated vs proprietary/undisclosed |
|
|
364
364
|
| **Anti-Sycophancy** | Only agent with CONSENSAGENT-based blind review |
|
|
365
365
|
| **Memory** | 3-tier memory (episodic/semantic/procedural) + review learning + cross-project |
|
package/docs/INSTALLATION.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The flagship product of [Autonomi](https://www.autonomi.dev/). Complete installation instructions for all platforms and use cases.
|
|
4
4
|
|
|
5
|
-
**Version:** v7.5.
|
|
5
|
+
**Version:** v7.5.11
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -128,15 +128,25 @@ package, while `loki-mode-sdk` is the thin client.
|
|
|
128
128
|
|
|
129
129
|
## Quick Start
|
|
130
130
|
|
|
131
|
+
Drop a spec -- any artifact that describes what you want built -- and Loki
|
|
132
|
+
Mode takes it from spec to deployed app. Specs can be a markdown PRD, a
|
|
133
|
+
GitHub issue URL, or a YAML feature description.
|
|
134
|
+
|
|
131
135
|
```bash
|
|
132
|
-
# CLI mode (works with any provider)
|
|
133
|
-
loki start ./
|
|
134
|
-
loki start ./
|
|
135
|
-
loki start ./
|
|
136
|
+
# CLI mode (works with any provider) -- spec as markdown PRD
|
|
137
|
+
loki start ./spec.md
|
|
138
|
+
loki start ./spec.md --provider codex
|
|
139
|
+
loki start ./spec.md --provider gemini
|
|
140
|
+
|
|
141
|
+
# Spec as a GitHub issue
|
|
142
|
+
loki start --github-issue https://github.com/owner/repo/issues/42
|
|
143
|
+
|
|
144
|
+
# Spec as a YAML feature description
|
|
145
|
+
loki start ./feature.yaml
|
|
136
146
|
|
|
137
147
|
# Interactive mode (inside your coding agent)
|
|
138
148
|
claude --dangerously-skip-permissions
|
|
139
|
-
# Then say: "Loki Mode with
|
|
149
|
+
# Then say: "Loki Mode with spec at ./my-spec.md"
|
|
140
150
|
```
|
|
141
151
|
|
|
142
152
|
---
|
|
@@ -198,11 +208,11 @@ Run Loki Mode in an isolated Docker container for enhanced security.
|
|
|
198
208
|
### Usage
|
|
199
209
|
|
|
200
210
|
```bash
|
|
201
|
-
# Run in sandbox mode
|
|
202
|
-
./autonomy/sandbox.sh ./my-
|
|
211
|
+
# Run in sandbox mode (spec can be PRD, issue link, or YAML)
|
|
212
|
+
./autonomy/sandbox.sh ./my-spec.md
|
|
203
213
|
|
|
204
214
|
# With provider selection
|
|
205
|
-
./autonomy/sandbox.sh --provider codex ./my-
|
|
215
|
+
./autonomy/sandbox.sh --provider codex ./my-spec.md
|
|
206
216
|
```
|
|
207
217
|
|
|
208
218
|
### Security Controls
|
|
@@ -213,10 +223,10 @@ By default, prompt injection is **disabled** for enterprise safety:
|
|
|
213
223
|
|
|
214
224
|
```bash
|
|
215
225
|
# Default: prompt injection disabled
|
|
216
|
-
./autonomy/run.sh ./my-
|
|
226
|
+
./autonomy/run.sh ./my-spec.md
|
|
217
227
|
|
|
218
228
|
# Opt-in to enable prompt injection
|
|
219
|
-
LOKI_PROMPT_INJECTION_ENABLED=true ./autonomy/run.sh ./my-
|
|
229
|
+
LOKI_PROMPT_INJECTION_ENABLED=true ./autonomy/run.sh ./my-spec.md
|
|
220
230
|
```
|
|
221
231
|
|
|
222
232
|
#### Human Input Security
|
|
@@ -228,7 +238,7 @@ The `HUMAN_INPUT.md` file has security controls:
|
|
|
228
238
|
|
|
229
239
|
### When to Use Sandbox Mode
|
|
230
240
|
|
|
231
|
-
- Running untrusted PRD
|
|
241
|
+
- Running untrusted spec files (PRD, issue export, YAML)
|
|
232
242
|
- Enterprise environments with strict security requirements
|
|
233
243
|
- Automated CI/CD pipelines
|
|
234
244
|
- Multi-tenant deployments
|
|
@@ -272,13 +282,13 @@ Use the `--provider` flag when invoking Loki Mode:
|
|
|
272
282
|
|
|
273
283
|
```bash
|
|
274
284
|
# Use Claude (default)
|
|
275
|
-
loki start ./my-
|
|
285
|
+
loki start ./my-spec.md --provider claude
|
|
276
286
|
|
|
277
287
|
# Use OpenAI Codex
|
|
278
|
-
loki start ./my-
|
|
288
|
+
loki start ./my-spec.md --provider codex
|
|
279
289
|
|
|
280
290
|
# Use Google Gemini
|
|
281
|
-
loki start ./my-
|
|
291
|
+
loki start ./my-spec.md --provider gemini
|
|
282
292
|
```
|
|
283
293
|
|
|
284
294
|
#### Docker
|
|
@@ -289,12 +299,12 @@ Pass the provider as an environment variable:
|
|
|
289
299
|
# Use Codex with Docker
|
|
290
300
|
docker run -e LOKI_PROVIDER=codex \
|
|
291
301
|
-v $(pwd):/workspace -w /workspace \
|
|
292
|
-
asklokesh/loki-mode:latest start ./my-
|
|
302
|
+
asklokesh/loki-mode:latest start ./my-spec.md
|
|
293
303
|
|
|
294
304
|
# Use Gemini with Docker
|
|
295
305
|
docker run -e LOKI_PROVIDER=gemini \
|
|
296
306
|
-v $(pwd):/workspace -w /workspace \
|
|
297
|
-
asklokesh/loki-mode:latest start ./my-
|
|
307
|
+
asklokesh/loki-mode:latest start ./my-spec.md
|
|
298
308
|
```
|
|
299
309
|
|
|
300
310
|
### Degraded Mode
|
|
@@ -445,7 +455,7 @@ description: Multi-Agent Autonomous Startup System
|
|
|
445
455
|
|
|
446
456
|
1. Start a new conversation
|
|
447
457
|
2. Type: `Loki Mode`
|
|
448
|
-
3. Claude should recognize the skill and ask for a PRD
|
|
458
|
+
3. Claude should recognize the skill and ask for a spec (PRD, GitHub issue link, or YAML)
|
|
449
459
|
|
|
450
460
|
### For API Console
|
|
451
461
|
|
|
@@ -475,7 +485,7 @@ loki-mode/
|
|
|
475
485
|
├── autonomy/ # Autonomous runner (CLI only)
|
|
476
486
|
│ ├── run.sh
|
|
477
487
|
│ └── README.md
|
|
478
|
-
├── templates/ # 22
|
|
488
|
+
├── templates/ # 22 spec templates (PRD-style) for project scaffolding
|
|
479
489
|
│ ├── simple-todo-app.md
|
|
480
490
|
│ ├── api-only.md
|
|
481
491
|
│ ├── static-landing-page.md
|
|
@@ -628,7 +638,7 @@ The completion scripts support:
|
|
|
628
638
|
* **Smart Context**
|
|
629
639
|
|
|
630
640
|
* `loki start --provider <TAB>` shows only installed providers (`claude`, `codex`, `gemini`).
|
|
631
|
-
* `loki start <TAB>` defaults to file completion for PRD templates.
|
|
641
|
+
* `loki start <TAB>` defaults to file completion for spec files (PRD templates, YAML).
|
|
632
642
|
|
|
633
643
|
* **Nested Commands**
|
|
634
644
|
Handles specific subcommands for `council`, `memory`, `config`, `audit`, `metrics`, `watchdog`, and `secrets`.
|
|
@@ -797,9 +807,9 @@ After installation:
|
|
|
797
807
|
cd my-app
|
|
798
808
|
```
|
|
799
809
|
|
|
800
|
-
3. **Start Building:** Launch autonomous development
|
|
810
|
+
3. **Start Building:** Launch autonomous development from any spec (PRD, GitHub issue, or YAML)
|
|
801
811
|
```bash
|
|
802
|
-
loki start
|
|
812
|
+
loki start spec.md
|
|
803
813
|
```
|
|
804
814
|
|
|
805
815
|
4. **Read Documentation:** Check out [README.md](../README.md) for usage guides
|
|
@@ -11,10 +11,10 @@
|
|
|
11
11
|
|-----------|--------|-----------|--------|
|
|
12
12
|
| **Proven Scale** | 1M+ LoC, large agent count | Benchmarks only | Cursor |
|
|
13
13
|
| **Research Foundation** | Empirical iteration | 25+ academic citations | Loki Mode |
|
|
14
|
-
| **Quality Assurance** | Workers self-manage |
|
|
14
|
+
| **Quality Assurance** | Workers self-manage | 11-gate system + anti-sycophancy | Loki Mode |
|
|
15
15
|
| **Anti-Sycophancy** | Not mentioned | CONSENSAGENT blind review | Loki Mode |
|
|
16
16
|
| **Velocity-Quality Balance** | Not mentioned | arXiv-backed metrics | Loki Mode |
|
|
17
|
-
| **Full SDLC Coverage** | Code generation focus | PRD to production + growth | Loki Mode |
|
|
17
|
+
| **Full SDLC Coverage** | Code generation focus | Spec (PRD/issue/YAML) to production + growth | Loki Mode |
|
|
18
18
|
| **Memory Systems** | Not detailed | Episodic/semantic/procedural | Loki Mode |
|
|
19
19
|
| **Scale Patterns** | Battle-tested | Now incorporated (v3.3.0) | Tie |
|
|
20
20
|
|
|
@@ -66,7 +66,7 @@ velocity_quality_balance:
|
|
|
66
66
|
|
|
67
67
|
---
|
|
68
68
|
|
|
69
|
-
### 3.
|
|
69
|
+
### 3. 11-Gate Quality System
|
|
70
70
|
|
|
71
71
|
**Loki Mode's Gates:**
|
|
72
72
|
1. Input Guardrails - Validate scope, detect injection (OpenAI SDK pattern)
|
|
@@ -174,7 +174,7 @@ Cursor learned through failure:
|
|
|
174
174
|
### 3. Simplicity Principle
|
|
175
175
|
> "A surprising amount of the system's behavior comes down to how we prompt the agents. The harness and models matter, but the prompts matter more."
|
|
176
176
|
|
|
177
|
-
**Loki Mode:** More
|
|
177
|
+
**Loki Mode:** More elaborate infrastructure (11 gates, 41 agent types, memory systems). May be over-engineered for some use cases.
|
|
178
178
|
|
|
179
179
|
---
|
|
180
180
|
|
|
@@ -192,10 +192,10 @@ We incorporated Cursor's proven patterns:
|
|
|
192
192
|
## Conclusion
|
|
193
193
|
|
|
194
194
|
**Loki Mode is scientifically better in:**
|
|
195
|
-
- Quality assurance (research-backed
|
|
195
|
+
- Quality assurance (research-backed 11-gate system)
|
|
196
196
|
- Anti-sycophancy (CONSENSAGENT blind review)
|
|
197
197
|
- Velocity-quality balance (arXiv metrics)
|
|
198
|
-
- Full SDLC coverage (
|
|
198
|
+
- Full SDLC coverage (spec to growth -- PRD, GitHub issue, or YAML)
|
|
199
199
|
- Memory architecture (episodic/semantic/procedural)
|
|
200
200
|
|
|
201
201
|
**Cursor is operationally better in:**
|
package/events/emit.sh
CHANGED
|
@@ -11,6 +11,82 @@
|
|
|
11
11
|
#
|
|
12
12
|
# Environment:
|
|
13
13
|
# LOKI_DIR - Path to .loki directory (default: .loki)
|
|
14
|
+
#
|
|
15
|
+
# Sourcing:
|
|
16
|
+
# This script can also be sourced (LOKI_EMIT_LIB_ONLY=1) to expose the
|
|
17
|
+
# safe_append_event_jsonl() helper without performing an emit.
|
|
18
|
+
|
|
19
|
+
# safe_append_event_jsonl <events_jsonl_path> <line>
|
|
20
|
+
#
|
|
21
|
+
# Cross-process serialized append to .loki/events.jsonl. POSIX append is
|
|
22
|
+
# atomic only for writes <PIPE_BUF (typically 4KB) and not all filesystems
|
|
23
|
+
# honor it; under parallel-worktree contention bare `>>` can interleave
|
|
24
|
+
# partial JSONL lines. This helper serializes appends across processes.
|
|
25
|
+
#
|
|
26
|
+
# Strategy (v7.5.10):
|
|
27
|
+
# - Prefer flock(1) when available (Linux, util-linux). Uses an
|
|
28
|
+
# exclusive lock on a sentinel FD bound to <events>.lock so the lock
|
|
29
|
+
# is released automatically when the subshell exits.
|
|
30
|
+
# - Fall back to a mkdir() mutex on macOS / BSDs where flock is not
|
|
31
|
+
# installed by default. mkdir is atomic on POSIX -- exactly one
|
|
32
|
+
# concurrent caller wins the create. We retry with backoff up to
|
|
33
|
+
# ~5s, and treat a stale lockdir (>30s old) as abandonable.
|
|
34
|
+
# - The newline is appended by the helper -- callers pass the JSON
|
|
35
|
+
# payload only.
|
|
36
|
+
safe_append_event_jsonl() {
|
|
37
|
+
local events_path="$1"
|
|
38
|
+
local line="$2"
|
|
39
|
+
local lock_target="${events_path}.lock"
|
|
40
|
+
local events_dir
|
|
41
|
+
events_dir="$(dirname "$events_path")"
|
|
42
|
+
mkdir -p "$events_dir" 2>/dev/null || true
|
|
43
|
+
|
|
44
|
+
if command -v flock >/dev/null 2>&1; then
|
|
45
|
+
# flock path: bind FD 9 to the sentinel file (created if absent),
|
|
46
|
+
# take an exclusive lock, append, release on subshell exit.
|
|
47
|
+
(
|
|
48
|
+
flock -x 9
|
|
49
|
+
printf '%s\n' "$line" >> "$events_path"
|
|
50
|
+
) 9>"$lock_target"
|
|
51
|
+
return $?
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
# Fallback: mkdir-based mutex. mkdir is atomic on POSIX.
|
|
55
|
+
local lock_dir="${events_path}.lockdir"
|
|
56
|
+
local attempts=0
|
|
57
|
+
local max_attempts=500 # ~5s at 10ms sleep
|
|
58
|
+
while ! mkdir "$lock_dir" 2>/dev/null; do
|
|
59
|
+
attempts=$((attempts + 1))
|
|
60
|
+
if [ "$attempts" -ge "$max_attempts" ]; then
|
|
61
|
+
# Stale lock: if the dir is older than 30s, force-remove it.
|
|
62
|
+
local age
|
|
63
|
+
age=$(( $(date +%s) - $(stat -f%m "$lock_dir" 2>/dev/null \
|
|
64
|
+
|| stat -c%Y "$lock_dir" 2>/dev/null \
|
|
65
|
+
|| echo 0) ))
|
|
66
|
+
if [ "$age" -gt 30 ]; then
|
|
67
|
+
rmdir "$lock_dir" 2>/dev/null || rm -rf "$lock_dir" 2>/dev/null || true
|
|
68
|
+
attempts=0
|
|
69
|
+
continue
|
|
70
|
+
fi
|
|
71
|
+
# Give up -- best-effort write so observability never blocks.
|
|
72
|
+
printf '%s\n' "$line" >> "$events_path" 2>/dev/null || true
|
|
73
|
+
return 1
|
|
74
|
+
fi
|
|
75
|
+
# Sleep ~10ms (perl avoids `sleep 0.01` portability issues).
|
|
76
|
+
perl -e 'select(undef,undef,undef,0.01)' 2>/dev/null || sleep 1
|
|
77
|
+
done
|
|
78
|
+
# Critical section.
|
|
79
|
+
printf '%s\n' "$line" >> "$events_path"
|
|
80
|
+
local rc=$?
|
|
81
|
+
rmdir "$lock_dir" 2>/dev/null || true
|
|
82
|
+
return $rc
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
# Library-only mode: source this file to get safe_append_event_jsonl
|
|
86
|
+
# without executing the emit logic below.
|
|
87
|
+
if [ "${LOKI_EMIT_LIB_ONLY:-0}" = "1" ]; then
|
|
88
|
+
return 0 2>/dev/null || exit 0
|
|
89
|
+
fi
|
|
14
90
|
|
|
15
91
|
set -euo pipefail
|
|
16
92
|
|
package/loki-ts/dist/loki.js
CHANGED
|
@@ -423,7 +423,7 @@ Subcommands:
|
|
|
423
423
|
|
|
424
424
|
This command is invoked by autonomy/run.sh between iterations. Users
|
|
425
425
|
should not run it directly -- run \`loki start\` instead.
|
|
426
|
-
`,T5;var $6=w(()=>{m();T1();T5=c1});m();import{readFileSync as U6}from"fs";import{resolve as q6,dirname as H6}from"path";import{fileURLToPath as G6}from"url";var o=null;function r1(){if(o!==null)return o;let $="7.5.
|
|
426
|
+
`,T5;var $6=w(()=>{m();T1();T5=c1});m();import{readFileSync as U6}from"fs";import{resolve as q6,dirname as H6}from"path";import{fileURLToPath as G6}from"url";var o=null;function r1(){if(o!==null)return o;let $="7.5.11";if(typeof $==="string"&&$.length>0)return o=$,o;try{let Q=H6(G6(import.meta.url)),z=E1(Q);o=U6(q6(z,"VERSION"),"utf-8").trim()}catch{o="unknown"}return o}function s1(){return process.stdout.write(`Loki Mode v${r1()}
|
|
427
427
|
`),0}p();n();m();import{readFileSync as A6,existsSync as T6}from"fs";import{resolve as O6}from"path";var j6=["claude","codex","gemini","cline","aider"];function i1(){let $=O6(P(),"state","provider");if(!T6($))return"";try{return A6($,"utf-8").trim()}catch{return""}}function _6($,Q){return $||Q||process.env.LOKI_PROVIDER||"claude"}function I6($){let Q=i1(),z=_6($,Q);switch(process.stdout.write(`${D}Current Provider${W}
|
|
428
428
|
`),process.stdout.write(`
|
|
429
429
|
`),process.stdout.write(`${A}Provider:${W} ${z}
|
|
@@ -506,4 +506,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
|
|
|
506
506
|
`),2}default:return process.stderr.write(`Unknown command: ${Q}
|
|
507
507
|
`),process.stderr.write(z6),2}}process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var _5=await j5(Bun.argv.slice(2));process.exit(_5);
|
|
508
508
|
|
|
509
|
-
//# debugId=
|
|
509
|
+
//# debugId=8438E5E6200ECBFA64756E2164756E21
|
package/loki-ts/package.json
CHANGED
package/mcp/__init__.py
CHANGED
package/memory/retrieval.py
CHANGED
|
@@ -295,6 +295,42 @@ class MemoryRetrieval:
|
|
|
295
295
|
"""Get the current namespace."""
|
|
296
296
|
return self._namespace
|
|
297
297
|
|
|
298
|
+
# Track which legacy entries we've already warned about to avoid log spam.
|
|
299
|
+
_LEGACY_WARN_LIMIT = 5
|
|
300
|
+
_legacy_warned_count: int = 0
|
|
301
|
+
|
|
302
|
+
def _belongs_to_namespace(self, result: Dict[str, Any]) -> bool:
|
|
303
|
+
"""
|
|
304
|
+
Check if a memory result belongs to the current namespace.
|
|
305
|
+
|
|
306
|
+
Cross-namespace leak defense (v7.5.10). Storage layer should isolate
|
|
307
|
+
files by directory, but this filter provides defense-in-depth and
|
|
308
|
+
handles cases where vector indices span namespaces.
|
|
309
|
+
|
|
310
|
+
Behavior:
|
|
311
|
+
- If self._namespace is None, accept all (backward compat for unscoped retrieval).
|
|
312
|
+
- If result has "_namespace" matching, accept.
|
|
313
|
+
- If result lacks "_namespace" (legacy entry written before stamping),
|
|
314
|
+
log a deprecation warning (rate-limited) and ACCEPT for backward compat.
|
|
315
|
+
- Otherwise, reject.
|
|
316
|
+
"""
|
|
317
|
+
if self._namespace is None:
|
|
318
|
+
return True
|
|
319
|
+
result_ns = result.get("_namespace")
|
|
320
|
+
if result_ns is None:
|
|
321
|
+
# Legacy entry without namespace stamp; accept for backward compat
|
|
322
|
+
# but warn so operators can re-save to add stamps.
|
|
323
|
+
if MemoryRetrieval._legacy_warned_count < MemoryRetrieval._LEGACY_WARN_LIMIT:
|
|
324
|
+
logger.warning(
|
|
325
|
+
"Memory entry id=%s lacks '_namespace' stamp (legacy "
|
|
326
|
+
"entry). Including in results for backward compatibility. "
|
|
327
|
+
"Re-save this entry to enable namespace isolation.",
|
|
328
|
+
result.get("id", "<unknown>"),
|
|
329
|
+
)
|
|
330
|
+
MemoryRetrieval._legacy_warned_count += 1
|
|
331
|
+
return True
|
|
332
|
+
return result_ns == self._namespace
|
|
333
|
+
|
|
298
334
|
def with_namespace(self, namespace: str) -> "MemoryRetrieval":
|
|
299
335
|
"""
|
|
300
336
|
Create a new MemoryRetrieval instance with a different namespace.
|
|
@@ -761,7 +797,10 @@ class MemoryRetrieval:
|
|
|
761
797
|
item["id"] = item_id
|
|
762
798
|
item["_score"] = float(score)
|
|
763
799
|
item["_source"] = collection
|
|
764
|
-
|
|
800
|
+
# Cross-namespace leak defense (v7.5.10): vector indices may be
|
|
801
|
+
# shared across namespaces, so filter here too.
|
|
802
|
+
if self._belongs_to_namespace(item):
|
|
803
|
+
items.append(item)
|
|
765
804
|
|
|
766
805
|
return items
|
|
767
806
|
|
|
@@ -810,7 +849,8 @@ class MemoryRetrieval:
|
|
|
810
849
|
)
|
|
811
850
|
if data:
|
|
812
851
|
data["_source"] = "episodic"
|
|
813
|
-
|
|
852
|
+
if self._belongs_to_namespace(data):
|
|
853
|
+
results.append(data)
|
|
814
854
|
|
|
815
855
|
# Filter semantic patterns by last_used
|
|
816
856
|
patterns_data = self.storage.read_json("semantic/patterns.json") or {}
|
|
@@ -831,7 +871,8 @@ class MemoryRetrieval:
|
|
|
831
871
|
|
|
832
872
|
if since <= last_used_dt <= until:
|
|
833
873
|
pattern["_source"] = "semantic"
|
|
834
|
-
|
|
874
|
+
if self._belongs_to_namespace(pattern):
|
|
875
|
+
results.append(pattern)
|
|
835
876
|
except (ValueError, TypeError):
|
|
836
877
|
continue
|
|
837
878
|
|
|
@@ -1428,7 +1469,8 @@ class MemoryRetrieval:
|
|
|
1428
1469
|
data_copy = dict(data)
|
|
1429
1470
|
data_copy["_score"] = score
|
|
1430
1471
|
data_copy["_source"] = "episodic"
|
|
1431
|
-
|
|
1472
|
+
if self._belongs_to_namespace(data_copy):
|
|
1473
|
+
results.append(data_copy)
|
|
1432
1474
|
|
|
1433
1475
|
return results
|
|
1434
1476
|
|
|
@@ -1457,7 +1499,8 @@ class MemoryRetrieval:
|
|
|
1457
1499
|
pattern_copy = dict(pattern)
|
|
1458
1500
|
pattern_copy["_score"] = score
|
|
1459
1501
|
pattern_copy["_source"] = "semantic"
|
|
1460
|
-
|
|
1502
|
+
if self._belongs_to_namespace(pattern_copy):
|
|
1503
|
+
results.append(pattern_copy)
|
|
1461
1504
|
|
|
1462
1505
|
return results
|
|
1463
1506
|
|
|
@@ -1486,7 +1529,8 @@ class MemoryRetrieval:
|
|
|
1486
1529
|
data_copy = dict(data)
|
|
1487
1530
|
data_copy["_score"] = score
|
|
1488
1531
|
data_copy["_source"] = "skills"
|
|
1489
|
-
|
|
1532
|
+
if self._belongs_to_namespace(data_copy):
|
|
1533
|
+
results.append(data_copy)
|
|
1490
1534
|
|
|
1491
1535
|
return results
|
|
1492
1536
|
|
|
@@ -1511,7 +1555,8 @@ class MemoryRetrieval:
|
|
|
1511
1555
|
anti_copy = dict(anti)
|
|
1512
1556
|
anti_copy["_score"] = score
|
|
1513
1557
|
anti_copy["_source"] = "anti_patterns"
|
|
1514
|
-
|
|
1558
|
+
if self._belongs_to_namespace(anti_copy):
|
|
1559
|
+
results.append(anti_copy)
|
|
1515
1560
|
|
|
1516
1561
|
return results
|
|
1517
1562
|
|
package/memory/storage.py
CHANGED
|
@@ -391,6 +391,11 @@ class MemoryStorage:
|
|
|
391
391
|
episode_id = episode_data.get("id") or self._generate_id("episode")
|
|
392
392
|
episode_data["id"] = episode_id
|
|
393
393
|
|
|
394
|
+
# Stamp namespace so retrieval can verify isolation (cross-namespace
|
|
395
|
+
# leak defense, v7.5.10). Defaults to DEFAULT_NAMESPACE for unscoped
|
|
396
|
+
# storage instances.
|
|
397
|
+
episode_data["_namespace"] = self._namespace or DEFAULT_NAMESPACE
|
|
398
|
+
|
|
394
399
|
# Determine storage path based on date
|
|
395
400
|
timestamp = episode_data.get("timestamp", datetime.now(timezone.utc).isoformat())
|
|
396
401
|
if isinstance(timestamp, str):
|
|
@@ -557,6 +562,8 @@ class MemoryStorage:
|
|
|
557
562
|
"created_at",
|
|
558
563
|
datetime.now(timezone.utc).isoformat()
|
|
559
564
|
)
|
|
565
|
+
# Stamp namespace for cross-namespace leak defense (v7.5.10).
|
|
566
|
+
pattern_data["_namespace"] = self._namespace or DEFAULT_NAMESPACE
|
|
560
567
|
|
|
561
568
|
patterns_path = self.base_path / "semantic" / "patterns.json"
|
|
562
569
|
|
|
@@ -750,6 +757,8 @@ class MemoryStorage:
|
|
|
750
757
|
"created_at",
|
|
751
758
|
datetime.now(timezone.utc).isoformat()
|
|
752
759
|
)
|
|
760
|
+
# Stamp namespace for cross-namespace leak defense (v7.5.10).
|
|
761
|
+
skill_data["_namespace"] = self._namespace or DEFAULT_NAMESPACE
|
|
753
762
|
|
|
754
763
|
# Use skill name for filename if available, otherwise use ID
|
|
755
764
|
skill_name = skill_data.get("name", skill_id)
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "loki-mode",
|
|
3
|
-
"version": "7.5.
|
|
4
|
-
"description": "Loki Mode by Autonomi
|
|
3
|
+
"version": "7.5.11",
|
|
4
|
+
"description": "Loki Mode by Autonomi. Multi-agent autonomous SDLC framework. Spec to deployed app: PRD, GitHub issue, OpenAPI/JSON/YAML, or one-line brief. 5 AI providers (Claude Code, OpenAI Codex, Google Gemini, Cline, Aider). 11 quality gates.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"agent",
|
|
7
7
|
"agent-orchestration",
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
],
|
|
103
103
|
"scripts": {
|
|
104
104
|
"prepack": "find . -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null; find . -name '*.pyc' -delete 2>/dev/null; if command -v bun >/dev/null 2>&1; then (cd loki-ts && bun install --production && bun run build) || echo 'WARN: loki-ts build failed, using existing dist if present'; else echo 'WARN: bun not on PATH, skipping loki-ts build (using committed dist if present)'; fi; true",
|
|
105
|
-
"prepublishOnly": "cd dashboard-ui && npm ci && npm run build:all",
|
|
105
|
+
"prepublishOnly": "cd dashboard-ui && npm ci && npm run build:all && test -f ../dashboard/static/index.html",
|
|
106
106
|
"test": "bash -n autonomy/run.sh && bash -n autonomy/loki && bash -n autonomy/completion-council.sh && bash -n autonomy/app-runner.sh && bash -n autonomy/prd-checklist.sh && bash -n autonomy/playwright-verify.sh && node --test tests/protocols/*.test.js && node --test tests/protocols/a2a/*.test.js && node --test tests/observability/*.test.js && node --test tests/policies/*.test.js && node --test tests/audit/*.test.js && node --test tests/integrations/*.test.js && node --test tests/integrations/jira/*.test.js && node --test tests/integrations/github/*.test.js && node --test tests/integrations/slack/*.test.js && bash tests/managed_memory/test_flag_matrix.sh && bash tests/managed_memory/test_sdk_isolation.sh && bash tests/managed_memory/test_kill_switch.sh && python3 -m unittest tests.managed_memory.test_shadow_write_mock tests.managed_memory.test_retrieve_mock && echo 'All checks passed'",
|
|
107
107
|
"test:visual": "node --experimental-vm-modules node_modules/jest/bin/jest.js dashboard-ui/tests/visual-regression.test.js",
|
|
108
108
|
"test:parity": "node --experimental-vm-modules dashboard-ui/scripts/check-parity.js",
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
"test:integration": "bash tests/integration/run_integration_suite.sh"
|
|
112
112
|
},
|
|
113
113
|
"engines": {
|
|
114
|
-
"node": ">=
|
|
114
|
+
"node": ">=20.0.0"
|
|
115
115
|
},
|
|
116
116
|
"os": [
|
|
117
117
|
"darwin",
|
|
@@ -124,7 +124,7 @@
|
|
|
124
124
|
"@opentelemetry/exporter-trace-otlp-http": "^0.57.0"
|
|
125
125
|
},
|
|
126
126
|
"overrides": {
|
|
127
|
-
"protobufjs": ">=7.5.
|
|
127
|
+
"protobufjs": ">=7.5.6"
|
|
128
128
|
},
|
|
129
129
|
"devDependencies": {
|
|
130
130
|
"@types/node": "^25.2.0",
|
package/skills/healing.md
CHANGED
|
@@ -505,3 +505,15 @@ loki heal --report
|
|
|
505
505
|
# Strict mode: block any behavioral change without approval
|
|
506
506
|
LOKI_HEAL_STRICT=true loki heal ./legacy-app
|
|
507
507
|
```
|
|
508
|
+
|
|
509
|
+
## Checkpoint metadata hardening (v7.5.8)
|
|
510
|
+
|
|
511
|
+
As defense-in-depth for the healing checkpoint store, the checkpoint
|
|
512
|
+
writer now rejects ASCII control characters (U+0000-U+001F except TAB,
|
|
513
|
+
LF, CR, plus U+007F) anywhere in checkpoint metadata keys or values
|
|
514
|
+
before persisting `.loki/healing/checkpoints/<phase>.json`. This blocks
|
|
515
|
+
log-injection and JSON-poisoning vectors where adapter output, friction
|
|
516
|
+
notes, or institutional-knowledge excerpts could smuggle terminal
|
|
517
|
+
escapes or NUL bytes into the resume path. Rejected writes raise a
|
|
518
|
+
typed error and never partially overwrite the prior checkpoint, so
|
|
519
|
+
`loki heal --resume` always restarts from a clean, validated state.
|
package/skills/quality-gates.md
CHANGED
|
@@ -160,6 +160,16 @@ are silently dropped at load time. The override council uses a stub
|
|
|
160
160
|
judge in v7.5.x that approves any of those six trusted proofTypes;
|
|
161
161
|
real provider-backed judges land in Phase 2 of Part B.
|
|
162
162
|
|
|
163
|
+
**Cross-process gate counter (v7.5.5+)**: the per-iteration gate counter
|
|
164
|
+
at `.loki/state/gate-counter-<iter>.json` is now incremented under a
|
|
165
|
+
cross-process file lock via `withFileLockSync` in
|
|
166
|
+
`loki-ts/src/util/atomic.ts`. Concurrent gate runs (parallel worktrees,
|
|
167
|
+
overlapping `runQualityGates` invocations) no longer race the
|
|
168
|
+
read-modify-write, so override-council quotas and per-finding counters
|
|
169
|
+
remain consistent across processes. The lock file lives at
|
|
170
|
+
`.loki/state/gate-counter-<iter>.json.lock` and is released even on
|
|
171
|
+
crash via the primitive's `finally` cleanup.
|
|
172
|
+
|
|
163
173
|
---
|
|
164
174
|
|
|
165
175
|
## Guardrails Execution Modes
|
package/web-app/requirements.txt
CHANGED