loki-mode 11.17.59 → 11.17.61

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 (74) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/autonomy/lib/engine10-push.sh +79 -1
  4. package/autonomy/lib/proof_redact.py +26 -2
  5. package/autonomy/run.sh +11 -1
  6. package/dashboard/__init__.py +1 -1
  7. package/docs/CLI-REFERENCE.md +1 -1
  8. package/docs/INSTALLATION.md +1 -1
  9. package/docs/QUICKSTART.md +7 -0
  10. package/docs/v10/FAILURE-CLASSES.md +20 -0
  11. package/docs/v10/PROGRESS.md +3 -0
  12. package/loki-ts/dist/cockpit.js +10 -10
  13. package/loki-ts/dist/loki.js +1211 -1208
  14. package/mcp/__init__.py +1 -1
  15. package/package.json +2 -2
  16. package/packages/control-plane/dist/server.js +8 -7
  17. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  18. package/web-app/dist/assets/{AdminPage-CCO9zGD0.js → AdminPage-CUXH4xaY.js} +1 -1
  19. package/web-app/dist/assets/{Avatar-JPtFS3re.js → Avatar-CuAg8cd6.js} +1 -1
  20. package/web-app/dist/assets/{Badge-1bUFOFcI.js → Badge-CcRQixFz.js} +1 -1
  21. package/web-app/dist/assets/{Button-BQn8thxN.js → Button-DAMyKckC.js} +1 -1
  22. package/web-app/dist/assets/{CockpitPage-olBRJMLN.js → CockpitPage-Bt7STzl7.js} +1 -1
  23. package/web-app/dist/assets/{ComparePage-B-o4mxlZ.js → ComparePage---ACjFGI.js} +1 -1
  24. package/web-app/dist/assets/{ErrorBoundary-C4IN6YYt.js → ErrorBoundary-CrsirUAh.js} +1 -1
  25. package/web-app/dist/assets/{EvidenceReceiptPanel-CH4iRJiJ.js → EvidenceReceiptPanel-C1EfP_dv.js} +1 -1
  26. package/web-app/dist/assets/{GitHubIssuesPanel-BNgRlwGt.js → GitHubIssuesPanel-CfU1Yn-D.js} +1 -1
  27. package/web-app/dist/assets/{GitHubPRsPanel-B6M_lVU3.js → GitHubPRsPanel-CyRqGlLT.js} +1 -1
  28. package/web-app/dist/assets/{HomePage-CSlr_5vo.js → HomePage-VSi0DS3d.js} +2 -2
  29. package/web-app/dist/assets/{LoginPage-DJhYZ0SQ.js → LoginPage-CKTWO2H8.js} +1 -1
  30. package/web-app/dist/assets/{MagicPage-B4XpvDFP.js → MagicPage-D2gGNx7S.js} +1 -1
  31. package/web-app/dist/assets/{MetricsPage-DlgPEc5f.js → MetricsPage-08ju5i_4.js} +1 -1
  32. package/web-app/dist/assets/{NotFoundPage-oE1Fvllj.js → NotFoundPage-D5QVAQR2.js} +1 -1
  33. package/web-app/dist/assets/{ProjectPage-B94pP0UO.js → ProjectPage-BWcp6jwS.js} +3 -3
  34. package/web-app/dist/assets/{ProjectsPage-Bk67iaJq.js → ProjectsPage-DnQskG8l.js} +1 -1
  35. package/web-app/dist/assets/{SettingsPage-BGVzSJ3n.js → SettingsPage-9yOOUzI7.js} +1 -1
  36. package/web-app/dist/assets/{ShowcasePage-DtGaDxE5.js → ShowcasePage-sumauNzR.js} +1 -1
  37. package/web-app/dist/assets/{SystemSettingsPage-CfyOGdC-.js → SystemSettingsPage-B8ySfCOM.js} +1 -1
  38. package/web-app/dist/assets/{TeamsPage-CuGmdY85.js → TeamsPage-nnj1knbH.js} +1 -1
  39. package/web-app/dist/assets/{TemplatesPage-Db4OZ-o0.js → TemplatesPage-ftUeNOv3.js} +1 -1
  40. package/web-app/dist/assets/{TerminalOutput-B1W28fpH.js → TerminalOutput-BT9ZWZ9X.js} +1 -1
  41. package/web-app/dist/assets/{activity-DKFtW1Dz.js → activity-CeDz0afa.js} +1 -1
  42. package/web-app/dist/assets/{bell-D2iqUEiO.js → bell-DLmHvvPs.js} +1 -1
  43. package/web-app/dist/assets/{bot-DgV5jnOz.js → bot-Ccv2QTs7.js} +1 -1
  44. package/web-app/dist/assets/{check-BgJBmYEn.js → check-CXAH5y4Y.js} +1 -1
  45. package/web-app/dist/assets/{chevron-left-lPbv6ogy.js → chevron-left-BeUekL4x.js} +1 -1
  46. package/web-app/dist/assets/{circle-alert-CKhQ_hdo.js → circle-alert-CrAQaS38.js} +1 -1
  47. package/web-app/dist/assets/{clock-DWq8vor5.js → clock-DUhqW9ec.js} +1 -1
  48. package/web-app/dist/assets/{cloud-BvQxG3Q2.js → cloud--llyVqYp.js} +1 -1
  49. package/web-app/dist/assets/{code-xml-aL36Csaf.js → code-xml-DlpSK0vE.js} +1 -1
  50. package/web-app/dist/assets/{database-CFzHMx2h.js → database-CCDsbqQj.js} +1 -1
  51. package/web-app/dist/assets/{dollar-sign-C-jqbXs_.js → dollar-sign-CwXnoBfY.js} +1 -1
  52. package/web-app/dist/assets/{file-code-corner-pZ_KZ1YO.js → file-code-corner-dYtsjZgC.js} +1 -1
  53. package/web-app/dist/assets/{file-plus-fRMGiUh4.js → file-plus-DAm1iCop.js} +1 -1
  54. package/web-app/dist/assets/{globe-CVyRdgIZ.js → globe-C97Xeo9v.js} +1 -1
  55. package/web-app/dist/assets/{hammer-DRokcz-I.js → hammer-ChuYr67R.js} +1 -1
  56. package/web-app/dist/assets/{index-CLY7CAQL.js → index-BvbIDxfY.js} +3 -3
  57. package/web-app/dist/assets/{layers-CEWB89or.js → layers-ClcZHqJX.js} +1 -1
  58. package/web-app/dist/assets/{loader-circle-C5OvUx9K.js → loader-circle-uVjaC7Zz.js} +1 -1
  59. package/web-app/dist/assets/{lock-TGMA_-t0.js → lock-ibSk1r0W.js} +1 -1
  60. package/web-app/dist/assets/{package-QJ4Wad2J.js → package-BKBrVVwl.js} +1 -1
  61. package/web-app/dist/assets/{plus-Dgj8mPvu.js → plus-B8aG88Gh.js} +1 -1
  62. package/web-app/dist/assets/{refresh-cw-AGMW2syT.js → refresh-cw-BMGjvAnW.js} +1 -1
  63. package/web-app/dist/assets/{rotate-ccw-BvQ3PO0r.js → rotate-ccw-BAquI5Yt.js} +1 -1
  64. package/web-app/dist/assets/{scroll-text-iwC90pRp.js → scroll-text-B-jFU-a-.js} +1 -1
  65. package/web-app/dist/assets/{server-TUwkkzsm.js → server-CszwUjtL.js} +1 -1
  66. package/web-app/dist/assets/{shield-alert-CR3ONYJ5.js → shield-alert-CykH0zmQ.js} +1 -1
  67. package/web-app/dist/assets/{thumbs-up-DC2-6Rb1.js → thumbs-up-D1g0lsuC.js} +1 -1
  68. package/web-app/dist/assets/{trash-2-o9Iijmor.js → trash-2-D149dHuq.js} +1 -1
  69. package/web-app/dist/assets/{trending-down-d0olJaN5.js → trending-down-CLzrbsgI.js} +1 -1
  70. package/web-app/dist/assets/{trending-up-BB6Q7LpE.js → trending-up-DDpOpi42.js} +1 -1
  71. package/web-app/dist/assets/{upload-5ck9hJ9r.js → upload-DPXg7dD1.js} +1 -1
  72. package/web-app/dist/assets/{usePolling-BLGH4uFR.js → usePolling-RhnPFcLb.js} +1 -1
  73. package/web-app/dist/assets/{user-CNCAMMb7.js → user-CaMr8ZRC.js} +1 -1
  74. package/web-app/dist/index.html +1 -1
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: loki-mode
3
3
  description: An autonomous software factory that knows what it is supposed to deliver, and proves it did. Use when the user says Loki Mode or asks to build, fix or verify software autonomously.
4
4
  ---
5
5
 
6
- # Loki Mode v11.17.59
6
+ # Loki Mode v11.17.61
7
7
 
8
8
  **Current entry points (Loki 10 engine):** `loki "<task>"`, `loki owner/repo#N` and `loki quick "<task>"` run the Loki 10 engine and end with a signed receipt (`loki verify`). `loki backlog owner/repo --all` runs many issues in parallel. Guide: `docs/v10/GUIDE.md`. The skill instructions below, and `loki start`, describe the previous bash loop. PRD-file starts (`loki start ./prd.md`) and the opencode provider still run on it until FC38-SWEEP ports them; the legacy-engine command and the LOKI_ENGINE switch remain removed. Prefer `loki owner/repo#N` for issues.
9
9
 
@@ -483,4 +483,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
483
483
 
484
484
  ---
485
485
 
