loki-mode 10.1.0 → 10.1.1

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.
Files changed (69) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/autonomy/lib/modernize/py_capture.py +642 -0
  4. package/autonomy/lib/modernize/py_imports.py +260 -0
  5. package/dashboard/__init__.py +1 -1
  6. package/docs/INSTALLATION.md +1 -1
  7. package/docs/v10/BOARD.md +16 -14
  8. package/docs/v10/PROGRESS.md +6 -0
  9. package/loki-ts/dist/loki.js +2 -2
  10. package/mcp/__init__.py +1 -1
  11. package/package.json +1 -1
  12. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  13. package/web-app/dist/assets/{AdminPage-2Vvbl-44.js → AdminPage-wMjhCb2R.js} +1 -1
  14. package/web-app/dist/assets/{Avatar-BOhL0n6E.js → Avatar-DZrKgEX4.js} +1 -1
  15. package/web-app/dist/assets/{Badge-BBUiD0l_.js → Badge-B98xzprY.js} +1 -1
  16. package/web-app/dist/assets/{Button-CyWOw1Bk.js → Button-Wo3WJ5Kd.js} +1 -1
  17. package/web-app/dist/assets/{CockpitPage-n_2b26I6.js → CockpitPage-SU0qpwFJ.js} +1 -1
  18. package/web-app/dist/assets/{ComparePage-DiVUELHq.js → ComparePage-BEKIJ4I5.js} +1 -1
  19. package/web-app/dist/assets/{ErrorBoundary-D3C-yCJk.js → ErrorBoundary-U_89NZcK.js} +1 -1
  20. package/web-app/dist/assets/{EvidenceReceiptPanel-BMvYMVPw.js → EvidenceReceiptPanel-DKeK7rwF.js} +1 -1
  21. package/web-app/dist/assets/{GitHubIssuesPanel-z6xHKZmn.js → GitHubIssuesPanel-Bzwgxvzl.js} +1 -1
  22. package/web-app/dist/assets/{GitHubPRsPanel-CukSUgaq.js → GitHubPRsPanel-CLyXZXt9.js} +1 -1
  23. package/web-app/dist/assets/{HomePage-a677lI6k.js → HomePage-jPDT7src.js} +2 -2
  24. package/web-app/dist/assets/{LoginPage-2S4fAPpI.js → LoginPage-W91noLcb.js} +1 -1
  25. package/web-app/dist/assets/{MagicPage-CMxPqcqC.js → MagicPage-DdIXXbgO.js} +1 -1
  26. package/web-app/dist/assets/{MetricsPage-SS7Oj6Pk.js → MetricsPage-FhjqTGMb.js} +1 -1
  27. package/web-app/dist/assets/{NotFoundPage-BZXdsLzP.js → NotFoundPage-B7gXwg03.js} +1 -1
  28. package/web-app/dist/assets/{ProjectPage-CqpoFnd2.js → ProjectPage-DMP7-lF9.js} +3 -3
  29. package/web-app/dist/assets/{ProjectsPage-BUth71nx.js → ProjectsPage-BEv3tKH5.js} +1 -1
  30. package/web-app/dist/assets/{SettingsPage-BdmBARGN.js → SettingsPage-BahxJ6e-.js} +1 -1
  31. package/web-app/dist/assets/{ShowcasePage-BuPyRdsp.js → ShowcasePage-B8ZK_eFm.js} +1 -1
  32. package/web-app/dist/assets/{SystemSettingsPage-nWi3Y49V.js → SystemSettingsPage-i_ua6JYr.js} +1 -1
  33. package/web-app/dist/assets/{TeamsPage-Bbzd2c18.js → TeamsPage-BxKtdgg8.js} +1 -1
  34. package/web-app/dist/assets/{TemplatesPage-CFaCEASB.js → TemplatesPage-B74RvPRL.js} +1 -1
  35. package/web-app/dist/assets/{TerminalOutput-CwMRjG7N.js → TerminalOutput-CusdIPW5.js} +1 -1
  36. package/web-app/dist/assets/{activity-DSavuwyT.js → activity-BzYTwsTy.js} +1 -1
  37. package/web-app/dist/assets/{bell-BlhMsQEo.js → bell-DH9nf5zB.js} +1 -1
  38. package/web-app/dist/assets/{bot-CNA95IKJ.js → bot-HoIZK7eB.js} +1 -1
  39. package/web-app/dist/assets/{check-DOrNSoDM.js → check-Bg2o382k.js} +1 -1
  40. package/web-app/dist/assets/{chevron-left-B2USiPOZ.js → chevron-left-v-IUHzhm.js} +1 -1
  41. package/web-app/dist/assets/{circle-alert-Bo5f9KMG.js → circle-alert-G3MHxw9O.js} +1 -1
  42. package/web-app/dist/assets/{clock-rzxwnuLM.js → clock-CR8oME3b.js} +1 -1
  43. package/web-app/dist/assets/{cloud-DjFY4qb6.js → cloud-FNlrpEVb.js} +1 -1
  44. package/web-app/dist/assets/{code-xml-DoEdsIKW.js → code-xml-THwmjPSI.js} +1 -1
  45. package/web-app/dist/assets/{database-G9bBiLg8.js → database-DGS4lCam.js} +1 -1
  46. package/web-app/dist/assets/{dollar-sign-bvddxRmc.js → dollar-sign-D1D7210y.js} +1 -1
  47. package/web-app/dist/assets/{file-code-corner-B4pgv1xC.js → file-code-corner-BEZS0NVh.js} +1 -1
  48. package/web-app/dist/assets/{file-plus-Mr4Q0b_Z.js → file-plus-slraMnC-.js} +1 -1
  49. package/web-app/dist/assets/{globe-BM6uvx4Q.js → globe-Ckj7P6MF.js} +1 -1
  50. package/web-app/dist/assets/{hammer-Dbg_jerN.js → hammer-BzjDp6gZ.js} +1 -1
  51. package/web-app/dist/assets/{index-JLmXzxqi.js → index-Dtrn_88z.js} +2 -2
  52. package/web-app/dist/assets/{layers-duNSn4MK.js → layers-mUcW7Lcv.js} +1 -1
  53. package/web-app/dist/assets/{loader-circle-BTy_2p55.js → loader-circle-CwrHVSiy.js} +1 -1
  54. package/web-app/dist/assets/{lock-Da91KLZZ.js → lock-a4yooVvD.js} +1 -1
  55. package/web-app/dist/assets/{package-CUrUe6vT.js → package-H3syThe6.js} +1 -1
  56. package/web-app/dist/assets/{plus-CyFRqzGH.js → plus-R5BxuvRb.js} +1 -1
  57. package/web-app/dist/assets/{refresh-cw-YelQ45nx.js → refresh-cw-CA64KPjz.js} +1 -1
  58. package/web-app/dist/assets/{rotate-ccw-BIU7xZyT.js → rotate-ccw-DbYX6fj6.js} +1 -1
  59. package/web-app/dist/assets/{scroll-text-C88oxteF.js → scroll-text-DSAnxmlo.js} +1 -1
  60. package/web-app/dist/assets/{server-X3H7bWFy.js → server--M5B5u1M.js} +1 -1
  61. package/web-app/dist/assets/{shield-alert-gpP8kh02.js → shield-alert-DL9xNxeK.js} +1 -1
  62. package/web-app/dist/assets/{thumbs-up-BxwJ7kT_.js → thumbs-up-2MLPuEWk.js} +1 -1
  63. package/web-app/dist/assets/{trash-2-M7R3o6Ds.js → trash-2-CjFzSYHy.js} +1 -1
  64. package/web-app/dist/assets/{trending-down-DYXErqkJ.js → trending-down-BVWPFfUX.js} +1 -1
  65. package/web-app/dist/assets/{trending-up-CqZThz26.js → trending-up-CwcHClXI.js} +1 -1
  66. package/web-app/dist/assets/{upload-BZPVsx2j.js → upload-ODPqesIu.js} +1 -1
  67. package/web-app/dist/assets/{usePolling-CFDpdEmJ.js → usePolling-5s1fbj3D.js} +1 -1
  68. package/web-app/dist/assets/{user-CG96I_PT.js → user-B249yxJV.js} +1 -1
  69. package/web-app/dist/index.html +1 -1
