loki-mode 9.77.0 → 9.80.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/autonomy/lib/engine10-legacy-notice.txt +3 -0
  4. package/autonomy/lib/engine10-push-gitlab.sh +96 -0
  5. package/autonomy/lib/engine10-push.sh +149 -0
  6. package/autonomy/run.sh +2 -2
  7. package/bin/loki +21 -0
  8. package/dashboard/__init__.py +1 -1
  9. package/docs/INSTALLATION.md +1 -1
  10. package/docs/dev/tmp-cleanup.md +3 -3
  11. package/docs/v10/BOARD.md +105 -35
  12. package/docs/v10/DECISIONS.md +10 -0
  13. package/docs/v10/ENGINE-MEASURE.md +69 -0
  14. package/docs/v10/ENGINE.md +272 -0
  15. package/docs/v10/METRICS.md +26 -0
  16. package/docs/v10/PROGRESS.md +45 -0
  17. package/loki-ts/dist/loki.js +562 -620
  18. package/loki-ts/package.json +1 -1
  19. package/mcp/__init__.py +1 -1
  20. package/package.json +1 -1
  21. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  22. package/web-app/dist/assets/{AdminPage-_YAgQxgp.js → AdminPage-Brg7_Lyr.js} +1 -1
  23. package/web-app/dist/assets/{Avatar-Bxbdwgz5.js → Avatar-7nY6uJxD.js} +1 -1
  24. package/web-app/dist/assets/{Badge-DFOiCwzh.js → Badge-Cbf2CTvW.js} +1 -1
  25. package/web-app/dist/assets/{Button-84KGqMJR.js → Button-CvKmf9hm.js} +1 -1
  26. package/web-app/dist/assets/{CockpitPage-Ck8i3mNd.js → CockpitPage-wLAuI5UQ.js} +1 -1
  27. package/web-app/dist/assets/{ComparePage-BpIdW5x8.js → ComparePage-CMdzzTeh.js} +1 -1
  28. package/web-app/dist/assets/{ErrorBoundary-Dcwg_4nU.js → ErrorBoundary-CAIYBXBt.js} +1 -1
  29. package/web-app/dist/assets/{EvidenceReceiptPanel-6II8hA4-.js → EvidenceReceiptPanel-BnrDrzRA.js} +1 -1
  30. package/web-app/dist/assets/{GitHubIssuesPanel-CCpJxUo5.js → GitHubIssuesPanel-CnWx9CiK.js} +1 -1
  31. package/web-app/dist/assets/{GitHubPRsPanel-BN7KtPRB.js → GitHubPRsPanel-y8gYUjnH.js} +1 -1
  32. package/web-app/dist/assets/{HomePage-Dmh8Ompu.js → HomePage-CqaADKqJ.js} +2 -2
  33. package/web-app/dist/assets/{LoginPage-e_wvWykS.js → LoginPage-C4-UpzUT.js} +1 -1
  34. package/web-app/dist/assets/{MagicPage-SkEbXneS.js → MagicPage-CQ7UMIwO.js} +1 -1
  35. package/web-app/dist/assets/{MetricsPage-Jr2E8O4h.js → MetricsPage-nGehSAp4.js} +1 -1
  36. package/web-app/dist/assets/{NotFoundPage-Bo-xIGHn.js → NotFoundPage-EkC6K3N-.js} +1 -1
  37. package/web-app/dist/assets/{ProjectPage--lRlzM8G.js → ProjectPage-Cdjs0beW.js} +3 -3
  38. package/web-app/dist/assets/{ProjectsPage-CG_L0UkM.js → ProjectsPage-CHcSeyxO.js} +1 -1
  39. package/web-app/dist/assets/{SettingsPage-DdZ4UAJM.js → SettingsPage-DDhw0s6W.js} +1 -1
  40. package/web-app/dist/assets/{ShowcasePage-CnV468WN.js → ShowcasePage-BBxQDg5j.js} +1 -1
  41. package/web-app/dist/assets/{SystemSettingsPage-CyvaTJ_t.js → SystemSettingsPage-Aj91V7Zy.js} +1 -1
  42. package/web-app/dist/assets/{TeamsPage-g5hHDx0X.js → TeamsPage-H10Qp1fu.js} +1 -1
  43. package/web-app/dist/assets/{TemplatesPage-CRcRm9ED.js → TemplatesPage-AcxgsKwZ.js} +1 -1
  44. package/web-app/dist/assets/{TerminalOutput-BDBfTY9s.js → TerminalOutput-O6dQA9Qa.js} +1 -1
  45. package/web-app/dist/assets/{activity-CpH9qoQP.js → activity-CMnBtTxM.js} +1 -1
  46. package/web-app/dist/assets/{bell-BtlnNdD8.js → bell-Dseaifqw.js} +1 -1
  47. package/web-app/dist/assets/{bot-BAH-qJ4B.js → bot-Bm_xcawB.js} +1 -1
  48. package/web-app/dist/assets/{check-D7ydqeHo.js → check-TXNSTOop.js} +1 -1
  49. package/web-app/dist/assets/{chevron-left-CJ48kXi_.js → chevron-left-D35Mb_-x.js} +1 -1
  50. package/web-app/dist/assets/{circle-alert-C3m8Jdum.js → circle-alert-Rt6AMJ2V.js} +1 -1
  51. package/web-app/dist/assets/{clock-CpVxJ_xL.js → clock-Dlc0SEVv.js} +1 -1
  52. package/web-app/dist/assets/{cloud-C5RpwJJ2.js → cloud-DPd4GLS2.js} +1 -1
  53. package/web-app/dist/assets/{code-xml-D8Ch_l6l.js → code-xml-B_scyMd5.js} +1 -1
  54. package/web-app/dist/assets/{database-Dc-r_JaX.js → database-DuPEBXUA.js} +1 -1
  55. package/web-app/dist/assets/{dollar-sign-CXOSNCEc.js → dollar-sign-C49nrBOI.js} +1 -1
  56. package/web-app/dist/assets/{file-code-corner-il9KkndN.js → file-code-corner-B3wt8I4V.js} +1 -1
  57. package/web-app/dist/assets/{file-plus-CduheFSQ.js → file-plus-CuHHSDVU.js} +1 -1
  58. package/web-app/dist/assets/{globe-C_H2CJ0N.js → globe-Kl77FTuJ.js} +1 -1
  59. package/web-app/dist/assets/{hammer-Dd0DZNve.js → hammer-D0LLVOf5.js} +1 -1
  60. package/web-app/dist/assets/{index-CnURGAFT.js → index-ufh2YvPO.js} +2 -2
  61. package/web-app/dist/assets/{layers-CofXpCI5.js → layers-C3vb5zor.js} +1 -1
  62. package/web-app/dist/assets/{loader-circle-Z2PHP1vi.js → loader-circle-BfFuGacT.js} +1 -1
  63. package/web-app/dist/assets/{lock-BKZcBfqE.js → lock-CicpAGtr.js} +1 -1
  64. package/web-app/dist/assets/{package-VeINyJLx.js → package-Bw8snKHr.js} +1 -1
  65. package/web-app/dist/assets/{plus-BdRdn_Ne.js → plus-KXZkO61K.js} +1 -1
  66. package/web-app/dist/assets/{refresh-cw-SQlfufGR.js → refresh-cw-CshUF54x.js} +1 -1
  67. package/web-app/dist/assets/{rotate-ccw-z7xY1hor.js → rotate-ccw-S9JJTBcV.js} +1 -1
  68. package/web-app/dist/assets/{scroll-text-D9DLjkO9.js → scroll-text-CLOq2Mvg.js} +1 -1
  69. package/web-app/dist/assets/{server-VlEVEIp_.js → server-ClM4a2Wx.js} +1 -1
  70. package/web-app/dist/assets/{shield-alert-D0ulDTaf.js → shield-alert-DXhyR0S_.js} +1 -1
  71. package/web-app/dist/assets/{thumbs-up-7_JKRnvS.js → thumbs-up-CYb6ycQ-.js} +1 -1
  72. package/web-app/dist/assets/{trash-2-DmRmNre3.js → trash-2-BcHIiT3v.js} +1 -1
  73. package/web-app/dist/assets/{trending-down-DZwkFd-S.js → trending-down-C5eAxnkt.js} +1 -1
  74. package/web-app/dist/assets/{trending-up-4ql9Pr4t.js → trending-up-m9XmNKav.js} +1 -1
  75. package/web-app/dist/assets/{upload-D2KPx9Uo.js → upload-ZYJCPyYM.js} +1 -1
  76. package/web-app/dist/assets/{usePolling-D6alWGU5.js → usePolling-uC-lirzx.js} +1 -1
  77. package/web-app/dist/assets/{user-Bo3EjryF.js → user-C1dyK-6p.js} +1 -1
  78. package/web-app/dist/index.html +1 -1
