loki-mode 11.3.9 → 11.5.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.
- package/README.md +34 -18
- package/SKILL.md +3 -3
- package/VERSION +1 -1
- package/agents/custom_agents.py +280 -0
- package/autonomy/council-v2.sh +22 -1
- package/autonomy/edit.sh +242 -0
- package/autonomy/lib/chat.sh +315 -0
- package/autonomy/lib/engine10-push.sh +19 -1
- package/autonomy/lib/help-core.sh +164 -0
- package/autonomy/lib/json-output.sh +38 -0
- package/autonomy/lib/proof-generator.py +23 -5
- package/autonomy/lib/proof-verify.py +607 -5
- package/autonomy/lib/run-summary.sh +112 -0
- package/autonomy/lib/setup-requirements.json +35 -0
- package/autonomy/loki +337 -46
- package/autonomy/provider-offer.sh +95 -47
- package/autonomy/route.sh +302 -0
- package/autonomy/run.sh +48 -14
- package/autonomy/setup-wizard.sh +170 -0
- package/autonomy/verify.sh +62 -3
- package/bin/loki +73 -18
- package/completions/_loki +58 -1
- package/completions/loki.bash +57 -5
- package/dashboard/__init__.py +1 -1
- package/docs/CLI-CORE-VERBS.md +112 -0
- package/docs/CLI-REFERENCE.md +9 -1
- package/docs/COMPARE-OPENCODE.md +94 -0
- package/docs/COMPONENTS.md +1 -0
- package/docs/EVALUATING.md +27 -0
- package/docs/HARNESS-INTELLIGENCE-PLAN.md +20 -0
- package/docs/INSTALLATION.md +56 -12
- package/docs/KNOWN-ISSUES.md +8 -9
- package/docs/PROOF-PASSPORT.md +114 -0
- package/docs/QUICKSTART.md +108 -0
- package/docs/alternative-installations.md +103 -0
- package/docs/cost-controls.md +139 -0
- package/docs/environment-variables.md +45 -2
- package/docs/exit-codes.md +129 -12
- package/docs/spec-first-intent.md +29 -0
- package/docs/v10/CLI-MODERN.md +11 -5
- package/docs/v10/ENGINE.md +32 -0
- package/docs/v10/GUIDE.md +270 -44
- package/docs/v10/OPENCODE-PARITY-PLAN.md +84 -0
- package/loki-ts/data/model-pricing.json +1 -0
- package/loki-ts/dist/loki.js +1065 -978
- package/mcp/__init__.py +1 -1
- package/package.json +2 -2
- package/packages/control-plane/dist/server.js +1829 -715
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/plugins/loki-mode/README.md +41 -1
- package/plugins/loki-mode/commands/handoff.md +12 -0
- package/plugins/loki-mode/commands/loki-verify.md +9 -2
- package/plugins/loki-mode/commands/start.md +20 -0
- package/plugins/loki-mode/hooks/hooks.json +11 -0
- package/plugins/loki-mode/scripts/loki-stop-verify.sh +84 -0
- package/providers/claude.sh +16 -2
- package/providers/model_route_exec.sh +22 -0
- package/providers/model_routes.sh +188 -0
- package/skills/providers.md +13 -0
- package/templates/agents/planner.md +10 -0
- package/templates/agents/reviewer.md +10 -0
- package/templates/agents/tester.md +10 -0
- package/web-app/dist/assets/{AdminPage-QK-i_x-O.js → AdminPage-Cbu3pXL8.js} +1 -1
- package/web-app/dist/assets/{Avatar-DblkLNjB.js → Avatar-DGqGGcGx.js} +1 -1
- package/web-app/dist/assets/{Badge-DIV2ny5H.js → Badge-Bhlipt6v.js} +1 -1
- package/web-app/dist/assets/{Button--rePJOlQ.js → Button-CpN2sO61.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-BZlKxpGy.js → CockpitPage-BqeDJwdL.js} +1 -1
- package/web-app/dist/assets/{ComparePage-3_INSVux.js → ComparePage-DUieA2ba.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-DHG63CNr.js → ErrorBoundary-DTWsYrOm.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-DFsBnLlO.js → EvidenceReceiptPanel-BU_B9X19.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-phPGah98.js → GitHubIssuesPanel-DEZoLOsP.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-T7KQqJmx.js → GitHubPRsPanel-BEsnrq7Y.js} +1 -1
- package/web-app/dist/assets/{HomePage-DFjGUF5I.js → HomePage-BoUVuq7h.js} +2 -2
- package/web-app/dist/assets/{LoginPage-CorUid_5.js → LoginPage-CmOED7vb.js} +1 -1
- package/web-app/dist/assets/{MagicPage-DofbSxKD.js → MagicPage-DATZitrZ.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-qzrhhfLC.js → MetricsPage-DGL1v0I-.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-BAZR0mMb.js → NotFoundPage-C2WgOjZd.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-BOSUzG9J.js → ProjectPage-BMi1tepj.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-Ba0YLtzD.js → ProjectsPage-vc3y5YPh.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-Cr10Ue2K.js → SettingsPage-kbq0Ftvi.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-Czn655fe.js → ShowcasePage-Bn6Q8Kbg.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-Dwjnw6Ob.js → SystemSettingsPage-Basmhs_b.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-D8nc69Be.js → TeamsPage-BTqOc4TR.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-DHsaCDGv.js → TemplatesPage-2P9002VL.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-DBejni2a.js → TerminalOutput-CAoSPBrg.js} +1 -1
- package/web-app/dist/assets/{activity-B2VsBl1C.js → activity-BcWVWCqU.js} +1 -1
- package/web-app/dist/assets/{bell-CT77Fq2H.js → bell-CYRqqgZ6.js} +1 -1
- package/web-app/dist/assets/{bot-DfaWgF4H.js → bot-CU7gdn3g.js} +1 -1
- package/web-app/dist/assets/{check-D1yp7Ndv.js → check-DLlCpz9V.js} +1 -1
- package/web-app/dist/assets/{chevron-left-B6Pa8IOX.js → chevron-left-CE9Cb30C.js} +1 -1
- package/web-app/dist/assets/{circle-alert-D5jrL_Y7.js → circle-alert-uou4bjua.js} +1 -1
- package/web-app/dist/assets/{clock-DIsY_fa_.js → clock-C_dSJcDX.js} +1 -1
- package/web-app/dist/assets/{cloud-eGwLh1As.js → cloud-DZ22ITF6.js} +1 -1
- package/web-app/dist/assets/{code-xml-CGDIcZ3m.js → code-xml-BrJS0hhS.js} +1 -1
- package/web-app/dist/assets/{database-CWpdaykI.js → database-D2HOmxtl.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-DZEuTCs6.js → dollar-sign-CQ1vK_6q.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-BHBW6m9v.js → file-code-corner-w2vpGm5d.js} +1 -1
- package/web-app/dist/assets/{file-plus-D4h1jZSR.js → file-plus-DlF6wjkD.js} +1 -1
- package/web-app/dist/assets/{globe-CXdqKgwd.js → globe-Dy3lBJg1.js} +1 -1
- package/web-app/dist/assets/{hammer-B3YuuYI_.js → hammer-C3xIiRXN.js} +1 -1
- package/web-app/dist/assets/{index-BLEnboSv.js → index-4t-_IW2y.js} +3 -3
- package/web-app/dist/assets/{layers-Dvp5nFtw.js → layers-Y8Fs8qXI.js} +1 -1
- package/web-app/dist/assets/{loader-circle-DodDmIZ3.js → loader-circle-CxgN1v4m.js} +1 -1
- package/web-app/dist/assets/{lock-EiuaH1Ep.js → lock-DFFNbXDs.js} +1 -1
- package/web-app/dist/assets/{package-Cx4m2hFg.js → package-5e6qCTUg.js} +1 -1
- package/web-app/dist/assets/{plus-D-Sd5rpH.js → plus-C0Go_ytj.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-C0w1cdmF.js → refresh-cw-D4i-NW3o.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-C_qk6MTT.js → rotate-ccw-YlKkiUW6.js} +1 -1
- package/web-app/dist/assets/{scroll-text-DSxiFtkc.js → scroll-text-4qXOHTap.js} +1 -1
- package/web-app/dist/assets/{server-NTJt7I8M.js → server-BB6zXNp9.js} +1 -1
- package/web-app/dist/assets/{shield-alert-HBxMQOvH.js → shield-alert-D4tzjB1H.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-DEgsHzSD.js → thumbs-up-DZiRwdFj.js} +1 -1
- package/web-app/dist/assets/{trash-2-px46FnTD.js → trash-2-Dv_LkRIK.js} +1 -1
- package/web-app/dist/assets/{trending-down-CBosVGKa.js → trending-down-BJYp9PQe.js} +1 -1
- package/web-app/dist/assets/{trending-up-Dbd7zrQj.js → trending-up-BTcXLklK.js} +1 -1
- package/web-app/dist/assets/{upload-nhdFKAs1.js → upload-fcHqwOxr.js} +1 -1
- package/web-app/dist/assets/{usePolling-BgaGdinh.js → usePolling-BeJYw_4L.js} +1 -1
- package/web-app/dist/assets/{user-CzIihUy9.js → user-BcDwUCsO.js} +1 -1
- package/web-app/dist/index.html +1 -1
package/autonomy/loki
CHANGED
|
@@ -71,6 +71,15 @@ if [ -f "$_LOKI_SCRIPT_DIR/lib/lock.sh" ]; then
|
|
|
71
71
|
source "$_LOKI_SCRIPT_DIR/lib/lock.sh"
|
|
72
72
|
fi
|
|
73
73
|
|
|
74
|
+
# Default per-run spend cap (single source: default_max_cost_usd in loki-ts/data/model-pricing.json,
|
|
75
|
+
# also read by loki-ts/src/e10ext/budget_cap.ts and autonomy/run.sh). Prints a plain number; 100 only if the file is unreadable.
|
|
76
|
+
loki_budget_default_usd() {
|
|
77
|
+
local v=""
|
|
78
|
+
[ -f "$_LOKI_SCRIPT_DIR/../loki-ts/data/model-pricing.json" ] && \
|
|
79
|
+
v="$(sed -n 's/.*"default_max_cost_usd"[[:space:]]*:[[:space:]]*\([0-9][0-9.]*\).*/\1/p' "$_LOKI_SCRIPT_DIR/../loki-ts/data/model-pricing.json" | head -1)"
|
|
80
|
+
printf '%s\n' "${v:-100}"
|
|
81
|
+
}
|
|
82
|
+
|
|
74
83
|
# Guarded browser opener (loki_open_url). Every browser open goes through it
|
|
75
84
|
# so tests, CI and non-TTY runs never pop a tab. If missing, nothing opens.
|
|
76
85
|
if [ -f "$_LOKI_SCRIPT_DIR/lib/browser-open.sh" ]; then
|
|
@@ -123,6 +132,12 @@ _loki_caveman_narration_level() {
|
|
|
123
132
|
fi
|
|
124
133
|
}
|
|
125
134
|
|
|
135
|
+
# loki edit: one-pass small change fast path (functions-only, self-guarded).
|
|
136
|
+
if [ -f "$_LOKI_SCRIPT_DIR/edit.sh" ]; then
|
|
137
|
+
# shellcheck source=edit.sh
|
|
138
|
+
source "$_LOKI_SCRIPT_DIR/edit.sh"
|
|
139
|
+
fi
|
|
140
|
+
|
|
126
141
|
# Quickstart guided interview (v7.29.0): provides cmd_quickstart and its
|
|
127
142
|
# deterministic offline template matcher. Functions-only file (no top-level
|
|
128
143
|
# command), sourced here so the dispatch case can call cmd_quickstart. Composes
|
|
@@ -1722,7 +1737,14 @@ _help_verify_dsse() {
|
|
|
1722
1737
|
echo " 66 no signing key, or no runs"
|
|
1723
1738
|
}
|
|
1724
1739
|
|
|
1740
|
+
# Default help screen: core verbs only. `loki help all` prints show_help_all.
|
|
1725
1741
|
show_help() {
|
|
1742
|
+
# shellcheck source=/dev/null
|
|
1743
|
+
source "$_LOKI_SCRIPT_DIR/lib/help-core.sh"
|
|
1744
|
+
help_core_screen "$(get_version)"
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1747
|
+
show_help_all() {
|
|
1726
1748
|
local version=$(get_version)
|
|
1727
1749
|
# Strip color when stdout is not a TTY (piped/redirected) so captured help
|
|
1728
1750
|
# output is clean, matching the bare-loki welcome path. Local overrides only.
|
|
@@ -1735,6 +1757,7 @@ show_help() {
|
|
|
1735
1757
|
echo "Usage: loki <command> [options]"
|
|
1736
1758
|
echo ""
|
|
1737
1759
|
echo "New here? Try these in order:"
|
|
1760
|
+
echo " loki setup One-step wizard: tools, provider login, model route, spend cap (--yes for defaults)"
|
|
1738
1761
|
echo " loki welcome Friendly first-run opener (what Loki is, next steps)"
|
|
1739
1762
|
echo " loki doctor Check your setup is ready (a few seconds)"
|
|
1740
1763
|
echo " loki quickstart Guided first build from your idea (no PRD needed)"
|
|
@@ -1815,6 +1838,7 @@ show_help() {
|
|
|
1815
1838
|
echo ""
|
|
1816
1839
|
echo "Options for 'start':"
|
|
1817
1840
|
echo " --provider NAME AI provider: claude (default), codex, cline, aider, opencode"
|
|
1841
|
+
echo " --model ID Model tier or route (e.g. ollama/qwen3-coder)"
|
|
1818
1842
|
echo " --simple Force simple complexity tier (3 phases)"
|
|
1819
1843
|
echo " --complex Force complex complexity tier (8 phases)"
|
|
1820
1844
|
echo " --no-dashboard Disable web dashboard"
|
|
@@ -1823,7 +1847,7 @@ show_help() {
|
|
|
1823
1847
|
echo " --spec FILE Run against an edited spec (written by 'loki plan <task> --spec'; see also --spec-first)"
|
|
1824
1848
|
echo " --fresh-prd Regenerate the PRD from the codebase (no-PRD runs; ignores the reusable generated PRD)"
|
|
1825
1849
|
echo " --compliance PRESET Enable compliance mode (default|healthcare|fintech|government)"
|
|
1826
|
-
echo " --budget USD
|
|
1850
|
+
echo " --budget USD Per-run cost cap in USD (default $(loki_budget_default_usd); auto-pause when exceeded; see docs/cost-controls.md)"
|
|
1827
1851
|
echo " --bmad-project PATH Use BMAD Method project artifacts as input"
|
|
1828
1852
|
echo " --openspec PATH Use OpenSpec change directory as input"
|
|
1829
1853
|
echo " --config PATH Load settings from a config file (.yaml/.json/.env). Alias: --env-file, --vars"
|
|
@@ -1899,6 +1923,7 @@ show_help() {
|
|
|
1899
1923
|
# missing from this list, so a new command cannot ship invisible.
|
|
1900
1924
|
echo ""
|
|
1901
1925
|
echo "All commands:"
|
|
1926
|
+
echo " agents chat diff edit models route"
|
|
1902
1927
|
echo " acp agent analyze api assets audit backlog bench checkpoint (cp) ci cleanup"
|
|
1903
1928
|
echo " cluster cockpit code compliance completions compound config context (ctx)"
|
|
1904
1929
|
echo " cost council crash dashboard demo deploy docker docs doctor dogfood"
|
|
@@ -1908,7 +1933,7 @@ show_help() {
|
|
|
1908
1933
|
echo " next notify onboard open optimize otel outcomes own (handoff) pause plan preview"
|
|
1909
1934
|
echo " projects proof (receipt) provider quick quickstart rc remote report reset"
|
|
1910
1935
|
echo " merge resume review rollback run sandbox secrets secure self-update sentrux"
|
|
1911
|
-
echo " serve setup-skill share ship spec start state stats status steer stop"
|
|
1936
|
+
echo " serve setup setup-skill share ship spec start state stats status steer stop"
|
|
1912
1937
|
echo " syslog telemetry template test tour trigger trust trust-metrics"
|
|
1913
1938
|
echo " ultracode undo update verify version voice watch watchdog web welcome why"
|
|
1914
1939
|
echo " wiki workspace worktree (wt)"
|
|
@@ -2575,7 +2600,8 @@ cmd_start() {
|
|
|
2575
2600
|
echo " Token from LOKI_REMOTE_TOKEN / LOKI_REMOTE_TOKEN_FILE"
|
|
2576
2601
|
echo " (never an argument). Env: LOKI_REMOTE_URL."
|
|
2577
2602
|
echo " --provider NAME AI provider: claude (default), codex, cline, aider, opencode"
|
|
2578
|
-
echo " --
|
|
2603
|
+
echo " --model NAME Model or route override (for example ollama/qwen3-coder)"
|
|
2604
|
+
echo " --allow-haiku Enable Haiku model for the fast tier (default: disabled)"
|
|
2579
2605
|
echo " --simple Force simple complexity tier (3 phases)"
|
|
2580
2606
|
echo " --complex Force complex complexity tier (8 phases)"
|
|
2581
2607
|
echo " --no-dashboard Disable web dashboard"
|
|
@@ -2591,7 +2617,7 @@ cmd_start() {
|
|
|
2591
2617
|
echo " (ignores the reusable generated PRD; aliases: --regen-prd,"
|
|
2592
2618
|
echo " --regenerate-prd, --regen, or LOKI_PRD_REGEN=1)"
|
|
2593
2619
|
echo " --compliance PRESET Enable compliance mode (default|healthcare|fintech|government)"
|
|
2594
|
-
echo " --budget USD
|
|
2620
|
+
echo " --budget USD Per-run cost cap (default $(loki_budget_default_usd); auto-pause when exceeded)"
|
|
2595
2621
|
echo " --bmad-project PATH Use BMAD Method project artifacts as input"
|
|
2596
2622
|
echo " --openspec PATH Use OpenSpec change directory as input"
|
|
2597
2623
|
echo " --mirofish [URL] Enable MiroFish market validation (default: localhost:5001)"
|
|
@@ -2634,7 +2660,7 @@ cmd_start() {
|
|
|
2634
2660
|
echo " LOKI_AUTO_CONFIRM Set to 'true'/'false' to control prompts (takes precedence over CI)"
|
|
2635
2661
|
echo " CI Fallback: auto-confirms when 'true' and LOKI_AUTO_CONFIRM is unset"
|
|
2636
2662
|
echo " LOKI_MAX_ITERATIONS Max iteration count"
|
|
2637
|
-
echo " LOKI_BUDGET_LIMIT Cost
|
|
2663
|
+
echo " LOKI_BUDGET_LIMIT Cost cap in USD (default $(loki_budget_default_usd); empty means unlimited)"
|
|
2638
2664
|
echo ""
|
|
2639
2665
|
echo "Examples:"
|
|
2640
2666
|
echo " loki start # Interactive, analyze current dir"
|
|
@@ -3032,7 +3058,7 @@ cmd_start() {
|
|
|
3032
3058
|
echo -e "${RED}--budget must be greater than 0 (a 0 budget pauses before any work)${NC}" >&2
|
|
3033
3059
|
exit 1
|
|
3034
3060
|
fi
|
|
3035
|
-
export LOKI_BUDGET_LIMIT="$2"
|
|
3061
|
+
export LOKI_BUDGET_LIMIT="$2" LOKI_BUDGET_SOURCE=flag
|
|
3036
3062
|
shift 2
|
|
3037
3063
|
else
|
|
3038
3064
|
echo -e "${RED}--budget requires a USD amount (e.g., --budget 5.00)${NC}"
|
|
@@ -3050,7 +3076,7 @@ cmd_start() {
|
|
|
3050
3076
|
echo -e "${RED}--budget must be greater than 0 (a 0 budget pauses before any work)${NC}" >&2
|
|
3051
3077
|
exit 1
|
|
3052
3078
|
fi
|
|
3053
|
-
export LOKI_BUDGET_LIMIT="$budget_val"
|
|
3079
|
+
export LOKI_BUDGET_LIMIT="$budget_val" LOKI_BUDGET_SOURCE=flag
|
|
3054
3080
|
shift
|
|
3055
3081
|
;;
|
|
3056
3082
|
# v6.84.0: explicit mode flags (override auto-detection)
|
|
@@ -3184,7 +3210,7 @@ cmd_start() {
|
|
|
3184
3210
|
;;
|
|
3185
3211
|
-*)
|
|
3186
3212
|
echo -e "${RED}Unknown option: $1${NC}"
|
|
3187
|
-
exit
|
|
3213
|
+
exit 64
|
|
3188
3214
|
;;
|
|
3189
3215
|
*)
|
|
3190
3216
|
# Capture first positional arg for unified mode detection.
|
|
@@ -3939,15 +3965,8 @@ cmd_start() {
|
|
|
3939
3965
|
if ! command -v "$effective_provider" &>/dev/null; then
|
|
3940
3966
|
echo -e "${RED}Error: Provider CLI '$effective_provider' is not installed.${NC}"
|
|
3941
3967
|
echo ""
|
|
3942
|
-
echo "Install it first:"
|
|
3943
|
-
|
|
3944
|
-
claude) echo " npm install -g @anthropic-ai/claude-code" ;;
|
|
3945
|
-
codex) echo " npm install -g @openai/codex" ;;
|
|
3946
|
-
cline) echo " npm install -g cline" ;;
|
|
3947
|
-
aider) echo " pip install aider-chat" ;;
|
|
3948
|
-
opencode) echo " npm install -g opencode-ai" ;;
|
|
3949
|
-
*) echo " Check the provider documentation for installation." ;;
|
|
3950
|
-
esac
|
|
3968
|
+
echo "Install it first (same fix as loki doctor):"
|
|
3969
|
+
_loki_req_fix_line "$effective_provider"
|
|
3951
3970
|
echo ""
|
|
3952
3971
|
echo "Check your environment: loki doctor"
|
|
3953
3972
|
exit 1
|
|
@@ -5153,6 +5172,17 @@ cmd_resume() {
|
|
|
5153
5172
|
exit 0
|
|
5154
5173
|
fi
|
|
5155
5174
|
|
|
5175
|
+
# RECOVERY: an interrupted engine10 run is resumed at its phase by loki-ts/src/util/run_outputs.ts
|
|
5176
|
+
# (exit 0 resumed, 4 phase reported, 5 publish failed, anything else: nothing for it, fall through).
|
|
5177
|
+
if ls "$LOKI_DIR"/runs/e10-*/events.jsonl >/dev/null 2>&1; then
|
|
5178
|
+
local _e10_rc=0
|
|
5179
|
+
( _loki_bun_delegate engine10 resume "$@" ) || _e10_rc=$?
|
|
5180
|
+
case "$_e10_rc" in
|
|
5181
|
+
0 | 4) return 0 ;;
|
|
5182
|
+
5) return 1 ;;
|
|
5183
|
+
esac
|
|
5184
|
+
fi
|
|
5185
|
+
|
|
5156
5186
|
# Check if there is anything to resume before touching signal files
|
|
5157
5187
|
local has_pause_signal=false
|
|
5158
5188
|
local has_stop_signal=false
|
|
@@ -7102,8 +7132,14 @@ cmd_provider() {
|
|
|
7102
7132
|
cmd_provider_list
|
|
7103
7133
|
;;
|
|
7104
7134
|
info)
|
|
7135
|
+
case " $* " in
|
|
7136
|
+
*" --json "*) _loki_bun_delegate provider info "$@" || { echo "loki provider info --json needs bun: ${_LOKI_DELEGATE_WHY}" >&2; return 1; } ;;
|
|
7137
|
+
esac
|
|
7105
7138
|
cmd_provider_info "$@"
|
|
7106
7139
|
;;
|
|
7140
|
+
matrix)
|
|
7141
|
+
_loki_bun_delegate provider matrix "$@" || { echo "loki provider matrix needs bun: ${_LOKI_DELEGATE_WHY}" >&2; return 1; }
|
|
7142
|
+
;;
|
|
7107
7143
|
models)
|
|
7108
7144
|
cmd_provider_models
|
|
7109
7145
|
;;
|
|
@@ -7116,7 +7152,8 @@ cmd_provider() {
|
|
|
7116
7152
|
echo " show Show current provider (default)"
|
|
7117
7153
|
echo " set Set provider for this project"
|
|
7118
7154
|
echo " list List available providers"
|
|
7119
|
-
echo " info Show provider details"
|
|
7155
|
+
echo " info Show provider details (--json: capability contract)"
|
|
7156
|
+
echo " matrix Show the capability matrix per provider and engine"
|
|
7120
7157
|
echo " models Show resolved model configuration for all providers"
|
|
7121
7158
|
echo ""
|
|
7122
7159
|
echo "Precedence (highest wins):"
|
|
@@ -10848,7 +10885,7 @@ cmd_run() {
|
|
|
10848
10885
|
echo " --no-dashboard Disable web dashboard"
|
|
10849
10886
|
echo " --sandbox Run in Docker sandbox (default: off; requires Docker)"
|
|
10850
10887
|
echo " --no-plan Skip auto-shown PRD analysis at startup"
|
|
10851
|
-
echo " --budget USD
|
|
10888
|
+
echo " --budget USD Per-run cost cap (default $(loki_budget_default_usd))"
|
|
10852
10889
|
echo ""
|
|
10853
10890
|
echo "Progressive Isolation:"
|
|
10854
10891
|
echo " --worktree, -w Git worktree isolation (separate branch)"
|
|
@@ -12931,6 +12968,16 @@ cmd_config() {
|
|
|
12931
12968
|
show)
|
|
12932
12969
|
cmd_config_show
|
|
12933
12970
|
;;
|
|
12971
|
+
list)
|
|
12972
|
+
# HELP slice: `config list [--json]` is `config show` (json: wrapped).
|
|
12973
|
+
# shellcheck source=/dev/null
|
|
12974
|
+
source "$_LOKI_SCRIPT_DIR/lib/json-output.sh"
|
|
12975
|
+
if loki_json_requested "$@"; then
|
|
12976
|
+
loki_json_wrap config-list cmd_config_show
|
|
12977
|
+
else
|
|
12978
|
+
cmd_config_show
|
|
12979
|
+
fi
|
|
12980
|
+
;;
|
|
12934
12981
|
init)
|
|
12935
12982
|
cmd_config_init
|
|
12936
12983
|
;;
|
|
@@ -12956,9 +13003,10 @@ cmd_config() {
|
|
|
12956
13003
|
cmd_config_validate "$@"
|
|
12957
13004
|
;;
|
|
12958
13005
|
*)
|
|
12959
|
-
echo -e "${YELLOW}Usage: loki config [show|init|edit|path|set|get|example|schema|validate]${NC}"
|
|
13006
|
+
echo -e "${YELLOW}Usage: loki config [show|list|init|edit|path|set|get|example|schema|validate]${NC}"
|
|
12960
13007
|
echo ""
|
|
12961
13008
|
echo " show Show current configuration (default)"
|
|
13009
|
+
echo " list [--json] Same as show; --json emits one JSON object"
|
|
12962
13010
|
echo " init Create a config file from template"
|
|
12963
13011
|
echo " edit Open config file in editor"
|
|
12964
13012
|
echo " path Show config file paths"
|
|
@@ -13447,6 +13495,100 @@ cmd_config_path() {
|
|
|
13447
13495
|
echo "Create a config file with: loki config init"
|
|
13448
13496
|
}
|
|
13449
13497
|
|
|
13498
|
+
# Merge the Loki plugin into a Claude Code settings.json (loki setup-skill --claude-code).
|
|
13499
|
+
# Existing keys are never overwritten, invalid JSON is refused (rc 3), writes are atomic.
|
|
13500
|
+
_setup_skill_claude_code() {
|
|
13501
|
+
local print_only=0 project=0 stop=0 settings=""
|
|
13502
|
+
while [ $# -gt 0 ]; do
|
|
13503
|
+
case "$1" in
|
|
13504
|
+
--print) print_only=1 ;;
|
|
13505
|
+
--project) project=1 ;;
|
|
13506
|
+
--stop-hook) stop=1 ;;
|
|
13507
|
+
--settings) settings="${2:-}"; shift ;;
|
|
13508
|
+
--help|-h)
|
|
13509
|
+
echo "Usage: loki setup-skill --claude-code [--print] [--project] [--stop-hook] [--settings FILE]"
|
|
13510
|
+
echo ""
|
|
13511
|
+
echo "Registers the Loki plugin marketplace and enables the plugin in Claude Code"
|
|
13512
|
+
echo "settings (default ~/.claude/settings.json; --project uses ./.claude/settings.json)."
|
|
13513
|
+
echo "Merges only: existing keys are kept, invalid JSON is refused."
|
|
13514
|
+
echo ""
|
|
13515
|
+
echo " --print Print the settings snippet and change nothing"
|
|
13516
|
+
echo " --stop-hook Also opt in to the Stop-hook fast verifier (LOKI_STOP_VERIFY=1)"
|
|
13517
|
+
return 0
|
|
13518
|
+
;;
|
|
13519
|
+
*) echo "Unknown option: $1" >&2; return 2 ;;
|
|
13520
|
+
esac
|
|
13521
|
+
shift
|
|
13522
|
+
done
|
|
13523
|
+
command -v python3 >/dev/null 2>&1 || { echo "python3 is required" >&2; return 1; }
|
|
13524
|
+
if [ -z "$settings" ] && [ "$print_only" -eq 0 ]; then
|
|
13525
|
+
if [ "$project" -eq 1 ]; then
|
|
13526
|
+
settings="${TARGET_DIR:-.}/.claude/settings.json"
|
|
13527
|
+
else
|
|
13528
|
+
settings="$HOME/.claude/settings.json"
|
|
13529
|
+
fi
|
|
13530
|
+
fi
|
|
13531
|
+
local out rc
|
|
13532
|
+
out="$(python3 - "$settings" "$stop" "$print_only" <<'PY'
|
|
13533
|
+
import json, os, sys, tempfile
|
|
13534
|
+
path, stop, print_only = sys.argv[1], sys.argv[2] == "1", sys.argv[3] == "1"
|
|
13535
|
+
want = {
|
|
13536
|
+
"extraKnownMarketplaces": {
|
|
13537
|
+
"loki-mode": {"source": {"source": "github", "repo": "asklokesh/loki-mode"}}
|
|
13538
|
+
},
|
|
13539
|
+
"enabledPlugins": {"loki-mode@loki-mode": True},
|
|
13540
|
+
}
|
|
13541
|
+
if stop:
|
|
13542
|
+
want["env"] = {"LOKI_STOP_VERIFY": "1"}
|
|
13543
|
+
if print_only:
|
|
13544
|
+
print(json.dumps(want, indent=2))
|
|
13545
|
+
sys.exit(0)
|
|
13546
|
+
cur = {}
|
|
13547
|
+
if os.path.exists(path):
|
|
13548
|
+
try:
|
|
13549
|
+
raw = open(path).read()
|
|
13550
|
+
cur = json.loads(raw) if raw.strip() else {}
|
|
13551
|
+
except Exception as e:
|
|
13552
|
+
print("REFUSED %s is not valid JSON (%s); fix or move it aside" % (path, e))
|
|
13553
|
+
sys.exit(3)
|
|
13554
|
+
if not isinstance(cur, dict):
|
|
13555
|
+
print("REFUSED %s top level is not an object" % path)
|
|
13556
|
+
sys.exit(3)
|
|
13557
|
+
added = []
|
|
13558
|
+
for top, kv in want.items():
|
|
13559
|
+
node = cur.get(top)
|
|
13560
|
+
if node is None:
|
|
13561
|
+
cur[top] = {}
|
|
13562
|
+
node = cur[top]
|
|
13563
|
+
elif not isinstance(node, dict):
|
|
13564
|
+
print("KEPT %s (existing value is not an object)" % top)
|
|
13565
|
+
continue
|
|
13566
|
+
for k, v in kv.items():
|
|
13567
|
+
if k in node:
|
|
13568
|
+
print("KEPT %s.%s" % (top, k))
|
|
13569
|
+
else:
|
|
13570
|
+
node[k] = v
|
|
13571
|
+
added.append("%s.%s" % (top, k))
|
|
13572
|
+
print("ADDED %s.%s" % (top, k))
|
|
13573
|
+
if added:
|
|
13574
|
+
d = os.path.dirname(os.path.abspath(path))
|
|
13575
|
+
os.makedirs(d, exist_ok=True)
|
|
13576
|
+
fd, tmp = tempfile.mkstemp(dir=d, prefix=".settings.", suffix=".tmp")
|
|
13577
|
+
with os.fdopen(fd, "w") as f:
|
|
13578
|
+
json.dump(cur, f, indent=2)
|
|
13579
|
+
f.write("\n")
|
|
13580
|
+
os.replace(tmp, path)
|
|
13581
|
+
else:
|
|
13582
|
+
print("UNCHANGED %s" % path)
|
|
13583
|
+
PY
|
|
13584
|
+
)"
|
|
13585
|
+
rc=$?
|
|
13586
|
+
printf '%s\n' "$out"
|
|
13587
|
+
[ "$rc" -eq 0 ] || return "$rc"
|
|
13588
|
+
[ "$print_only" -eq 1 ] || echo "Next: in Claude Code run /reload-plugins, then try /loki-mode:start, /loki-mode:loki-verify, /loki-mode:handoff."
|
|
13589
|
+
return 0
|
|
13590
|
+
}
|
|
13591
|
+
|
|
13450
13592
|
# Set up skill symlinks for all providers
|
|
13451
13593
|
cmd_setup_skill() {
|
|
13452
13594
|
# v7.6.2 B-13 fix: --help must print help, not install skills.
|
|
@@ -13460,11 +13602,17 @@ cmd_setup_skill() {
|
|
|
13460
13602
|
echo "skills directory: ~/.claude/skills/, ~/.codex/skills/, etc."
|
|
13461
13603
|
echo ""
|
|
13462
13604
|
echo "Options:"
|
|
13605
|
+
echo " --claude-code Merge the Loki plugin into Claude Code settings (see --claude-code --help)"
|
|
13463
13606
|
echo " --help, -h Show this help and exit"
|
|
13464
13607
|
echo ""
|
|
13465
13608
|
echo "Side effects: writes symlinks/files under ~/.<provider>/skills/loki-mode/."
|
|
13466
13609
|
return 0
|
|
13467
13610
|
;;
|
|
13611
|
+
--claude-code)
|
|
13612
|
+
shift
|
|
13613
|
+
_setup_skill_claude_code "$@"
|
|
13614
|
+
return $?
|
|
13615
|
+
;;
|
|
13468
13616
|
esac
|
|
13469
13617
|
echo -e "${BOLD}Loki Mode Skill Setup${NC}"
|
|
13470
13618
|
echo ""
|
|
@@ -14052,6 +14200,18 @@ _loki_bun_delegate() {
|
|
|
14052
14200
|
exec "$bun_bin" "$cli" "$cmd" "$@"
|
|
14053
14201
|
}
|
|
14054
14202
|
|
|
14203
|
+
# One-line fix for a requirement id (a provider name is an id), read from the shared
|
|
14204
|
+
# table autonomy/lib/setup-requirements.json so runtime errors match loki doctor.
|
|
14205
|
+
_loki_req_fix_line() {
|
|
14206
|
+
local _id="$1" _fix=""
|
|
14207
|
+
_fix="$(jq -r --arg id "$_id" '.requirements[] | select(.id == $id) | .fix' "${SKILL_DIR}/autonomy/lib/setup-requirements.json" 2>/dev/null | head -n 1)" || _fix=""
|
|
14208
|
+
if [ -n "$_fix" ]; then
|
|
14209
|
+
echo " $_fix"
|
|
14210
|
+
else
|
|
14211
|
+
echo " Check the provider documentation for installation."
|
|
14212
|
+
fi
|
|
14213
|
+
}
|
|
14214
|
+
|
|
14055
14215
|
# loki doctor. The one implementation is loki-ts/src/commands/doctor.ts; this is a
|
|
14056
14216
|
# delegator. Only --airgap stays in bash (_loki_airgap_audit). If the Bun route is
|
|
14057
14217
|
# unavailable we print a minimal diagnostic (never a second copy of the checks).
|
|
@@ -14097,7 +14257,12 @@ cmd_doctor_json() {
|
|
|
14097
14257
|
why="${why//\\/\\\\}"; why="${why//\"/\\\"}"
|
|
14098
14258
|
fix="${fix//\\/\\\\}"; fix="${fix//\"/\\\"}"
|
|
14099
14259
|
ver="${ver//\\/\\\\}"; ver="${ver//\"/\\\"}"
|
|
14100
|
-
|
|
14260
|
+
local reqs=null
|
|
14261
|
+
if declare -F loki_requirements_json >/dev/null 2>&1; then
|
|
14262
|
+
reqs="$(loki_requirements_json 2>/dev/null | jq -c . 2>/dev/null)" || reqs=null
|
|
14263
|
+
[ -n "$reqs" ] || reqs=null
|
|
14264
|
+
fi
|
|
14265
|
+
printf '{"loki_mode_version":"%s","checks":[],"provider_availability":null,"disk":null,"ai_provider":null,"skills":[],"sentrux":null,"memory":null,"model_catalog":null,"requirements":%s,"summary":{"passed":0,"failed":1,"warnings":0,"ok":false},"route":"unavailable","reason":"%s","fix":"%s"}\n' "$ver" "$reqs" "$why" "$fix"
|
|
14101
14266
|
}
|
|
14102
14267
|
|
|
14103
14268
|
# Architectural-drift gate (v7.5.14, opt-in).
|
|
@@ -15625,6 +15790,7 @@ cmd_quick() {
|
|
|
15625
15790
|
echo ""
|
|
15626
15791
|
echo "Runs the Loki 10 engine on one small task (no PR is opened). Best for"
|
|
15627
15792
|
echo "tiny tasks."
|
|
15793
|
+
echo "quick = small task with the verify loop. For a single pass with no loop, use loki edit."
|
|
15628
15794
|
echo ""
|
|
15629
15795
|
echo "Examples:"
|
|
15630
15796
|
echo " loki quick \"add dark mode to this React app\""
|
|
@@ -15654,16 +15820,7 @@ cmd_quick() {
|
|
|
15654
15820
|
echo " loki quick \"fix the login bug in auth.js\""
|
|
15655
15821
|
echo " loki quick \"add input validation to the signup form\""
|
|
15656
15822
|
echo " loki quick \"write unit tests for the API endpoints\""
|
|
15657
|
-
exit
|
|
15658
|
-
fi
|
|
15659
|
-
|
|
15660
|
-
# v7.29.0: provider pre-flight gate. Offer install on a TTY; print honest
|
|
15661
|
-
# manual instructions and exit 2 on non-TTY/CI, before any spend. --help and
|
|
15662
|
-
# the no-args usage path already returned/exited above.
|
|
15663
|
-
if declare -f provider_offer_gate >/dev/null 2>&1; then
|
|
15664
|
-
if ! provider_offer_gate; then
|
|
15665
|
-
exit 2
|
|
15666
|
-
fi
|
|
15823
|
+
exit 64
|
|
15667
15824
|
fi
|
|
15668
15825
|
|
|
15669
15826
|
# #691: drop the unified config-file aliases from the task description. The
|
|
@@ -15682,6 +15839,12 @@ cmd_quick() {
|
|
|
15682
15839
|
--verbose|-v) if [ "$_quick_task_seen" = "false" ]; then export LOKI_VERBOSE=1; continue; fi ;;
|
|
15683
15840
|
--config|--vars|--env-file) _skip_next=true; continue ;;
|
|
15684
15841
|
--config=*|--vars=*|--env-file=*) continue ;;
|
|
15842
|
+
# LM-006: a leading unknown --flag is a usage error, never task text (a typo must not start a paid run).
|
|
15843
|
+
--?*) if [ "$_quick_task_seen" = "false" ] &&[[ "$_qa" != *" "* ]]; then
|
|
15844
|
+
echo -e "${RED}Error: unknown option: $_qa${NC}" >&2
|
|
15845
|
+
echo "Usage: loki quick [--verbose] \"description of what to do\"" >&2
|
|
15846
|
+
exit 64
|
|
15847
|
+
fi ;;
|
|
15685
15848
|
esac
|
|
15686
15849
|
_quick_task_seen=true
|
|
15687
15850
|
_quick_args+=("$_qa")
|
|
@@ -15690,7 +15853,17 @@ cmd_quick() {
|
|
|
15690
15853
|
if [ $# -eq 0 ]; then
|
|
15691
15854
|
echo -e "${RED}Error: No task description provided${NC}"
|
|
15692
15855
|
echo "Usage: loki quick [--verbose] \"description of what to do\""
|
|
15693
|
-
exit
|
|
15856
|
+
exit 64
|
|
15857
|
+
fi
|
|
15858
|
+
|
|
15859
|
+
# v7.29.0: provider pre-flight gate. Offer install on a TTY; print honest
|
|
15860
|
+
# manual instructions and exit 2 on non-TTY/CI, before any spend. --help and
|
|
15861
|
+
# every usage error (no task, unknown option, exit 64) is decided above,
|
|
15862
|
+
# so a host with no provider still reports a typo as 64, not 2.
|
|
15863
|
+
if declare -f provider_offer_gate >/dev/null 2>&1; then
|
|
15864
|
+
if ! provider_offer_gate; then
|
|
15865
|
+
exit 2
|
|
15866
|
+
fi
|
|
15694
15867
|
fi
|
|
15695
15868
|
|
|
15696
15869
|
local task_desc="$*"
|
|
@@ -15757,14 +15930,8 @@ QPRDEOF
|
|
|
15757
15930
|
if ! command -v "$_quick_provider" &>/dev/null; then
|
|
15758
15931
|
echo -e "${RED}Error: Provider CLI '$_quick_provider' is not installed.${NC}"
|
|
15759
15932
|
echo ""
|
|
15760
|
-
echo "Install your AI provider CLI first:"
|
|
15761
|
-
|
|
15762
|
-
claude) echo " npm install -g @anthropic-ai/claude-code" ;;
|
|
15763
|
-
codex) echo " npm install -g @openai/codex" ;;
|
|
15764
|
-
cline) echo " npm install -g cline" ;;
|
|
15765
|
-
aider) echo " pip install aider-chat" ;;
|
|
15766
|
-
*) echo " Check the provider documentation for installation." ;;
|
|
15767
|
-
esac
|
|
15933
|
+
echo "Install your AI provider CLI first (same fix as loki doctor):"
|
|
15934
|
+
_loki_req_fix_line "$_quick_provider"
|
|
15768
15935
|
echo ""
|
|
15769
15936
|
echo "Then verify: loki doctor"
|
|
15770
15937
|
exit 1
|
|
@@ -17902,6 +18069,8 @@ cmd_verify() {
|
|
|
17902
18069
|
fi
|
|
17903
18070
|
# shellcheck source=/dev/null
|
|
17904
18071
|
source "$verify_mod"
|
|
18072
|
+
# verify_main handles --json natively (evidence document on stdout, banner
|
|
18073
|
+
# on stderr); the generic json-output.sh wrapper must not intercept it.
|
|
17905
18074
|
verify_main "$@"
|
|
17906
18075
|
return $?
|
|
17907
18076
|
}
|
|
@@ -20677,8 +20846,33 @@ print()
|
|
|
20677
20846
|
# Dry-run PRD analysis and cost estimation (v6.18.0; refactored v6.81.1)
|
|
20678
20847
|
# Thin wrapper around show_prd_plan() so the same analysis is reusable from
|
|
20679
20848
|
# `loki start`, `loki run`, and other commands without duplicated code.
|
|
20849
|
+
# Read-only view of .loki/state/requirements-map.json (REQTRACE; contract: docs/spec-first-intent.md).
|
|
20850
|
+
_plan_show_requirements() {
|
|
20851
|
+
local as_json="${1:-false}" map="${LOKI_DIR:-.loki}/state/requirements-map.json"
|
|
20852
|
+
if [ ! -s "$map" ]; then
|
|
20853
|
+
if [ "$as_json" = true ]; then printf '{"error":"no requirements map","path":"%s"}\n' "$map"; return 1; fi
|
|
20854
|
+
echo "No requirements map at $map (written after a run that had a PRD checklist, a spec, or a multi-requirement PRD)."
|
|
20855
|
+
return 1
|
|
20856
|
+
fi
|
|
20857
|
+
if [ "$as_json" = true ]; then cat "$map"; return 0; fi
|
|
20858
|
+
LOKI_RM="$map" python3 -I -c "
|
|
20859
|
+
import json, os, sys
|
|
20860
|
+
try:
|
|
20861
|
+
m = json.load(open(os.environ['LOKI_RM']))
|
|
20862
|
+
reqs = m['requirements']
|
|
20863
|
+
except Exception:
|
|
20864
|
+
print('requirements map is unreadable: ' + os.environ['LOKI_RM']); sys.exit(1)
|
|
20865
|
+
cov = sum(1 for r in reqs if r.get('status') == 'covered')
|
|
20866
|
+
print('Requirements: %d/%d covered (revision %s)' % (cov, len(reqs), str(m.get('revision', ''))[:12]))
|
|
20867
|
+
for r in reqs:
|
|
20868
|
+
chk = (' <- ' + ', '.join(r.get('checks', []))) if r.get('checks') else ''
|
|
20869
|
+
print(' %s %-9s %-9s %s%s' % (r.get('id'), r.get('status'), r.get('method'), str(r.get('text', ''))[:80], chk))
|
|
20870
|
+
"
|
|
20871
|
+
}
|
|
20872
|
+
|
|
20680
20873
|
cmd_plan() {
|
|
20681
20874
|
local prd_file=""
|
|
20875
|
+
local show_requirements=false
|
|
20682
20876
|
local show_json=false
|
|
20683
20877
|
local show_verbose=false
|
|
20684
20878
|
|
|
@@ -20695,6 +20889,7 @@ cmd_plan() {
|
|
|
20695
20889
|
echo "Options:"
|
|
20696
20890
|
echo " --json Machine-readable JSON output"
|
|
20697
20891
|
echo " --spec With a task: write the acceptance criteria to .loki/specs/<slug>.md for you to edit"
|
|
20892
|
+
echo " --requirements Print the last run's requirement-to-check map (.loki/state/requirements-map.json), read-only"
|
|
20698
20893
|
echo " --verbose Show detailed per-iteration breakdown"
|
|
20699
20894
|
echo " --help, -h Show this help"
|
|
20700
20895
|
echo ""
|
|
@@ -20712,6 +20907,7 @@ cmd_plan() {
|
|
|
20712
20907
|
;;
|
|
20713
20908
|
--json) show_json=true; shift ;;
|
|
20714
20909
|
--verbose) show_verbose=true; shift ;;
|
|
20910
|
+
--requirements) show_requirements=true; shift ;;
|
|
20715
20911
|
*)
|
|
20716
20912
|
if [ -z "$prd_file" ]; then
|
|
20717
20913
|
prd_file="$1"
|
|
@@ -20721,6 +20917,11 @@ cmd_plan() {
|
|
|
20721
20917
|
esac
|
|
20722
20918
|
done
|
|
20723
20919
|
|
|
20920
|
+
if [ "$show_requirements" = true ]; then
|
|
20921
|
+
_plan_show_requirements "$show_json"
|
|
20922
|
+
return $?
|
|
20923
|
+
fi
|
|
20924
|
+
|
|
20724
20925
|
if [ -z "$prd_file" ]; then
|
|
20725
20926
|
# Under --json, a machine consumer expects JSON on every path, including
|
|
20726
20927
|
# errors -- never ANSI-colored prose. Emit a structured error to stdout.
|
|
@@ -20794,13 +20995,14 @@ _suggest_command() {
|
|
|
20794
20995
|
ultracode council demo dogfood heal modernize import issue github init template \
|
|
20795
20996
|
status stop pause resume monitor watch watchdog dashboard web open preview share \
|
|
20796
20997
|
memory context ctx checkpoint state report kpis cost metrics stats logs otel \
|
|
20797
|
-
syslog telemetry crash config provider doctor setup-skill onboard quickstart \
|
|
20998
|
+
syslog telemetry crash config provider doctor setup setup-skill onboard quickstart \
|
|
20798
20999
|
welcome update self-update rollback merge failover cluster enterprise remote deploy docker \
|
|
20799
21000
|
sandbox api mcp magic compound assets export wiki control docs explain why audit compliance \
|
|
20800
21001
|
welcome update self-update rollback failover cluster enterprise remote deploy docker \
|
|
20801
21002
|
sandbox api mcp acp magic compound assets export wiki control docs explain why audit compliance \
|
|
20802
21003
|
secrets analyze optimize bench ci reset cleanup notify trigger voice sentrux \
|
|
20803
|
-
worktree wt projects cp rc trust-metrics serve agent code self_update test help version
|
|
21004
|
+
worktree wt projects cp rc trust-metrics serve agent code self_update test help version \
|
|
21005
|
+
chat route agents models edit receipt setup diff undo"
|
|
20804
21006
|
local best
|
|
20805
21007
|
best=$(printf '%s\n' $known | awk -v t="$typo" '
|
|
20806
21008
|
function min3(a, b, c) { if (a < b) { if (a < c) return a; return c } if (b < c) return b; return c }
|
|
@@ -20968,6 +21170,32 @@ main() {
|
|
|
20968
21170
|
quick)
|
|
20969
21171
|
cmd_quick "$@"
|
|
20970
21172
|
;;
|
|
21173
|
+
chat)
|
|
21174
|
+
# shellcheck disable=SC1091
|
|
21175
|
+
source "$_LOKI_SCRIPT_DIR/lib/chat.sh"
|
|
21176
|
+
cmd_chat "$@"
|
|
21177
|
+
;;
|
|
21178
|
+
edit)
|
|
21179
|
+
cmd_edit "$@"
|
|
21180
|
+
;;
|
|
21181
|
+
diff)
|
|
21182
|
+
# Show what the last run changed: uncommitted changes, else the HEAD commit.
|
|
21183
|
+
# Extra args pass through to git (for example --stat or a path).
|
|
21184
|
+
if [ "${1:-}" = "--help" ] || [ "${1:-}" = "-h" ]; then
|
|
21185
|
+
echo "Usage: loki diff [git diff args]"
|
|
21186
|
+
echo "Show uncommitted changes; if there are none, show the latest commit."
|
|
21187
|
+
exit 0
|
|
21188
|
+
fi
|
|
21189
|
+
if ! git rev-parse --git-dir >/dev/null 2>&1; then
|
|
21190
|
+
echo "loki diff: not inside a git repository" >&2
|
|
21191
|
+
exit 1
|
|
21192
|
+
fi
|
|
21193
|
+
if git diff --quiet HEAD -- 2>/dev/null; then
|
|
21194
|
+
git show --format='%h %s' "$@" HEAD
|
|
21195
|
+
else
|
|
21196
|
+
git diff "$@" HEAD
|
|
21197
|
+
fi
|
|
21198
|
+
;;
|
|
20971
21199
|
monitor)
|
|
20972
21200
|
cmd_monitor "$@"
|
|
20973
21201
|
;;
|
|
@@ -20991,6 +21219,11 @@ main() {
|
|
|
20991
21219
|
welcome)
|
|
20992
21220
|
cmd_welcome "$@"
|
|
20993
21221
|
;;
|
|
21222
|
+
setup)
|
|
21223
|
+
# shellcheck disable=SC1091
|
|
21224
|
+
. "${SKILL_DIR}/autonomy/setup-wizard.sh"
|
|
21225
|
+
cmd_setup "$@"
|
|
21226
|
+
;;
|
|
20994
21227
|
init)
|
|
20995
21228
|
cmd_init "$@"
|
|
20996
21229
|
;;
|
|
@@ -21174,6 +21407,9 @@ main() {
|
|
|
21174
21407
|
doctor)
|
|
21175
21408
|
cmd_doctor "$@"
|
|
21176
21409
|
;;
|
|
21410
|
+
models)
|
|
21411
|
+
bash "$SKILL_DIR/providers/model_routes.sh" "$@"
|
|
21412
|
+
;;
|
|
21177
21413
|
sentrux)
|
|
21178
21414
|
cmd_sentrux "$@"
|
|
21179
21415
|
;;
|
|
@@ -21255,6 +21491,9 @@ main() {
|
|
|
21255
21491
|
agent)
|
|
21256
21492
|
cmd_agent "$@"
|
|
21257
21493
|
;;
|
|
21494
|
+
agents)
|
|
21495
|
+
cmd_agents "$@"
|
|
21496
|
+
;;
|
|
21258
21497
|
template)
|
|
21259
21498
|
cmd_template "$@"
|
|
21260
21499
|
;;
|
|
@@ -21401,6 +21640,10 @@ main() {
|
|
|
21401
21640
|
# deprecated-alias table; bare help prints the grouped front page.
|
|
21402
21641
|
if [ "${1:-}" = "aliases" ]; then
|
|
21403
21642
|
show_help_aliases
|
|
21643
|
+
elif [ "${1:-}" = "all" ]; then
|
|
21644
|
+
show_help_all
|
|
21645
|
+
elif [ -n "${1:-}" ] && case "${1:-}" in providers|exit-codes) true ;; *) false ;; esac && { source "$_LOKI_SCRIPT_DIR/lib/help-core.sh"; help_topic_text "$1"; }; then
|
|
21646
|
+
:
|
|
21404
21647
|
elif [ -n "${1:-}" ]; then
|
|
21405
21648
|
# `loki help <command>` reaches the command's own help. Before
|
|
21406
21649
|
# this, $1 was read only for the literal "aliases" and otherwise
|
|
@@ -21470,8 +21713,8 @@ main() {
|
|
|
21470
21713
|
echo "Did you mean 'loki ${_suggestion}'?" >&2
|
|
21471
21714
|
fi
|
|
21472
21715
|
# Always point to the full command list, even with no near-miss match.
|
|
21473
|
-
echo "Run 'loki help'
|
|
21474
|
-
exit
|
|
21716
|
+
echo "Run 'loki help' for the core commands, 'loki help all' for every command." >&2
|
|
21717
|
+
exit 2
|
|
21475
21718
|
;;
|
|
21476
21719
|
esac
|
|
21477
21720
|
}
|
|
@@ -29495,6 +29738,28 @@ PYEOF
|
|
|
29495
29738
|
esac
|
|
29496
29739
|
}
|
|
29497
29740
|
|
|
29741
|
+
# User-configurable child agents: .loki/agents/<name>.md, ~/.config/loki/agents/<name>.md
|
|
29742
|
+
cmd_agents() {
|
|
29743
|
+
local sub="${1:-list}"
|
|
29744
|
+
case "$sub" in
|
|
29745
|
+
help|-h|--help)
|
|
29746
|
+
echo "Usage: loki agents <list|new|show|export> [args]"
|
|
29747
|
+
echo " list List configured agents (project overrides user)"
|
|
29748
|
+
echo " new <name> [--user] Scaffold .loki/agents/<name>.md (or ~/.config/loki/agents)"
|
|
29749
|
+
echo " Names reviewer, planner, tester copy the shipped examples"
|
|
29750
|
+
echo " show <name> Show one agent and its system prompt"
|
|
29751
|
+
echo " export --claude [--user] Write agents as Claude Code subagents (.claude/agents/)"
|
|
29752
|
+
echo "Council reviewers use a configured agent named reviewer, tester or security."
|
|
29753
|
+
return 0
|
|
29754
|
+
;;
|
|
29755
|
+
esac
|
|
29756
|
+
local script_dir helper
|
|
29757
|
+
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
29758
|
+
helper="${script_dir}/../agents/custom_agents.py"
|
|
29759
|
+
[ -f "$helper" ] || { echo -e "${RED}Error: agents/custom_agents.py not found${NC}"; return 1; }
|
|
29760
|
+
python3 -I "$helper" "$@"
|
|
29761
|
+
}
|
|
29762
|
+
|
|
29498
29763
|
# Agent type dispatch (v6.7.0)
|
|
29499
29764
|
cmd_agent() {
|
|
29500
29765
|
local subcommand="${1:-list}"
|
|
@@ -35999,7 +36264,7 @@ PYEOF
|
|
|
35999
36264
|
}
|
|
36000
36265
|
|
|
36001
36266
|
# loki bench - head-to-head benchmark harness (R2).
|
|
36002
|
-
# Subcommands: run <task> | vs <task> | list | verify <result.json
|
|
36267
|
+
# Subcommands: run <task> | vs <task> | list | verify <result.json> | attribution.
|
|
36003
36268
|
# Thin pass-through to benchmarks/bench/run.sh (shared python core runner.py).
|
|
36004
36269
|
# CREDIBILITY: Loki NEVER grades its own success. Success is decided by a
|
|
36005
36270
|
# held-out acceptance command run by the grader OUTSIDE the agent (exit code).
|
|
@@ -36033,6 +36298,7 @@ cmd_bench() {
|
|
|
36033
36298
|
echo " verify <file> Recompute task_hash + check tool versions for a result.json"
|
|
36034
36299
|
echo " oracles Are the graders trustworthy? Hash-bound, no spend, no provider"
|
|
36035
36300
|
echo " report <files> Build results.json + RESULTS.md from per-tool result-rows"
|
|
36301
|
+
echo " attribution Same-model harness attribution: raw Claude Code vs Loki (--dry-run, --execute)"
|
|
36036
36302
|
echo ""
|
|
36037
36303
|
echo "Options:"
|
|
36038
36304
|
echo " --trials N Number of trials per tool (default 3)"
|
|
@@ -36229,7 +36495,9 @@ cmd_proof() {
|
|
|
36229
36495
|
echo " reads UNKNOWN when it cannot be computed"
|
|
36230
36496
|
echo " phases [--json] Measured phase history from real phase_change"
|
|
36231
36497
|
echo " events; unrecorded boundaries read UNKNOWN"
|
|
36232
|
-
echo " show <id>
|
|
36498
|
+
echo " show <id> [--json] Compact reviewer summary (label, revision, checks,"
|
|
36499
|
+
echo " requirements, modified tests); --json prints the"
|
|
36500
|
+
echo " full .loki/proofs/<id>/proof.json"
|
|
36233
36501
|
echo " verify <id> Re-check a receipt against the repo (tamper + drift)."
|
|
36234
36502
|
echo " Exit 0 clean, 1 tamper/drift, 2 could not check,"
|
|
36235
36503
|
echo " 64 usage (no id, more than one id, unknown option,"
|
|
@@ -36401,6 +36669,14 @@ PYEOF
|
|
|
36401
36669
|
exit 0
|
|
36402
36670
|
;;
|
|
36403
36671
|
show)
|
|
36672
|
+
local _ps_json=0 _ps_a _ps_args=()
|
|
36673
|
+
for _ps_a in "$@"; do
|
|
36674
|
+
case "$_ps_a" in
|
|
36675
|
+
--json) _ps_json=1 ;;
|
|
36676
|
+
*) _ps_args+=("$_ps_a") ;;
|
|
36677
|
+
esac
|
|
36678
|
+
done
|
|
36679
|
+
set -- "${_ps_args[@]+"${_ps_args[@]}"}"
|
|
36404
36680
|
local id="${1:-}"
|
|
36405
36681
|
if [ -z "$id" ]; then
|
|
36406
36682
|
echo -e "${RED}Missing proof id.${NC} Use 'loki proof list'."
|
|
@@ -36412,6 +36688,21 @@ PYEOF
|
|
|
36412
36688
|
echo "Use 'loki proof list' to see available proofs."
|
|
36413
36689
|
exit 1
|
|
36414
36690
|
fi
|
|
36691
|
+
if [ "$_ps_json" -eq 0 ]; then
|
|
36692
|
+
# Compact reviewer summary (docs/PROOF-PASSPORT.md).
|
|
36693
|
+
local _ps_py _ps_vr="${_LOKI_SCRIPT_DIR}/lib/proof-verify.py"
|
|
36694
|
+
_ps_py="$(loki_verify_tool_path python3)" || {
|
|
36695
|
+
echo -e "${RED}python3 is unavailable${NC}" >&2
|
|
36696
|
+
exit 2
|
|
36697
|
+
}
|
|
36698
|
+
local _ps_root
|
|
36699
|
+
_ps_root="$(loki_verify_root 2>/dev/null)" || {
|
|
36700
|
+
echo -e "${YELLOW}Summary unavailable (project tree not resolved; not checking the ambient cwd).${NC} Use 'loki proof show ${id} --json' for the full record." >&2
|
|
36701
|
+
exit 2
|
|
36702
|
+
}
|
|
36703
|
+
"$_ps_py" -E "$_ps_vr" summary "$pj" --repo "$_ps_root" --loki-dir "$loki_dir" || exit $?
|
|
36704
|
+
exit 0
|
|
36705
|
+
fi
|
|
36415
36706
|
if command -v jq &>/dev/null; then
|
|
36416
36707
|
jq . "$pj"
|
|
36417
36708
|
else
|