@@ -0,0 +1,260 @@
1
+ #!/usr/bin/env python3
2
+ """M-03: Python import graph via tokenize (docs/v10/MODERNIZE.md section 3.1).
3
+
4
+ Uses the `tokenize` module, not `ast`, on purpose: ast.parse raises SyntaxError
5
+ on py2-only source (print statements, backticks, `except Foo, e:`), which is
6
+ exactly the code this modernizer exists to migrate. tokenize is purely lexical
7
+ and reads all of that fine, so a py2 file still yields a usable import list.
8
+
9
+ Usage: py_imports.py <repo_dir> <rel_file1.py> [rel_file2.py ...]
10
+ Prints one JSON object to stdout:
11
+ {"nodes": [{"id": "<relpath>", "lines": N}, ...],
12
+ "edges": [["<relpath>", "<relpath>"], ...],
13
+ "unresolved": [{"from": "<relpath>", "spec": "<import text>", "line": N}, ...]}
14
+
15
+ A file that fails to tokenize still gets a node (with its line count); it
16
+ just contributes no edges (recorded nowhere as an error -- best effort).
17
+ """
18
+ import io
19
+ import json
20
+ import os
21
+ import sys
22
+ import tokenize
23
+
24
+ SKIP_TOKENS = {
25
+ tokenize.COMMENT, tokenize.NL, tokenize.INDENT, tokenize.DEDENT,
26
+ tokenize.ENCODING, tokenize.ENDMARKER,
27
+ }
28
+
29
+
30
+ def read_source(abs_path):
31
+ try:
32
+ with open(abs_path, "rb") as f:
33
+ raw = f.read()
34
+ except OSError:
35
+ return ""
36
+ try:
37
+ return raw.decode("utf-8")
38
+ except UnicodeDecodeError:
39
+ return raw.decode("latin-1")
40
+
41
+
42
+ def count_lines(source):
43
+ return sum(1 for line in source.splitlines() if line.strip())
44
+
45
+
46
+ def statements(source):
47
+ """Yield logical-line token groups (a list of (type, string, lineno)),
48
+ split on NEWLINE / top-level ';'. tokenize already merges bracket- and
49
+ backslash-continued physical lines into one logical line for us."""
50
+ try:
51
+ toks = tokenize.generate_tokens(io.StringIO(source).readline)
52
+ group = []
53
+ for tok in toks:
54
+ ttype, tstr, start = tok[0], tok[1], tok[2]
55
+ if ttype in SKIP_TOKENS:
56
+ continue
57
+ if ttype == tokenize.NEWLINE:
58
+ if group:
59
+ yield group
60
+ group = []
61
+ continue
62
+ if ttype == tokenize.OP and tstr == ";":
63
+ if group:
64
+ yield group
65
+ group = []
66
+ continue
67
+ group.append((ttype, tstr, start[0]))
68
+ if group:
69
+ yield group
70
+ except (tokenize.TokenError, IndentationError, SyntaxError):
71
+ return
72
+
73
+
74
+ def dotted(tokens, i):
75
+ """Read a NAME('.'NAME)* run starting at tokens[i]. Returns (parts, next_i).
76
+ 'import' is a reserved word and can never be a real module/attr name, so it
77
+ stops the run here -- this is what lets a bare-dot relative import like
78
+ `from . import util` (module_parts empty, next token literally 'import')
79
+ resolve instead of swallowing 'import' itself as a fake first part."""
80
+ parts = []
81
+ while i < len(tokens) and tokens[i][0] == tokenize.NAME and tokens[i][1] != "import":
82
+ parts.append(tokens[i][1])
83
+ i += 1
84
+ if i < len(tokens) and tokens[i][1] == ".":
85
+ i += 1
86
+ continue
87
+ break
88
+ return parts, i
89
+
90
+
91
+ def parse_import(stmt):
92
+ """stmt is 'import ...'. Yields (level=0, module_parts, name=None) per
93
+ comma-separated dotted target (alias, if any, is irrelevant to the graph)."""
94
+ i = 1 # skip 'import'
95
+ n = len(stmt)
96
+ while i < n:
97
+ parts, i = dotted(stmt, i)
98
+ if parts:
99
+ yield (0, parts, None, stmt[0][2])
100
+ while i < n and stmt[i][1] != ",":
101
+ i += 1
102
+ i += 1 # skip ','
103
+
104
+
105
+ def parse_from(stmt):
106
+ """stmt is 'from ... import ...'. Yields (level, module_parts, name, lineno)
107
+ once per imported name ('*' for a star import)."""
108
+ i = 1 # skip 'from'
109
+ n = len(stmt)
110
+ level = 0
111
+ while i < n and stmt[i][1] in (".", "..."):
112
+ level += len(stmt[i][1]) # '...' (Ellipsis token) counts as 3 dots
113
+ i += 1
114
+ module_parts, i = dotted(stmt, i)
115
+ if i >= n or stmt[i][1] != "import":
116
+ return # malformed; nothing usable
117
+ i += 1
118
+ lineno = stmt[0][2]
119
+ if i < n and stmt[i][1] == "*":
120
+ yield (level, module_parts, "*", lineno)
121
+ return
122
+ while i < n:
123
+ if stmt[i][1] in ("(", ")"):
124
+ i += 1
125
+ continue
126
+ if stmt[i][0] == tokenize.NAME:
127
+ name = stmt[i][1]
128
+ i += 1
129
+ if i < n and stmt[i][1] == "as":
130
+ i += 2
131
+ yield (level, module_parts, name, lineno)
132
+ continue
133
+ i += 1 # comma or stray token
134
+
135
+
136
+ def find_file_or_pkg(repo_dir, parts):
137
+ if not parts:
138
+ return None
139
+ rel_file = "/".join(parts) + ".py"
140
+ if os.path.isfile(os.path.join(repo_dir, *parts) + ".py"):
141
+ return rel_file
142
+ if os.path.isfile(os.path.join(repo_dir, *parts, "__init__.py")):
143
+ return "/".join(parts + ["__init__.py"])
144
+ return None
145
+
146
+
147
+ # ponytail: absolute imports are resolved against the repo root and a top-level
148
+ # `src/` (the one extra layout PEP 517 projects commonly use); real sys.path
149
+ # (installed packages, PYTHONPATH, namespace-package search across multiple
150
+ # src dirs) is out of scope for a dependency scan -- add more roots if a repo
151
+ # needs them.
152
+ def search_roots(repo_dir):
153
+ roots = [repo_dir]
154
+ src = os.path.join(repo_dir, "src")
155
+ if os.path.isdir(src):
156
+ roots.append(src)
157
+ return roots
158
+
159
+
160
+ def resolve(repo_dir, roots, level, module_parts, name, cur_rel):
161
+ if level > 0:
162
+ cur_dir_parts = os.path.dirname(cur_rel).split("/") if os.path.dirname(cur_rel) else []
163
+ keep = len(cur_dir_parts) - (level - 1)
164
+ if keep < 0:
165
+ return None # dots climb past the repo root
166
+ base = cur_dir_parts[:keep] + module_parts
167
+ candidates = [repo_dir]
168
+ else:
169
+ base = module_parts
170
+ candidates = roots
171
+
172
+ if name is None:
173
+ for root in candidates:
174
+ hit = find_file_or_pkg(root, base)
175
+ if hit:
176
+ return hit
177
+ return None
178
+
179
+ if name != "*":
180
+ for root in candidates:
181
+ hit = find_file_or_pkg(root, base + [name])
182
+ if hit:
183
+ return hit
184
+ # Fall back to the "from" target itself: `name` may be an attribute
185
+ # (function, class, constant) defined inside that module/package, not a
186
+ # submodule of its own.
187
+ for root in candidates:
188
+ hit = find_file_or_pkg(root, base)
189
+ if hit:
190
+ return hit
191
+ return None
192
+
193
+
194
+ def spec_text(level, module_parts, name):
195
+ # A "." separates a module part from the following name, but the dots of a
196
+ # bare-dot relative import (`from . import x`, module_parts empty) already
197
+ # act as that separator -- adding another would misreport `from .. import x`
198
+ # (2 dots) as `...x` (3 dots) instead of the as-written `..x`.
199
+ head = "." * level + ".".join(module_parts)
200
+ sep = "." if module_parts else ""
201
+ if name is None:
202
+ return head
203
+ if name == "*":
204
+ return f"{head}{sep}*" if head else "*"
205
+ return f"{head}{sep}{name}" if head else name
206
+
207
+
208
+ def scan_file(repo_dir, roots, rel_path):
209
+ source = read_source(os.path.join(repo_dir, rel_path))
210
+ node = {"id": rel_path, "lines": count_lines(source)}
211
+ edges = set()
212
+ unresolved = []
213
+ for stmt in statements(source):
214
+ if not stmt or stmt[0][0] != tokenize.NAME:
215
+ continue
216
+ head = stmt[0][1]
217
+ if head == "import":
218
+ items = parse_import(stmt)
219
+ elif head == "from":
220
+ items = parse_from(stmt)
221
+ else:
222
+ continue
223
+ for level, module_parts, name, lineno in items:
224
+ target = resolve(repo_dir, roots, level, module_parts, name, rel_path)
225
+ if target and target != rel_path:
226
+ edges.add((rel_path, target))
227
+ # target == rel_path (a self-import) is intentionally neither an edge
228
+ # (a self-loop is useless to the dependency graph) nor unresolved
229
+ # (it did resolve); it is silently dropped, matching this scanner's
230
+ # best-effort contract.
231
+ elif not target:
232
+ unresolved.append({"from": rel_path, "spec": spec_text(level, module_parts, name), "line": lineno})
233
+ return node, edges, unresolved
234
+
235
+
236
+ def main(argv):
237
+ if len(argv) < 2:
238
+ print(json.dumps({"nodes": [], "edges": [], "unresolved": []}))
239
+ return 0
240
+ repo_dir = os.path.abspath(argv[1])
241
+ files = argv[2:]
242
+ roots = search_roots(repo_dir)
243
+ nodes = []
244
+ all_edges = set()
245
+ all_unresolved = []
246
+ for rel_path in files:
247
+ node, edges, unresolved = scan_file(repo_dir, roots, rel_path)
248
+ nodes.append(node)
249
+ all_edges.update(edges)
250
+ all_unresolved.extend(unresolved)
251
+ print(json.dumps({
252
+ "nodes": nodes,
253
+ "edges": sorted(list(e) for e in all_edges),
254
+ "unresolved": all_unresolved,
255
+ }))
256
+ return 0
257
+
258
+
259
+ if __name__ == "__main__":
260
+ sys.exit(main(sys.argv))
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "10.1.0"
10
+ __version__ = "10.1.1"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -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:** v10.1.0
5
+ **Version:** v10.1.1
6
6
 
7
7
  ---
8
8
 
package/docs/v10/BOARD.md CHANGED
@@ -344,45 +344,45 @@ set is declared to avoid overlap with those and with each other.
344
344
  | E-57 | Line reclaim: engine10 back to 4,700 or fewer by deleting dead exports and duplicated helpers, no behavior change | loki-ts/src/engine10/ (deletions only, no new files) | LOW | cd loki-ts && bun test tests/engine10/ && bunx tsc --noEmit; budget.test count at or below 4700 | released@2026-09-28T02:38Z | Source: train E10 hit 5,019 and needed a header trim; E-36, E-45 and E-52..E-56 need room. Merge after the gate-path slices to avoid conflicts. Dispatched after train E13. Merged 3ab2a8fa (train E14, rebased on main): engine10 404 pass 0 fail (402 pass 0 fail with claude removed from PATH), tsc exit 0, test-harness 86/0, test-local-ci-gitleaks 6/0, test-engine10-dist 18/0. Released v9.81.0 (npm view loki-mode time: 2026-09-28T02:38:54Z). |
345
345
  | EV-10 | Harness reaps arm descendants that escape the timeout process group: after the cap, KILL recorded PIDs under the run clone (.loki/**/*.pid) and processes whose cwd is inside that run-owned clone; guard in docs/v10/GUARDS.md | eval/loki10/harness.py (kill_orphans only), eval/loki10/test-harness.sh (one leg), docs/v10/GUARDS.md (one entry) | HIGH | bash eval/loki10/test-harness.sh; a fixture arm that setsid-spawns a sleeper leaves no live process after the cap | released@2026-09-28T02:38Z | Source: incident 00:08Z, pulse ORPHAN_WORKTREE caught 4 legacy /tmp/loki-run-*.sh loops (ppid 1, 30 min, 15-min cap) plus 2 sleep 300 children from run dir loki-run.u6ikBxCT; stopped by PID (kill -TERM 58249 58251 58633 58634 57049 56916, ps -p afterwards empty). Never match by name. Opus CONCERN: Linux /proc/<pid> mtime is not process start, so the age filter passes everything. Rework dispatched. Merged 3ab2a8fa (train E14, rebased on main): engine10 404 pass 0 fail (402 pass 0 fail with claude removed from PATH), tsc exit 0, test-harness 86/0, test-local-ci-gitleaks 6/0, test-engine10-dist 18/0. Released v9.81.0 (npm view loki-mode time: 2026-09-28T02:38:54Z). |
346
346
  | E-60 | Secret-scan guard before push: scripts/local-ci.sh fast tier runs gitleaks v8.30.0 with .gitleaksignore over origin/main..HEAD when the binary is present (SKIP line, not green, when absent); fixtures must build secret-shaped strings at runtime; entry in docs/v10/GUARDS.md | scripts/local-ci.sh (one step), tests/test-local-ci-gitleaks.sh, docs/v10/GUARDS.md | MEDIUM | bash tests/test-local-ci-gitleaks.sh: a commit adding a planted AKIA fixture fails the step; the same fixture built by concatenation passes | released@2026-09-28T02:38Z | Source: incident 00:45Z. Security Audit gitleaks failed on 9dc0b1d3 and 085306ae (3 findings: deep.test.ts aws-access-token, test-engine10-push-gitlab.sh gitlab-pat, rule_of_two.test.ts generic-api-key, all synthetic), so v9.79.0 and v9.80.0 never reached npm (npm view loki-mode version = 9.78.0). Baselined in 5190756f; local full-history scan shows only local-branch copies. Dispatched. Merged 3ab2a8fa (train E14, rebased on main): engine10 404 pass 0 fail (402 pass 0 fail with claude removed from PATH), tsc exit 0, test-harness 86/0, test-local-ci-gitleaks 6/0, test-engine10-dist 18/0. Released v9.81.0 (npm view loki-mode time: 2026-09-28T02:38:54Z). |