package/SKILL.md CHANGED
@@ -3,7 +3,7 @@ name: loki-mode
3
3
  description: Autonomous spec-driven build system with a built-in trust layer. It does not call work done until it is verified (RARV-C closure loop, 8 quality gates, completion council, verified-completion evidence gate). Triggers on "Loki Mode". Takes a spec (PRD, GitHub issue, OpenAPI doc, etc.) to deployed product with minimal human intervention. Provider-agnostic. Requires --dangerously-skip-permissions flag.
4
4
  ---
5
5
 
6
- # Loki Mode v9.77.0
6
+ # Loki Mode v9.80.1
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -470,4 +470,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
470
470
 
471
471
  ---
472
472
 
473
- **v9.77.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
473
+ **v9.80.1 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 9.77.0
1
+ 9.80.1
@@ -0,0 +1,3 @@
1
+ Legacy engine: deprecated in v10.0.0, still fully supported.
2
+ No removal this release. Set LOKI_ENGINE=legacy to pin it.
3
+ Guide: docs/v10/GUIDE.md
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env bash
2
+ # Loki 10 engine P4 push child for GitLab (ENGINE.md sections 6, 7 and 13).
3
+ #
4
+ # engine10-push-gitlab.sh push-mr <repo-dir> <branch> <title> <body-file> [--draft]
5
+ #
6
+ # Prints the merge request URL. Holds GitLab credentials, runs no LLM, reads
7
+ # no untrusted text beyond argv. The target project comes only from the origin
8
+ # P0 pinned before any provider ran (_LOKI_ORIGIN_PINNED=1
9
+ # _LOKI_PINNED_ORIGIN=<url>), and that origin must be a literal gitlab.com
10
+ # https or ssh URL. _loki_trusted_push refuses non-github.com origins, so this
11
+ # mirrors its shape: the branch is fetched into a fresh --template= repo and
12
+ # pushed from there, so no agent-repo hook or config runs in the credentialed
13
+ # process; glab runs from / with the host fixed to gitlab.com.
14
+ set -o pipefail
15
+
16
+ die() { printf 'engine10-push-gitlab: %s\n' "$*" >&2; exit "${2:-2}"; }
17
+
18
+ # <url> -> GROUP[/SUBGROUP...]/PROJECT on stdout, or rc 1. Literal gitlab.com
19
+ # only: no host alias, no port, no embedded credentials, no odd characters.
20
+ _e10_gitlab_project_from_url() {
21
+ local u="${1:-}" lc pre p
22
+ lc="$(printf '%s' "$u" | tr '[:upper:]' '[:lower:]')"
23
+ case "$lc" in
24
+ https://gitlab.com/*) pre="https://gitlab.com/" ;;
25
+ git@gitlab.com:*) pre="git@gitlab.com:" ;;
26
+ ssh://git@gitlab.com/*) pre="ssh://git@gitlab.com/" ;;
27
+ *) return 1 ;;
28
+ esac
29
+ p="${u:${#pre}}"
30
+ p="${p%/}"
31
+ p="${p%.git}"
32
+ case "$p" in
33
+ /* | */ | *//* | */.* | .* | *..* | */-/* | *[!A-Za-z0-9._/-]*) return 1 ;;
34
+ ?*/?*) printf '%s\n' "$p" ;;
35
+ *) return 1 ;;
36
+ esac
37
+ }
38
+
39
+ # Neutral glab: cwd /, no git dir, host pinned so an ambient GITLAB_HOST
40
+ # cannot send the token elsewhere.
41
+ _e10_glab() {
42
+ (
43
+ cd / || exit 1
44
+ unset GIT_DIR GIT_WORK_TREE GL_HOST GITLAB_API_HOST
45
+ export GITLAB_HOST=gitlab.com
46
+ command glab "$@"
47
+ )
48
+ }
49
+
50
+ [ "${_LOKI_ORIGIN_PINNED:-}" = "1" ] || die "origin not pinned (_LOKI_ORIGIN_PINNED=1 required)"
51
+ url="${_LOKI_PINNED_ORIGIN:-}"
52
+ proj="$(_e10_gitlab_project_from_url "$url")" \
53
+ || die "pinned origin refused: not a literal gitlab.com https or ssh GROUP/PROJECT URL"
54
+
55
+ mode="${1:-}"
56
+ shift || true
57
+ [ "$mode" = "push-mr" ] || die "usage: engine10-push-gitlab.sh push-mr <repo-dir> <branch> <title> <body-file> [--draft]"
58
+ [ "$#" -ge 4 ] && [ "$#" -le 5 ] || die "usage: push-mr <repo-dir> <branch> <title> <body-file> [--draft]"
59
+ dir="$1" branch="$2" title="$3" body="$4" draft=()
60
+ if [ "$#" -eq 5 ]; then
61
+ [ "$5" = "--draft" ] || die "unknown flag: $5"
62
+ draft=(--draft)
63
+ fi
64
+ [ -f "$body" ] || die "body file not found: $body"
65
+ dir="$(cd "$dir" 2>/dev/null && pwd -P)" || die "repo dir not found"
66
+ git check-ref-format --branch "$branch" >/dev/null 2>&1 || die "bad branch name"
67
+ case "$branch" in
68
+ main | master | HEAD) die "Not pushing branch '$branch': Loki never pushes directly to a default branch." ;;
69
+ esac
70
+ cur="$(git -C "$dir" config --get remote.origin.url 2>/dev/null)" || cur=""
71
+ [ "$cur" = "$url" ] || die "Not pushing branch '$branch': origin changed during the run; Loki does not push to a destination the agent could have chosen."
72
+
73
+ enc="${proj//\//%2F}"
74
+ def="$(_e10_glab api "projects/$enc" 2>/dev/null \
75
+ | python3 -c 'import json,sys; print(json.load(sys.stdin).get("default_branch") or "")' 2>/dev/null)" || def=""
76
+ [ -n "$def" ] || die "Not pushing branch '$branch': could not resolve the default branch of $proj."
77
+ [ "$branch" != "$def" ] || die "Not pushing branch '$branch': it is the default branch of $proj."
78
+
79
+ tmp="$(mktemp -d "${TMPDIR:-/tmp}/loki-push-gl.XXXXXX")" || die "mktemp failed" 1
80
+ trap 'rm -rf "$tmp"' EXIT
81
+ git init -q --template= "$tmp" >/dev/null 2>&1 \
82
+ && git -C "$tmp" fetch -q --no-tags --update-shallow "$dir" "+refs/heads/$branch:refs/heads/$branch" >/dev/null 2>&1 \
83
+ && git -C "$tmp" rev-parse -q --verify "refs/heads/$branch" >/dev/null 2>&1 \
84
+ || die "could not stage branch '$branch' in a fresh repo"
85
+ git -C "$tmp" push -q "$url" "refs/heads/$branch:refs/heads/$branch" || die "push failed (rc=$?)"
86
+
87
+ mr="$(_e10_glab mr list --repo "$proj" --source-branch "$branch" --output json 2>/dev/null \
88
+ | python3 -c 'import json,sys; d=json.load(sys.stdin); print(d[0].get("web_url","") if d else "")' 2>/dev/null)" \
89
+ || die "glab mr list failed"
90
+ if [ -z "$mr" ]; then
91
+ mr="$(_e10_glab mr create --repo "$proj" --source-branch "$branch" --title "$title" \
92
+ --description "$(cat "$body")" --yes "${draft[@]}" | grep -Eo 'https://gitlab\.com/[^[:space:]]+' | tail -n 1)" \
93
+ || die "glab mr create failed"
94
+ [ -n "$mr" ] || die "glab mr create printed no URL"
95
+ fi
96
+ printf '%s\n' "$mr"
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/env bash
2
+ # Loki 10 engine P4 push child (ENGINE.md sections 6 and 7).
3
+ #
4
+ # engine10-push.sh push-pr <repo-dir> <branch> <title> <body-file> [--draft]
5
+ # engine10-push.sh comment <pr-number> <body-file>
6
+ # engine10-push.sh status <sha> <pending|success|failure|error> <description>
7
+ #
8
+ # Holds GitHub credentials, runs no LLM, reads no untrusted text. Inputs come
9
+ # only from argv and the origin pinned by P0 before any provider ran
10
+ # (_LOKI_ORIGIN_PINNED=1 _LOKI_PINNED_ORIGIN=<url>). The target repository is
11
+ # always derived from that pin, never from the agent-writable tree.
12
+ #
13
+ # The push and gh helpers are not copied: this sources exactly the run.sh
14
+ # region tests/test-trusted-push-agent-config.sh extracts, by the same awk
15
+ # anchors, and fails closed when an anchor is missing.
16
+ set -o pipefail
17
+
18
+ log_warn() { printf 'WARN: %s\n' "$*" >&2; }
19
+ log_info() { printf 'INFO: %s\n' "$*" >&2; }
20
+ die() { printf 'engine10-push: %s\n' "$*" >&2; exit "${2:-2}"; }
21
+
22
+ # Capture the pin before sourcing: the region resets both variables to "".
23
+ _e10_pinned="${_LOKI_ORIGIN_PINNED:-}"
24
+ _e10_origin="${_LOKI_PINNED_ORIGIN:-}"
25
+
26
+ _e10_run_sh="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." 2>/dev/null && pwd -P)/run.sh"
27
+ [ -f "$_e10_run_sh" ] || die "run.sh not found at $_e10_run_sh" 3
28
+ _e10_region="$(awk '
29
+ /^_LOKI_WITHHELD_TOKENS=""$/ { on = 1 }
30
+ on { print }
31
+ on && /^_loki_withhold_github_tokens\(\) \{$/ { last = 1 }
32
+ last && /^}$/ { done = 1; exit }
33
+ END { if (!done) exit 3 }
34
+ ' "$_e10_run_sh")" || die "run.sh trusted-push anchors not found; refusing to push" 3
35
+ for _e10_fn in _loki_trusted_push _loki_with_github_tokens _loki_run_neutral _loki_github_repo_from_url; do
36
+ printf '%s\n' "$_e10_region" | grep -q "^${_e10_fn}() {\$" \
37
+ || die "run.sh region lacks ${_e10_fn}; refusing to push" 3
38
+ done
39
+ eval "$_e10_region" || die "run.sh region failed to load" 3
40
+ _LOKI_ORIGIN_PINNED="$_e10_pinned"
41
+ _LOKI_PINNED_ORIGIN="$_e10_origin"
42
+
43
+ [ "$_LOKI_ORIGIN_PINNED" = "1" ] || die "origin not pinned (_LOKI_ORIGIN_PINNED=1 required)"
44
+
45
+ # E-41: the eval harness (eval/loki10/harness.py) pins origin to a local bare
46
+ # repo and scores "PR opened" as a branch landing there. Only an absolute,
47
+ # colon-free path whose own git dir is itself a bare repo qualifies; anything
48
+ # else (URL, scp host:path, relative, non-bare, a subdirectory) takes the
49
+ # GitHub path below and its refusal.
50
+ _e10_local_bare() {
51
+ local p="$1" abs
52
+ case "$p" in /*) ;; *) return 1 ;; esac
53
+ case "$p" in *:*) return 1 ;; esac
54
+ abs="$(cd "$p" 2>/dev/null && pwd -P)" || return 1
55
+ [ "$(git -C "$abs" rev-parse --is-bare-repository 2>/dev/null)" = "true" ] || return 1
56
+ [ "$(git -C "$abs" rev-parse --absolute-git-dir 2>/dev/null)" = "$abs" ]
57
+ }
58
+ _e10_local=""
59
+ _e10_git_env="GIT_DIR GIT_WORK_TREE GIT_COMMON_DIR GIT_CONFIG_PARAMETERS GIT_CONFIG_COUNT"
60
+ # shellcheck disable=SC2086 # word-split list of variable names
61
+ if (unset $_e10_git_env; _e10_local_bare "$_LOKI_PINNED_ORIGIN"); then
62
+ _e10_local=1
63
+ else
64
+ _e10_repo="$(_loki_github_repo_from_url "$_LOKI_PINNED_ORIGIN")" \
65
+ || die "pinned origin refused: $(_loki_origin_refusal "$_LOKI_PINNED_ORIGIN")"
66
+ fi
67
+
68
+ # Local push: like _loki_trusted_push, the branch is fetched into a fresh
69
+ # template-less repo and pushed from there, so the agent repo's config
70
+ # (pushInsteadOf, remote.<url>.receivepack) and hooks never apply. The bare
71
+ # repo's own receive-side hooks (and its core.hooksPath) DO run: git does not
72
+ # pass -c core.hooksPath to the local receive-pack. What protects them is the
73
+ # allowlisted env below: they inherit it, so no token, SSH agent or askpass
74
+ # reaches them.
75
+ _e10_git() {
76
+ env -i PATH="$PATH" HOME=/dev/null TMPDIR="${TMPDIR:-/tmp}" GIT_CONFIG_NOSYSTEM=1 \
77
+ GIT_CONFIG_GLOBAL=/dev/null GIT_TERMINAL_PROMPT=0 git -c core.hooksPath=/dev/null "$@"
78
+ }
79
+ _e10_local_push() {
80
+ local dir="$1" branch="$2" origin="$_LOKI_PINNED_ORIGIN" def tmp rc=1
81
+ dir="$(cd "$dir" 2>/dev/null && pwd -P)" || return 1
82
+ git check-ref-format --branch "$branch" >/dev/null 2>&1 || return 1
83
+ case "$branch" in
84
+ main | master | HEAD)
85
+ log_warn "Not pushing branch '$branch': Loki never pushes directly to a default branch."
86
+ return 2 ;;
87
+ esac
88
+ def="$(_e10_git -C "$origin" symbolic-ref --short HEAD 2>/dev/null)" || def=""
89
+ if [ -z "$def" ] || [ "$branch" = "$def" ]; then
90
+ log_warn "Not pushing branch '$branch': it is (or may be) the default branch of $origin."
91
+ return 2
92
+ fi
93
+ tmp="$(mktemp -d "${TMPDIR:-/tmp}/loki-push.XXXXXX")" || return 1
94
+ if _e10_git init -q --template= "$tmp" >/dev/null 2>&1 \
95
+ && _e10_git -C "$tmp" fetch -q --no-tags --update-shallow "$dir" \
96
+ "+refs/heads/$branch:refs/heads/$branch" >/dev/null 2>&1 \
97
+ && _e10_git -C "$tmp" rev-parse -q --verify "refs/heads/$branch" >/dev/null 2>&1; then
98
+ rc=0
99
+ _e10_git -C "$tmp" push -q "$origin" "refs/heads/$branch:refs/heads/$branch" || rc=$?
100
+ fi
101
+ rm -rf "$tmp"
102
+ return "$rc"
103
+ }
104
+
105
+ _e10_gh() { _loki_with_github_tokens _loki_run_neutral "$_e10_repo" command gh "$@"; }
106
+
107
+ mode="${1:-}"
108
+ shift || true
109
+ case "$mode" in
110
+ push-pr)
111
+ [ "$#" -ge 4 ] && [ "$#" -le 5 ] || die "usage: push-pr <repo-dir> <branch> <title> <body-file> [--draft]"
112
+ dir="$1" branch="$2" title="$3" body="$4" draft=()
113
+ if [ "$#" -eq 5 ]; then
114
+ [ "$5" = "--draft" ] || die "unknown flag: $5"
115
+ draft=(--draft)
116
+ fi
117
+ [ -f "$body" ] || die "body file not found: $body"
118
+ if [ -n "$_e10_local" ]; then
119
+ _e10_local_push "$dir" "$branch" || die "push refused or failed (rc=$?)"
120
+ printf 'local://%s#%s\n' "$_LOKI_PINNED_ORIGIN" "$branch"
121
+ exit 0
122
+ fi
123
+ _loki_trusted_push _loki_with_github_tokens "$dir" "$branch" || die "push refused or failed (rc=$?)"
124
+ url="$(_e10_gh pr list --repo "$_e10_repo" --head "$branch" --state open --json url --jq '.[0].url')" \
125
+ || die "gh pr list failed"
126
+ if [ -z "$url" ] || [ "$url" = "null" ]; then
127
+ url="$(_e10_gh pr create --repo "$_e10_repo" --head "$branch" --title "$title" --body-file "$body" "${draft[@]}")" \
128
+ || die "gh pr create failed"
129
+ url="$(printf '%s\n' "$url" | tail -n 1)"
130
+ fi
131
+ printf '%s\n' "$url"
132
+ ;;
133
+ comment)
134
+ [ "$#" -eq 2 ] || die "usage: comment <pr-number> <body-file>"
135
+ case "$1" in '' | *[!0-9]*) die "pr number must be digits" ;; esac
136
+ [ -f "$2" ] || die "body file not found: $2"
137
+ [ -z "$_e10_local" ] || { log_info "local origin: no PR to comment on (no-op)"; exit 0; }
138
+ _e10_gh pr comment "$1" --repo "$_e10_repo" --body-file "$2" || die "gh pr comment failed"
139
+ ;;
140
+ status)
141
+ [ "$#" -eq 3 ] || die "usage: status <sha> <state> <description>"
142
+ [[ "$1" =~ ^[0-9a-f]{40}$ ]] || die "sha must be 40 lowercase hex characters"
143
+ case "$2" in pending | success | failure | error) ;; *) die "bad state: $2" ;; esac
144
+ [ -z "$_e10_local" ] || { log_info "local origin: no commit status to set (no-op)"; exit 0; }
145
+ _e10_gh api "repos/$_e10_repo/statuses/$1" -f "state=$2" -f context=loki/deep-verify \
146
+ -f "description=$3" >/dev/null || die "gh api status failed"
147
+ ;;
148
+ *) die "usage: engine10-push.sh push-pr|comment|status ..." ;;
149
+ esac
package/autonomy/run.sh CHANGED
@@ -15033,7 +15033,7 @@ run_magic_debate_gate() {
15033
15033
  log_info "Magic Modules: running debate on '$latest_name'"
15034
15034
  local debate_out debate_rc
15035
15035
  debate_out=$(cd "$TARGET_DIR" && PYTHONPATH="$PROJECT_DIR" LOKI_PROVIDER="${PROVIDER_NAME:-claude}" \
15036
- timeout 300 "$PROJECT_DIR/autonomy/loki" magic debate "$latest_name" --rounds 2 2>&1) \
15036
+ timeout -k 10 300 "$PROJECT_DIR/autonomy/loki" magic debate "$latest_name" --rounds 2 2>&1) \
15037
15037
  && debate_rc=0 || debate_rc=$?
15038
15038
 
15039
15039
  # A debate that could not RUN is not a debate that found nothing. The old
@@ -24120,7 +24120,7 @@ show_run_start_estimate() {
24120
24120
  [ -x "$loki_bin" ] || { command -v loki >/dev/null 2>&1 && loki_bin="loki" || return 0; }
24121
24121
 
24122
24122
  local plan_json=""
24123
- plan_json=$(timeout 30 "$loki_bin" plan "$prd_path" --json 2>/dev/null) || plan_json=""
24123
+ plan_json=$(timeout -k 10 30 "$loki_bin" plan "$prd_path" --json 2>/dev/null) || plan_json=""
24124
24124
  [ -n "$plan_json" ] || { log_info "Estimate: unavailable (estimator did not return a result); the run continues."; return 0; }
24125
24125
 
24126
24126
  # Parse REAL numbers only. argv keeps the JSON out of the script body so
package/bin/loki CHANGED
@@ -243,6 +243,27 @@ if [ "${LOKI_LEGACY_BASH:-0}" = "1" ] || [ "${LOKI_LEGACY_BASH:-}" = "true" ]; t
243
243
  exec "$BASH_CLI" "$@"
244
244
  fi
245
245
 
246
+ # Loki 10 engine (D29): additive; skipped entirely unless LOKI_ENGINE=v10.
247
+ if [ "${LOKI_ENGINE:-}" = "v10" ]; then
248
+ _e10=0
249
+ case "${1:-}" in
250
+ status|verify|dashboard) _e10=1 ;;
251
+ ""|-*) _e10=0 ;;
252
+ # http*://*/issues/* also covers GitLab's /-/issues/ URLs.
253
+ */*\#[0-9]*|http*://*/issues/*|http*://*/browse/*) _e10=1 ;;
254
+ *" "*) _e10=1 ;;
255
+ # ponytail: a one-word argument stays on the legacy CLI. The telemetry
256
+ # allowlist is not a command registry (estimate, intent, outcomes are
257
+ # missing from it), so it cannot decide routing. Multi-word tasks and
258
+ # issue refs reach v10.
259
+ *) _e10=0 ;;
260
+ esac
261
+ if [ "$_e10" = "1" ]; then
262
+ command -v bun >/dev/null 2>&1 || { echo "Error: LOKI_ENGINE=v10 needs bun. Unset LOKI_ENGINE to use the current engine." >&2; exit 1; }
263
+ exec bun "$BUN_CLI" engine10 "$@"
264
+ fi
265
+ fi
266
+
246
267
  # Bun must be installed for the new path; if it isn't, fall through to bash