486
- **v11.17.59 | [Autonomi](https://www.autonomi.dev/) flagship product | core skill**
486
+ **v11.17.61 | [Autonomi](https://www.autonomi.dev/) flagship product | core skill**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 11.17.59
1
+ 11.17.61
@@ -8,6 +8,16 @@
8
8
  # engine10-push.sh issue-comment [--update] <issue-ref> <body-file>
9
9
  # engine10-push.sh status <sha> <pending|success|failure|error> <description>
10
10
  #
11
+ # Fork mode: when gh reports the authenticated user cannot push to the pinned
12
+ # repo (permissions.push false), push-pr pushes to that user's fork (created
13
+ # if missing, verified as a fork of the pinned repo owned by that user) and
14
+ # opens the PR upstream from <user>:<branch>. A draft run in fork mode pushes
15
+ # to the fork only and exits 4: Loki does not open draft PRs on a repository
16
+ # the user cannot push to. issue-comment (status and backstop comments) is a
17
+ # no-op there for the same reason; a receipt comment on the user's own PR is
18
+ # still posted. LOKI_PR_FORK=0 turns fork mode off (the direct push runs and
19
+ # fails as before). No token is needed beyond the user's gh/git login.
20
+ #
11
21
  # Holds GitHub credentials, runs no LLM, reads no untrusted text. Inputs come
12
22
  # only from argv and the origin pinned by P0 before any provider ran
13
23
  # (_LOKI_ORIGIN_PINNED=1 _LOKI_PINNED_ORIGIN=<url>). The target repository is
@@ -128,6 +138,37 @@ _e10_find_pr() {
128
138
  --jq "[.[] | select(.isCrossRepository == false and .state == \"OPEN\" and (.headRepositoryOwner.login | ascii_downcase) == \"$(printf '%s' "$owner" | tr '[:upper:]' '[:lower:]')\")] | .[0].url // empty"
129
139
  }
130
140
 
141
+ # Fork mode probe. Prints true, false, or nothing (unknown: gh failed or did not say). Only a literal false means no push
142
+ # access; anything else keeps the direct path (fail open, so a gh hiccup never reroutes a push the user could make).
143
+ _e10_can_push() { _e10_gh api "repos/$_e10_repo" --jq '.permissions.push' 2>/dev/null | head -n 1; }
144
+ _e10_fork_off() { [ "${LOKI_PR_FORK:-}" = "0" ]; }
145
+ # Creates or finds the gh user's fork of the pinned repo; prints OWNER/REPO only after gh confirms it is a fork of
146
+ # that repo owned by that user. A fork can take a few seconds to appear after the create call.
147
+ _e10_fork() {
148
+ local me="$1" fork="" info i
149
+ fork="$(_e10_gh api -X POST "repos/$_e10_repo/forks" --jq .full_name 2>/dev/null | head -n 1)" || fork=""
150
+ [[ "$fork" =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]] || return 1
151
+ for i in 1 2 3 4 5 6; do
152
+ info="$(_e10_gh api "repos/$fork" --jq '[(.fork|tostring), (.parent.full_name // ""), .owner.login] | join(" ")' 2>/dev/null)" || info=""
153
+ if [ -n "$info" ]; then
154
+ [ "$(printf '%s' "$info" | tr '[:upper:]' '[:lower:]')" = "$(printf 'true %s %s' "$_e10_repo" "$me" | tr '[:upper:]' '[:lower:]')" ] || return 1
155
+ printf '%s\n' "$fork"
156
+ return 0
157
+ fi
158
+ [ "$i" -lt 6 ] && sleep 2
159
+ done
160
+ return 3 # the fork exists by name but GitHub has not served it yet
161
+ }
162
+ # Fork-mode twin of _e10_find_pr: the open cross-repo PR whose head is <me>:<branch> (--head matches the branch name
163
+ # only; the jq owner filter is what pins it to <me>).
164
+ _e10_find_fork_pr() {
165
+ local me="$1"
166
+ case "$me" in '' | *[!A-Za-z0-9_.-]*) return 1 ;; esac
167
+ _e10_gh pr list --repo "$_e10_repo" --head "$2" --state open \
168
+ --json url,isCrossRepository,headRepositoryOwner,headRefName,state \
169
+ --jq "[.[] | select(.isCrossRepository == true and .state == \"OPEN\" and (.headRepositoryOwner.login | ascii_downcase) == \"$(printf '%s' "$me" | tr '[:upper:]' '[:lower:]')\")] | .[0].url // empty"
170
+ }
171
+
131
172
  mode="${1:-}"
132
173
  shift || true
133
174
  case "$mode" in
@@ -157,6 +198,33 @@ case "$mode" in
157
198
  printf 'local://%s#%s\n' "$_LOKI_PINNED_ORIGIN" "$branch"
158
199
  exit 0
159
200
  fi
201
+ if ! _e10_fork_off && [ "$(_e10_can_push)" = "false" ]; then
202
+ # A stacked parent published in fork mode lives on the fork, not upstream, so an upstream base would not exist.
203
+ [ "${#base[@]}" -eq 0 ] || die "no push access to $_e10_repo: a stacked PR (--base) needs push access there; rerun without LOKI_PR_BASE"
204
+ _e10_me="$(_e10_gh api user --jq .login 2>/dev/null)" || _e10_me=""
205
+ [[ "$_e10_me" =~ ^[A-Za-z0-9_.-]+$ ]] || die "no push access to $_e10_repo and the gh user could not be resolved for a fork; run gh auth login"
206
+ log_info "no push access to $_e10_repo: creating or reusing the fork under $_e10_me (LOKI_PR_FORK=0 turns this off)"
207
+ _e10_fork_repo="$(_e10_fork "$_e10_me")" || { [ "$?" -eq 3 ] && die "no push access to $_e10_repo: the fork under $_e10_me is still being created on GitHub; rerun to push once it exists"
208
+ die "no push access to $_e10_repo and its fork under $_e10_me could not be created or verified"; }
209
+ log_info "no push access to $_e10_repo: pushing to the fork $_e10_fork_repo"
210
+ _loki_trusted_push _loki_with_github_tokens "$dir" "$branch" "$_e10_fork_repo" || die "push to fork $_e10_fork_repo refused or failed (rc=$?)"
211
+ if [ "${#draft[@]}" -gt 0 ]; then
212
+ printf 'fork-only: pushed %s to %s; no draft PR is opened on %s, which you cannot push to. Open one yourself: gh pr create --repo %s --head %s:%s\n' \
213
+ "$branch" "$_e10_fork_repo" "$_e10_repo" "$_e10_repo" "$_e10_me" "$branch" >&2
214
+ exit 4
215
+ fi
216
+ url="$(_e10_find_fork_pr "$_e10_me" "$branch")" || die "gh pr list failed"
217
+ _e10_pr_state=reused
218
+ if [ -z "$url" ]; then
219
+ _e10_pr_state=created
220
+ url="$(_e10_gh pr create --repo "$_e10_repo" --head "$_e10_me:$branch" --title "$title" --body-file "$body" "${base[@]}")" \
221
+ || die "gh pr create failed"
222
+ url="$(printf '%s\n' "$url" | tail -n 1)"
223
+ fi
224
+ printf '%s\n' "$_e10_pr_state"
225
+ printf '%s\n' "$url"
226
+ exit 0
227
+ fi
160
228
  # RECOVERY: a resumed publish skips the push when the remote branch is already at the local commit.
161
229
  _e10_want="$(_e10_git -C "$dir" rev-parse -q --verify "refs/heads/$branch" 2>/dev/null)" || _e10_want=""
162
230
  _e10_have=""
@@ -214,7 +282,17 @@ case "$mode" in
214
282
  num="${1##*#}"
215
283
  case "$num" in '' | *[!0-9]*) die "cannot extract issue number from: $1" ;; esac
216
284
  [ -f "$2" ] || die "body file not found: $2"
217
- [ -z "$_e10_local" ] || { log_info "local origin: no issue to comment on (no-op)"; exit 0; }
285
+ [ -z "$_e10_local" ] || { log_info "local origin: no issue to comment on (no-op)"; echo "skipped: local origin"; exit 0; }
286
+ # Status and backstop comments are for a repo the user maintains; on one they cannot push to they would land on
287
+ # someone else's issue. The receipt comment rides the user's own PR and is still posted.
288
+ # The receipt body starts with its marker (receipt_surface.ts); only that first line exempts a comment, so issue
289
+ # text quoting the marker inside a status body cannot. Unlike push-pr this fails closed: a status or backstop
290
+ # comment is posted only when gh confirms push access, since a wrong guess is a public comment on someone's issue.
291
+ if [ "$(head -n 1 -- "$2")" != '<!-- loki-receipt -->' ] && [ "$(_e10_can_push)" != "true" ]; then
292
+ log_info "push access to $_e10_repo not confirmed: not commenting on its issue $num"
293
+ echo "skipped: no push access to $_e10_repo"
294
+ exit 0
295
+ fi
218
296
  if [ -n "$_e10_upd" ]; then
219
297
  _e10_marker=""
220
298
  for _e10_m in '<!-- loki-status -->' '<!-- loki-receipt -->'; do
@@ -194,8 +194,31 @@ def _env_assign_sub(m):
194
194
  # The password class is [^\s@]+ (stops only at the closing @) so passwords that
195
195
  # contain "/" (e.g. postgres://user:p/ss@host) are still fully captured.
196
196
  _URI_CREDENTIAL = re.compile(
197
- r"\b([A-Za-z][A-Za-z0-9+.\-]*://[^\s:/@]*:)([^\s@]+)(@)"
197
+ r"\b([A-Za-z][A-Za-z0-9+.\-]{0,63}://[^\s:/@]*:)([^\s@]+)(@)" # bounded scheme: linear (TEN-SECURITY-26)
198
198
  )
199
+ _TOKEN = re.compile(r"\S+")
200
+
201
+
202
+ def _redact_uri_credentials(s):
203
+ """Apply _URI_CREDENTIAL to the part of each whitespace-delimited token up to
204
+ its last "@". No match ends past that "@" (the password class stops at "@"),
205
+ and scanning an "@"-free tail from every scheme start is quadratic even with
206
+ the bounded scheme ("a://" * 16000 took 5.6s). TEN-SECURITY-26 follow-up.
207
+ Returns (new_string, count)."""
208
+ total = 0
209
+
210
+ def tok(m):
211
+ nonlocal total
212
+ t = m.group(0)
213
+ cut = t.rfind("@") + 1
214
+ if not cut:
215
+ return t
216
+ head, n = _URI_CREDENTIAL.subn(r"\1[REDACTED]\3", t[:cut])
217
+ total += n
218
+ return head + t[cut:]
219
+
220
+ return _TOKEN.sub(tok, s), total
221
+
199
222
 
200
223
  # Absolute user home paths -> ~ . Applied to every string (paths, diffs,
201
224
  # brief, summaries). Windows form handled separately to keep the backslash
@@ -289,7 +312,8 @@ def _redact_value(s):
289
312
  # Connection-string / URI credentials: scheme://user:PASSWORD@ -> redact
290
313
  # the password. Runs before the generic env-assign so the "scheme://user:"
291
314
  # prefix is consumed and the assign rule does not double-process it.
292
- s, n = _URI_CREDENTIAL.subn(r"\1[REDACTED]\3", s)
315
+ # The helper applies _URI_CREDENTIAL per token; keep the two in sync.
316
+ s, n = _redact_uri_credentials(s)
293
317
  total += n
294
318
 
295
319
  # Secret assignments (bare, JSON-quoted, YAML-quoted): keep key, redact value.