347
- | E-61 | A session that exits with an error fails its stage (implement reported done after exit "error" in 1s with 0 tokens) and its stderr tail is kept under the run dir for diagnosis | loki-ts/src/engine10/session.ts (stderr capture only), loki-ts/src/engine10/stages/implement.ts, loki-ts/src/engine10/stages/plan.ts, tests | HIGH | cd loki-ts && bun test tests/engine10/; a stub provider exiting 1 yields stage.failed with the stderr tail path | building@2026-09-28T04:25Z | Source: incident 01:38Z (EV-8 0/5 twice). Opus reviewer. Overlaps E-68 (exit classification) and E-69; builder of E-68 covers the stage-failure part. Wave E19, after E-68 landed (ea288330). D33: states its net core line delta; core must stay under 5,000 (92 lines of headroom shared by E-67, E-66, E-61, M-14, merge order E-67, E-66, E-61); offset any excess by deleting dead core code. |
348
- | E-62 | Eval harness v10 arm defaults to this repo's bin/loki (never the global loki, which was v9.78.0) and the manifest records its path and the agent SDK version; local-ci and the harness refuse when loki-ts/node_modules differs from bun.lock | eval/loki10/harness.py (loki_bin default, manifest), scripts/local-ci.sh (one check), eval/loki10/test-harness.sh (one leg) | HIGH | bash eval/loki10/test-harness.sh; a leg asserts the v10 arm binary is the repo bin/loki | building@2026-09-28T04:25Z | Source: incident 01:38Z. Wave E19, after EV-13 landed (ea288330). |
347
+ | E-61 | A session that exits with an error fails its stage (implement reported done after exit "error" in 1s with 0 tokens) and its stderr tail is kept under the run dir for diagnosis | loki-ts/src/engine10/session.ts (stderr capture only), loki-ts/src/engine10/stages/implement.ts, loki-ts/src/engine10/stages/plan.ts, tests | HIGH | cd loki-ts && bun test tests/engine10/; a stub provider exiting 1 yields stage.failed with the stderr tail path | review@2026-09-28T14:20Z | Source: incident 01:38Z (EV-8 0/5 twice). Opus reviewer. Overlaps E-68 (exit classification) and E-69; builder of E-68 covers the stage-failure part. Wave E19, after E-68 landed (ea288330). D33: states its net core line delta; core must stay under 5,000 (92 lines of headroom shared by E-67, E-66, E-61, M-14, merge order E-67, E-66, E-61); offset any excess by deleting dead core code. Built b5f9f7fe (branch slice-E-61) at 04:30Z; its Opus review died on the 04:48Z access outage. Needs review only; D33 core delta must be checked. Wave E21 (wf_39ab3f7d-8f3). Opus review. |
348
+ | E-62 | Eval harness v10 arm defaults to this repo's bin/loki (never the global loki, which was v9.78.0) and the manifest records its path and the agent SDK version; local-ci and the harness refuse when loki-ts/node_modules differs from bun.lock | eval/loki10/harness.py (loki_bin default, manifest), scripts/local-ci.sh (one check), eval/loki10/test-harness.sh (one leg) | HIGH | bash eval/loki10/test-harness.sh; a leg asserts the v10 arm binary is the repo bin/loki | building@2026-09-28T14:20Z | Source: incident 01:38Z. Wave E19, after EV-13 landed (ea288330). Built 3e8f6dc8 (branch slice-E-62). Opus REJECT (reproduced): the new lockfile check in scripts/local-ci.sh is not in _FAST_KEEP, so the fast tier (the only gate) skips it. Next: rework. Wave E21 (wf_39ab3f7d-8f3). r2. |
349
349
  | E-63 | Pulse STALE_PROGRESS violation when the newest PROGRESS.md entry is over 35 minutes old | scripts/v10-pulse.sh, tests/test-v10-pulse.sh | MEDIUM | bash tests/test-v10-pulse.sh | approved@2026-09-28T02:50Z | Source: Loki 01:49Z (PROGRESS.md was 100 minutes stale). Built 67c6b8ac, TL APPROVE; train E17 test-v10-pulse 95/0. |
350
350
  | E-64 | Lean small path and model cascade (D31): small tasks get one sonnet implement session with the cached repo map, impacted tests, PR; no plan or Wall unless no relevant tests; opus only on a test failure, reason logged; cost per call type | loki-ts/src/engine10 (implement, fix, plan, wall, sizing, session) | HIGH | cd loki-ts && bun test tests/engine10/; then EV-8 5-task measurement | merged@2026-09-28T04:15Z | Source: D30, D31. Opus REJECT (47f0d33a): a non-escalated fix round still runs on the top model while the event says no escalation; does not merge onto main. Rework dispatched. Rework APPROVE (branch worktree-wf_4601e7b3-4d8-1: 70bae9be, db2c104f, 01ff7737): non-escalated fix rounds run on the cheap model and the event records the real model. Not merged; must be re-measured (full small arm) before it becomes the default. Merged c9c15f38 (trainE18), session.ts conflict with E-68 resolved to the 30s heartbeat; `bun test tests/engine10/` 444 pass. Still behind the gate: re-measure before default. |
351
351
  | E-65 | Session token diet: find and cut what makes one v10 session cost more than raw claude -p on the same task and model | loki-ts/src/engine10, engine10-only flag in loki-ts/src/runner if needed | HIGH | before/after token table on one task, then the EV-8 5 tasks | merged@2026-09-28T02:38Z | Source: EV-8 variant C (a sonnet session $0.155 to $0.32 vs raw opus $0.216 per whole task). Built 92e3c06c: engine sessions 6 tools, no legacy append, no MCP, settingSources project; prefix 20.4k -> 7.1k tokens; 5 tasks on claude-sonnet-5 v10 4/5 $0.1523 per completed vs raw 4/5 $0.2113. Opus CONCERN: M5 (tools spread removed) and M6 (noAppend ignored) survive 1345 tests; rework sent (query()-level assertion, rebase). Opus APPROVE on rework c9a90cce (M5, M6, M7, M8 all red; runner plus engine10 1347 pass 0 fail, also without claude on PATH). Merged 8b76fd9a with dist rebuilt. EV-8 D (opus, lean, no plan or Wall) 4/5 $0.1571 per completed p50 28s; E (sonnet, lean) 4/5 $0.1519 p50 27.5s; raw opus on the same 5 tasks 5/5 $0.2161 p50 41s (~/loki-ci-logs/ev8r-{D,E}/results.jsonl). |
352
- | EV-11 | Medium eval tier: 15 multi-file tasks with hidden tests, tier field and --tier selection | eval/loki10/tasks/, eval/loki10/harness.py, run.sh | HIGH | python3 eval/loki10/harness.py validate; no-op baseline grades 15 not completed, 0 invalid | building@2026-09-28T04:25Z | Source: D30. Opus CONCERN: 3 of 15 medium tasks verified (ea04f1e0). Rework dispatched to finish the 15. Rework (branch worktree-wf_4601e7b3-4d8-2, head 5718225a): 4 of 15 medium tasks verified (pub-attrs-1313, pub-click-2869, pub-faker-1817, pub-jinja-1413). Opus CONCERN: 11 tasks still missing; leads in eval/loki10/tasks/INDEX.md. Wave E18 rework: 11 missing medium tasks, branch slice-EV-11-medium-15. Opus REJECT: pub-werkzeug-3121 hidden test not verbatim as claimed; pub-werkzeug-3105 grades a feature deletion as completed. Rework wave E19. |
353
- | EV-12 | Large eval tier: 10 feature or legacy tasks with hidden tests, including augmentiq-style issues | eval/loki10/tasks/ | HIGH | validate plus no-op baseline over 10 | building@2026-09-28T04:25Z | Source: D30. Opus REJECT (fbd32234): 3 legacy tasks point at fixtures absent before merge (prepare_failed); spec items missing. Rework dispatched. Rework (branch worktree-wf_4601e7b3-4d8-3, head 0b9a2d91: 10 large tasks, repo-relative fixture sources). Opus REJECT: the repo-relative sources, .. rejection and fixture fixes are reproduced, but the large tasks are still smaller than the medium ones (task-size finding open). Next: rework with genuinely feature-sized tasks. Wave E18 rework: feature-sized large tasks, branch slice-EV-12-large-tasks. Opus REJECT: only lg-rbac reworked (1 of 10 feature-sized); fixture files outside the set. Rework wave E19 (fixtures now in set). |
352
+ | EV-11 | Medium eval tier: 15 multi-file tasks with hidden tests, tier field and --tier selection | eval/loki10/tasks/, eval/loki10/harness.py, run.sh | HIGH | python3 eval/loki10/harness.py validate; no-op baseline grades 15 not completed, 0 invalid | building@2026-09-28T14:20Z | Source: D30. Opus CONCERN: 3 of 15 medium tasks verified (ea04f1e0). Rework dispatched to finish the 15. Rework (branch worktree-wf_4601e7b3-4d8-2, head 5718225a): 4 of 15 medium tasks verified (pub-attrs-1313, pub-click-2869, pub-faker-1817, pub-jinja-1413). Opus CONCERN: 11 tasks still missing; leads in eval/loki10/tasks/INDEX.md. Wave E18 rework: 11 missing medium tasks, branch slice-EV-11-medium-15. Opus REJECT: pub-werkzeug-3121 hidden test not verbatim as claimed; pub-werkzeug-3105 grades a feature deletion as completed. Rework wave E19. Rework r2 f7cf7b58 (branch slice-EV-11-r2). Opus REJECT (reproduced): pub-faker-1817 grades a feature deletion (uniqueness tracking removed) as completed. Next: per-task deletion-mutant audit. Wave E21 (wf_39ab3f7d-8f3). Split EV-11a/EV-11b by task, per-task deletion-mutant audit. |
353
+ | EV-12 | Large eval tier: 10 feature or legacy tasks with hidden tests, including augmentiq-style issues | eval/loki10/tasks/ | HIGH | validate plus no-op baseline over 10 | building@2026-09-28T14:20Z | Source: D30. Opus REJECT (fbd32234): 3 legacy tasks point at fixtures absent before merge (prepare_failed); spec items missing. Rework dispatched. Rework (branch worktree-wf_4601e7b3-4d8-3, head 0b9a2d91: 10 large tasks, repo-relative fixture sources). Opus REJECT: the repo-relative sources, .. rejection and fixture fixes are reproduced, but the large tasks are still smaller than the medium ones (task-size finding open). Next: rework with genuinely feature-sized tasks. Wave E18 rework: feature-sized large tasks, branch slice-EV-12-large-tasks. Opus REJECT: only lg-rbac reworked (1 of 10 feature-sized); fixture files outside the set. Rework wave E19 (fixtures now in set). Rework r2 237daa65 (branch slice-EV-12-r2). Opus REJECT: large tasks still not all feature-sized (engineer report agrees). Next: split across engineers, a few tasks each. Wave E21 (wf_39ab3f7d-8f3). Split EV-12a/b/c by task. |
354
354
  | M-00 | MODERNIZE.md design (CTO and Architect) and the Part 2 slice table M-01.. | docs/v10/MODERNIZE.md | HIGH | doc under 400 lines with a 20 to 30 slice plan | merged@2026-09-28T02:50Z | Source: D30 Part 2. ETA 02:45Z. Built 17e97855 (399 lines, 30 slices); merges in train E17 (b2ad73ce). |