247
268
  # silently rather than fail. This keeps users on systems without Bun working.
248
269
  if ! command -v bun &>/dev/null; then
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "9.77.0"
10
+ __version__ = "9.80.1"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try:
@@ -2,7 +2,7 @@
2
2
 
3
3
  The flagship product of [Autonomi](https://www.autonomi.dev/). Loki Mode is a spec-driven autonomous builder with a built-in trust layer that takes any spec to a deployed product and verifies completion with evidence (quality gates plus a completion council), not just a "done" claim. Complete installation instructions for all platforms and use cases.
4
4
 
5
- **Version:** v9.77.0
5
+ **Version:** v9.80.1
6
6
 
7
7
  ---
8
8
 
@@ -62,11 +62,11 @@ loki_run_tmp_create() {
62
62
  # usage string, a filesystem block, an empty result, or a concatenation of any
63
63
  # of those is rejected on every platform.
64
64
  loki_run_tmp_stat_field() {
65
- local gnu_fmt="$1" bsd_fmt="$2" path="$3" value
65
+ local gnu_fmt="$1" bsd_fmt="$2" target_path="$3" value
66
66
 
67
- value="$(stat -c "$gnu_fmt" -- "$path" 2>/dev/null)" || value=''
67
+ value="$(stat -c "$gnu_fmt" -- "$target_path" 2>/dev/null)" || value=''
68
68
  case "$value" in
69
- '' | *[!0-9]*) value="$(stat -f "$bsd_fmt" -- "$path" 2>/dev/null)" || value='' ;;
69
+ '' | *[!0-9]*) value="$(stat -f "$bsd_fmt" -- "$target_path" 2>/dev/null)" || value='' ;;
70
70
  esac
71
71
  case "$value" in
72
72
  '' | *[!0-9]*) return 1 ;;