loki-mode 7.78.0 → 7.80.0
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/lib/checkpoint_sync.py +189 -0
- package/autonomy/lib/config-map.sh +955 -0
- package/autonomy/loki +273 -8
- package/autonomy/run.sh +230 -195
- package/autonomy/sandbox.sh +98 -0
- package/autonomy/trigger-server.py +419 -43
- package/dashboard/__init__.py +1 -1
- package/dashboard/registry.py +212 -0
- package/dashboard/server.py +299 -7
- package/dashboard/static/index.html +383 -150
- package/docs/CONFIG-FILE-PLAN.md +459 -0
- package/docs/ENTERPRISE-IDENTITY-ROADMAP.md +206 -0
- package/docs/INSTALLATION.md +2 -2
- package/loki-ts/dist/loki.js +2 -2
- package/lokistore/__init__.py +65 -0
- package/lokistore/base.py +172 -0
- package/lokistore/cloud.py +305 -0
- package/lokistore/factory.py +187 -0
- package/lokistore/local.py +219 -0
- package/mcp/__init__.py +1 -1
- package/memory/retrieval.py +147 -0
- package/memory/tree_index.py +499 -0
- package/memory/tree_search.py +305 -0
- package/package.json +2 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
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 v7.
|
|
6
|
+
# Loki Mode v7.80.0
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
@@ -406,4 +406,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
|
|
|
406
406
|
|
|
407
407
|
---
|
|
408
408
|
|
|
409
|
-
**v7.
|
|
409
|
+
**v7.80.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
7.
|
|
1
|
+
7.80.0
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
A3: object-store checkpoint sync shim for run.sh.
|
|
4
|
+
|
|
5
|
+
This is the thin bridge between run.sh (bash) and the LokiStore object-store
|
|
6
|
+
backends (S3 / GCS / Azure). It is invoked ONLY when LOKI_STORAGE_BACKEND is set
|
|
7
|
+
to a non-local backend; when the backend is local/unset, run.sh never calls this
|
|
8
|
+
and behavior is unchanged.
|
|
9
|
+
|
|
10
|
+
Honest scope
|
|
11
|
+
------------
|
|
12
|
+
- This syncs the lightweight checkpoint state (.loki/state/checkpoints/**) to the
|
|
13
|
+
configured object store, and hydrates it back on a durable resume when the
|
|
14
|
+
local volume came up empty. It does NOT sync the git refs/loki/cp/* worktree
|
|
15
|
+
snapshots (those live in .git, not .loki, and are out of LokiStore's root);
|
|
16
|
+
the checkpoint metadata + .loki snapshot are what this transfers.
|
|
17
|
+
- All operations are best-effort. A sync/hydrate error never raises to the
|
|
18
|
+
caller's control flow (run.sh treats a nonzero exit as "skip, continue").
|
|
19
|
+
The bash side logs and continues a build on any failure.
|
|
20
|
+
|
|
21
|
+
Run identity
|
|
22
|
+
------------
|
|
23
|
+
Object-store keys are namespaced per run so concurrent / sequential runs do not
|
|
24
|
+
overwrite each other: runs/<run-id>/state/checkpoints/<...>
|
|
25
|
+
The run-id resolves from (first set wins): LOKI_RUN_ID, LOKI_SESSION_ID, or the
|
|
26
|
+
persisted trust-run-id at .loki/state/trust-run-id. For a durable resume on a
|
|
27
|
+
FRESH volume to find its prior checkpoints, the operator MUST provide a STABLE
|
|
28
|
+
id across pod restarts (set LOKI_RUN_ID or LOKI_SESSION_ID on the Job); the
|
|
29
|
+
minted trust-run-id is per-process and will not match after a restart.
|
|
30
|
+
|
|
31
|
+
Usage
|
|
32
|
+
-----
|
|
33
|
+
checkpoint_sync.py sync # push local .loki/state/checkpoints/** to store
|
|
34
|
+
checkpoint_sync.py hydrate # pull store -> local IF local checkpoints empty
|
|
35
|
+
|
|
36
|
+
Exit codes: 0 on success (including "nothing to do"); nonzero on any error
|
|
37
|
+
(caller ignores it and continues).
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
from __future__ import annotations
|
|
41
|
+
|
|
42
|
+
import os
|
|
43
|
+
import sys
|
|
44
|
+
|
|
45
|
+
# Local-first guard: this shim is only meaningful for a non-local backend. If the
|
|
46
|
+
# backend is local/unset, do nothing (run.sh should not even call us, but be
|
|
47
|
+
# defensive so a stray call is a no-op rather than a needless local copy).
|
|
48
|
+
_BACKEND = (os.environ.get("LOKI_STORAGE_BACKEND") or "local").strip().lower()
|
|
49
|
+
|
|
50
|
+
# The subtree of the .loki/ store that holds checkpoint state.
|
|
51
|
+
_CHECKPOINT_PREFIX = "state/checkpoints/"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def _resolve_run_id() -> str:
|
|
55
|
+
"""Resolve the per-run key namespace component (see module docstring)."""
|
|
56
|
+
for env_name in ("LOKI_RUN_ID", "LOKI_SESSION_ID"):
|
|
57
|
+
val = os.environ.get(env_name)
|
|
58
|
+
if val and val.strip():
|
|
59
|
+
return val.strip()
|
|
60
|
+
# Fall back to the persisted trust-run-id on the local volume.
|
|
61
|
+
loki_dir = os.environ.get("LOKI_DIR") or os.path.join(
|
|
62
|
+
os.environ.get("TARGET_DIR", "."), ".loki"
|
|
63
|
+
)
|
|
64
|
+
id_file = os.path.join(loki_dir, "state", "trust-run-id")
|
|
65
|
+
try:
|
|
66
|
+
with open(id_file, "r", encoding="utf-8") as f:
|
|
67
|
+
persisted = f.read().strip()
|
|
68
|
+
if persisted:
|
|
69
|
+
return persisted
|
|
70
|
+
except OSError:
|
|
71
|
+
pass
|
|
72
|
+
return "default"
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def _run_key(run_id: str, store_subkey: str) -> str:
|
|
76
|
+
"""Build the object-store key for a checkpoint subkey under this run."""
|
|
77
|
+
return f"runs/{run_id}/{store_subkey}"
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _get_store():
|
|
81
|
+
"""Import + construct the configured store. Raises on backend/SDK error."""
|
|
82
|
+
# Make the repo root importable so `import lokistore` works regardless of cwd.
|
|
83
|
+
here = os.path.dirname(os.path.abspath(__file__))
|
|
84
|
+
repo_root = os.path.abspath(os.path.join(here, os.pardir, os.pardir))
|
|
85
|
+
if repo_root not in sys.path:
|
|
86
|
+
sys.path.insert(0, repo_root)
|
|
87
|
+
from lokistore import get_store # noqa: E402
|
|
88
|
+
|
|
89
|
+
return get_store()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _local_store():
|
|
93
|
+
"""A LocalStore rooted at the project .loki/ for reading/writing local keys."""
|
|
94
|
+
here = os.path.dirname(os.path.abspath(__file__))
|
|
95
|
+
repo_root = os.path.abspath(os.path.join(here, os.pardir, os.pardir))
|
|
96
|
+
if repo_root not in sys.path:
|
|
97
|
+
sys.path.insert(0, repo_root)
|
|
98
|
+
from lokistore import build_store # noqa: E402
|
|
99
|
+
|
|
100
|
+
return build_store({"backend": "local"})
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def cmd_sync() -> int:
|
|
104
|
+
"""Push local checkpoint state to the object store under this run's prefix."""
|
|
105
|
+
if _BACKEND in ("local", "", "file", "filesystem"):
|
|
106
|
+
return 0 # no-op for local backend
|
|
107
|
+
|
|
108
|
+
run_id = _resolve_run_id()
|
|
109
|
+
local = _local_store()
|
|
110
|
+
remote = _get_store()
|
|
111
|
+
|
|
112
|
+
keys = local.list(_CHECKPOINT_PREFIX)
|
|
113
|
+
if not keys:
|
|
114
|
+
return 0 # nothing to sync yet
|
|
115
|
+
|
|
116
|
+
count = 0
|
|
117
|
+
for subkey in keys:
|
|
118
|
+
data = local.get(subkey)
|
|
119
|
+
remote.put(_run_key(run_id, subkey), data)
|
|
120
|
+
count += 1
|
|
121
|
+
sys.stderr.write(
|
|
122
|
+
f"[checkpoint-sync] pushed {count} checkpoint object(s) to "
|
|
123
|
+
f"{_BACKEND} under runs/{run_id}/\n"
|
|
124
|
+
)
|
|
125
|
+
return 0
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def cmd_hydrate() -> int:
|
|
129
|
+
"""
|
|
130
|
+
Pull checkpoint state from the object store into the local volume, but ONLY
|
|
131
|
+
when the local checkpoint state is empty (a fresh volume). If the local
|
|
132
|
+
volume already has checkpoints, do nothing (the local copy wins; we never
|
|
133
|
+
clobber a live volume).
|
|
134
|
+
"""
|
|
135
|
+
if _BACKEND in ("local", "", "file", "filesystem"):
|
|
136
|
+
return 0 # no-op for local backend
|
|
137
|
+
|
|
138
|
+
local = _local_store()
|
|
139
|
+
# Guard: never overwrite a non-empty local volume.
|
|
140
|
+
if local.list(_CHECKPOINT_PREFIX):
|
|
141
|
+
return 0
|
|
142
|
+
|
|
143
|
+
run_id = _resolve_run_id()
|
|
144
|
+
remote = _get_store()
|
|
145
|
+
remote_prefix = _run_key(run_id, _CHECKPOINT_PREFIX)
|
|
146
|
+
remote_keys = remote.list(remote_prefix)
|
|
147
|
+
if not remote_keys:
|
|
148
|
+
return 0 # store has nothing for this run; fall through to normal flow
|
|
149
|
+
|
|
150
|
+
loki_dir = os.environ.get("LOKI_DIR") or os.path.join(
|
|
151
|
+
os.environ.get("TARGET_DIR", "."), ".loki"
|
|
152
|
+
)
|
|
153
|
+
strip = f"runs/{run_id}/"
|
|
154
|
+
loki_dir_real = os.path.realpath(loki_dir)
|
|
155
|
+
count = 0
|
|
156
|
+
for rk in remote_keys:
|
|
157
|
+
if not rk.startswith(strip):
|
|
158
|
+
continue
|
|
159
|
+
local_subkey = rk[len(strip):] # e.g. state/checkpoints/cp-1/metadata.json
|
|
160
|
+
dest = os.path.join(loki_dir, *local_subkey.split("/"))
|
|
161
|
+
# Path-traversal guard: a malicious/buggy store key with ../ could make
|
|
162
|
+
# dest escape loki_dir. Skip + log anything that does not stay inside.
|
|
163
|
+
if not os.path.realpath(dest).startswith(loki_dir_real + os.sep):
|
|
164
|
+
sys.stderr.write(f"[checkpoint-sync] skipped out-of-tree key: {rk}\n")
|
|
165
|
+
continue
|
|
166
|
+
remote.get_to(rk, dest)
|
|
167
|
+
count += 1
|
|
168
|
+
sys.stderr.write(
|
|
169
|
+
f"[checkpoint-sync] hydrated {count} checkpoint object(s) from "
|
|
170
|
+
f"{_BACKEND} for runs/{run_id}/\n"
|
|
171
|
+
)
|
|
172
|
+
return 0
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def main(argv) -> int:
|
|
176
|
+
if len(argv) < 2 or argv[1] not in ("sync", "hydrate"):
|
|
177
|
+
sys.stderr.write("usage: checkpoint_sync.py {sync|hydrate}\n")
|
|
178
|
+
return 2
|
|
179
|
+
try:
|
|
180
|
+
if argv[1] == "sync":
|
|
181
|
+
return cmd_sync()
|
|
182
|
+
return cmd_hydrate()
|
|
183
|
+
except Exception as exc: # best-effort: never break the build
|
|
184
|
+
sys.stderr.write(f"[checkpoint-sync] {argv[1]} skipped: {exc}\n")
|
|
185
|
+
return 1
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
if __name__ == "__main__":
|
|
189
|
+
raise SystemExit(main(sys.argv))
|