355
355
  | M-01 | Modernize event types, log wrapper and state paths | loki-ts/src/engine10/modernize/types.ts, loki-ts/src/engine10/modernize/log.ts, loki-ts/tests/engine10/modernize/log.test.ts | MEDIUM | cd loki-ts && bun test tests/engine10/modernize/log.test.ts | merged@2026-09-28T04:25Z | Source: MODERNIZE.md (D30). Depends on none. Built on branch worktree-wf_4601e7b3-4d8-4 (777f6cdd M-01, 212a7404 M-02, 6b00c05c M-05, 3d8edb5d M-06). TL CONCERN: cluster.ts tarjanSCC recursion overflows the stack on dependency chains of about 20-50k nodes (the M-28/M-29 scale); needs an iterative SCC. Wave E18 (wf_5063e58d-7a5) carries it with the M-05 iterative SCC rework, branch slice-M-05-iterative-scc. Merged f4d98c0b with M-05. |
356
356
  | M-02 | Inventory core: files, languages, build, entry points, tests | loki-ts/src/engine10/modernize/inventory.ts, loki-ts/tests/engine10/modernize/inventory.test.ts, loki-ts/tests/engine10/modernize/fixtures/inv/ | MEDIUM | cd loki-ts && bun test tests/engine10/modernize/inventory.test.ts | merged@2026-09-28T04:25Z | Source: MODERNIZE.md (D30). Depends on M-01. Built on branch worktree-wf_4601e7b3-4d8-4 (777f6cdd M-01, 212a7404 M-02, 6b00c05c M-05, 3d8edb5d M-06). TL CONCERN: cluster.ts tarjanSCC recursion overflows the stack on dependency chains of about 20-50k nodes (the M-28/M-29 scale); needs an iterative SCC. Wave E18 with M-05, branch slice-M-05-iterative-scc. Merged f4d98c0b with M-05. |
357
- | M-03 | Python import graph via tokenize (lexes py2 source) | loki-ts/src/engine10/modernize/lang/python.ts, autonomy/lib/modernize/py_imports.py, loki-ts/tests/engine10/modernize/python_graph.test.ts | MEDIUM | cd loki-ts && bun test tests/engine10/modernize/python_graph.test.ts | building@2026-09-28T04:25Z | Source: MODERNIZE.md (D30). Depends on M-02. Wave E18, based on the M-02 branch, branch slice-M-03-python-graph. TL REJECT: bare relative from-imports (from . import X) mis-parsed in py_imports.py. Rework wave E19. |
358
- | M-04 | Java graph via jdeps, import-scan fallback recorded | loki-ts/src/engine10/modernize/lang/java.ts, loki-ts/tests/engine10/modernize/java_graph.test.ts, loki-ts/tests/engine10/modernize/fixtures/java8/ | MEDIUM | cd loki-ts && bun test tests/engine10/modernize/java_graph.test.ts | building@2026-09-28T04:25Z | Source: MODERNIZE.md (D30). Depends on M-02. Wave E18, based on the M-02 branch, branch slice-M-04-java-graph. TL REJECT: wildcard and static imports silently dropped in the import-scan fallback. Rework wave E19. |
357
+ | M-03 | Python import graph via tokenize (lexes py2 source) | loki-ts/src/engine10/modernize/lang/python.ts, autonomy/lib/modernize/py_imports.py, loki-ts/tests/engine10/modernize/python_graph.test.ts | MEDIUM | cd loki-ts && bun test tests/engine10/modernize/python_graph.test.ts | merged@2026-09-28T14:10Z | Source: MODERNIZE.md (D30). Depends on M-02. Wave E18, based on the M-02 branch, branch slice-M-03-python-graph. TL REJECT: bare relative from-imports (from . import X) mis-parsed in py_imports.py. Rework wave E19. Rework 8b5e1340 TL APPROVE (sonnet); merged c90d7924; `bun test tests/engine10/` 481 pass 0 fail. |
358
+ | M-04 | Java graph via jdeps, import-scan fallback recorded | loki-ts/src/engine10/modernize/lang/java.ts, loki-ts/tests/engine10/modernize/java_graph.test.ts, loki-ts/tests/engine10/modernize/fixtures/java8/ | MEDIUM | cd loki-ts && bun test tests/engine10/modernize/java_graph.test.ts | building@2026-09-28T14:20Z | Source: MODERNIZE.md (D30). Depends on M-02. Wave E18, based on the M-02 branch, branch slice-M-04-java-graph. TL REJECT: wildcard and static imports silently dropped in the import-scan fallback. Rework wave E19. Rework r2 7713ad9b (branch slice-M-04-r2). TL REJECT (reproduced): an unresolved wildcard whose package has no local files is dropped silently (java.ts importScanGraph). Next: rework. Wave E21 (wf_39ab3f7d-8f3). r3. |
359
359
  | M-05 | SCC clustering, 1,500-line unit cap, topological waves | loki-ts/src/engine10/modernize/cluster.ts, loki-ts/tests/engine10/modernize/cluster.test.ts | MEDIUM | cd loki-ts && bun test tests/engine10/modernize/cluster.test.ts | merged@2026-09-28T04:25Z | Source: MODERNIZE.md (D30). Depends on M-02. Built on branch worktree-wf_4601e7b3-4d8-4 (777f6cdd M-01, 212a7404 M-02, 6b00c05c M-05, 3d8edb5d M-06). TL CONCERN: cluster.ts tarjanSCC recursion overflows the stack on dependency chains of about 20-50k nodes (the M-28/M-29 scale); needs an iterative SCC. Wave E18 rework: iterative Tarjan, branch slice-M-05-iterative-scc. TL APPROVE (sonnet): iterative Tarjan 372ebe11, red on recursive (RangeError), 2000/2000 fuzz identical; merged f4d98c0b, `bun test tests/engine10/modernize/` 28 pass 0 fail. |
360
360
  | M-06 | Up-front estimate (cost, time, risk), --budget math, --dry-run print | loki-ts/src/engine10/modernize/estimate.ts, loki-ts/tests/engine10/modernize/estimate.test.ts | LOW | cd loki-ts && bun test tests/engine10/modernize/estimate.test.ts | merged@2026-09-28T04:25Z | Source: MODERNIZE.md (D30). Depends on M-05. Built on branch worktree-wf_4601e7b3-4d8-4 (777f6cdd M-01, 212a7404 M-02, 6b00c05c M-05, 3d8edb5d M-06). TL CONCERN: cluster.ts tarjanSCC recursion overflows the stack on dependency chains of about 20-50k nodes (the M-28/M-29 scale); needs an iterative SCC. Wave E18 with M-05, branch slice-M-05-iterative-scc. Merged f4d98c0b with M-05. |
361
- | M-07 | modernize CLI and flag parsing; TABLE route in engine10 cli | loki-ts/src/engine10/modernize/cli.ts, loki-ts/src/engine10/cli.ts (TABLE and USAGE line only), loki-ts/tests/engine10/modernize/cli.test.ts | MEDIUM | cd loki-ts && bun test tests/engine10/modernize/cli.test.ts | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-06, E-31 merged or parked. |
361
+ | M-07 | modernize CLI and flag parsing; TABLE route in engine10 cli | loki-ts/src/engine10/modernize/cli.ts, loki-ts/src/engine10/cli.ts (TABLE and USAGE line only), loki-ts/tests/engine10/modernize/cli.test.ts | MEDIUM | cd loki-ts && bun test tests/engine10/modernize/cli.test.ts | building@2026-09-28T14:20Z | Source: MODERNIZE.md (D30). Depends on M-06, E-31 merged or parked. Wave E21 (wf_39ab3f7d-8f3). |
362
362
  | M-08 | bin/loki modernize arm to engine10 regardless of default | bin/loki (modernize arm only), tests/test-modernize-dispatch.sh | MEDIUM | bash tests/test-modernize-dispatch.sh | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-07. |
363
- | M-09 | py2/3 capture tracer with type-tagged JSON and branch coverage | autonomy/lib/modernize/py_capture.py, tests/test-modernize-py-capture.sh, tests/fixtures/modernize/py2/ | HIGH | bash tests/test-modernize-py-capture.sh | building@2026-09-28T04:25Z | Source: MODERNIZE.md (D30). Depends on M-01. Built a4fbf034 (branch worktree-wf_4601e7b3-4d8-5). Opus REJECT (reproduced): unsupported types (sets, Decimal, datetime, bytearray, custom classes) record as equal with no not_proven entry, so the oracle could certify unproven equivalence. Next: rework. Wave E18 rework: unsupported types yield not_proven, branch slice-M-09-not-proven-types. Opus REJECT of 3594eee5: subclasses of supported types (namedtuple, IntEnum, OrderedDict) tag as the base type with no not_proven. Rework wave E19. |
363
+ | M-09 | py2/3 capture tracer with type-tagged JSON and branch coverage | autonomy/lib/modernize/py_capture.py, tests/test-modernize-py-capture.sh, tests/fixtures/modernize/py2/ | HIGH | bash tests/test-modernize-py-capture.sh | merged@2026-09-28T14:10Z | Source: MODERNIZE.md (D30). Depends on M-01. Built a4fbf034 (branch worktree-wf_4601e7b3-4d8-5). Opus REJECT (reproduced): unsupported types (sets, Decimal, datetime, bytearray, custom classes) record as equal with no not_proven entry, so the oracle could certify unproven equivalence. Next: rework. Wave E18 rework: unsupported types yield not_proven, branch slice-M-09-not-proven-types. Opus REJECT of 3594eee5: subclasses of supported types (namedtuple, IntEnum, OrderedDict) tag as the base type with no not_proven. Rework wave E19. Rework 085bc2e0 Opus APPROVE; merged b8d40a34; `bash tests/test-modernize-py-capture.sh` Passed 50 Failed 0 Skipped 1 (no python2). |
364
364
  | M-10 | Coverage-guided input search (read-only session, plateau stop) | loki-ts/src/engine10/modernize/oracle/search.ts, loki-ts/tests/engine10/modernize/search.test.ts | HIGH | cd loki-ts && bun test tests/engine10/modernize/search.test.ts | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-09. |
365
365
  | M-11 | Java capture: JUnit under JDK 8 with JaCoCo plus Randoop | autonomy/lib/modernize/java_capture.sh, loki-ts/src/engine10/modernize/oracle/java.ts, loki-ts/tests/engine10/modernize/java_capture.test.ts | HIGH | cd loki-ts && bun test tests/engine10/modernize/java_capture.test.ts | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-04. |
366
366
  | M-12 | Oracle seal, held-out split, 80% floor, up-front NOT PROVEN | loki-ts/src/engine10/modernize/oracle/seal.ts, loki-ts/tests/engine10/modernize/oracle_seal.test.ts | HIGH | cd loki-ts && bun test tests/engine10/modernize/oracle_seal.test.ts | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-09. |
367
367
  | M-13 | Equivalence checker with sealed normalizers and contract output | loki-ts/src/engine10/modernize/equiv.ts, loki-ts/tests/engine10/modernize/equiv.test.ts, loki-ts/tests/engine10/modernize/fixtures/equiv/ | HIGH | cd loki-ts && bun test tests/engine10/modernize/equiv.test.ts | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-12. |
368
368
  | M-14 | Wall pre-sealed mode: oracle plus conformance, green base is an error | loki-ts/src/engine10/stages/wall.ts (pre-sealed branch only), loki-ts/tests/engine10/modernize/wall_presealed.test.ts | HIGH | cd loki-ts && bun test tests/engine10/modernize/wall_presealed.test.ts | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-12, E-54. D33: states its net core line delta; core must stay under 5,000 (92 lines of headroom shared by E-67, E-66, E-61, M-14, merge order E-67, E-66, E-61); offset any excess by deleting dead core code. |
