loki-mode 11.17.59 → 11.17.60
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/lib/engine10-push.sh +77 -0
- package/autonomy/lib/proof_redact.py +26 -2
- package/autonomy/run.sh +11 -1
- package/dashboard/__init__.py +1 -1
- package/docs/CLI-REFERENCE.md +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/docs/QUICKSTART.md +7 -0
- package/docs/v10/FAILURE-CLASSES.md +13 -0
- package/loki-ts/dist/cockpit.js +10 -10
- package/loki-ts/dist/loki.js +1202 -1201
- package/mcp/__init__.py +1 -1
- package/package.json +2 -2
- package/packages/control-plane/dist/server.js +8 -7
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/web-app/dist/assets/{AdminPage-CCO9zGD0.js → AdminPage-DUuYBy7U.js} +1 -1
- package/web-app/dist/assets/{Avatar-JPtFS3re.js → Avatar-apqPQq7o.js} +1 -1
- package/web-app/dist/assets/{Badge-1bUFOFcI.js → Badge-BCKC5rw5.js} +1 -1
- package/web-app/dist/assets/{Button-BQn8thxN.js → Button-Ii2qz5ro.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-olBRJMLN.js → CockpitPage-DCRCbvnY.js} +1 -1
- package/web-app/dist/assets/{ComparePage-B-o4mxlZ.js → ComparePage-BoEYx63C.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-C4IN6YYt.js → ErrorBoundary-XXVx8_4-.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-CH4iRJiJ.js → EvidenceReceiptPanel-k40RtZB_.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-BNgRlwGt.js → GitHubIssuesPanel-BgPkc-75.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-B6M_lVU3.js → GitHubPRsPanel-CwhorB4G.js} +1 -1
- package/web-app/dist/assets/{HomePage-CSlr_5vo.js → HomePage-CIZPEgSM.js} +2 -2
- package/web-app/dist/assets/{LoginPage-DJhYZ0SQ.js → LoginPage-DZSoNZ3y.js} +1 -1
- package/web-app/dist/assets/{MagicPage-B4XpvDFP.js → MagicPage-eThBQUgO.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-DlgPEc5f.js → MetricsPage-BWtdAivK.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-oE1Fvllj.js → NotFoundPage-CNeOANG9.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-B94pP0UO.js → ProjectPage-CdFR-RTO.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-Bk67iaJq.js → ProjectsPage-BPdXEovl.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-BGVzSJ3n.js → SettingsPage-B3vsyBHf.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-DtGaDxE5.js → ShowcasePage-DhtEGTId.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-CfyOGdC-.js → SystemSettingsPage-CCRMF5oP.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-CuGmdY85.js → TeamsPage-B5jpVrT8.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-Db4OZ-o0.js → TemplatesPage-B0NOrY9y.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-B1W28fpH.js → TerminalOutput-Y7S9_kCF.js} +1 -1
- package/web-app/dist/assets/{activity-DKFtW1Dz.js → activity-DDGuxXV8.js} +1 -1
- package/web-app/dist/assets/{bell-D2iqUEiO.js → bell-v1a0v0aO.js} +1 -1
- package/web-app/dist/assets/{bot-DgV5jnOz.js → bot-Dh9apAJT.js} +1 -1
- package/web-app/dist/assets/{check-BgJBmYEn.js → check-BIqFwS-y.js} +1 -1
- package/web-app/dist/assets/{chevron-left-lPbv6ogy.js → chevron-left-EBM7yWz9.js} +1 -1
- package/web-app/dist/assets/{circle-alert-CKhQ_hdo.js → circle-alert-Czhu4uRg.js} +1 -1
- package/web-app/dist/assets/{clock-DWq8vor5.js → clock-BdJ55LJy.js} +1 -1
- package/web-app/dist/assets/{cloud-BvQxG3Q2.js → cloud-CC4nJD4m.js} +1 -1
- package/web-app/dist/assets/{code-xml-aL36Csaf.js → code-xml-2TmM3ZXT.js} +1 -1
- package/web-app/dist/assets/{database-CFzHMx2h.js → database-0TieR4KZ.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-C-jqbXs_.js → dollar-sign-pTh1osY0.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-pZ_KZ1YO.js → file-code-corner-DQ8FfkCJ.js} +1 -1
- package/web-app/dist/assets/{file-plus-fRMGiUh4.js → file-plus-CYgNMECJ.js} +1 -1
- package/web-app/dist/assets/{globe-CVyRdgIZ.js → globe-KQA_9R6O.js} +1 -1
- package/web-app/dist/assets/{hammer-DRokcz-I.js → hammer-CZMQWpu3.js} +1 -1
- package/web-app/dist/assets/{index-CLY7CAQL.js → index-BRCtE1U8.js} +3 -3
- package/web-app/dist/assets/{layers-CEWB89or.js → layers-CPYePIbK.js} +1 -1
- package/web-app/dist/assets/{loader-circle-C5OvUx9K.js → loader-circle-DmvGxkYe.js} +1 -1
- package/web-app/dist/assets/{lock-TGMA_-t0.js → lock-BTKaeWpE.js} +1 -1
- package/web-app/dist/assets/{package-QJ4Wad2J.js → package-Blxc3ohw.js} +1 -1
- package/web-app/dist/assets/{plus-Dgj8mPvu.js → plus-DxtJyvK_.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-AGMW2syT.js → refresh-cw-hA4AfO_9.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-BvQ3PO0r.js → rotate-ccw-CEqVnL9N.js} +1 -1
- package/web-app/dist/assets/{scroll-text-iwC90pRp.js → scroll-text-tJPLGtKd.js} +1 -1
- package/web-app/dist/assets/{server-TUwkkzsm.js → server-TuWGPUjH.js} +1 -1
- package/web-app/dist/assets/{shield-alert-CR3ONYJ5.js → shield-alert-C8d0Z4Ax.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-DC2-6Rb1.js → thumbs-up-C6hv5hUr.js} +1 -1
- package/web-app/dist/assets/{trash-2-o9Iijmor.js → trash-2-Dk9XPU3k.js} +1 -1
- package/web-app/dist/assets/{trending-down-d0olJaN5.js → trending-down-BJp7dvps.js} +1 -1
- package/web-app/dist/assets/{trending-up-BB6Q7LpE.js → trending-up-Rh6ULiPp.js} +1 -1
- package/web-app/dist/assets/{upload-5ck9hJ9r.js → upload-CRP_Npdp.js} +1 -1
- package/web-app/dist/assets/{usePolling-BLGH4uFR.js → usePolling-UXubXtkC.js} +1 -1
- package/web-app/dist/assets/{user-CNCAMMb7.js → user-AiyHiPpF.js} +1 -1
- 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.
|
|
6
|
+
# Loki Mode v11.17.60
|
|
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.
|
|
486
|
+
**v11.17.60 | [Autonomi](https://www.autonomi.dev/) flagship product | core skill**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
11.17.
|
|
1
|
+
11.17.60
|
|
@@ -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=""
|
|
@@ -215,6 +283,15 @@ case "$mode" in
|
|
|
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
285
|
[ -z "$_e10_local" ] || { log_info "local origin: no issue to comment on (no-op)"; 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
|
+
exit 0
|
|
294
|
+
fi
|
|
218
295
|
if [ -n "$_e10_upd" ]; then
|
|
219
296
|
_e10_marker=""
|
|
220
297
|
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+.\-]
|
|
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
|
-
|
|
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."
|
package/dashboard/__init__.py
CHANGED
package/docs/CLI-REFERENCE.md
CHANGED
|
@@ -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.
|
|
3
|
+
Generated from `loki-ts/src/cli/registry.ts` by `scripts/generate-stale-zero.sh` for v11.17.60. 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 |
|
package/docs/INSTALLATION.md
CHANGED
|
@@ -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.
|
|
5
|
+
**Version:** v11.17.60
|
|
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
|
|
package/docs/QUICKSTART.md
CHANGED
|
@@ -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,16 @@ 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).
|
package/loki-ts/dist/cockpit.js
CHANGED
|
@@ -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
|
|
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,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}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,
|
|
9
|
-
<text x="${J}" y="${Q+24}" font-family="'JetBrains Mono','SF Mono',ui-monospace,monospace" font-size="20" font-weight="600" fill="${
|
|
10
|
-
<rect x="0" y="0" width="900" height="${
|
|
11
|
-
${
|
|
12
|
-
</svg>`}var f,u;function
|
|
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=${
|
|
15
|
-
`),0}async function eJ(J=process.argv.slice(2)){if(J.includes("--probe"))return await tJ();let{protocol:Q,noImage:
|
|
16
|
-
`),3}let
|
|
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=
|
|
19
|
+
//# debugId=DC6384A5E20B0D85C10FC2AD2CD64E13
|