package/autonomy/run.sh CHANGED
@@ -6043,8 +6043,11 @@ _loki_run_neutral() {
6043
6043
  # the credentialed process. <runner> is the credential re-grant wrapper
6044
6044
  # (_loki_with_github_tokens, or on_run_complete's timed _loki_net). The agent
6045
6045
  # repo's branch gets no upstream set (it did with `push -u`); nothing reads it.
6046
+ # Optional <dest> OWNER/REPO (engine10-push.sh fork mode): the pinned origin is
6047
+ # still validated, then the push goes to https://github.com/<dest>.git, a fork
6048
+ # the push child resolved from gh and checked, never a value from the tree.
6046
6049
  _loki_trusted_push() {
6047
- local _runner="$1" _dir="$2" _branch="$3" _url _tmp _rc=1
6050
+ local _runner="$1" _dir="$2" _branch="$3" _dest="${4:-}" _url _tmp _rc=1
6048
6051
  _dir="$(cd "$_dir" 2>/dev/null && pwd -P)" || return 1
6049
6052
  git check-ref-format --branch "$_branch" >/dev/null 2>&1 || return 1
6050
6053
  _url="$(git -C "$_dir" config --get remote.origin.url 2>/dev/null)" || _url=""
@@ -6068,6 +6071,13 @@ _loki_trusted_push() {
6068
6071
  return 2 ;;
6069
6072
  esac
6070
6073
  _repo="$(_loki_github_repo_from_url "$_url")"
6074
+ if [ -n "$_dest" ]; then
6075
+ if ! _loki_github_repo_from_url "https://github.com/${_dest}.git" >/dev/null; then
6076
+ log_warn "Not pushing branch '$_branch': fork destination '$_dest' is not a plain OWNER/REPO."
6077
+ return 2
6078
+ fi
6079
+ _repo="$_dest" _url="https://github.com/${_dest}.git"
6080
+ fi
6071
6081
  _def="$(_loki_run_neutral "$_repo" "$_runner" gh repo view "$_repo" --json defaultBranchRef --jq '.defaultBranchRef.name' 2>/dev/null)" || _def=""
6072
6082
  if [ -z "$_def" ]; then
6073
6083
  log_warn "Not pushing branch '$_branch': could not resolve the default branch of $_repo, and Loki never risks a direct push to it."
@@ -7,6 +7,6 @@ Modules:
7
7
  control: Session control helpers (status, atomic writes, origin check)
8
8
  """
9
9
 
10
- __version__ = "11.17.59"
10
+ __version__ = "11.17.61"
11
11
 
12
12
  __all__ = ["__version__"]
@@ -1,6 +1,6 @@
1
1
  # CLI reference
2
2
 
3
- Generated from `loki-ts/src/cli/registry.ts` by `scripts/generate-stale-zero.sh` for v11.17.59. Do not edit by hand.
3
+ Generated from `loki-ts/src/cli/registry.ts` by `scripts/generate-stale-zero.sh` for v11.17.61. Do not edit by hand.
4
4
  Hidden and legacy-only commands are omitted; see `docs/v10/CLI-MODERN.md` for the full inventory.
5
5
 
6
6
  | Command | Description |
@@ -2,7 +2,7 @@
2
2
 
3
3
  Loki Mode, by [Autonomi](https://www.autonomi.dev/), turns a spec or an issue into a verified pull request with a receipt you can check. This page covers installing it, a first run, and the options around it.
4
4
 
5
- **Version:** v11.17.59
5
+ **Version:** v11.17.61
6
6
 
7
7
  **Engine note:** `loki start` is the primary command. `loki start`, `loki "<task>"`, `loki owner/repo#N` and `loki quick` all run the Loki 10 engine, whatever the flag order or input form (PRD file, issue ref, task or one-word brief). The previous loop runs only on `--engine legacy`, `LOKI_ENGINE=legacy`, or for one call when a flag Loki 10 cannot honor is present. See the [user guide](v10/GUIDE.md) and the [5-minute quickstart](QUICKSTART.md).
8
8
 
@@ -40,6 +40,13 @@ loki start "add rate limiting to /api/login"
40
40
 
41
41
  Also accepted: `loki start prd.md`, `loki start owner/repo#123`, and a
42
42
  one-word brief as `loki start <word>`. Add `--no-pr` to skip the pull request.
43
+ The PR uses your existing `gh auth login` (and git) credentials; no extra token
44
+ is needed. On a repo you cannot push to, Loki pushes the branch to your fork and
45
+ opens the PR upstream from it (the branch is public on your fork); a draft
46
+ outcome (anything but VERIFIED) stays on the fork, and Loki posts no status
47
+ comment on that repo's issue. Status and backstop issue comments post only when
48
+ gh confirms you can push; a failed check skips them rather than guessing.
49
+ `LOKI_PR_FORK=0` turns the fork fallback off.
43
50
  Preview the route first with `loki route start prd.md`.
44
51
 
45
52
  The spend cap defaults to $100 when `ANTHROPIC_API_KEY` or `OPENAI_API_KEY` is
@@ -1104,3 +1104,23 @@ L0 review rule (ENGINE-LAWS.md L0): a fix that adds an `if` or a regex about the
1104
1104
  - Sibling sweep: pr.ts push-pr, push-mr, pr-ready and status now share spawnBounded (LOKI_PR_PUSH_TIMEOUT_MS, default 50s). Still unbounded: src/util/pr_lessons.ts:348, src/runner/attempts.ts:376, src/engine10/supervisor.ts:374.
1105
1105
  - One shared mechanism: spawnBounded and failReason in loki-ts/src/engine10/stages/pr.ts.
1106
1106
  - Regression fixture: loki-ts/tests/engine10/pr.test.ts "hung push script".
1107
+
1108
+ ## FC-TEN-SECURITY-26 The URL userinfo redact rule restarted inside one scheme-char run, so redaction was quadratic and the Bun suite went red on slow runners (URI-SCHEME-RESTART)
1109
+ - User-visible vs raw: user-visible. `redact.test.ts` "assignment redact covers flag and separator-prefixed names" failed on GitHub runners (175-220ms against a 100ms budget, main v11.17.58 run 39048066486 and PR #225 run 39122713723). The slow input was `"--a".repeat(7000) + "token"`; the TEN-SECURITY-25 assignment rule took 0.1ms on it. The URL userinfo rule `\b[a-z][a-z0-9+.-]*://` restarted at every letter after - + or . and rescanned the run: 49, 212, 847ms at N, 2N, 4N.
1110
+ - Law broken: redaction runs on every event, log line and proof field, so it must stay linear in input length; a quadratic rule lets one long token stall the engine writer, shipper or proof generator.
1111
+ - Siblings: the same scheme shape in loki-ts/src/util/redact.ts, loki-ts/src/council/finding_schema.ts and autonomy/lib/proof_redact.py `_URI_CREDENTIAL`, all bounded in 01e81302c. A second, Python-only quadratic survived that fix: the password class `[^\s@]+@` scanned an "@"-free tail from every scheme start (`"a://" * 16000` took 5.6s with the bounded scheme). Left as is: the TEN-SECURITY-25 ASSIGNMENT rule's `(?:[A-Za-z0-9]+[_.-]+)*` group drops off the JSC regex JIT above about 80000 iterations (`"--a".repeat(80000)` 57ms, 320000 reps 393ms); still linear, roughly 0.5us per char past the cliff, far above the sizes the suite or real log lines use.
1112
+ - Mechanism: scheme bounded to 64 chars in all three rules (01e81302c). For the Python password tail, `_redact_uri_credentials` runs `_URI_CREDENTIAL` only on each whitespace token up to its last "@"; no match can end past it. Differential fuzz against the plain regex: 0 diffs over 400k random strings, redaction count included.
1113
+ - Fixture: loki-ts/tests/util/redact.test.ts and tests/test_proof_redaction.py `test_assignment_redaction_is_linear_on_long_input` (scheme inputs from 01e81302c; `"a://" * 50000` and `"a://u:" * 35000` added for the password tail, red on the bounded-only source, green after).
1114
+ ## FC-ISSUE-FOREIGN-REPO Issue mode on a repo the user cannot push to ended in a raw 403, posted on someone else's issue, and sealed no Wall result (FOREIGN-REPO-NO-PROOF)
1115
+ - User-visible vs raw: user-visible. `loki start anthropics/claude-code#21527` (a repo the operator cannot push to, no test runner) printed BLOCKED with NOT PROVEN carrying three raw lines of git stderr (`remote: Permission to anthropics/claude-code.git denied`, `fatal: ... 403`), a Reason cut mid-word at 200 chars, the intent card glued to the live line, and "wall result not recorded by verify". A no-PR rerun on the same repo sealed PARTIAL "no tests to run": the Wall wrote a bun:test file and verify never ran it.
1116
+ - Law broken: a run must end in a sealed, honest result the operator can act on; a credential or permission miss must read as one line naming the cause, and Loki must not act on a third-party issue the operator does not maintain.
1117
+ - Siblings: push-pr (direct push, no fork path), issue-comment status and backstop comments (posted on the foreign issue), verify (Wall tests only from the project test map; `wall_passed` never written anywhere, so every Wall receipt carried the not-recorded line), wall guessRunner (any non-py/go file mapped to the JS runner), output Reason (mid-word slice) and NOT PROVEN (newlines kept), intent card (stderr write over the supervisor's live line).
1118
+ - Mechanism: engine10-push.sh fork mode (gh `permissions.push` false: push to the verified fork through `_loki_trusted_push`'s new destination arg, PR upstream from user:branch; a draft run stops at the fork, exit 4; status and backstop comments skipped, the receipt comment on the user's own PR kept; `LOKI_PR_FORK=0` off). testmap `harnessRunners`: no detected runner and no Python/Go test suite means Loki's bun runs the Wall file in the Wall and in verify (`LOKI_WALL_HARNESS_RUNNER=0` off). verify writes `wall_passed`. term_width `clipWords` and `pushErrLine` for one-line output.
1119
+ - Fixture: tests/test-engine10-push.sh fork-mode block (6 cases, 5 red before), loki-ts/tests/engine10/verify.test.ts "no project runner", testmap.test.ts harnessRunners, output.test.ts clip and one-line NOT PROVEN, pr.test.ts fork-only and pushErrLine. Live: the same task on a clone of anthropics/claude-code went from verify 0s with no checks to the Wall check executed and failing for the stated reason (BLOCKED, the request lives in the Slack backend, not that repo).
1120
+
1121
+ ## FC-NO-DIFF-PUBLISH A run with nothing to publish still pushed a branch, and its stop reason read as glued prose (NO-DIFF-PUBLISH)
1122
+ - User-visible vs raw: user-visible. A rerun of `loki start anthropics/claude-code#21527` after FC-ISSUE-FOREIGN-REPO ended BLOCKED (SPEC_CONFLICT, 0 files changed) yet pushed an empty branch to the operator's fork (NOT PROVEN: "PR not opened: fork-only: pushed ..."), logged the skipped status comment as ok, spent two more fix rounds (one on opus) after the implement session had already declared the conflict, and printed a Reason with two model messages joined mid-word ("has shippedI still").
1123
+ - Law broken: a run publishes only what it changed, and its result reads as one honest line; spend stops once the outcome is decided.
1124
+ - Siblings: the supervisor PR gate (net diff computed only for FAILED, so SPEC_CONFLICT, PARTIAL and VERIFIED skipped it), the status projector and backstop comment (a skip read as a post), session marker parsing (LOKI_SPEC_CONFLICT and LOKI_ALREADY_DONE both line-anchored on glued text), the fix loop (E-98b keeps verifying a single conflict claim, but a fix session confirming it with an unchanged tree was not treated as confirmation).
1125
+ - Mechanism: one net-diff check for every verdict gates every push; the push script reports a skipped comment on stdout and callers record it; session text blocks are newline-separated before marker parsing; a fix round that also exits spec_conflict on an unchanged tree ends the loop with the SPEC_CONFLICT verdict.
1126
+ - Fixture: supervisor no-diff SPEC_CONFLICT case (no push), tests/test-engine10-push.sh skipped-comment line, session two-block marker case, machine confirmed-conflict case.
@@ -2554,3 +2554,6 @@ v11.17.21 published (Release success on 462fbc40a; npm latest 11.17.21, next 11.
2554
2554
 
2555
2555
  ## 2026-10-17T16:07Z (CoS) v11.17.58
2556
2556
  - STAB-1 follow-up: Tests 39046745996 on v11.17.57 failed only on shard 1 help drift (FAIL: 'loki queue rm' (CHANGELOG) is absent from help), caused by the 11.17.57 notes. Reworded; tests/test-help-changelog-drift.sh 4 passed, 0 failed. Release 39046745968 all jobs success; npm latest and next 11.17.57.
2557
+
2558
+ ## 2026-10-18T20:30Z (CoS) v11.17.61
2559
+ - P1 FC-NO-DIFF-PUBLISH (anthropics/claude-code#21527 rerun): empty fork push, skipped comment logged ok, glued reason, extra fix rounds. Slices P1-AD (551267ec5) and P1-C (8fcc1315b) merged. Checks: tsc clean (control-plane excluded); bun test budget, supervisor_backstop, machine, sdk_stream_parser, spawn_env_guard, contract 192 pass 0 fail; e2e, issue_ref_e2e, already_done, pr, tests/util 571 tests 0 fail; test-engine10-push.sh 85 passed 0 failed; sigpipe 4 passed; select-tests 119 passed.
@@ -1,19 +1,19 @@
1
1
  // @bun
2
- var WJ=Object.defineProperty;var FJ=(J)=>J;function BJ(J,Q){this[J]=FJ.bind(null,Q)}var HJ=(J,Q)=>{for(var X in Q)WJ(J,X,{get:Q[X],enumerable:!0,configurable:!0,set:BJ.bind(Q,X)})};var RJ=(J,Q)=>()=>(J&&(Q=J(J=0)),Q);var F=import.meta.require;var qJ={};HJ(qJ,{initWasm:()=>pJ,Resvg:()=>gJ});function C(J){if(_===T.length)T.push(T.length+1);let Q=_;return _=T[Q],T[Q]=J,Q}function A(J){return T[J]}function xJ(J){if(J<132)return;T[J]=_,_=J}function W(J){let Q=A(J);return xJ(J),Q}function y(){if(j===null||j.byteLength===0)j=new Uint8Array(D.memory.buffer);return j}function g(J,Q,X){if(X===void 0){let K=b.encode(J),P=Q(K.length,1)>>>0;return y().subarray(P,P+K.length).set(K),h=K.length,P}let Z=J.length,$=Q(Z,1)>>>0,G=y(),q=0;for(;q<Z;q++){let K=J.charCodeAt(q);if(K>127)break;G[$+q]=K}if(q!==Z){if(q!==0)J=J.slice(q);$=X($,Z,Z=q+J.length*3,1)>>>0;let K=y().subarray($+q,$+Z),P=_J(J,K);q+=P.written,$=X($,Z,q,1)>>>0}return h=q,$}function i(J){return J===void 0||J===null}function N(){if(x===null||x.byteLength===0)x=new Int32Array(D.memory.buffer);return x}function w(J,Q){return J=J>>>0,DJ.decode(y().subarray(J,J+Q))}function hJ(J,Q){if(!(J instanceof Q))throw Error(`expected instance of ${Q.name}`);return J.ptr}function fJ(J,Q){try{return J.apply(this,Q)}catch(X){D.__wbindgen_exn_store(C(X))}}async function bJ(J,Q){if(typeof Response==="function"&&J instanceof Response){if(typeof WebAssembly.instantiateStreaming==="function")try{return await WebAssembly.instantiateStreaming(J,Q)}catch(Z){if(J.headers.get("Content-Type")!="application/wasm")console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n",Z);else throw Z}let X=await J.arrayBuffer();return await WebAssembly.instantiate(X,Q)}else{let X=await WebAssembly.instantiate(J,Q);if(X instanceof WebAssembly.Instance)return{instance:X,module:J};else return X}}function wJ(){let J={};return J.wbg={},J.wbg.__wbg_new_28c511d9baebfa89=function(Q,X){let Z=Error(w(Q,X));return C(Z)},J.wbg.__wbindgen_memory=function(){let Q=D.memory;return C(Q)},J.wbg.__wbg_buffer_12d079cc21e14bdb=function(Q){let X=A(Q).buffer;return C(X)},J.wbg.__wbg_newwithbyteoffsetandlength_aa4a17c33a06e5cb=function(Q,X,Z){let $=new Uint8Array(A(Q),X>>>0,Z>>>0);return C($)},J.wbg.__wbindgen_object_drop_ref=function(Q){W(Q)},J.wbg.__wbg_new_63b92bc8671ed464=function(Q){let X=new Uint8Array(A(Q));return C(X)},J.wbg.__wbg_values_839f3396d5aac002=function(Q){let X=A(Q).values();return C(X)},J.wbg.__wbg_next_196c84450b364254=function(){return fJ(function(Q){let X=A(Q).next();return C(X)},arguments)},J.wbg.__wbg_done_298b57d23c0fc80c=function(Q){return A(Q).done},J.wbg.__wbg_value_d93c65011f51a456=function(Q){let X=A(Q).value;return C(X)},J.wbg.__wbg_instanceof_Uint8Array_2b3bbecd033d19f6=function(Q){let X;try{X=A(Q)instanceof Uint8Array}catch($){X=!1}return X},J.wbg.__wbindgen_string_get=function(Q,X){let Z=A(X),$=typeof Z==="string"?Z:void 0;var G=i($)?0:g($,D.__wbindgen_malloc,D.__wbindgen_realloc),q=h;N()[Q/4+1]=q,N()[Q/4+0]=G},J.wbg.__wbg_new_16b304a2cfa7ff4a=function(){return C([])},J.wbg.__wbindgen_string_new=function(Q,X){let Z=w(Q,X);return C(Z)},J.wbg.__wbg_push_a5b05aedc7234f9f=function(Q,X){return A(Q).push(A(X))},J.wbg.__wbg_length_c20a40f15020d68a=function(Q){return A(Q).length},J.wbg.__wbg_set_a47bac70306a19a7=function(Q,X,Z){A(Q).set(A(X),Z>>>0)},J.wbg.__wbindgen_throw=function(Q,X){throw Error(w(Q,X))},J}function lJ(J,Q){}function mJ(J,Q){return D=J.exports,KJ.__wbindgen_wasm_module=Q,x=null,j=null,D}async function KJ(J){if(D!==void 0)return D;if(typeof J>"u")J=new URL("index_bg.wasm",void 0);let Q=wJ();if(typeof J==="string"||typeof Request==="function"&&J instanceof Request||typeof URL==="function"&&J instanceof URL)J=fetch(J);lJ(Q);let{instance:X,module:Z}=await bJ(await J,Q);return mJ(X,Z)}function iJ(J){return Object.prototype.hasOwnProperty.call(J,"fontBuffers")}var D,T,_,h=0,j=null,b,_J,x=null,DJ,$J,p=class J{static __wrap(Q){Q=Q>>>0;let X=Object.create(J.prototype);return X.__wbg_ptr=Q,$J.register(X,X.__wbg_ptr,X),X}__destroy_into_raw(){let Q=this.__wbg_ptr;return this.__wbg_ptr=0,$J.unregister(this),Q}free(){let Q=this.__destroy_into_raw();D.__wbg_bbox_free(Q)}get x(){return D.__wbg_get_bbox_x(this.__wbg_ptr)}set x(Q){D.__wbg_set_bbox_x(this.__wbg_ptr,Q)}get y(){return D.__wbg_get_bbox_y(this.__wbg_ptr)}set y(Q){D.__wbg_set_bbox_y(this.__wbg_ptr,Q)}get width(){return D.__wbg_get_bbox_width(this.__wbg_ptr)}set width(Q){D.__wbg_set_bbox_width(this.__wbg_ptr,Q)}get height(){return D.__wbg_get_bbox_height(this.__wbg_ptr)}set height(Q){D.__wbg_set_bbox_height(this.__wbg_ptr,Q)}},GJ,uJ=class J{static __wrap(Q){Q=Q>>>0;let X=Object.create(J.prototype);return X.__wbg_ptr=Q,GJ.register(X,X.__wbg_ptr,X),X}__destroy_into_raw(){let Q=this.__wbg_ptr;return this.__wbg_ptr=0,GJ.unregister(this),Q}free(){let Q=this.__destroy_into_raw();D.__wbg_renderedimage_free(Q)}get width(){return D.renderedimage_width(this.__wbg_ptr)>>>0}get height(){return D.renderedimage_height(this.__wbg_ptr)>>>0}asPng(){try{let $=D.__wbindgen_add_to_stack_pointer(-16);D.renderedimage_asPng($,this.__wbg_ptr);var Q=N()[$/4+0],X=N()[$/4+1],Z=N()[$/4+2];if(Z)throw W(X);return W(Q)}finally{D.__wbindgen_add_to_stack_pointer(16)}}get pixels(){let Q=D.renderedimage_pixels(this.__wbg_ptr);return W(Q)}},vJ,yJ=class{__destroy_into_raw(){let J=this.__wbg_ptr;return this.__wbg_ptr=0,vJ.unregister(this),J}free(){let J=this.__destroy_into_raw();D.__wbg_resvg_free(J)}constructor(J,Q,X){try{let P=D.__wbindgen_add_to_stack_pointer(-16);var Z=i(Q)?0:g(Q,D.__wbindgen_malloc,D.__wbindgen_realloc),$=h;D.resvg_new(P,C(J),Z,$,i(X)?0:C(X));var G=N()[P/4+0],q=N()[P/4+1],K=N()[P/4+2];if(K)throw W(q);return this.__wbg_ptr=G>>>0,this}finally{D.__wbindgen_add_to_stack_pointer(16)}}get width(){return D.resvg_width(this.__wbg_ptr)}get height(){return D.resvg_height(this.__wbg_ptr)}render(){try{let Z=D.__wbindgen_add_to_stack_pointer(-16);D.resvg_render(Z,this.__wbg_ptr);var J=N()[Z/4+0],Q=N()[Z/4+1],X=N()[Z/4+2];if(X)throw W(Q);return uJ.__wrap(J)}finally{D.__wbindgen_add_to_stack_pointer(16)}}toString(){let J,Q;try{let $=D.__wbindgen_add_to_stack_pointer(-16);D.resvg_toString($,this.__wbg_ptr);var X=N()[$/4+0],Z=N()[$/4+1];return J=X,Q=Z,w(X,Z)}finally{D.__wbindgen_add_to_stack_pointer(16),D.__wbindgen_free(J,Q,1)}}innerBBox(){let J=D.resvg_innerBBox(this.__wbg_ptr);return J===0?void 0:p.__wrap(J)}getBBox(){let J=D.resvg_getBBox(this.__wbg_ptr);return J===0?void 0:p.__wrap(J)}cropByBBox(J){hJ(J,p),D.resvg_cropByBBox(this.__wbg_ptr,J.__wbg_ptr)}imagesToResolve(){try{let Z=D.__wbindgen_add_to_stack_pointer(-16);D.resvg_imagesToResolve(Z,this.__wbg_ptr);var J=N()[Z/4+0],Q=N()[Z/4+1],X=N()[Z/4+2];if(X)throw W(Q);return W(J)}finally{D.__wbindgen_add_to_stack_pointer(16)}}resolveImage(J,Q){try{let $=D.__wbindgen_add_to_stack_pointer(-16),G=g(J,D.__wbindgen_malloc,D.__wbindgen_realloc),q=h;D.resvg_resolveImage($,this.__wbg_ptr,G,q,C(Q));var X=N()[$/4+0],Z=N()[$/4+1];if(Z)throw W(X)}finally{D.__wbindgen_add_to_stack_pointer(16)}}},dJ,c=!1,pJ=async(J)=>{if(c)throw Error("Already initialized. The `initWasm()` function can be used only once.");await dJ(await J),c=!0},gJ;var VJ=RJ(()=>{T=Array(128).fill(void 0);T.push(void 0,null,!0,!1);_=T.length;b=typeof TextEncoder<"u"?new TextEncoder("utf-8"):{encode:()=>{throw Error("TextEncoder not available")}},_J=typeof b.encodeInto==="function"?function(J,Q){return b.encodeInto(J,Q)}:function(J,Q){let X=b.encode(J);return Q.set(X),{read:J.length,written:X.length}};DJ=typeof TextDecoder<"u"?new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0}):{decode:()=>{throw Error("TextDecoder not available")}};if(typeof TextDecoder<"u")DJ.decode();$J=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry((J)=>D.__wbg_bbox_free(J>>>0)),GJ=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry((J)=>D.__wbg_renderedimage_free(J>>>0)),vJ=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry((J)=>D.__wbg_resvg_free(J>>>0));dJ=KJ,gJ=class extends yJ{constructor(J,Q){if(!c)throw Error("Wasm has not been initialized. Call `initWasm()` function.");let X=Q?.font;if(!!X&&iJ(X)){let Z={...Q,font:{...X,fontBuffers:void 0}};super(J,JSON.stringify(Z),X.fontBuffers)}else super(J,JSON.stringify(Q))}}});function U(J){return String(J??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function IJ(J,Q,X){let Z=X/512;return`<g transform="translate(${J},${Q}) scale(${Z})">
2
+ var WJ=Object.defineProperty;var FJ=(J)=>J;function BJ(J,Q){this[J]=FJ.bind(null,Q)}var HJ=(J,Q)=>{for(var Z in Q)WJ(J,Z,{get:Q[Z],enumerable:!0,configurable:!0,set:BJ.bind(Q,Z)})};var IJ=(J,Q)=>()=>(J&&(Q=J(J=0)),Q);var F=import.meta.require;var qJ={};HJ(qJ,{initWasm:()=>dJ,Resvg:()=>gJ});function N(J){if(x===T.length)T.push(T.length+1);let Q=x;return x=T[Q],T[Q]=J,Q}function C(J){return T[J]}function _J(J){if(J<132)return;T[J]=x,x=J}function W(J){let Q=C(J);return _J(J),Q}function b(){if(O===null||O.byteLength===0)O=new Uint8Array(D.memory.buffer);return O}function g(J,Q,Z){if(Z===void 0){let K=y.encode(J),L=Q(K.length,1)>>>0;return b().subarray(L,L+K.length).set(K),h=K.length,L}let $=J.length,G=Q($,1)>>>0,X=b(),q=0;for(;q<$;q++){let K=J.charCodeAt(q);if(K>127)break;X[G+q]=K}if(q!==$){if(q!==0)J=J.slice(q);G=Z(G,$,$=q+J.length*3,1)>>>0;let K=b().subarray(G+q,G+$),L=xJ(J,K);q+=L.written,G=Z(G,$,q,1)>>>0}return h=q,G}function c(J){return J===void 0||J===null}function U(){if(_===null||_.byteLength===0)_=new Int32Array(D.memory.buffer);return _}function w(J,Q){return J=J>>>0,DJ.decode(b().subarray(J,J+Q))}function hJ(J,Q){if(!(J instanceof Q))throw Error(`expected instance of ${Q.name}`);return J.ptr}function fJ(J,Q){try{return J.apply(this,Q)}catch(Z){D.__wbindgen_exn_store(N(Z))}}async function yJ(J,Q){if(typeof Response==="function"&&J instanceof Response){if(typeof WebAssembly.instantiateStreaming==="function")try{return await WebAssembly.instantiateStreaming(J,Q)}catch($){if(J.headers.get("Content-Type")!="application/wasm")console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n",$);else throw $}let Z=await J.arrayBuffer();return await WebAssembly.instantiate(Z,Q)}else{let Z=await WebAssembly.instantiate(J,Q);if(Z instanceof WebAssembly.Instance)return{instance:Z,module:J};else return Z}}function wJ(){let J={};return J.wbg={},J.wbg.__wbg_new_28c511d9baebfa89=function(Q,Z){let $=Error(w(Q,Z));return N($)},J.wbg.__wbindgen_memory=function(){let Q=D.memory;return N(Q)},J.wbg.__wbg_buffer_12d079cc21e14bdb=function(Q){let Z=C(Q).buffer;return N(Z)},J.wbg.__wbg_newwithbyteoffsetandlength_aa4a17c33a06e5cb=function(Q,Z,$){let G=new Uint8Array(C(Q),Z>>>0,$>>>0);return N(G)},J.wbg.__wbindgen_object_drop_ref=function(Q){W(Q)},J.wbg.__wbg_new_63b92bc8671ed464=function(Q){let Z=new Uint8Array(C(Q));return N(Z)},J.wbg.__wbg_values_839f3396d5aac002=function(Q){let Z=C(Q).values();return N(Z)},J.wbg.__wbg_next_196c84450b364254=function(){return fJ(function(Q){let Z=C(Q).next();return N(Z)},arguments)},J.wbg.__wbg_done_298b57d23c0fc80c=function(Q){return C(Q).done},J.wbg.__wbg_value_d93c65011f51a456=function(Q){let Z=C(Q).value;return N(Z)},J.wbg.__wbg_instanceof_Uint8Array_2b3bbecd033d19f6=function(Q){let Z;try{Z=C(Q)instanceof Uint8Array}catch(G){Z=!1}return Z},J.wbg.__wbindgen_string_get=function(Q,Z){let $=C(Z),G=typeof $==="string"?$:void 0;var X=c(G)?0:g(G,D.__wbindgen_malloc,D.__wbindgen_realloc),q=h;U()[Q/4+1]=q,U()[Q/4+0]=X},J.wbg.__wbg_new_16b304a2cfa7ff4a=function(){return N([])},J.wbg.__wbindgen_string_new=function(Q,Z){let $=w(Q,Z);return N($)},J.wbg.__wbg_push_a5b05aedc7234f9f=function(Q,Z){return C(Q).push(C(Z))},J.wbg.__wbg_length_c20a40f15020d68a=function(Q){return C(Q).length},J.wbg.__wbg_set_a47bac70306a19a7=function(Q,Z,$){C(Q).set(C(Z),$>>>0)},J.wbg.__wbindgen_throw=function(Q,Z){throw Error(w(Q,Z))},J}function lJ(J,Q){}function mJ(J,Q){return D=J.exports,KJ.__wbindgen_wasm_module=Q,_=null,O=null,D}async function KJ(J){if(D!==void 0)return D;if(typeof J>"u")J=new URL("index_bg.wasm",void 0);let Q=wJ();if(typeof J==="string"||typeof Request==="function"&&J instanceof Request||typeof URL==="function"&&J instanceof URL)J=fetch(J);lJ(Q);let{instance:Z,module:$}=await yJ(await J,Q);return mJ(Z,$)}function cJ(J){return Object.prototype.hasOwnProperty.call(J,"fontBuffers")}var D,T,x,h=0,O=null,y,xJ,_=null,DJ,GJ,d=class J{static __wrap(Q){Q=Q>>>0;let Z=Object.create(J.prototype);return Z.__wbg_ptr=Q,GJ.register(Z,Z.__wbg_ptr,Z),Z}__destroy_into_raw(){let Q=this.__wbg_ptr;return this.__wbg_ptr=0,GJ.unregister(this),Q}free(){let Q=this.__destroy_into_raw();D.__wbg_bbox_free(Q)}get x(){return D.__wbg_get_bbox_x(this.__wbg_ptr)}set x(Q){D.__wbg_set_bbox_x(this.__wbg_ptr,Q)}get y(){return D.__wbg_get_bbox_y(this.__wbg_ptr)}set y(Q){D.__wbg_set_bbox_y(this.__wbg_ptr,Q)}get width(){return D.__wbg_get_bbox_width(this.__wbg_ptr)}set width(Q){D.__wbg_set_bbox_width(this.__wbg_ptr,Q)}get height(){return D.__wbg_get_bbox_height(this.__wbg_ptr)}set height(Q){D.__wbg_set_bbox_height(this.__wbg_ptr,Q)}},XJ,uJ=class J{static __wrap(Q){Q=Q>>>0;let Z=Object.create(J.prototype);return Z.__wbg_ptr=Q,XJ.register(Z,Z.__wbg_ptr,Z),Z}__destroy_into_raw(){let Q=this.__wbg_ptr;return this.__wbg_ptr=0,XJ.unregister(this),Q}free(){let Q=this.__destroy_into_raw();D.__wbg_renderedimage_free(Q)}get width(){return D.renderedimage_width(this.__wbg_ptr)>>>0}get height(){return D.renderedimage_height(this.__wbg_ptr)>>>0}asPng(){try{let G=D.__wbindgen_add_to_stack_pointer(-16);D.renderedimage_asPng(G,this.__wbg_ptr);var Q=U()[G/4+0],Z=U()[G/4+1],$=U()[G/4+2];if($)throw W(Z);return W(Q)}finally{D.__wbindgen_add_to_stack_pointer(16)}}get pixels(){let Q=D.renderedimage_pixels(this.__wbg_ptr);return W(Q)}},vJ,bJ=class{__destroy_into_raw(){let J=this.__wbg_ptr;return this.__wbg_ptr=0,vJ.unregister(this),J}free(){let J=this.__destroy_into_raw();D.__wbg_resvg_free(J)}constructor(J,Q,Z){try{let L=D.__wbindgen_add_to_stack_pointer(-16);var $=c(Q)?0:g(Q,D.__wbindgen_malloc,D.__wbindgen_realloc),G=h;D.resvg_new(L,N(J),$,G,c(Z)?0:N(Z));var X=U()[L/4+0],q=U()[L/4+1],K=U()[L/4+2];if(K)throw W(q);return this.__wbg_ptr=X>>>0,this}finally{D.__wbindgen_add_to_stack_pointer(16)}}get width(){return D.resvg_width(this.__wbg_ptr)}get height(){return D.resvg_height(this.__wbg_ptr)}render(){try{let $=D.__wbindgen_add_to_stack_pointer(-16);D.resvg_render($,this.__wbg_ptr);var J=U()[$/4+0],Q=U()[$/4+1],Z=U()[$/4+2];if(Z)throw W(Q);return uJ.__wrap(J)}finally{D.__wbindgen_add_to_stack_pointer(16)}}toString(){let J,Q;try{let G=D.__wbindgen_add_to_stack_pointer(-16);D.resvg_toString(G,this.__wbg_ptr);var Z=U()[G/4+0],$=U()[G/4+1];return J=Z,Q=$,w(Z,$)}finally{D.__wbindgen_add_to_stack_pointer(16),D.__wbindgen_free(J,Q,1)}}innerBBox(){let J=D.resvg_innerBBox(this.__wbg_ptr);return J===0?void 0:d.__wrap(J)}getBBox(){let J=D.resvg_getBBox(this.__wbg_ptr);return J===0?void 0:d.__wrap(J)}cropByBBox(J){hJ(J,d),D.resvg_cropByBBox(this.__wbg_ptr,J.__wbg_ptr)}imagesToResolve(){try{let $=D.__wbindgen_add_to_stack_pointer(-16);D.resvg_imagesToResolve($,this.__wbg_ptr);var J=U()[$/4+0],Q=U()[$/4+1],Z=U()[$/4+2];if(Z)throw W(Q);return W(J)}finally{D.__wbindgen_add_to_stack_pointer(16)}}resolveImage(J,Q){try{let G=D.__wbindgen_add_to_stack_pointer(-16),X=g(J,D.__wbindgen_malloc,D.__wbindgen_realloc),q=h;D.resvg_resolveImage(G,this.__wbg_ptr,X,q,N(Q));var Z=U()[G/4+0],$=U()[G/4+1];if($)throw W(Z)}finally{D.__wbindgen_add_to_stack_pointer(16)}}},pJ,i=!1,dJ=async(J)=>{if(i)throw Error("Already initialized. The `initWasm()` function can be used only once.");await pJ(await J),i=!0},gJ;var VJ=IJ(()=>{T=Array(128).fill(void 0);T.push(void 0,null,!0,!1);x=T.length;y=typeof TextEncoder<"u"?new TextEncoder("utf-8"):{encode:()=>{throw Error("TextEncoder not available")}},xJ=typeof y.encodeInto==="function"?function(J,Q){return y.encodeInto(J,Q)}:function(J,Q){let Z=y.encode(J);return Q.set(Z),{read:J.length,written:Z.length}};DJ=typeof TextDecoder<"u"?new TextDecoder("utf-8",{ignoreBOM:!0,fatal:!0}):{decode:()=>{throw Error("TextDecoder not available")}};if(typeof TextDecoder<"u")DJ.decode();GJ=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry((J)=>D.__wbg_bbox_free(J>>>0)),XJ=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry((J)=>D.__wbg_renderedimage_free(J>>>0)),vJ=typeof FinalizationRegistry>"u"?{register:()=>{},unregister:()=>{}}:new FinalizationRegistry((J)=>D.__wbg_resvg_free(J>>>0));pJ=KJ,gJ=class extends bJ{constructor(J,Q){if(!i)throw Error("Wasm has not been initialized. Call `initWasm()` function.");let Z=Q?.font;if(!!Z&&cJ(Z)){let $={...Q,font:{...Z,fontBuffers:void 0}};super(J,JSON.stringify($),Z.fontBuffers)}else super(J,JSON.stringify(Q))}}});function A(J){return String(J??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}function RJ(J,Q,Z){let $=Z/512;return`<g transform="translate(${J},${Q}) scale(${$})">
3
3
  <rect x="0" y="0" width="512" height="512" rx="118" fill="#553de9"/>
4
4
  <path d="M152 405 L242 120" stroke="#FFFEFB" stroke-width="28" stroke-linecap="round" fill="none"/>
5
5
  <path d="M360 405 L270 120" stroke="#FFFEFB" stroke-width="28" stroke-linecap="round" fill="none"/>
6
6
  <path d="M242 120 Q256 86 270 120" stroke="#FFFEFB" stroke-width="28" stroke-linecap="round" fill="none"/>
7
7
  <circle cx="256" cy="295" r="20" fill="#1FC5A8"/>
8
- </g>`}function SJ(J){switch(J){case"verified":return"#1f8a52";case"failed":return"#b23a3a";case"working":case"pending":return"#9a6a12";default:return"#6b6675"}}function kJ(J){switch(J){case"pass":return"#1f8a52";case"fail":return"#b23a3a";case"pending":return"#9a6a12";default:return"#6b6675"}}function MJ(J){switch(J){case"approve":return"#1f8a52";case"reject":return"#b23a3a";case"concern":return"#9a6a12";default:return"#6b6675"}}function v(J,Q,X,Z,$="#201515"){return`<text x="${J}" y="${Q}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="12" fill="#6b6675" letter-spacing="0.5">${U(X.toUpperCase())}</text>
9
- <text x="${J}" y="${Q+24}" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="20" font-weight="600" fill="${$}">${U(Z)}</text>`}var OJ=["Reason","Act","Reflect","Verify"];function jJ(J){let Q=(J||"").toLowerCase();if(/verif|complet|done|ship|deploy/.test(Q))return 3;if(/reflect|review|council|critique|assess/.test(Q))return 2;if(/reason|plan|design|architect|spec|analy/.test(Q))return 0;return 1}function ZJ(J){let Z={run:J?.run||"cockpit",iteration:typeof J?.iteration==="number"?J.iteration:0,phase:J?.phase||"idle",tier:J?.tier||"",provider:J?.provider||"",verdict:J?.verdict||"unknown",budgetUsd:typeof J?.budgetUsd==="number"?J.budgetUsd:0,budgetLimitUsd:J?.budgetLimitUsd,freshness:J?.freshness,gates:Array.isArray(J?.gates)?J.gates:[],council:Array.isArray(J?.council)?J.council:[],fleet:Array.isArray(J?.fleet)?J.fleet:[]},$=Z.budgetLimitUsd&&Z.budgetLimitUsd>0?`$${Z.budgetUsd.toFixed(2)} / $${Z.budgetLimitUsd.toFixed(2)}`:`$${Z.budgetUsd.toFixed(2)}`,G="";G+=IJ(32,32,44),G+=`<text x="92" y="54" font-family="'Fraunces','Georgia',serif" font-size="24" font-weight="600" fill="#201515">Autonomi</text>`,G+=`<text x="92" y="74" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="13" fill="#6b6675">Loki Cockpit</text>`;let q=Z.freshness?`updated ${Z.freshness}`:"live";G+=`<text x="868" y="54" text-anchor="end" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="12" fill="#6b6675">${U(q)}</text>`,G+=`<text x="868" y="74" text-anchor="end" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="13" fill="${SJ(Z.verdict)}" font-weight="600">${U(Z.verdict.toUpperCase())}</text>`;let K=96,P=168;G+=`<rect x="32" y="${K}" width="836" height="${P}" rx="16" fill="#ffffff" stroke="#e2e0e8"/>`,G+=`<text x="56" y="${K+34}" font-family="'Fraunces','Georgia',serif" font-size="20" font-weight="600" fill="#201515">${U(Z.run)}</text>`,G+=`<text x="56" y="${K+54}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="13" fill="#6b6675">phase ${U(Z.phase)}</text>`;let z=K+96,E=(V)=>56+V*168;G+=v(E(0),z,"iteration",String(Z.iteration)),G+=v(E(1),z,"tier",Z.tier),G+=v(E(2),z,"provider",Z.provider),G+=v(E(3),z,"budget",$);let n=K+P+40;G+=`<text x="32" y="${n}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="13" font-weight="600" fill="#6b6675" letter-spacing="0.5">RARV LOOP</text>`;let s=jJ(Z.phase),I=n+14,o=200;OJ.forEach((V,Y)=>{let L=32+Y*(o+12),O=Y<s,H=Y===s;G+=`<rect x="${L}" y="${I}" width="${o}" height="40" rx="10" fill="${H?"#553de9":"#ffffff"}" fill-opacity="${H?"0.10":"1"}" stroke="${H?"#553de9":O?"#1f8a52":"#6b6675"}" stroke-width="${H?2:1}"/>`;let XJ=O?"check":H?"dot":"wait";if(XJ==="check")G+=`<path d="M${L+16} ${I+20} l6 6 l10 -12" stroke="#1f8a52" stroke-width="2.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>`;else if(XJ==="dot")G+=`<circle cx="${L+22}" cy="${I+20}" r="5" fill="#553de9"/>`;else G+=`<circle cx="${L+22}" cy="${I+20}" r="5" fill="none" stroke="#6b6675" stroke-width="1.5"/>`;G+=`<text x="${L+40}" y="${I+25}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="14" font-weight="${H?600:500}" fill="${H?"#553de9":O?"#201515":"#6b6675"}">${V}</text>`});let a=I+40+40;G+=`<text x="32" y="${a}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="13" font-weight="600" fill="#6b6675" letter-spacing="0.5">QUALITY GATES</text>`;let r=Z.gates.length?Z.gates:[{name:"no gates yet",status:"pending"}],S=30,k=a+12;G+=`<rect x="32" y="${k}" width="836" height="${r.slice(0,8).length*S+8}" rx="12" fill="#ffffff" stroke="#e2e0e8"/>`,k+=8;for(let V of r.slice(0,8)){let Y=kJ(V.status),L=k+S/2;if(G+=`<circle cx="50" cy="${L}" r="4" fill="${Y}"/>`,G+=`<text x="66" y="${L+4}" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="12" fill="#201515">${U(V.name)}</text>`,V.runner)G+=`<text x="242" y="${L+4}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="11" fill="#6b6675">${U(V.runner)}</text>`;if(V.evidence){let O=V.evidence.length>52?`${V.evidence.slice(0,49)}...`:V.evidence;G+=`<text x="332" y="${L+4}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="11" fill="#6b6675">${U(O)}</text>`}G+=`<text x="852" y="${L+4}" text-anchor="end" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="11" font-weight="700" fill="${Y}">${U(V.status.toUpperCase())}</text>`,k+=S}let t=k+40;G+=`<text x="32" y="${t}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="13" font-weight="600" fill="#6b6675" letter-spacing="0.5">COMPLETION COUNCIL</text>`;let e=Z.council.length?Z.council:[{reviewer:"pending",vote:"pending"}],M=t+12;G+=`<rect x="32" y="${M}" width="836" height="${e.slice(0,6).length*S+8}" rx="12" fill="#ffffff" stroke="#e2e0e8"/>`,M+=8;for(let V of e.slice(0,6)){let Y=MJ(V.vote),L=M+S/2;if(G+=`<circle cx="50" cy="${L}" r="4" fill="${Y}"/>`,G+=`<text x="66" y="${L+4}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="12.5" font-weight="500" fill="#201515">${U(V.reviewer)}</text>`,V.tier)G+=`<text x="292" y="${L+4}" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="11" fill="#6b6675">${U(V.tier)}</text>`;G+=`<text x="852" y="${L+4}" text-anchor="end" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="11" font-weight="700" fill="${Y}">${U(V.vote.toUpperCase())}</text>`,M+=S}let JJ=M+46,QJ=Z.fleet.filter((V)=>V.running).length,TJ=QJ>0?`FLEET (${QJ} active / ${Z.fleet.length})`:`FLEET (${Z.fleet.length}, none active)`;G+=`<text x="32" y="${JJ}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="13" font-weight="600" fill="#6b6675" letter-spacing="0.5">${TJ}</text>`;let B=JJ+20,m=Z.fleet.slice(0,4);for(let V of m){let Y=V.running?"#1f8a52":"#6b6675";G+=`<circle cx="38" cy="${B-4}" r="5" fill="${Y}"/>`,G+=`<text x="52" y="${B}" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="13" fill="#201515">${U(V.name)}</text>`;let L=`iter ${V.iteration??0} ${U(V.phase||V.status||"")}`;G+=`<text x="868" y="${B}" text-anchor="end" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="12" fill="#6b6675">${L}</text>`,B+=26}if(Z.fleet.length>m.length)G+=`<text x="52" y="${B}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="12" fill="#6b6675">+ ${Z.fleet.length-m.length} more</text>`,B+=26;let d=Math.round(B+32);return`<svg xmlns="http://www.w3.org/2000/svg" width="900" height="${d}" viewBox="0 0 900 ${d}">
10
- <rect x="0" y="0" width="900" height="${d}" fill="#f1f2f6"/>
11
- ${G}
12
- </svg>`}var f,u;function PJ(){if(f!==void 0)return f;try{let J=globalThis.require??F;J.resolve("@resvg/resvg-js"),f=J("@resvg/resvg-js")}catch{f=null}return f}async function LJ(){if(u!==void 0)return u;try{let J=await Promise.resolve().then(() => (VJ(),qJ)),Q=globalThis.require??F,{readFileSync:X,existsSync:Z}=await import("fs"),{resolve:$,dirname:G}=await import("path"),{fileURLToPath:q}=await import("url"),K=null;try{let P=G(q(import.meta.url));for(let z of["../data/resvg.wasm","../../data/resvg.wasm"]){let E=$(P,z);if(Z(E)){K=X(E);break}}}catch{}if(!K){let P=Q.resolve("@resvg/resvg-wasm/index_bg.wasm");K=X(P)}await J.initWasm(K),u={Resvg:J.Resvg}}catch{u=null}return u}async function NJ(){if(PJ()?.Resvg)return!0;return(await LJ())?.Resvg!=null}var R;async function cJ(){if(R!==void 0)return R;try{let{readFileSync:J,existsSync:Q}=await import("fs"),X=["/System/Library/Fonts/Supplemental/Arial.ttf","/System/Library/Fonts/Helvetica.ttc","/Library/Fonts/Arial.ttf","/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf","/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf","/usr/share/fonts/dejavu/DejaVuSans.ttf","/usr/share/fonts/TTF/DejaVuSans.ttf","C:\\Windows\\Fonts\\arial.ttf","C:\\Windows\\Fonts\\segoeui.ttf"];for(let Z of X)if(Q(Z))return R=new Uint8Array(J(Z)),R;R=null}catch{R=null}return R}async function UJ(J,Q=900){let X=PJ();if(X?.Resvg)try{let $=new X.Resvg(J,{fitTo:{mode:"width",value:Q}});return{png:Uint8Array.from($.render().asPng()),available:!0}}catch{}let Z=await LJ();if(Z?.Resvg)try{let $=await cJ(),G={fitTo:{mode:"width",value:Q}};if($)G.font={fontBuffers:[$],defaultFontFamily:"Arial",loadSystemFonts:!1};else G.font={loadSystemFonts:!0};let q=new Z.Resvg(J,G);return{png:Uint8Array.from(q.render().asPng()),available:!0}}catch($){return{png:null,available:!1,reason:`raster failed: ${$.message}`}}return{png:null,available:!1,reason:"rasterizer unavailable (no resvg native or wasm)"}}function AJ(J){return Buffer.from(J).toString("base64")}function nJ(J,Q){let X=AJ(J),Z=Q&&Q>0?`${Q}`:"auto";return`\x1B]1337;File=${`inline=1;size=${J.length};width=${Z};height=auto;preserveAspectRatio=1`}:${X}\x07`}function sJ(J,Q=4096,X){let Z=AJ(J);if(Z.length===0)return"\x1B_Ga=T,f=100,m=0;\x1B\\";let $=[];for(let K=0;K<Z.length;K+=Q)$.push(Z.slice(K,K+Q));let G=X&&X>0?`,c=${X}`:"",q="";for(let K=0;K<$.length;K++){let z=K===$.length-1?0:1,E=K===0?`a=T,f=100${G},m=${z}`:`m=${z}`;q+=`\x1B_G${E};${$[K]}\x1B\\`}return q}function CJ(J,Q,X){return J==="kitty"?sJ(Q,4096,X):nJ(Q,X)}var oJ=new Set(["iterm.app","wezterm","ghostty"]);function l(J=process.env){let Q=(J.LOKI_COCKPIT_PROTOCOL||"").trim().toLowerCase();if(Q==="iterm2"||Q==="kitty"||Q==="none")return Q;let X=(J.KITTY_WINDOW_ID||"").trim(),Z=(J.TERM||"").trim().toLowerCase();if(X.length>0||Z==="xterm-kitty")return"kitty";let $=(J.TERM_PROGRAM||"").trim().toLowerCase();if(oJ.has($))return"iterm2";return"none"}async function YJ(J,Q={}){let X=ZJ(J);if(Q.forceText)return{kind:"fallback",protocol:"none",reason:"--no-image (text/browser fallback)",svg:X};let Z;if(Q.protocol&&Q.protocol!=="auto")Z=Q.protocol;else Z=l(Q.env);if(Z==="none")return{kind:"fallback",protocol:Z,reason:"no inline-image terminal detected",svg:X};let $=await UJ(X);if(!$.available||!$.png)return{kind:"fallback",protocol:Z,reason:$.reason||"rasterization unavailable",svg:X};let G=CJ(Z,$.png,Q.cols);return{kind:"image",protocol:Z,data:G,svg:X}}var zJ=(J)=>typeof J==="number"&&Number.isFinite(J)&&J>=40;function EJ(J=process.stdout,Q=process.env){let X=J?.columns;if(zJ(X))return Math.floor(X);let Z=Number(Q.COLUMNS);if(zJ(Z))return Math.floor(Z);return 80}async function aJ(){let J=[];for await(let Q of process.stdin)J.push(Q);return Buffer.concat(J).toString("utf-8")}function rJ(J){let Q="auto",X=!1,Z;for(let $=0;$<J.length;$++){let G=J[$];if(G==="--protocol"){let q=(J[++$]||"auto").toLowerCase();Q=q==="iterm2"||q==="kitty"||q==="none"?q:"auto"}else if(G==="--no-image")X=!0;else if(G==="--svg-out")Z=J[++$]}return{protocol:Q,noImage:X,svgOut:Z}}async function tJ(){let J=l(),Q=await NJ(),X=J!=="none"&&Q?"image":"text+dashboard";return process.stdout.write(`protocol=${J}
8
+ </g>`}function SJ(J){switch(J){case"verified":return"#1f8a52";case"failed":return"#b23a3a";case"working":case"pending":return"#9a6a12";default:return"#6b6675"}}function kJ(J){switch(J){case"pass":return"#1f8a52";case"fail":return"#b23a3a";case"pending":return"#9a6a12";default:return"#6b6675"}}function MJ(J){switch(J){case"approve":return"#1f8a52";case"reject":return"#b23a3a";case"concern":return"#9a6a12";default:return"#6b6675"}}function v(J,Q,Z,$,G="#201515"){return`<text x="${J}" y="${Q}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="12" fill="#6b6675" letter-spacing="0.5">${A(Z.toUpperCase())}</text>
9
+ <text x="${J}" y="${Q+24}" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="20" font-weight="600" fill="${G}">${A($)}</text>`}var jJ=["Reason","Act","Reflect","Verify"];function OJ(J){let Q=(J||"").toLowerCase();if(/verif|complet|done|ship|deploy/.test(Q))return 3;if(/reflect|review|council|critique|assess/.test(Q))return 2;if(/reason|plan|design|architect|spec|analy/.test(Q))return 0;return 1}function $J(J){let $={run:J?.run||"cockpit",iteration:typeof J?.iteration==="number"?J.iteration:0,phase:J?.phase||"idle",tier:J?.tier||"",provider:J?.provider||"",verdict:J?.verdict||"unknown",budgetUsd:typeof J?.budgetUsd==="number"?J.budgetUsd:0,budgetLimitUsd:J?.budgetLimitUsd,freshness:J?.freshness,gates:Array.isArray(J?.gates)?J.gates:[],council:Array.isArray(J?.council)?J.council:[],fleet:Array.isArray(J?.fleet)?J.fleet:[]},G=$.budgetLimitUsd&&$.budgetLimitUsd>0?`$${$.budgetUsd.toFixed(2)} / $${$.budgetLimitUsd.toFixed(2)}`:`$${$.budgetUsd.toFixed(2)}`,X="";X+=RJ(32,32,44),X+=`<text x="92" y="54" font-family="'Fraunces','Georgia',serif" font-size="24" font-weight="600" fill="#201515">Autonomi</text>`,X+=`<text x="92" y="74" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="13" fill="#6b6675">Loki Cockpit</text>`;let q=$.freshness?`updated ${$.freshness}`:"live";X+=`<text x="868" y="54" text-anchor="end" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="12" fill="#6b6675">${A(q)}</text>`,X+=`<text x="868" y="74" text-anchor="end" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="13" fill="${SJ($.verdict)}" font-weight="600">${A($.verdict.toUpperCase())}</text>`;let K=96,L=168;X+=`<rect x="32" y="${K}" width="836" height="${L}" rx="16" fill="#ffffff" stroke="#e2e0e8"/>`,X+=`<text x="56" y="${K+34}" font-family="'Fraunces','Georgia',serif" font-size="20" font-weight="600" fill="#201515">${A($.run)}</text>`,X+=`<text x="56" y="${K+54}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="13" fill="#6b6675">phase ${A($.phase)}</text>`;let z=K+96,E=(V)=>56+V*168;X+=v(E(0),z,"iteration",String($.iteration)),X+=v(E(1),z,"tier",$.tier),X+=v(E(2),z,"provider",$.provider),X+=v(E(3),z,"budget",G);let n=K+L+40;X+=`<text x="32" y="${n}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="13" font-weight="600" fill="#6b6675" letter-spacing="0.5">RARV LOOP</text>`;let s=OJ($.phase),R=n+14,o=200;jJ.forEach((V,Y)=>{let P=32+Y*(o+12),j=Y<s,H=Y===s;X+=`<rect x="${P}" y="${R}" width="${o}" height="40" rx="10" fill="${H?"#553de9":"#ffffff"}" fill-opacity="${H?"0.10":"1"}" stroke="${H?"#553de9":j?"#1f8a52":"#6b6675"}" stroke-width="${H?2:1}"/>`;let ZJ=j?"check":H?"dot":"wait";if(ZJ==="check")X+=`<path d="M${P+16} ${R+20} l6 6 l10 -12" stroke="#1f8a52" stroke-width="2.5" fill="none" stroke-linecap="round" stroke-linejoin="round"/>`;else if(ZJ==="dot")X+=`<circle cx="${P+22}" cy="${R+20}" r="5" fill="#553de9"/>`;else X+=`<circle cx="${P+22}" cy="${R+20}" r="5" fill="none" stroke="#6b6675" stroke-width="1.5"/>`;X+=`<text x="${P+40}" y="${R+25}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="14" font-weight="${H?600:500}" fill="${H?"#553de9":j?"#201515":"#6b6675"}">${V}</text>`});let a=R+40+40;X+=`<text x="32" y="${a}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="13" font-weight="600" fill="#6b6675" letter-spacing="0.5">QUALITY GATES</text>`;let r=$.gates.length?$.gates:[{name:"no gates yet",status:"pending"}],S=30,k=a+12;X+=`<rect x="32" y="${k}" width="836" height="${r.slice(0,8).length*S+8}" rx="12" fill="#ffffff" stroke="#e2e0e8"/>`,k+=8;for(let V of r.slice(0,8)){let Y=kJ(V.status),P=k+S/2;if(X+=`<circle cx="50" cy="${P}" r="4" fill="${Y}"/>`,X+=`<text x="66" y="${P+4}" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="12" fill="#201515">${A(V.name)}</text>`,V.runner)X+=`<text x="242" y="${P+4}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="11" fill="#6b6675">${A(V.runner)}</text>`;if(V.evidence){let j=V.evidence.length>52?`${V.evidence.slice(0,49)}...`:V.evidence;X+=`<text x="332" y="${P+4}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="11" fill="#6b6675">${A(j)}</text>`}X+=`<text x="852" y="${P+4}" text-anchor="end" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="11" font-weight="700" fill="${Y}">${A(V.status.toUpperCase())}</text>`,k+=S}let t=k+40;X+=`<text x="32" y="${t}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="13" font-weight="600" fill="#6b6675" letter-spacing="0.5">COMPLETION COUNCIL</text>`;let e=$.council.length?$.council:[{reviewer:"pending",vote:"pending"}],M=t+12;X+=`<rect x="32" y="${M}" width="836" height="${e.slice(0,6).length*S+8}" rx="12" fill="#ffffff" stroke="#e2e0e8"/>`,M+=8;for(let V of e.slice(0,6)){let Y=MJ(V.vote),P=M+S/2;if(X+=`<circle cx="50" cy="${P}" r="4" fill="${Y}"/>`,X+=`<text x="66" y="${P+4}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="12.5" font-weight="500" fill="#201515">${A(V.reviewer)}</text>`,V.tier)X+=`<text x="292" y="${P+4}" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="11" fill="#6b6675">${A(V.tier)}</text>`;X+=`<text x="852" y="${P+4}" text-anchor="end" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="11" font-weight="700" fill="${Y}">${A(V.vote.toUpperCase())}</text>`,M+=S}let JJ=M+46,QJ=$.fleet.filter((V)=>V.running).length,TJ=QJ>0?`FLEET (${QJ} active / ${$.fleet.length})`:`FLEET (${$.fleet.length}, none active)`;X+=`<text x="32" y="${JJ}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="13" font-weight="600" fill="#6b6675" letter-spacing="0.5">${TJ}</text>`;let B=JJ+20,m=$.fleet.slice(0,4);for(let V of m){let Y=V.running?"#1f8a52":"#6b6675";X+=`<circle cx="38" cy="${B-4}" r="5" fill="${Y}"/>`,X+=`<text x="52" y="${B}" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="13" fill="#201515">${A(V.name)}</text>`;let P=`iter ${V.iteration??0} ${A(V.phase||V.status||"")}`;X+=`<text x="868" y="${B}" text-anchor="end" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="12" fill="#6b6675">${P}</text>`,B+=26}if($.fleet.length>m.length)X+=`<text x="52" y="${B}" font-family="'Inter','Helvetica Neue',Arial,sans-serif" font-size="12" fill="#6b6675">+ ${$.fleet.length-m.length} more</text>`,B+=26;let p=Math.round(B+32);return`<svg xmlns="http://www.w3.org/2000/svg" width="900" height="${p}" viewBox="0 0 900 ${p}">
10
+ <rect x="0" y="0" width="900" height="${p}" fill="#f1f2f6"/>
11
+ ${X}
12
+ </svg>`}var f,u;function LJ(){if(f!==void 0)return f;try{let J=globalThis.require??F;J.resolve("@resvg/resvg-js"),f=J("@resvg/resvg-js")}catch{f=null}return f}async function PJ(){if(u!==void 0)return u;try{let J=await Promise.resolve().then(() => (VJ(),qJ)),Q=globalThis.require??F,{readFileSync:Z,existsSync:$}=await import("fs"),{resolve:G,dirname:X}=await import("path"),{fileURLToPath:q}=await import("url"),K=null;try{let L=X(q(import.meta.url));for(let z of["../data/resvg.wasm","../../data/resvg.wasm"]){let E=G(L,z);if($(E)){K=Z(E);break}}}catch{}if(!K){let L=Q.resolve("@resvg/resvg-wasm/index_bg.wasm");K=Z(L)}await J.initWasm(K),u={Resvg:J.Resvg}}catch{u=null}return u}async function UJ(){if(LJ()?.Resvg)return!0;return(await PJ())?.Resvg!=null}var I;async function iJ(){if(I!==void 0)return I;try{let{readFileSync:J,existsSync:Q}=await import("fs"),Z=["/System/Library/Fonts/Supplemental/Arial.ttf","/System/Library/Fonts/Helvetica.ttc","/Library/Fonts/Arial.ttf","/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf","/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf","/usr/share/fonts/dejavu/DejaVuSans.ttf","/usr/share/fonts/TTF/DejaVuSans.ttf","C:\\Windows\\Fonts\\arial.ttf","C:\\Windows\\Fonts\\segoeui.ttf"];for(let $ of Z)if(Q($))return I=new Uint8Array(J($)),I;I=null}catch{I=null}return I}async function AJ(J,Q=900){let Z=LJ();if(Z?.Resvg)try{let G=new Z.Resvg(J,{fitTo:{mode:"width",value:Q}});return{png:Uint8Array.from(G.render().asPng()),available:!0}}catch{}let $=await PJ();if($?.Resvg)try{let G=await iJ(),X={fitTo:{mode:"width",value:Q}};if(G)X.font={fontBuffers:[G],defaultFontFamily:"Arial",loadSystemFonts:!1};else X.font={loadSystemFonts:!0};let q=new $.Resvg(J,X);return{png:Uint8Array.from(q.render().asPng()),available:!0}}catch(G){return{png:null,available:!1,reason:`raster failed: ${G.message}`}}return{png:null,available:!1,reason:"rasterizer unavailable (no resvg native or wasm)"}}function CJ(J){return Buffer.from(J).toString("base64")}function nJ(J,Q){let Z=CJ(J),$=Q&&Q>0?`${Q}`:"auto";return`\x1B]1337;File=${`inline=1;size=${J.length};width=${$};height=auto;preserveAspectRatio=1`}:${Z}\x07`}function sJ(J,Q=4096,Z){let $=CJ(J);if($.length===0)return"\x1B_Ga=T,f=100,m=0;\x1B\\";let G=[];for(let K=0;K<$.length;K+=Q)G.push($.slice(K,K+Q));let X=Z&&Z>0?`,c=${Z}`:"",q="";for(let K=0;K<G.length;K++){let z=K===G.length-1?0:1,E=K===0?`a=T,f=100${X},m=${z}`:`m=${z}`;q+=`\x1B_G${E};${G[K]}\x1B\\`}return q}function NJ(J,Q,Z){return J==="kitty"?sJ(Q,4096,Z):nJ(Q,Z)}var oJ=new Set(["iterm.app","wezterm","ghostty"]);function l(J=process.env){let Q=(J.LOKI_COCKPIT_PROTOCOL||"").trim().toLowerCase();if(Q==="iterm2"||Q==="kitty"||Q==="none")return Q;let Z=(J.KITTY_WINDOW_ID||"").trim(),$=(J.TERM||"").trim().toLowerCase();if(Z.length>0||$==="xterm-kitty")return"kitty";let G=(J.TERM_PROGRAM||"").trim().toLowerCase();if(oJ.has(G))return"iterm2";return"none"}async function YJ(J,Q={}){let Z=$J(J);if(Q.forceText)return{kind:"fallback",protocol:"none",reason:"--no-image (text/browser fallback)",svg:Z};let $;if(Q.protocol&&Q.protocol!=="auto")$=Q.protocol;else $=l(Q.env);if($==="none")return{kind:"fallback",protocol:$,reason:"no inline-image terminal detected",svg:Z};let G=await AJ(Z);if(!G.available||!G.png)return{kind:"fallback",protocol:$,reason:G.reason||"rasterization unavailable",svg:Z};let X=NJ($,G.png,Q.cols);return{kind:"image",protocol:$,data:X,svg:Z}}var zJ=(J)=>typeof J==="number"&&Number.isFinite(J)&&J>=40;function EJ(J=process.stdout,Q=process.env){let Z=J?.columns;if(zJ(Z))return Math.floor(Z);let $=Number(Q.COLUMNS);if(zJ($))return Math.floor($);return 80}async function aJ(){let J=[];for await(let Q of process.stdin)J.push(Q);return Buffer.concat(J).toString("utf-8")}function rJ(J){let Q="auto",Z=!1,$;for(let G=0;G<J.length;G++){let X=J[G];if(X==="--protocol"){let q=(J[++G]||"auto").toLowerCase();Q=q==="iterm2"||q==="kitty"||q==="none"?q:"auto"}else if(X==="--no-image")Z=!0;else if(X==="--svg-out")$=J[++G]}return{protocol:Q,noImage:Z,svgOut:$}}async function tJ(){let J=l(),Q=await UJ(),Z=J!=="none"&&Q?"image":"text+dashboard";return process.stdout.write(`protocol=${J}
13
13
  `),process.stdout.write(`resvg=${Q?"yes":"no"}
14
- `),process.stdout.write(`path=${X}
15
- `),0}async function eJ(J=process.argv.slice(2)){if(J.includes("--probe"))return await tJ();let{protocol:Q,noImage:X,svgOut:Z}=rJ(J),$;try{let K=await aJ();$=JSON.parse(K)}catch(K){return process.stderr.write(`FALLBACK could not parse cockpit state: ${K.message}
16
- `),3}let G=EJ()-2,q=await YJ($,{protocol:Q,forceText:X,cols:G});if(Z)try{let{writeFileSync:K}=await import("fs");K(Z,q.svg)}catch{}if(q.kind==="image"&&q.data)return process.stdout.write(q.data),0;return process.stderr.write(`FALLBACK ${q.reason||"image unavailable"}
14
+ `),process.stdout.write(`path=${Z}
15
+ `),0}async function eJ(J=process.argv.slice(2)){if(J.includes("--probe"))return await tJ();let{protocol:Q,noImage:Z,svgOut:$}=rJ(J),G;try{let K=await aJ();G=JSON.parse(K)}catch(K){return process.stderr.write(`FALLBACK could not parse cockpit state: ${K.message}
16
+ `),3}let X=EJ()-2,q=await YJ(G,{protocol:Q,forceText:Z,cols:X});if($)try{let{writeFileSync:K}=await import("fs");K($,q.svg)}catch{}if(q.kind==="image"&&q.data)return process.stdout.write(q.data),0;return process.stderr.write(`FALLBACK ${q.reason||"image unavailable"}
17
17
  `),3}if(import.meta.main)eJ().then((J)=>process.exit(J));export{eJ as main};
18
18
 
19
- //# debugId=8D6BC88E3E25DA192460C5798D71C777
19
+ //# debugId=DC6384A5E20B0D85C10FC2AD2CD64E13