369
369
  | M-15 | Unit runner: card to v10 run with oracle Wall and equiv check | loki-ts/src/engine10/modernize/unit.ts, loki-ts/tests/engine10/modernize/unit.test.ts | HIGH | cd loki-ts && bun test tests/engine10/modernize/unit.test.ts | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-13, M-14. |
370
- | M-16 | Deterministic codemods first (futurize, OpenRewrite) or skipped | loki-ts/src/engine10/modernize/codemod.ts, loki-ts/tests/engine10/modernize/codemod.test.ts | MEDIUM | cd loki-ts && bun test tests/engine10/modernize/codemod.test.ts | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-02. |
370
+ | M-16 | Deterministic codemods first (futurize, OpenRewrite) or skipped | loki-ts/src/engine10/modernize/codemod.ts, loki-ts/tests/engine10/modernize/codemod.test.ts | MEDIUM | cd loki-ts && bun test tests/engine10/modernize/codemod.test.ts | review@2026-09-28T14:20Z | Source: MODERNIZE.md (D30). Depends on M-02. Built 0a8bbe6c (branch slice-M-16-codemods); TL review died on the 04:48Z access outage. Wave E21 (wf_39ab3f7d-8f3). TL review. |
371
371
  | M-17 | Scheduler: N workers, worktrees, cascade, best-of-2, budget stop | loki-ts/src/engine10/modernize/scheduler.ts, loki-ts/tests/engine10/modernize/scheduler.test.ts | HIGH | cd loki-ts && bun test tests/engine10/modernize/scheduler.test.ts | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-15. |
372
372
  | M-18 | Re-slice non-equivalent units to depth 2, then NOT PROVEN | loki-ts/src/engine10/modernize/reslice.ts, loki-ts/tests/engine10/modernize/reslice.test.ts | MEDIUM | cd loki-ts && bun test tests/engine10/modernize/reslice.test.ts | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-05, M-13. |
373
- | M-19 | Strangler targets and routes.json (py2/dual/py3, per-module release) | loki-ts/src/engine10/modernize/routes.ts, loki-ts/src/engine10/modernize/targets/python3.ts, loki-ts/src/engine10/modernize/targets/java21.ts, loki-ts/tests/engine10/modernize/routes.test.ts | MEDIUM | cd loki-ts && bun test tests/engine10/modernize/routes.test.ts | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-05. |
373
+ | M-19 | Strangler targets and routes.json (py2/dual/py3, per-module release) | loki-ts/src/engine10/modernize/routes.ts, loki-ts/src/engine10/modernize/targets/python3.ts, loki-ts/src/engine10/modernize/targets/java21.ts, loki-ts/tests/engine10/modernize/routes.test.ts | MEDIUM | cd loki-ts && bun test tests/engine10/modernize/routes.test.ts | review@2026-09-28T14:20Z | Source: MODERNIZE.md (D30). Depends on M-05. Built 3299d359 (branch slice-M-19-routes); TL review died on the 04:48Z access outage. Wave E21 (wf_39ab3f7d-8f3). TL review. |
374
374
  | M-20 | Wave verify: full build, integration and original suite | loki-ts/src/engine10/modernize/wave.ts, loki-ts/tests/engine10/modernize/wave.test.ts | MEDIUM | cd loki-ts && bun test tests/engine10/modernize/wave.test.ts | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-17, M-19. |
375
375
  | M-21 | Wave ship: one PR per wave with unit receipts, draft unless all proven | loki-ts/src/engine10/modernize/ship.ts, loki-ts/tests/engine10/modernize/ship.test.ts | HIGH | cd loki-ts && bun test tests/engine10/modernize/ship.test.ts | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-20. |
376
376
  | M-22 | Unit-level resume after coordinator crash | loki-ts/src/engine10/modernize/resume.ts, loki-ts/tests/engine10/modernize/resume.test.ts | MEDIUM | cd loki-ts && bun test tests/engine10/modernize/resume.test.ts | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-17, E-39. |
377
377
  | M-23 | Remote units via POST /jobs kind unit, Helm worker.engine v10, local re-verify | autonomy/trigger-server.py (unit job kind only), deploy/helm/autonomi/templates/job-worker.yaml, deploy/helm/autonomi/values.yaml, loki-ts/src/engine10/modernize/remote.ts, loki-ts/tests/engine10/modernize/remote.test.ts, tests/test-trigger-server-unit-jobs.py | HIGH | python3 tests/test-trigger-server-unit-jobs.py && (cd loki-ts && bun test tests/engine10/modernize/remote.test.ts) | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-17. |
378
- | M-24 | Dashboard /modernize view | loki-ts/src/engine10/dashboard/modernize.ts, loki-ts/src/engine10/dashboard/server.ts (one route), loki-ts/tests/engine10/modernize/dashboard.test.ts | LOW | cd loki-ts && bun test tests/engine10/modernize/dashboard.test.ts | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-01. |
378
+ | M-24 | Dashboard /modernize view | loki-ts/src/engine10/dashboard/modernize.ts, loki-ts/src/engine10/dashboard/server.ts (one route), loki-ts/tests/engine10/modernize/dashboard.test.ts | LOW | cd loki-ts && bun test tests/engine10/modernize/dashboard.test.ts | review@2026-09-28T14:20Z | Source: MODERNIZE.md (D30). Depends on M-01. Built fe3dd87a (branch slice-M-24-dashboard); TL review died on the 04:48Z access outage. Wave E21 (wf_39ab3f7d-8f3). TL review. |
379
379
  | M-25 | Final report and verdict (COMPLETE only if all proven), sealed | loki-ts/src/engine10/modernize/report.ts, loki-ts/tests/engine10/modernize/report.test.ts | HIGH | cd loki-ts && bun test tests/engine10/modernize/report.test.ts | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-13, M-21. |
380
380
  | M-26 | End-to-end: py2 fixture repo modernized with stub provider | loki-ts/tests/engine10/modernize/e2e.test.ts, loki-ts/tests/engine10/modernize/fixtures/e2e_py2/ | MEDIUM | cd loki-ts && bun test tests/engine10/modernize/e2e.test.ts | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-08, M-22, M-25. |
381
381
  | M-27 | Legacy-Bench pilot harness; confirm public set; calibrate cap | eval/modernize/pilot.py, eval/modernize/test-pilot.sh | HIGH | bash eval/modernize/test-pilot.sh | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-26. |
382
382
  | M-28 | 200K scale run (Mercurial 4.x, measured first, fallback Calibre) | eval/modernize/scale.py, eval/modernize/SCALE.md | HIGH | python3 eval/modernize/scale.py --target hg --dry-run-first | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-27. |
383
383
  | M-29 | 1M scale run (Hadoop 2.x Java 8 to 21, measured first) | eval/modernize/scale_1m.py, eval/modernize/SCALE-1M.md | HIGH | python3 eval/modernize/scale_1m.py --dry-run-first | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-28, M-11. |
384
384
  | M-30 | User docs for loki modernize, no dashes, commands match USAGE | docs/v10/GUIDE-MODERNIZE.md, tests/test-modernize-docs.sh | LOW | bash tests/test-modernize-docs.sh | ready@2026-09-28T02:45Z | Source: MODERNIZE.md (D30). Depends on M-07. |
