loki-mode 7.69.0 → 7.71.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +2 -2
- package/VERSION +1 -1
- package/autonomy/hooks/migration-hooks.sh +1 -1
- package/autonomy/run.sh +143 -0
- package/dashboard/__init__.py +1 -1
- package/docs/BUILD-HUD-PLAN.md +90 -0
- package/docs/INSTALLATION.md +2 -2
- package/loki-ts/dist/loki.js +118 -118
- package/mcp/__init__.py +1 -1
- package/memory/layers/loader.py +8 -4
- package/package.json +1 -1
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/providers/aider.sh +1 -1
- package/providers/claude.sh +9 -1
- package/providers/codex.sh +7 -0
package/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: loki-mode
|
|
|
3
3
|
description: Autonomous spec-driven build system with a built-in trust layer. It does not call work done until it is verified (RARV-C closure loop, 8 quality gates, completion council, verified-completion evidence gate). Triggers on "Loki Mode". Takes a spec (PRD, GitHub issue, OpenAPI doc, etc.) to deployed product with minimal human intervention. Provider-agnostic. Requires --dangerously-skip-permissions flag.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
# Loki Mode v7.
|
|
6
|
+
# Loki Mode v7.71.0
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
@@ -406,4 +406,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
|
|
|
406
406
|
|
|
407
407
|
---
|
|
408
408
|
|
|
409
|
-
**v7.
|
|
409
|
+
**v7.71.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
7.
|
|
1
|
+
7.71.0
|
|
@@ -393,7 +393,7 @@ for friction in data.get('frictions', []):
|
|
|
393
393
|
print(f'BLOCKED (strict): Friction {friction.get(\"id\", \"?\")} in {loc} - strict mode requires explicit approval')
|
|
394
394
|
sys.exit(0)
|
|
395
395
|
print('OK')
|
|
396
|
-
" "$file_path" "$strict" "$heal_dir/friction-map.json" 2>/dev/null || echo "
|
|
396
|
+
" "$file_path" "$strict" "$heal_dir/friction-map.json" 2>/dev/null || echo "BLOCKED: friction-map check failed (corrupt/unreadable friction-map.json or python3 unavailable) -- failing closed")
|
|
397
397
|
|
|
398
398
|
if [[ "$blocked" == BLOCKED* ]]; then
|
|
399
399
|
echo "HOOK_BLOCKED: $blocked"
|
package/autonomy/run.sh
CHANGED
|
@@ -1005,6 +1005,129 @@ log_error() { echo -e "${RED}[ERROR]${NC} $*"; }
|
|
|
1005
1005
|
log_step() { echo -e "${CYAN}[STEP]${NC} $*"; }
|
|
1006
1006
|
log_debug() { [[ "${LOKI_DEBUG:-}" == "true" ]] && echo -e "${CYAN}[DEBUG]${NC} $*" >&2 || true; }
|
|
1007
1007
|
|
|
1008
|
+
# Live Build HUD (v7.71.0): a single append-only per-iteration status line on the
|
|
1009
|
+
# interactive TTY path. Pure additive stdout decoration -- never piped into any
|
|
1010
|
+
# tee, so the dashboard agent.log and the stream-json parser are untouched. The
|
|
1011
|
+
# whole function is structured so any internal failure still returns 0; it can
|
|
1012
|
+
# never abort the iteration loop. Gated: TTY + not background + LOKI_HUD != 0.
|
|
1013
|
+
# Usage: render_build_hud <iter> <phase> <duration_secs>
|
|
1014
|
+
render_build_hud() {
|
|
1015
|
+
# Gate first: emit nothing unless interactive TTY, not --bg, and not opted out.
|
|
1016
|
+
# Inverted into an early return so the off-TTY path is byte-identical (no output).
|
|
1017
|
+
if ! { [ -t 1 ] && [ "${BACKGROUND_MODE:-false}" != "true" ] && [ "${LOKI_HUD:-1}" != "0" ]; }; then
|
|
1018
|
+
return 0
|
|
1019
|
+
fi
|
|
1020
|
+
|
|
1021
|
+
local _iter="${1:-0}" _phase="${2:-?}" _dur="${3:-0}"
|
|
1022
|
+
[ -z "$_phase" ] && _phase="?"
|
|
1023
|
+
# Sanitize numerics so set -u arithmetic/format below can never error out.
|
|
1024
|
+
case "$_dur" in (*[!0-9]*|'') _dur=0 ;; esac
|
|
1025
|
+
local _max="${MAX_ITERATIONS:-0}"
|
|
1026
|
+
case "$_max" in (*[!0-9]*|'') _max=0 ;; esac
|
|
1027
|
+
|
|
1028
|
+
# Field list: each field is appended only when its data is present. Missing
|
|
1029
|
+
# data => the field is omitted entirely (never a fabricated value).
|
|
1030
|
+
local _fields="$_phase"
|
|
1031
|
+
_fields="${_fields} | iter ${_iter}/${_max}"
|
|
1032
|
+
|
|
1033
|
+
# Cost from the context tracker totals (the same field the dashboard shows).
|
|
1034
|
+
# NOTE: tracking.json totals accumulate across runs in the same dir (not reset
|
|
1035
|
+
# on a fresh `loki start`), so this is cumulative cost for the project dir, not
|
|
1036
|
+
# strictly this single run. Labeled plainly "$" / "cost" to avoid overclaiming.
|
|
1037
|
+
# OMIT entirely when empty/missing/non-Claude.
|
|
1038
|
+
local _cost=""
|
|
1039
|
+
if command -v python3 >/dev/null 2>&1; then
|
|
1040
|
+
_cost="$(python3 -c "
|
|
1041
|
+
import json
|
|
1042
|
+
try:
|
|
1043
|
+
t = json.load(open('.loki/context/tracking.json'))
|
|
1044
|
+
c = t.get('totals', {}).get('total_cost_usd', 0)
|
|
1045
|
+
c = float(c)
|
|
1046
|
+
if c > 0:
|
|
1047
|
+
print('%.2f' % c)
|
|
1048
|
+
except Exception:
|
|
1049
|
+
pass
|
|
1050
|
+
" 2>/dev/null || true)"
|
|
1051
|
+
fi
|
|
1052
|
+
[ -n "$_cost" ] && _fields="${_fields} | \$${_cost}"
|
|
1053
|
+
|
|
1054
|
+
# Files changed (+ins/-del and file count) vs the run start SHA. Reuse the
|
|
1055
|
+
# build_completion_summary diff approach incl. the .loki/.git exclude pathspec.
|
|
1056
|
+
# OMIT when no start sha, not a git repo, or no diff data.
|
|
1057
|
+
local _start_sha="${_LOKI_RUN_START_SHA:-}"
|
|
1058
|
+
if [ -n "$_start_sha" ]; then
|
|
1059
|
+
local _shortstat _ins _del _files
|
|
1060
|
+
_shortstat="$( (cd "${TARGET_DIR:-.}" && git diff --shortstat "${_start_sha}..HEAD" -- . ':(exclude).loki/' ':(exclude).git/' ':(exclude)**/.loki/**') 2>/dev/null || true )"
|
|
1061
|
+
if [ -n "$_shortstat" ]; then
|
|
1062
|
+
_files="$(printf '%s\n' "$_shortstat" | grep -oE '[0-9]+ file' | grep -oE '[0-9]+' | head -1 2>/dev/null || true)"
|
|
1063
|
+
_ins="$(printf '%s\n' "$_shortstat" | grep -oE '[0-9]+ insertion' | grep -oE '[0-9]+' | head -1 2>/dev/null || true)"
|
|
1064
|
+
_del="$(printf '%s\n' "$_shortstat" | grep -oE '[0-9]+ deletion' | grep -oE '[0-9]+' | head -1 2>/dev/null || true)"
|
|
1065
|
+
[ -z "$_files" ] && _files=0
|
|
1066
|
+
[ -z "$_ins" ] && _ins=0
|
|
1067
|
+
[ -z "$_del" ] && _del=0
|
|
1068
|
+
_fields="${_fields} | +${_ins}/-${_del} (${_files} files)"
|
|
1069
|
+
fi
|
|
1070
|
+
fi
|
|
1071
|
+
|
|
1072
|
+
# Per-iteration time (the duration arg). Labeled "took" (not "iter") so it
|
|
1073
|
+
# does not collide with the "iter N/max" iteration-count field above.
|
|
1074
|
+
_fields="${_fields} | took $(_hud_fmt_secs "$_dur")"
|
|
1075
|
+
|
|
1076
|
+
# Elapsed time for the whole run, from the once-captured run-start epoch.
|
|
1077
|
+
local _start_epoch="${_LOKI_RUN_START_EPOCH:-}"
|
|
1078
|
+
case "$_start_epoch" in (*[!0-9]*|'') _start_epoch="" ;; esac
|
|
1079
|
+
if [ -n "$_start_epoch" ]; then
|
|
1080
|
+
local _now _elapsed
|
|
1081
|
+
_now="$(date +%s 2>/dev/null || true)"
|
|
1082
|
+
case "$_now" in (*[!0-9]*|'') _now="" ;; esac
|
|
1083
|
+
if [ -n "$_now" ] && [ "$_now" -ge "$_start_epoch" ] 2>/dev/null; then
|
|
1084
|
+
_elapsed=$(( _now - _start_epoch ))
|
|
1085
|
+
_fields="${_fields} | elapsed $(_hud_fmt_secs "$_elapsed")"
|
|
1086
|
+
fi
|
|
1087
|
+
fi
|
|
1088
|
+
|
|
1089
|
+
# ETA (PO lock #1): omit by default. Only a SMALL user-set LOKI_MAX_ITERATIONS
|
|
1090
|
+
# (not the 1000 default) yields a meaningful target, so that is the single ETA
|
|
1091
|
+
# trigger here. A LOKI_BUDGET_LIMIT cap is also an allowed trigger per the
|
|
1092
|
+
# plan, but a budget-derived ETA needs cost-rate math that is easy to get
|
|
1093
|
+
# wrong; per "keep it simple and safe, when unsure omit", budget ETA is left
|
|
1094
|
+
# out rather than rendered approximately.
|
|
1095
|
+
local _lmi="${LOKI_MAX_ITERATIONS:-}"
|
|
1096
|
+
case "$_lmi" in (*[!0-9]*|'') _lmi="" ;; esac
|
|
1097
|
+
if [ -n "$_lmi" ] && [ "$_lmi" -gt 0 ] 2>/dev/null && [ "$_lmi" -lt 1000 ] 2>/dev/null \
|
|
1098
|
+
&& [ "$_iter" -gt 0 ] 2>/dev/null && [ "$_iter" -lt "$_lmi" ] 2>/dev/null \
|
|
1099
|
+
&& [ -n "$_start_epoch" ]; then
|
|
1100
|
+
local _now2 _el2 _per _remain_iters _eta
|
|
1101
|
+
_now2="$(date +%s 2>/dev/null || true)"
|
|
1102
|
+
case "$_now2" in (*[!0-9]*|'') _now2="" ;; esac
|
|
1103
|
+
if [ -n "$_now2" ] && [ "$_now2" -ge "$_start_epoch" ] 2>/dev/null; then
|
|
1104
|
+
_el2=$(( _now2 - _start_epoch ))
|
|
1105
|
+
_per=$(( _el2 / _iter ))
|
|
1106
|
+
_remain_iters=$(( _lmi - _iter ))
|
|
1107
|
+
_eta=$(( _per * _remain_iters ))
|
|
1108
|
+
[ "$_eta" -gt 0 ] 2>/dev/null && _fields="${_fields} | eta ~$(_hud_fmt_secs "$_eta")"
|
|
1109
|
+
fi
|
|
1110
|
+
fi
|
|
1111
|
+
|
|
1112
|
+
echo -e "${CYAN}[HUD]${NC} ${_fields}"
|
|
1113
|
+
return 0
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
# Format a whole-seconds integer as a compact duration: 37s, 2m11s, 1h03m.
|
|
1117
|
+
# Best-effort and set -u safe; any odd input degrades to "0s".
|
|
1118
|
+
_hud_fmt_secs() {
|
|
1119
|
+
local _s="${1:-0}"
|
|
1120
|
+
case "$_s" in (*[!0-9]*|'') _s=0 ;; esac
|
|
1121
|
+
if [ "$_s" -lt 60 ] 2>/dev/null; then
|
|
1122
|
+
printf '%ds' "$_s"
|
|
1123
|
+
elif [ "$_s" -lt 3600 ] 2>/dev/null; then
|
|
1124
|
+
printf '%dm%02ds' "$(( _s / 60 ))" "$(( _s % 60 ))"
|
|
1125
|
+
else
|
|
1126
|
+
printf '%dh%02dm' "$(( _s / 3600 ))" "$(( (_s % 3600) / 60 ))"
|
|
1127
|
+
fi
|
|
1128
|
+
return 0
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1008
1131
|
#===============================================================================
|
|
1009
1132
|
# Process Registry (PID Supervisor)
|
|
1010
1133
|
# Central registry of all spawned child processes for reliable cleanup
|
|
@@ -14156,6 +14279,13 @@ except Exception:
|
|
|
14156
14279
|
_LOKI_RUN_START_SHA="$(cat "$_start_sha_file" 2>/dev/null || echo "")"
|
|
14157
14280
|
export _LOKI_RUN_START_SHA
|
|
14158
14281
|
|
|
14282
|
+
# Live Build HUD (v7.71.0): capture the run-start epoch ONCE for the elapsed
|
|
14283
|
+
# field. Pure assignment (`:` builtin), emits no output, so the non-TTY/CI/Bun
|
|
14284
|
+
# parity surface is byte-identical. := preserves a value across a resume only
|
|
14285
|
+
# within the same process; a fresh run stamps now.
|
|
14286
|
+
: "${_LOKI_RUN_START_EPOCH:=$(date +%s)}"
|
|
14287
|
+
export _LOKI_RUN_START_EPOCH
|
|
14288
|
+
|
|
14159
14289
|
# Session-scope the mid-flight model override (model-honesty fix). The
|
|
14160
14290
|
# override file (.loki/state/model-override) is a LIVE-RUN control: the
|
|
14161
14291
|
# dashboard UI and docs state it "applies to the current run". A leftover
|
|
@@ -15779,6 +15909,13 @@ else:
|
|
|
15779
15909
|
if [ $exit_code -eq 0 ]; then
|
|
15780
15910
|
# Episode trace already captured by auto_capture_episode above (v6.15.0)
|
|
15781
15911
|
|
|
15912
|
+
# Live Build HUD (v7.71.0): one append-only status line per successful
|
|
15913
|
+
# iteration. At the top of the success branch so it fires for ALL
|
|
15914
|
+
# success sub-paths (incl. perpetual mode / completion). TTY-gated and
|
|
15915
|
+
# `|| true` so it can never abort the loop. Never tee'd -> dashboard
|
|
15916
|
+
# agent.log + stream parser untouched.
|
|
15917
|
+
render_build_hud "${ITERATION_COUNT:-0}" "${rarv_phase:-?}" "${duration:-0}" || true
|
|
15918
|
+
|
|
15782
15919
|
# Perpetual mode: NEVER stop, always continue
|
|
15783
15920
|
if [ "$PERPETUAL_MODE" = "true" ]; then
|
|
15784
15921
|
log_info "Perpetual mode: Ignoring exit, continuing immediately..."
|
|
@@ -16034,6 +16171,12 @@ else:
|
|
|
16034
16171
|
# Only apply retry logic for ERRORS (non-zero exit code)
|
|
16035
16172
|
# Episode trace already captured by auto_capture_episode above (v6.15.0)
|
|
16036
16173
|
|
|
16174
|
+
# Live Build HUD (v7.71.0): a failing iteration still shows motion (lock
|
|
16175
|
+
# #3). At the top of the failure fall-through so it fires for ALL failure
|
|
16176
|
+
# sub-paths, incl. the rate-limit/failover branch that `continue`s before
|
|
16177
|
+
# the "Will retry" log_warn below. TTY-gated, `|| true`, never tee'd.
|
|
16178
|
+
render_build_hud "${ITERATION_COUNT:-0}" "${rarv_phase:-?}" "${duration:-0}" || true
|
|
16179
|
+
|
|
16037
16180
|
# Checkpoint failed iteration state (v5.57.0)
|
|
16038
16181
|
create_checkpoint "iteration-${ITERATION_COUNT} failed (exit=$exit_code)" "iteration-${ITERATION_COUNT}-fail"
|
|
16039
16182
|
|
package/dashboard/__init__.py
CHANGED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# BUILD-HUD-PLAN.md -- In-Terminal Live Build HUD
|
|
2
|
+
|
|
3
|
+
## Product Owner scope locks (decided 2026-06-18)
|
|
4
|
+
1. ETA: OMIT unless an explicit small LOKI_MAX_ITERATIONS or a LOKI_BUDGET_LIMIT cap is present. Default behavior shows no ETA.
|
|
5
|
+
2. Phase wording: show the RARV phase name (REASON/ACT/REFLECT/VERIFY) -- that is what the live loop tracks. Do not add the planning/development tier word.
|
|
6
|
+
3. Failure-iteration render: YES, render the HUD on both the success and the retry/failure path (the "is it working" moment matters most when an iteration fails).
|
|
7
|
+
4. Opt-out var: LOKI_HUD (default 1 = on; LOKI_HUD=0 disables). TTY-gated.
|
|
8
|
+
|
|
9
|
+
## 1. Goal
|
|
10
|
+
When a user runs `loki start ./prd.md` in a foreground (interactive TTY) terminal, emit a single clean per-iteration status line at each iteration boundary showing: RARV phase, iteration N/max, cumulative cost, files changed (+/-) vs run start_sha, and per-iteration + elapsed time (ETA only when a real target exists per lock #1). Pure additive stdout decoration on the interactive path. Must not change non-TTY/CI/`--bg` output by a single byte, must not touch the stream-json parser, `log_step` lines, or the dashboard, and must degrade cleanly when cost data is unavailable.
|
|
11
|
+
|
|
12
|
+
## 2. Live route confirmation (re-verified)
|
|
13
|
+
- Orchestrator: `autonomy/run.sh`, `set -uo pipefail` (NOT `set -e`).
|
|
14
|
+
- Iteration loop body: provider dispatched after the RARV banner (`run.sh:14662`); `rarv_phase` set at `run.sh:14589` via `get_rarv_phase_name "$ITERATION_COUNT"` (in scope for the whole iteration body).
|
|
15
|
+
- `ITERATION_COUNT` = `run.sh:620` (init 0); `MAX_ITERATIONS` = `run.sh:619` (default `LOKI_MAX_ITERATIONS:-1000`).
|
|
16
|
+
- Provider exit + `duration=$((end_time - start_time))` computed at `run.sh:15279-15280`.
|
|
17
|
+
- Success path continues at `log_step "Starting next iteration..."` `run.sh:16026`.
|
|
18
|
+
- Bun runner `loki-ts/src/runner/autonomous.ts` `runAutonomous` is dormant for `loki start` (bash route is live).
|
|
19
|
+
|
|
20
|
+
## 3. Render point -- iteration END boundary (NOT start)
|
|
21
|
+
Render once per iteration, after the provider exits and cost/duration are available, before the loop continues. Insert a single call
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
render_build_hud "$ITERATION_COUNT" "$rarv_phase" "$duration" || true
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
immediately after `duration` is computed (`run.sh:15280`) and after the result-cost file for this iteration has been flushed by the embedded stream parser (~`run.sh:15206-15208`). Iteration start is wrong: current iteration cost/files do not exist yet. Per lock #3, also add a second guarded call on the failure/retry path (same region, after the exit-code log_warn).
|
|
28
|
+
|
|
29
|
+
## 4. Data sources (reuse only -- do not re-implement)
|
|
30
|
+
| Field | Source | Notes |
|
|
31
|
+
|---|---|---|
|
|
32
|
+
| Phase | `$rarv_phase` (already set `run.sh:14589`) | REASON/ACT/REFLECT/VERIFY. |
|
|
33
|
+
| Iteration N/max | `$ITERATION_COUNT` / `$MAX_ITERATIONS` | Already in scope. |
|
|
34
|
+
| Cumulative cost | `.loki/context/tracking.json` -> `totals.total_cost_usd` (read pattern at `run.sh:4531`) | Cumulative for the run. Do NOT re-sum result-cost-*.json. |
|
|
35
|
+
| Files changed (+/-) | `git diff --shortstat "${_LOKI_RUN_START_SHA}..HEAD"` with the exclude pathspec from `build_completion_summary` (`run.sh:2607-2618`) | Reuse `_LOKI_RUN_START_SHA` (exported `run.sh:14157`) + `':(exclude).loki/' ':(exclude).git/'`. |
|
|
36
|
+
| Per-iteration time | `$duration` (`run.sh:15280`) | Already computed. |
|
|
37
|
+
| Elapsed (run) | In-process epoch var captured once at loop entry (see SS6) | Parity-safe: var assignment emits no output. |
|
|
38
|
+
| ETA | Per lock #1: only when explicit small max or budget cap | Default: omit. |
|
|
39
|
+
|
|
40
|
+
## 5. Env / TTY gate
|
|
41
|
+
HUD renders only when ALL hold (first lines of `render_build_hud`, early `return 0` otherwise):
|
|
42
|
+
```
|
|
43
|
+
[ -t 1 ] && [ "${BACKGROUND_MODE:-false}" != "true" ] && [ "${LOKI_HUD:-1}" != "0" ]
|
|
44
|
+
```
|
|
45
|
+
- `[ -t 1 ]` is the established idiom (`run.sh:10241, 13929`).
|
|
46
|
+
- `BACKGROUND_MODE` guard mirrors the auto-open gate (`run.sh:10241`), covering `--bg`/`--detach`.
|
|
47
|
+
|
|
48
|
+
## 6. Rendering approach -- append-only clean line, never `\r`
|
|
49
|
+
The agent streams provider output to the same TTY during the iteration. A repainting `\r` bar would fight that stream. Therefore: a single append-only log line emitted only at the iteration boundary (after the stream for that iteration ended), styled like `log_step`/`log_info`. No carriage-return repaint, no cursor save/restore, no background thread. Distinct prefix `[HUD]` in `${CYAN}`/`${NC}` (`run.sh:1005`). Run-elapsed source: `: "${_LOKI_RUN_START_EPOCH:=$(date +%s)}"` placed once before the loop (pure assignment, parity-safe; do NOT stat start-sha mtime -- unreliable on resume).
|
|
50
|
+
|
|
51
|
+
Illustrative line:
|
|
52
|
+
```
|
|
53
|
+
[HUD] REASON | iter 3/1000 | $0.42 | +180/-24 (4 files) | took 37s | elapsed 2m11s
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 7. set -uo pipefail safety + degrade
|
|
57
|
+
- Guard every var with defaults: `${ITERATION_COUNT:-0}`, `${MAX_ITERATIONS:-0}`, `${rarv_phase:-?}`, `${_LOKI_RUN_START_SHA:-}`, `${_LOKI_RUN_START_EPOCH:-}`.
|
|
58
|
+
- No `((x++))` from unset/zero; arithmetic only on integer-defaulted values.
|
|
59
|
+
- Every external read best-effort: `2>/dev/null || true`, matching existing helpers.
|
|
60
|
+
- Degrade: cost unavailable -> OMIT the cost field (never print $0.00 as real, never crash). files unavailable -> omit files field. The call site is `render_build_hud ... || true` so the helper can never abort the loop.
|
|
61
|
+
|
|
62
|
+
## 8. Byte-identical-off-TTY guarantee (two mechanisms)
|
|
63
|
+
1. Gate: helper returns before emitting unless TTY + not background + LOKI_HUD != 0.
|
|
64
|
+
2. stdout-only, never tee'd: HUD uses plain `echo`/`printf` to stdout, NEVER piped into `tee -a "$log_file" "$agent_log"` (`run.sh:14643, 14662`). The dashboard reads `.loki/logs/agent.log`; the HUD never enters any `tee -a`, so logs + dashboard are untouched by construction. The stream-json parser reads the provider's stdout pipe, not the orchestrator terminal stdout.
|
|
65
|
+
|
|
66
|
+
## 9. Parity argument (bash-only HUD is safe)
|
|
67
|
+
- `runAutonomous` is dormant for `loki start`; the bash loop is the live route -> no live parity gap.
|
|
68
|
+
- `tests/test-bash-bun-parity.sh` compares build_prompt output, PHASE_KEYS/SDLC list, the effort matrix, report/stats stdout -- NOT the autonomous loop terminal stdout. A loop HUD line is invisible to every parity invariant. No Bun mirror required (track a follow-up if runAutonomous becomes live).
|
|
69
|
+
|
|
70
|
+
## 10. Test plan (`tests/test-build-hud.sh`, wired into run-all-tests)
|
|
71
|
+
1. HUD appears on a TTY (pty harness): assert `[HUD]` + `iter 1/`; with a fake tracking.json assert cost field; remove it and assert line still appears without cost (degrade).
|
|
72
|
+
2. HUD absent off-TTY byte-identical: capture full stdout off-TTY with LOKI_HUD unset and with LOKI_HUD=0; assert `diff` clean (HUD adds nothing off-TTY).
|
|
73
|
+
3. Opt-out on TTY: TTY + LOKI_HUD=0 -> no `[HUD]`.
|
|
74
|
+
4. Dashboard/log untouched: after a stubbed TTY iteration, assert `.loki/logs/agent.log` has no `[HUD]` (not tee'd).
|
|
75
|
+
5. set -u safety: run helper under `bash -u` with all vars unset; assert exit 0, no unbound error.
|
|
76
|
+
6. Regression: `tests/test-bash-bun-parity.sh` still green unchanged.
|
|
77
|
+
|
|
78
|
+
## 11. Step-by-step task list
|
|
79
|
+
Agent A -- implementation (`autonomy/run.sh` only):
|
|
80
|
+
1. Add `render_build_hud()` near logging helpers (after `run.sh:1005`); first lines = SS5 gate + early `return 0`; body builds line from present fields only; stdout-only echo; `[HUD]` + CYAN/NC; wrapped so it can never abort the loop.
|
|
81
|
+
2. Cumulative-cost read reusing the tracking.json totals pattern (`run.sh:4531`), `2>/dev/null || true`.
|
|
82
|
+
3. Files-changed read reusing `git diff --shortstat "${_LOKI_RUN_START_SHA}..HEAD"` + exclude pathspec (`run.sh:2607-2618`).
|
|
83
|
+
4. `: "${_LOKI_RUN_START_EPOCH:=$(date +%s)}"` once before the loop.
|
|
84
|
+
5. Single call after `duration` at `run.sh:15280`; second guarded call on the failure path (lock #3).
|
|
85
|
+
6. Confirm NOT inside any `tee -a`; stdout only.
|
|
86
|
+
|
|
87
|
+
Agent B -- tests + docs:
|
|
88
|
+
7. Write `tests/test-build-hud.sh` (all 6 cases); wire into `tests/run-all-tests.sh`.
|
|
89
|
+
8. Document `LOKI_HUD` in `.env.example` + env reference docs.
|
|
90
|
+
9. Run the new test + parity test; confirm green + off-TTY byte-identical.
|
package/docs/INSTALLATION.md
CHANGED
|
@@ -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:** v7.
|
|
5
|
+
**Version:** v7.71.0
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -395,7 +395,7 @@ provider works inside the container. Provide auth with your Anthropic API key:
|
|
|
395
395
|
# Run Loki Mode in Docker (Claude provider, API-key auth)
|
|
396
396
|
docker run --rm -e ANTHROPIC_API_KEY="$ANTHROPIC_API_KEY" \
|
|
397
397
|
-v $(pwd):/workspace -w /workspace \
|
|
398
|
-
asklokesh/loki-mode:7.
|
|
398
|
+
asklokesh/loki-mode:7.71.0 start ./my-spec.md
|
|
399
399
|
```
|
|
400
400
|
|
|
401
401
|
##### docker compose + .env (no host install)
|