385
- | E-66 | "Already implemented" outcome: evidence search in code, tests, docs, CHANGELOG; no change needed verdict, receipt, issue comment, no PR | loki-ts/src/engine10 (intake or plan, implement marker path, seal, pr) | HIGH | fixture with the feature ends no change needed, no implement session; fixture without proceeds | building@2026-09-28T04:25Z | Source: D32 (augmentiq #52). Opus REJECT (reproduced): no test that ALREADY_SATISFIED opens no PR; evidence search matched 652 hits for an unrelated task on this repo; confirmation need not cite files. Rework dispatched. Rework 1c7e1b09 (branch worktree-wf_b707f4ab-24f-1): all 3 blockers fixed (no-PR test F5, 0 hits for both review sentences on this repo, citation must name an existing code or test hit; evidence in receipt). Opus CONCERN: the real-repo test uses listRepoFiles capped at 2000 of 4784 files, so removing STOP_WORDS still passes; the existsSync branch of the citation check is untested. Next: small fix (full file list in that test, one existsSync test). Wave E18 small fix (uncapped file list, existsSync test), branch slice-E-66-test-fixes. Opus APPROVE of 0a64ea98 (uncapped list, existsSync test). Merge onto main conflicts in seal.ts, supervisor.ts, types.ts, rule_of_two.test.ts after E-68/E-69; rebase dispatched (wave E19). D33: states its net core line delta; core must stay under 5,000 (92 lines of headroom shared by E-67, E-66, E-61, M-14, merge order E-67, E-66, E-61); offset any excess by deleting dead core code. |
385
+ | E-66 | "Already implemented" outcome: evidence search in code, tests, docs, CHANGELOG; no change needed verdict, receipt, issue comment, no PR | loki-ts/src/engine10 (intake or plan, implement marker path, seal, pr) | HIGH | fixture with the feature ends no change needed, no implement session; fixture without proceeds | building@2026-09-28T14:20Z | Source: D32 (augmentiq #52). Opus REJECT (reproduced): no test that ALREADY_SATISFIED opens no PR; evidence search matched 652 hits for an unrelated task on this repo; confirmation need not cite files. Rework dispatched. Rework 1c7e1b09 (branch worktree-wf_b707f4ab-24f-1): all 3 blockers fixed (no-PR test F5, 0 hits for both review sentences on this repo, citation must name an existing code or test hit; evidence in receipt). Opus CONCERN: the real-repo test uses listRepoFiles capped at 2000 of 4784 files, so removing STOP_WORDS still passes; the existsSync branch of the citation check is untested. Next: small fix (full file list in that test, one existsSync test). Wave E18 small fix (uncapped file list, existsSync test), branch slice-E-66-test-fixes. Opus APPROVE of 0a64ea98 (uncapped list, existsSync test). Merge onto main conflicts in seal.ts, supervisor.ts, types.ts, rule_of_two.test.ts after E-68/E-69; rebase dispatched (wave E19). D33: states its net core line delta; core must stay under 5,000 (92 lines of headroom shared by E-67, E-66, E-61, M-14, merge order E-67, E-66, E-61); offset any excess by deleting dead core code. Rework 135ba06b Opus APPROVE, but merged it takes core to 5,189 (D33 cap 5,000; `bun test tests/engine10/budget.test.ts`). Not merged. Next: offset about 190 core lines in the same slice (dead or duplicated core code), then merge. Wave E21 (wf_39ab3f7d-8f3). r3: D33 offset. |
386
386
  | EV-13 | Eval expected_outcome no_change_needed; aiq-52 set to it | eval/loki10/harness.py, eval/loki10/tasks/aiq-52-searchbar, test-harness.sh | HIGH | bash eval/loki10/test-harness.sh | merged@2026-09-28T04:15Z | Source: D32. Opus CONCERN: a correct v10 no-change run on aiq-52 is graded as a source change. Rework dispatched. Rework APPROVE (branch worktree-wf_b707f4ab-24f-5: 19224201, e0264724): v10 Wall side effect excluded from the diff check. Not merged yet. Merged c9c15f38 (trainE18); `bash eval/loki10/test-harness.sh` 103 passed 0 failed. |
387
387
  | E-67 | No pause state: unfinishable runs end as a draft PR or an issue comment with the reason within the cap; stdin never read | loki-ts/src/engine10 (machine, supervisor, worker, escalate, session) | HIGH | a stub provider that asks for input ends within the cap with a draft-PR or comment argv | ready@2026-09-28T04:35Z | Source: D32. Opus REJECT (reproduced): a hung worker ended FAILED with no draft PR and no comment, after the cap. Rework dispatched. Rework ba679f4e (branch worktree-wf_b707f4ab-24f-2). Opus REJECT: at the default cap the supervisor backstop fires before the worker cap can seal; concern: the diff check misses untracked files and uncommitted work never reaches a PR. Next: rework. Held, no builder since 03:20Z (row was stale, not running). Dispatch after E-61 (session.ts) and the E-66 rebase (supervisor.ts) merge, from rework ba679f4e plus the Opus findings above. D33: states its net core line delta; core must stay under 5,000 (92 lines of headroom shared by E-67, E-66, E-61, M-14, merge order E-67, E-66, E-61); offset any excess by deleting dead core code. |
388
388
  | E-68 | Per-call deadline at the stage limit, progress every 30s, every exit code classified (125, 143 included), never "cause not classified" | loki-ts/src/engine10/session.ts, failures.ts | HIGH | per-code tests plus a grep test | merged@2026-09-28T04:15Z | Source: D32. Opus REJECT (reproduced): a real limit kill reports "exit 143 (SIGTERM)" because the session child traps SIGTERM; the stub test missed it. Rework dispatched. Rework APPROVE (branch worktree-wf_b707f4ab-24f-3: 4dd05bf9, 922bd923): a limit kill is classified from the engine, not the child exit code. Not merged yet. Merged c9c15f38 (trainE18); engine10 `bun test tests/engine10/` 444 pass 0 fail. |
@@ -391,9 +391,11 @@ set is declared to avoid overlap with those and with each other.
391
391
  | E-71 | Pulse UNEVIDENCED_CLAIM treats M-NN rows like S/E/EV rows (only status and notes cells can claim), so an M row's spec cell never flags | scripts/v10-pulse.sh (the row-id regex in check_unevidenced_claims only), tests/test-v10-pulse.sh | LOW | bash tests/test-v10-pulse.sh; a case with an M row whose Wall cell says "green" is not flagged, and its notes cell still is | merged@2026-09-28T04:35Z | Source: pulse flagged M-14 (8f4dc965) for its title "green base is an error", a spec, not a claim. TL APPROVE (sonnet): red without the fix (95 passed 1 failed), `bash tests/test-v10-pulse.sh` 96 passed 0 failed on main. |
392
392
  | E-72 | release.sh --bump-only leaves a dist bundle unchanged when only its debugId differs (no churn in cockpit.js on a version bump) | scripts/release.sh (dist step only), tests/test-release-bump-only.sh | LOW | bash tests/test-release-bump-only.sh | merged@2026-09-28T04:35Z | Source: v10.0.1 bump rewrote cockpit.js and .map with only a new debugId; the Release Manager reverted them by hand. TL APPROVE (sonnet): red on pre-fix release.sh (3 passed 3 failed), `bash tests/test-release-bump-only.sh` 6 passed 0 failed on main; registered in run-all-tests. |
393
393
  | E-73 | Guard (D26): no test writes a hardcoded "far-future" latest version that the current VERSION can overtake; derive it from VERSION instead | tests/test-no-stale-future-version.sh, docs/v10/GUARDS.md (one entry) | LOW | bash tests/test-no-stale-future-version.sh; red on a fixture test that writes latest 9.99.0 against VERSION 10.0.1 | merged@2026-09-28T04:35Z | Source: incident 898fa081, v10.0.0 blocked from npm by latest=9.99.0 in tests/test-start-update-hint.sh (fixed 306b6b0c). TL APPROVE (sonnet); `bash tests/test-no-stale-future-version.sh` RESULT: PASS on main; registered in run-all-tests. |
394
- | E-74 | release.sh run_bump_only actually calls the debugId restore helper (end-to-end test of the call site, not only the helper) | tests/test-release-bump-only.sh (one leg) | LOW | bash tests/test-release-bump-only.sh; deleting the call site in run_bump_only turns the new leg red | ready@2026-09-28T04:35Z | Source: E-72 TL non-blocking note on 1b06bc61: removing the call site does not turn the E-72 test red. |
395
- | E-75 | Pulse main-CI check never reads UNKNOWN for a completed Tests run: fall back to `gh run list --commit <sha> --workflow Tests` when the cached check fails, and report RED with the run id | scripts/v10-pulse.sh (main CI check only), tests/test-v10-pulse.sh | MEDIUM | bash tests/test-v10-pulse.sh; a stubbed gh whose check call fails but whose run list says failure yields CI_RED, not UNKNOWN | ready@2026-09-28T04:45Z | Source: main red at 5404b0c6, e26bf52b, 983dda58 (Tests run 36377688703) while the pulse printed Main CI UNKNOWN each turn. |
394
+ | E-74 | release.sh run_bump_only actually calls the debugId restore helper (end-to-end test of the call site, not only the helper) | tests/test-release-bump-only.sh (one leg) | LOW | bash tests/test-release-bump-only.sh; deleting the call site in run_bump_only turns the new leg red | building@2026-09-28T14:20Z | Source: E-72 TL non-blocking note on 1b06bc61: removing the call site does not turn the E-72 test red. Wave E21 (wf_39ab3f7d-8f3). |
395
+ | E-75 | Pulse main-CI check never reads UNKNOWN for a completed Tests run: fall back to `gh run list --commit <sha> --workflow Tests` when the cached check fails, and report RED with the run id | scripts/v10-pulse.sh (main CI check only), tests/test-v10-pulse.sh | MEDIUM | bash tests/test-v10-pulse.sh; a stubbed gh whose check call fails but whose run list says failure yields CI_RED, not UNKNOWN | building@2026-09-28T14:20Z | Source: main red at 5404b0c6, e26bf52b, 983dda58 (Tests run 36377688703) while the pulse printed Main CI UNKNOWN each turn. Wave E21 (wf_39ab3f7d-8f3). |
396
396
  | E-76 | Split the engine10 budget test per D33: core under 5,000, modernize/ under 4,000, core never imports modernize | loki-ts/tests/engine10/budget.test.ts | LOW | cd loki-ts && bun test tests/engine10/budget.test.ts; core limit 4900 turns test 1 red | merged@2026-09-28T04:42Z | Source: D33 (CTO). Main red since 5404b0c6 on the combined 5,288 count. TL APPROVE (sonnet) on 797705bc: `bun test tests/engine10/budget.test.ts` 3 pass exit 0, core 4907, modernize 381, core limit 4900 goes red; merged 84fbf9b4, full `bun test tests/engine10/` 474 pass 0 fail. |
397
+ | E-77 | Pulse SESSION_STALLED violation: no assistant turn for more than 20 minutes while the /loop is active (armed wakeup or live workflow), reading the newest session transcript mtime | scripts/v10-pulse.sh (one new check), tests/test-v10-pulse.sh | MEDIUM | bash tests/test-v10-pulse.sh; a fixture transcript 25 minutes old with an active-loop marker yields SESSION_STALLED, 10 minutes old does not, no marker does not | building@2026-09-28T14:20Z | Source: founder 14:00Z; session stalled 04:48Z to about 14:00Z on "organization has disabled Claude subscription access", pulse raised nothing. Wave E21 (wf_39ab3f7d-8f3). |
398
+ | EV-14 | v10 against raw on the medium and large tiers (same model, same tasks, both arms), gate table per tier for the default-flip decision (E-31) | eval/loki10 results, docs/v10/METRICS.md (one section) | HIGH | eval/loki10/run.sh per tier for arms raw and v10; every task has a row in both arms, none arm_unavailable; METRICS.md table cites the result files | ready@2026-09-28T14:20Z | Source: founder priority 14:00Z (flip v10 to default once it beats raw on the measured tiers). Depends on EV-11 and EV-12 merged; paid run, one tier at a time. |
397
399
  | E-58 | Issue-ref runs: supervisor creates runDir before the fetch child writes issue.json; makes E-47 green | loki-ts/src/engine10/supervisor.ts (one line before fetchIssueToFile), E-47 test files from 544348a7 | MEDIUM | cd loki-ts && bun test tests/engine10/issue_ref_e2e.test.ts (3 pass) | released@2026-09-28T02:38Z | Source: E-47 finding (TL reproduced). Merged 646a6cd7 (train E13): engine10 388 pass 0 fail, tsc exit 0, test-engine10-dist 18/0, test-engine10-docs 26 passed, test-harness 82/0. APPROVE (6384fff9); issue_ref_e2e 3 pass. Released v9.81.0 (npm view loki-mode time: 2026-09-28T02:38:54Z). |
398
400
  | E-59 | Receipt model and summary tokens match the provider: cost.ts takes model from the result-cost file; events.ts fold sums cache read and creation tokens; makes E-50 green | loki-ts/src/engine10/cost.ts, loki-ts/src/engine10/events.ts, E-50 test files from 716618d4 | HIGH | cd loki-ts && bun test tests/engine10/model_report.test.ts tests/engine10/output.test.ts | released@2026-09-28T02:38Z | Source: E-50 finding. Reconcile with E-44 (output.ts already folds cache tokens at render). Opus reviewer (cost numbers feed the gate). Opus CONCERN: writeResultCost writes no model, so real records still use the caller model; summary tokens at supervisor.ts still exclude cache. Rework dispatched. Merged 3ab2a8fa (train E14, rebased on main): engine10 404 pass 0 fail (402 pass 0 fail with claude removed from PATH), tsc exit 0, test-harness 86/0, test-local-ci-gitleaks 6/0, test-engine10-dist 18/0. Released v9.81.0 (npm view loki-mode time: 2026-09-28T02:38:54Z). |
399
401
  | EV-8 | v10 cost check on 5 tasks before the full arm (CEO 23:31Z): v10 arm, same model, after E-42 and E-45 merge | eval/loki10 results (gitignored) plus docs/v10/METRICS.md block | HIGH | eval/loki10/run.sh --arm v10 --tasks <5 ids> reports completed, time to PR and provider cost per task | released@2026-09-28T02:38Z | Target cost per completed task at or below $0.2363 (raw claude -p full arm). Depends on E-42, E-45, E-38 (--tasks). Incident 01:38Z: first run 0/5 on both variants measured the wrong code. The harness default arm binary is the global loki (loki --version: v9.78.0), and the main checkout node_modules still had agent SDK 0.3.267 (package.json pins 0.3.283), whose bundled Claude Code 2.1.267 rejects claude-opus-5-5, so every session exited "error" in about 1s with 0 tokens. Fixed in 7c3dea3d: bun install (node_modules 0.3.283), repro with the harness arm_env and arm_auth now completes on claude-opus-5-5 ($0.11, 13s); dist rebuilt. Rerun started with LOKI_EVAL_LOKI_BIN=<repo>/bin/loki. Guards E-61, E-62. Rerun measured (not a code slice): A 4/5 $0.5954, B 5/5 $0.3976, C (all sonnet, no plan, no Wall) 4/5 $0.294, raw 5/5 $0.2161 (~/loki-ci-logs/ev8r-{A,B,C}/results.jsonl). Gate not met on cost; D31 and E-64, E-65 follow. Released v9.81.0 (npm view loki-mode time: 2026-09-28T02:38:54Z). |
@@ -1,5 +1,11 @@
1
1
  # Progress
2
2
 
3
+ ## 2026-09-28T14:10Z: resumed after a 9-hour stall -- read first on resume
4
+ - Shipped before the stall: v10.0.1 (npm gitHead 76ec1c24) and v10.1.0 (Release run for b60ca0ef all jobs success; `npm view loki-mode@10.1.0 gitHead` b60ca0ef; dist-tag latest 10.1.0).
5
+ - Stall: every model call from 04:48Z failed with "Your organization has disabled Claude subscription access for Claude Code" (workflow failures in wf_bd919989-941 and wf_1efd6e89-1f3); nothing ran until about 14:00Z. The pulse raised no violation for it; E-77 adds SESSION_STALLED.
6
+ - Salvage: all 15 builder worktrees were clean (work committed on branches); removed them, branches kept. Approved and merged: M-03 (c90d7924), M-09 (b8d40a34); `bun test tests/engine10/` 481 pass 0 fail. E-66 (Opus APPROVE) not merged: it takes core to 5,189 against the D33 cap; back to ready with an offset requirement. Built but unreviewed (reviews died in the outage): E-61, M-16, M-19, M-24, now in review. Rejected with reproduced findings: EV-11, EV-12, M-04, E-62, back to ready.
7
+ - Founder priorities (14:00Z): EV-11 and EV-12 first, then the v10 default flip once v10 beats raw on the measured tiers (E-31 after EV-9 over all tiers), then loki modernize CLI wiring (M-07, M-08).
8
+
3
9
  ## 2026-09-28T04:45Z: drift audit (turn 432, 6-hour window) and main red again
4
10
  - Releases in 6h: 6 (v9.79.0, v9.80.0, v9.80.1, v9.81.0, v10.0.0 tag only, v10.0.1), 151 commits on main. CONTROL "1 per 90 min" met; the 30/day pace is not (about 24/day).
5
11
  - Red main windows in 6h, from `gh run list --workflow Tests --branch main`: 898fa081 to d8774dd5 (about 1h, version-literal test, fixed 306b6b0c, guard E-73) and 5404b0c6 to 983dda58 (now). Cause of the second: M-05 merged after only `bun test tests/engine10/modernize/`; the full `tests/engine10/` includes the E-02 size budget, which went 5,288 against 5,000. The Chief of Staff's own merge, not a builder's.
@@ -1,5 +1,5 @@
1
1
  // @bun
2
- var uo=Object.create;var{getPrototypeOf:po,defineProperty:QG,getOwnPropertyNames:co}=Object;var lo=Object.prototype.hasOwnProperty;function io($){return this[$]}var ao,oo,no=($,Z,Q)=>{var X=$!=null&&typeof $==="object";if(X){var J=Z?ao??=new WeakMap:oo??=new WeakMap,K=J.get($);if(K)return K}Q=$!=null?uo(po($)):{};let Y=Z||!$||!$.__esModule?QG(Q,"default",{value:$,enumerable:!0}):Q;for(let z of co($))if(!lo.call(Y,z))QG(Y,z,{get:io.bind($,z),enumerable:!0});if(X)J.set($,Y);return Y};var cJ=($,Z)=>()=>(Z||$((Z={exports:{}}).exports,Z),Z.exports);var so=($)=>$;function ro($,Z){this[$]=so.bind(null,Z)}var P0=($,Z)=>{for(var Q in Z)QG($,Q,{get:Z[Q],enumerable:!0,configurable:!0,set:ro.bind(Z,Q)})};var v=($,Z)=>()=>($&&(Z=$($=0)),Z);var D7=import.meta.require;var uC={};P0(uC,{lokiDir:()=>T0,homeLokiDir:()=>E3,findRepoRootForVersion:()=>JG,REPO_ROOT:()=>i0});import{resolve as I7,dirname as XG}from"path";import{fileURLToPath as to}from"url";import{existsSync as lJ}from"fs";import{homedir as eo}from"os";function $n(){let $=mC;for(let Z=0;Z<6;Z++){if(lJ(I7($,"VERSION"))&&lJ(I7($,"autonomy/run.sh")))return $;let Q=XG($);if(Q===$)break;$=Q}return I7(mC,"..","..","..")}function JG($){let Z=$;for(let Q=0;Q<6;Q++){if(lJ(I7(Z,"VERSION"))&&lJ(I7(Z,"autonomy/run.sh")))return Z;let X=XG(Z);if(X===Z)break;Z=X}return I7($,"..","..","..")}function T0(){return process.env.LOKI_DIR??I7(process.cwd(),".loki")}function E3(){return I7(eo(),".loki")}var mC,i0;var X8=v(()=>{mC=XG(to(import.meta.url));i0=$n()});import{readFileSync as Zn}from"fs";import{resolve as Qn,dirname as Xn}from"path";import{fileURLToPath as Jn}from"url";function F7(){if(k3!==null)return k3;let $="10.1.0";if(typeof $==="string"&&$.length>0)return k3=$,k3;try{let Z=Xn(Jn(import.meta.url)),Q=JG(Z);k3=Zn(Qn(Q,"VERSION"),"utf-8").trim()}catch{k3="unknown"}return k3}var k3=null;var L$=v(()=>{X8()});var oC={};P0(oC,{runOrThrow:()=>An,run:()=>D0,readStreamCapped:()=>iJ,commandVersion:()=>Tn,commandExists:()=>J9,ShellError:()=>YG,MAX_STDOUT_BYTES:()=>aC});async function iJ($,Z=aC){let Q=$.getReader(),X=new TextDecoder,J="",K=0;try{while(K<Z){let{done:Y,value:z}=await Q.read();if(Y)break;if(!z)continue;if(K+=z.byteLength,K>Z){let V=z.byteLength-(K-Z);J+=X.decode(z.subarray(0,V),{stream:!0});break}J+=X.decode(z,{stream:!0})}J+=X.decode()}finally{try{await Q.cancel()}catch{}Q.releaseLock()}return J}async function D0($,Z={}){let Q=Bun.spawn({cmd:[...$],stdout:"pipe",stderr:"pipe",env:Z.env?{...process.env,...Z.env}:process.env,cwd:Z.cwd}),X,J;if(Z.timeoutMs&&Z.timeoutMs>0)X=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}J=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},Z.timeoutMs);try{let[K,Y,z]=await Promise.all([iJ(Q.stdout),new Response(Q.stderr).text(),Q.exited]);return{stdout:K,stderr:Y,exitCode:z}}finally{if(X)clearTimeout(X);if(J)clearTimeout(J)}}async function An($,Z={}){let Q=await D0($,Z);if(Q.exitCode!==0)throw new YG(`command failed (${Q.exitCode}): ${$.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function J9($){let Z=Cn($),Q=await D0(["sh","-c",`command -v ${Z}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function Cn($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function Tn($,Z="--version"){if(!await J9($))return null;let X=await D0([$,Z],{timeoutMs:5000});if(X.exitCode!==0)return null;return((X.stdout||X.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var aC=16777216,YG;var K9=v(()=>{YG=class YG extends Error{message;exitCode;stdout;stderr;constructor($,Z,Q,X){super($);this.message=$;this.exitCode=Z;this.stdout=Q;this.stderr=X;this.name="ShellError"}}});function w7($){return Dn?"":$}var Dn,k0,P8,d0,k48,J8,j8,Y9,p;var c5=v(()=>{Dn=(process.env.NO_COLOR??"").length>0;k0=w7("\x1B[0;31m"),P8=w7("\x1B[0;32m"),d0=w7("\x1B[1;33m"),k48=w7("\x1B[0;34m"),J8=w7("\x1B[0;36m"),j8=w7("\x1B[1m"),Y9=w7("\x1B[2m"),p=w7("\x1B[0m")});import{accessSync as bn,constants as yn,existsSync as _n,statSync as fn}from"fs";async function s6(){if(A$!==void 0)return A$;let $="/opt/homebrew/bin/python3.12";if(_n($))return A$=$,$;let Z=await J9("python3.12");if(Z)return A$=Z,Z;let Q=await J9("python3");return A$=Q,Q}async function O6($,Z={}){let Q=await s6();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return D0([Q,"-c",$],Z)}async function R7(){let $=(process.env.PATH??"").split(":").filter((Z)=>Z.startsWith("/"));for(let Z of[...hn,...$.map((Q)=>`${Q}/python3`)])try{if(!fn(Z).isFile())continue;if(bn(Z,yn.X_OK),(await D0([Z,"-I","-S","-c",""],{timeoutMs:1e4})).exitCode===0)return Z}catch{}return null}var A$,vn,hn;var C5=v(()=>{K9();vn=["/usr/bin/python3","/bin/python3"],hn=vn});var UT={};P0(UT,{runStatus:()=>qs});import{existsSync as z9,readFileSync as t4,readdirSync as YT,statSync as zT}from"fs";import{resolve as u8,basename as Zs}from"path";import{homedir as Qs}from"os";function VT($){let Z=Math.trunc($);if(Z>=1e6)return`${(Math.trunc(Z/1e6*10)/10).toFixed(1)}M`;if(Z>=1000)return`${(Math.trunc(Z/1000*10)/10).toFixed(1)}K`;return String(Z)}function WT($,Z,Q){if(Z===0)return null;let X=Math.trunc($*100/Z),J=Math.trunc($*oJ/Z);if(J>oJ)J=oJ;let K=oJ-J,Y=P8;if(X>=80)Y=k0;else if(X>=50)Y=d0;let z="=".repeat(Math.max(0,J))+" ".repeat(Math.max(0,K)),V=VT($),W=VT(Z);return` ${j8}${Q}${p} ${Y}[${z}]${p} ${X}% (${V} / ${W})`}async function Js(){if(await J9("jq"))return!0;return process.stdout.write(`${k0}Error: jq is required but not installed.${p}
2
+ var uo=Object.create;var{getPrototypeOf:po,defineProperty:QG,getOwnPropertyNames:co}=Object;var lo=Object.prototype.hasOwnProperty;function io($){return this[$]}var ao,oo,no=($,Z,Q)=>{var X=$!=null&&typeof $==="object";if(X){var J=Z?ao??=new WeakMap:oo??=new WeakMap,K=J.get($);if(K)return K}Q=$!=null?uo(po($)):{};let Y=Z||!$||!$.__esModule?QG(Q,"default",{value:$,enumerable:!0}):Q;for(let z of co($))if(!lo.call(Y,z))QG(Y,z,{get:io.bind($,z),enumerable:!0});if(X)J.set($,Y);return Y};var cJ=($,Z)=>()=>(Z||$((Z={exports:{}}).exports,Z),Z.exports);var so=($)=>$;function ro($,Z){this[$]=so.bind(null,Z)}var P0=($,Z)=>{for(var Q in Z)QG($,Q,{get:Z[Q],enumerable:!0,configurable:!0,set:ro.bind(Z,Q)})};var v=($,Z)=>()=>($&&(Z=$($=0)),Z);var D7=import.meta.require;var uC={};P0(uC,{lokiDir:()=>T0,homeLokiDir:()=>E3,findRepoRootForVersion:()=>JG,REPO_ROOT:()=>i0});import{resolve as I7,dirname as XG}from"path";import{fileURLToPath as to}from"url";import{existsSync as lJ}from"fs";import{homedir as eo}from"os";function $n(){let $=mC;for(let Z=0;Z<6;Z++){if(lJ(I7($,"VERSION"))&&lJ(I7($,"autonomy/run.sh")))return $;let Q=XG($);if(Q===$)break;$=Q}return I7(mC,"..","..","..")}function JG($){let Z=$;for(let Q=0;Q<6;Q++){if(lJ(I7(Z,"VERSION"))&&lJ(I7(Z,"autonomy/run.sh")))return Z;let X=XG(Z);if(X===Z)break;Z=X}return I7($,"..","..","..")}function T0(){return process.env.LOKI_DIR??I7(process.cwd(),".loki")}function E3(){return I7(eo(),".loki")}var mC,i0;var X8=v(()=>{mC=XG(to(import.meta.url));i0=$n()});import{readFileSync as Zn}from"fs";import{resolve as Qn,dirname as Xn}from"path";import{fileURLToPath as Jn}from"url";function F7(){if(k3!==null)return k3;let $="10.1.1";if(typeof $==="string"&&$.length>0)return k3=$,k3;try{let Z=Xn(Jn(import.meta.url)),Q=JG(Z);k3=Zn(Qn(Q,"VERSION"),"utf-8").trim()}catch{k3="unknown"}return k3}var k3=null;var L$=v(()=>{X8()});var oC={};P0(oC,{runOrThrow:()=>An,run:()=>D0,readStreamCapped:()=>iJ,commandVersion:()=>Tn,commandExists:()=>J9,ShellError:()=>YG,MAX_STDOUT_BYTES:()=>aC});async function iJ($,Z=aC){let Q=$.getReader(),X=new TextDecoder,J="",K=0;try{while(K<Z){let{done:Y,value:z}=await Q.read();if(Y)break;if(!z)continue;if(K+=z.byteLength,K>Z){let V=z.byteLength-(K-Z);J+=X.decode(z.subarray(0,V),{stream:!0});break}J+=X.decode(z,{stream:!0})}J+=X.decode()}finally{try{await Q.cancel()}catch{}Q.releaseLock()}return J}async function D0($,Z={}){let Q=Bun.spawn({cmd:[...$],stdout:"pipe",stderr:"pipe",env:Z.env?{...process.env,...Z.env}:process.env,cwd:Z.cwd}),X,J;if(Z.timeoutMs&&Z.timeoutMs>0)X=setTimeout(()=>{try{Q.kill("SIGTERM")}catch{}J=setTimeout(()=>{try{Q.kill("SIGKILL")}catch{}},2000)},Z.timeoutMs);try{let[K,Y,z]=await Promise.all([iJ(Q.stdout),new Response(Q.stderr).text(),Q.exited]);return{stdout:K,stderr:Y,exitCode:z}}finally{if(X)clearTimeout(X);if(J)clearTimeout(J)}}async function An($,Z={}){let Q=await D0($,Z);if(Q.exitCode!==0)throw new YG(`command failed (${Q.exitCode}): ${$.join(" ")}`,Q.exitCode,Q.stdout,Q.stderr);return Q}async function J9($){let Z=Cn($),Q=await D0(["sh","-c",`command -v ${Z}`],{timeoutMs:5000});if(Q.exitCode===0)return Q.stdout.trim()||null;return null}function Cn($){if(!/^[A-Za-z0-9._/-]+$/.test($))throw Error(`refused to shell-escape suspect token: ${$}`);return $}async function Tn($,Z="--version"){if(!await J9($))return null;let X=await D0([$,Z],{timeoutMs:5000});if(X.exitCode!==0)return null;return((X.stdout||X.stderr).split(/\r?\n/)[0]?.trim()??"")||null}var aC=16777216,YG;var K9=v(()=>{YG=class YG extends Error{message;exitCode;stdout;stderr;constructor($,Z,Q,X){super($);this.message=$;this.exitCode=Z;this.stdout=Q;this.stderr=X;this.name="ShellError"}}});function w7($){return Dn?"":$}var Dn,k0,P8,d0,k48,J8,j8,Y9,p;var c5=v(()=>{Dn=(process.env.NO_COLOR??"").length>0;k0=w7("\x1B[0;31m"),P8=w7("\x1B[0;32m"),d0=w7("\x1B[1;33m"),k48=w7("\x1B[0;34m"),J8=w7("\x1B[0;36m"),j8=w7("\x1B[1m"),Y9=w7("\x1B[2m"),p=w7("\x1B[0m")});import{accessSync as bn,constants as yn,existsSync as _n,statSync as fn}from"fs";async function s6(){if(A$!==void 0)return A$;let $="/opt/homebrew/bin/python3.12";if(_n($))return A$=$,$;let Z=await J9("python3.12");if(Z)return A$=Z,Z;let Q=await J9("python3");return A$=Q,Q}async function O6($,Z={}){let Q=await s6();if(!Q)return{stdout:"",stderr:"python3 not found",exitCode:127};return D0([Q,"-c",$],Z)}async function R7(){let $=(process.env.PATH??"").split(":").filter((Z)=>Z.startsWith("/"));for(let Z of[...hn,...$.map((Q)=>`${Q}/python3`)])try{if(!fn(Z).isFile())continue;if(bn(Z,yn.X_OK),(await D0([Z,"-I","-S","-c",""],{timeoutMs:1e4})).exitCode===0)return Z}catch{}return null}var A$,vn,hn;var C5=v(()=>{K9();vn=["/usr/bin/python3","/bin/python3"],hn=vn});var UT={};P0(UT,{runStatus:()=>qs});import{existsSync as z9,readFileSync as t4,readdirSync as YT,statSync as zT}from"fs";import{resolve as u8,basename as Zs}from"path";import{homedir as Qs}from"os";function VT($){let Z=Math.trunc($);if(Z>=1e6)return`${(Math.trunc(Z/1e6*10)/10).toFixed(1)}M`;if(Z>=1000)return`${(Math.trunc(Z/1000*10)/10).toFixed(1)}K`;return String(Z)}function WT($,Z,Q){if(Z===0)return null;let X=Math.trunc($*100/Z),J=Math.trunc($*oJ/Z);if(J>oJ)J=oJ;let K=oJ-J,Y=P8;if(X>=80)Y=k0;else if(X>=50)Y=d0;let z="=".repeat(Math.max(0,J))+" ".repeat(Math.max(0,K)),V=VT($),W=VT(Z);return` ${j8}${Q}${p} ${Y}[${z}]${p} ${X}% (${V} / ${W})`}async function Js(){if(await J9("jq"))return!0;return process.stdout.write(`${k0}Error: jq is required but not installed.${p}
3
3
  `),process.stdout.write(`Install with:
4
4
  `),process.stdout.write(` brew install jq (macOS)
5
5
  `),process.stdout.write(` apt install jq (Debian/Ubuntu)
@@ -1470,4 +1470,4 @@ Set LOKI_LEGACY_BASH=1 to force the bash CLI for every command.
1470
1470
  `),2}case"start":{let{runStart:X}=await Promise.resolve().then(() => (nl(),ol));return X(Q)}case"engine10":{let{runEngine10:X}=await Promise.resolve().then(() => (tl(),rl)),{registryLoader:J}=await Promise.resolve().then(() => (Lq(),So));return X(Q,J)}default:return process.stderr.write(`Unknown command: ${Z}
1471
1471
  `),process.stderr.write(bo),2}}JT();process.on("SIGINT",()=>process.exit(130));process.on("SIGTERM",()=>process.exit(143));var H48=await G48(Bun.argv.slice(2));process.exit(H48);
1472
1472
 
1473
- //# debugId=8094C4D19BC46B6623398FB7BD743AE7
1473
+ //# debugId=444CD831E146876C325FF4D48982624E
package/mcp/__init__.py CHANGED
@@ -75,4 +75,4 @@ try:
75
75
  except ImportError:
76
76
  __all__ = ['mcp']
77
77
 
78
- __version__ = '10.1.0'
78
+ __version__ = '10.1.1'
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": "10.1.0",
4
+ "version": "10.1.1",
5
5
  "description": "Loki Mode by Autonomi. Autonomous spec-to-product system: takes a PRD, GitHub issue, OpenAPI/JSON/YAML, or one-line brief to a deployed app via the RARV-C closure loop with 8 quality gates. Provider-agnostic (Claude Code, OpenAI Codex, Cline, Aider, opencode).",
6
6
  "keywords": [
7
7
  "agent",
@@ -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": "10.1.0",
5
+ "version": "10.1.1",
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-JLmXzxqi.js";import{B as C}from"./Button-CyWOw1Bk.js";import{T as $e}from"./trending-up-CqZThz26.js";import{C as z}from"./clock-rzxwnuLM.js";import{A as Be,U as ue,M as De}from"./Avatar-BOhL0n6E.js";import{A as J}from"./activity-DSavuwyT.js";import{R as pe}from"./refresh-cw-YelQ45nx.js";import{G as ze}from"./globe-BM6uvx4Q.js";import{C as Le}from"./chevron-left-B2USiPOZ.js";import{C as je}from"./check-DOrNSoDM.js";import{D as Y}from"./dollar-sign-bvddxRmc.js";import{U as Te}from"./user-CG96I_PT.js";import{D as Me}from"./database-G9bBiLg8.js";import{L as Ue}from"./lock-Da91KLZZ.js";import{S as Re}from"./scroll-text-C88oxteF.js";import{S as Ie}from"./shield-alert-gpP8kh02.js";/**
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-Dtrn_88z.js";import{B as C}from"./Button-Wo3WJ5Kd.js";import{T as $e}from"./trending-up-CwcHClXI.js";import{C as z}from"./clock-CR8oME3b.js";import{A as Be,U as ue,M as De}from"./Avatar-DZrKgEX4.js";import{A as J}from"./activity-BzYTwsTy.js";import{R as pe}from"./refresh-cw-CA64KPjz.js";import{G as ze}from"./globe-Ckj7P6MF.js";import{C as Le}from"./chevron-left-v-IUHzhm.js";import{C as je}from"./check-Bg2o382k.js";import{D as Y}from"./dollar-sign-D1D7210y.js";import{U as Te}from"./user-B249yxJV.js";import{D as Me}from"./database-DGS4lCam.js";import{L as Ue}from"./lock-a4yooVvD.js";import{S as Re}from"./scroll-text-DSAnxmlo.js";import{S as Ie}from"./shield-alert-DL9xNxeK.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.
@@ -1,4 +1,4 @@
1
- import{c as l,j as s}from"./index-JLmXzxqi.js";/**
1
+ import{c as l,j as s}from"./index-Dtrn_88z.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-JLmXzxqi.js";import{C as r}from"./clock-rzxwnuLM.js";import{C as a}from"./circle-alert-Bo5f9KMG.js";import{C as l}from"./check-DOrNSoDM.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
+ import{j as e}from"./index-Dtrn_88z.js";import{C as r}from"./clock-CR8oME3b.js";import{C as a}from"./circle-alert-G3MHxw9O.js";import{C as l}from"./check-Bg2o382k.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-JLmXzxqi.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
+ import{r as p,j as t}from"./index-Dtrn_88z.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-JLmXzxqi.js";import{P as K,S as He,E as Be}from"./ErrorBoundary-D3C-yCJk.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-BxwJ7kT_.js";import{C as oe}from"./check-DOrNSoDM.js";import{C as Ye}from"./clock-rzxwnuLM.js";import{D as Xe}from"./dollar-sign-bvddxRmc.js";import{U as Ze}from"./upload-BZPVsx2j.js";import{L as V}from"./loader-circle-BTy_2p55.js";/**
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-Dtrn_88z.js";import{P as K,S as He,E as Be}from"./ErrorBoundary-U_89NZcK.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-2MLPuEWk.js";import{C as oe}from"./check-Bg2o382k.js";import{C as Ye}from"./clock-CR8oME3b.js";import{D as Xe}from"./dollar-sign-D1D7210y.js";import{U as Ze}from"./upload-ODPqesIu.js";import{L as V}from"./loader-circle-CwrHVSiy.js";/**
2
2
  * @license lucide-react v0.577.0 - ISC
3
3
  *
4
4
  * This source code is licensed under the ISC license.