loki-mode 7.31.0 → 7.32.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/loki +367 -48
- package/autonomy/mcp-launch.sh +27 -16
- package/autonomy/run.sh +20 -3
- package/bin/loki +52 -0
- package/dashboard/__init__.py +1 -1
- package/dashboard/server.py +128 -28
- package/docs/INSTALLATION.md +1 -1
- package/loki-ts/dist/loki.js +248 -247
- package/mcp/__init__.py +1 -1
- package/mcp/server.py +21 -0
- package/package.json +1 -1
- package/skills/model-selection.md +7 -3
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, 11 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.32.0
|
|
7
7
|
|
|
8
8
|
**You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
|
|
9
9
|
|
|
@@ -398,4 +398,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
|
|
|
398
398
|
|
|
399
399
|
---
|
|
400
400
|
|
|
401
|
-
**v7.
|
|
401
|
+
**v7.32.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
7.
|
|
1
|
+
7.32.0
|
package/autonomy/loki
CHANGED
|
@@ -392,6 +392,41 @@ _deprecated_alias() {
|
|
|
392
392
|
fi
|
|
393
393
|
}
|
|
394
394
|
|
|
395
|
+
# CLI consolidation (Phase B): kpis is a Bun-only command (Phase K, v7.5.28+).
|
|
396
|
+
# It ships in the Bun runtime (loki-ts) and reuses the canonical cost arithmetic
|
|
397
|
+
# in loki-ts/src/runner/budget.ts (PRICING map + calculateCostFromRecords, the
|
|
398
|
+
# cost single-source-of-truth). It is deliberately NOT reimplemented in bash:
|
|
399
|
+
# a bash port would duplicate that arithmetic and risk drift. On the bash route
|
|
400
|
+
# (LOKI_LEGACY_BASH=1, or a machine without Bun) both the canonical
|
|
401
|
+
# `report kpis` and the deprecated `kpis` alias print this honest requirement
|
|
402
|
+
# message rather than the generic "Unknown command" (which would contradict
|
|
403
|
+
# `loki help` listing kpis). --json yields a structured {"available": false}
|
|
404
|
+
# payload so a machine consumer is not handed prose. Exits 1.
|
|
405
|
+
# Usage: _kpis_bash_unavailable "$@" (the alias arm prints the pointer first)
|
|
406
|
+
# --json is honored FLAG-ANYWHERE (not just as $1): a machine consumer that
|
|
407
|
+
# passes the suppression flags first -- e.g. `kpis --quiet --json` or `report
|
|
408
|
+
# kpis -q --json` -- must still get the structured {"available": false} payload
|
|
409
|
+
# on stdout, not prose. This mirrors _deprecated_alias_should_suppress, which
|
|
410
|
+
# also scans all of "$@". Exit 1 either way (the bash route never produces KPIs).
|
|
411
|
+
# Copy points at the CANONICAL `loki report kpis` (the deprecated `loki kpis`
|
|
412
|
+
# alias prints its own pointer first, at the alias arm).
|
|
413
|
+
_kpis_bash_unavailable() {
|
|
414
|
+
local _ka _want_json=""
|
|
415
|
+
for _ka in "$@"; do
|
|
416
|
+
if [ "$_ka" = "--json" ]; then
|
|
417
|
+
_want_json=1
|
|
418
|
+
break
|
|
419
|
+
fi
|
|
420
|
+
done
|
|
421
|
+
if [ -n "$_want_json" ]; then
|
|
422
|
+
printf '{"available": false, "reason": "loki report kpis requires the Bun runtime; it is not implemented on the bash (LOKI_LEGACY_BASH) route"}\n'
|
|
423
|
+
else
|
|
424
|
+
echo "loki report kpis requires the Bun runtime and is not available on the bash route." >&2
|
|
425
|
+
echo "Remove LOKI_LEGACY_BASH=1 (or install Bun: https://bun.sh) to use 'loki report kpis'." >&2
|
|
426
|
+
fi
|
|
427
|
+
exit 1
|
|
428
|
+
}
|
|
429
|
+
|
|
395
430
|
# Emit learning signal (non-blocking) - SYN-018
|
|
396
431
|
# Usage: emit_learning_signal <signal_type> [options]
|
|
397
432
|
# Signal types: user_preference, error_pattern, success_pattern, tool_efficiency, workflow_pattern
|
|
@@ -643,10 +678,11 @@ show_help() {
|
|
|
643
678
|
echo " report [cmd] Reporting: session|metrics|cost|export|share|dogfood"
|
|
644
679
|
echo ""
|
|
645
680
|
echo "Knowledge:"
|
|
646
|
-
echo "
|
|
681
|
+
echo " analyze [cmd] Codebase intelligence: explain|onboard|code|context"
|
|
682
|
+
echo " memory [cmd] Cross-project learnings (list|show|search|stats|compound)"
|
|
647
683
|
echo ""
|
|
648
684
|
echo "Modernize:"
|
|
649
|
-
echo "
|
|
685
|
+
echo " modernize [cmd] Legacy modernization: heal|migrate"
|
|
650
686
|
echo ""
|
|
651
687
|
echo "Config:"
|
|
652
688
|
echo " config [cmd] Manage configuration + provider (show|set|get|provider)"
|
|
@@ -656,10 +692,10 @@ show_help() {
|
|
|
656
692
|
echo " help Show this help ('loki help aliases' for old names)"
|
|
657
693
|
echo ""
|
|
658
694
|
echo "More commands (init, watch, demo, web, api, logs, github,"
|
|
659
|
-
echo "import, council, proof, audit, agent, template, magic,
|
|
660
|
-
echo "
|
|
661
|
-
echo "
|
|
662
|
-
echo "
|
|
695
|
+
echo "import, council, proof, audit, agent, template, magic, docs, wiki, ci,"
|
|
696
|
+
echo "test, bench, secrets, telemetry, crash, worktree, failover, monitor,"
|
|
697
|
+
echo "remote, ...) are dispatchable and documented via"
|
|
698
|
+
echo "'loki <command> --help'."
|
|
663
699
|
echo ""
|
|
664
700
|
echo "Aliases (deprecated): older command names still work; they print a"
|
|
665
701
|
echo "one-line pointer to stderr and never alter --json output. See the full"
|
|
@@ -710,7 +746,7 @@ show_help() {
|
|
|
710
746
|
echo " # Session ops + observability"
|
|
711
747
|
echo " loki status [--json] # Current status"
|
|
712
748
|
echo " loki report session --efficiency # Token + cost stats"
|
|
713
|
-
echo " loki kpis [--json]
|
|
749
|
+
echo " loki report kpis [--json] # Accuracy + efficiency KPI snapshot"
|
|
714
750
|
echo " loki doctor [--json] # System prereq + skill symlinks"
|
|
715
751
|
echo " loki logs # Tail recent log output"
|
|
716
752
|
echo " loki report export json|markdown|csv|timeline # Export session"
|
|
@@ -783,9 +819,18 @@ show_help_aliases() {
|
|
|
783
819
|
echo " export report export"
|
|
784
820
|
echo " share report share"
|
|
785
821
|
echo " dogfood report dogfood"
|
|
822
|
+
echo " kpis report kpis"
|
|
786
823
|
echo " trust-metrics trust detail"
|
|
824
|
+
echo " compound memory compound"
|
|
825
|
+
echo " explain analyze explain"
|
|
826
|
+
echo " onboard analyze onboard"
|
|
827
|
+
echo " code analyze code"
|
|
828
|
+
echo " context analyze context"
|
|
829
|
+
echo " ctx analyze context"
|
|
830
|
+
echo " heal modernize heal"
|
|
831
|
+
echo " migrate modernize migrate"
|
|
787
832
|
echo ""
|
|
788
|
-
echo "More groupings (ui,
|
|
833
|
+
echo "More groupings (ui, new, admin) land in later Phase B slices."
|
|
789
834
|
echo "See internal/CLI-CONSOLIDATION-DESIGN.md for the full migration plan."
|
|
790
835
|
}
|
|
791
836
|
|
|
@@ -11843,6 +11888,37 @@ cmd_heal_help() {
|
|
|
11843
11888
|
echo " loki heal --friction-map ./legacy-app # View friction map"
|
|
11844
11889
|
}
|
|
11845
11890
|
|
|
11891
|
+
# CLI consolidation (Phase B, design item 6): the 'modernize' noun groups the
|
|
11892
|
+
# legacy-modernization surface (heal/migrate) under one entry. It is a THIN
|
|
11893
|
+
# dispatcher: each arm forwards verbatim to the existing cmd_* handler (no
|
|
11894
|
+
# handler logic moves; heal and migrate keep their separate phase vocabularies
|
|
11895
|
+
# and state). The two top-level tokens remain deprecated forwarding aliases.
|
|
11896
|
+
cmd_modernize() {
|
|
11897
|
+
local subcommand="${1:-help}"
|
|
11898
|
+
case "$subcommand" in
|
|
11899
|
+
heal) shift; cmd_heal "$@"; return $? ;;
|
|
11900
|
+
migrate) shift; cmd_migrate "$@"; return $? ;;
|
|
11901
|
+
--help|-h|help)
|
|
11902
|
+
echo -e "${BOLD}loki modernize${NC} - Legacy system modernization"
|
|
11903
|
+
echo ""
|
|
11904
|
+
echo "Usage: loki modernize <subcommand> [args]"
|
|
11905
|
+
echo ""
|
|
11906
|
+
echo "Subcommands (grouped modernization surface):"
|
|
11907
|
+
echo " heal <path> Legacy system healing in phases (was: loki heal)"
|
|
11908
|
+
echo " migrate <path> Codebase migration in phases (was: loki migrate)"
|
|
11909
|
+
echo ""
|
|
11910
|
+
echo "Run 'loki modernize <subcommand> --help' for each. The old"
|
|
11911
|
+
echo "top-level names still work; see 'loki help aliases'."
|
|
11912
|
+
return 0
|
|
11913
|
+
;;
|
|
11914
|
+
*)
|
|
11915
|
+
echo -e "${RED}Unknown modernize command: $subcommand${NC}" >&2
|
|
11916
|
+
echo "Run 'loki modernize --help' for usage." >&2
|
|
11917
|
+
return 1
|
|
11918
|
+
;;
|
|
11919
|
+
esac
|
|
11920
|
+
}
|
|
11921
|
+
|
|
11846
11922
|
cmd_heal() {
|
|
11847
11923
|
local codebase_path=""
|
|
11848
11924
|
local phase="${LOKI_HEAL_PHASE:-archaeology}"
|
|
@@ -13192,10 +13268,26 @@ def _loki_norm_alias(raw):
|
|
|
13192
13268
|
raw = (raw or '').strip().lower()
|
|
13193
13269
|
return raw if raw in ('haiku', 'sonnet', 'opus', 'fable') else ''
|
|
13194
13270
|
|
|
13271
|
+
# Session-pin normalization is BROADER than the override-file allowlist above.
|
|
13272
|
+
# run.sh's session-pin case (run.sh:12331) accepts the four model aliases AND
|
|
13273
|
+
# the three raw tier names (planning|development|fast) -- documented at
|
|
13274
|
+
# skills/model-selection.md:8 -- mapping each through resolve_model_for_tier.
|
|
13275
|
+
# The OVERRIDE file path (_loki_norm_alias) stays narrow because that value is
|
|
13276
|
+
# fed straight to 'claude --model', where tier names are not valid. The session
|
|
13277
|
+
# pin is a tier route, so tier names ARE valid pins. This normalizer mirrors
|
|
13278
|
+
# run.sh's trim+lowercase (interior whitespace preserved, so 'fab le' stays junk
|
|
13279
|
+
# and falls through to the default tier exactly like the runner's '*' arm).
|
|
13280
|
+
def _loki_norm_session_pin(raw):
|
|
13281
|
+
raw = (raw or '').strip().lower()
|
|
13282
|
+
return raw if raw in (
|
|
13283
|
+
'haiku', 'sonnet', 'opus', 'fable',
|
|
13284
|
+
'planning', 'development', 'fast',
|
|
13285
|
+
) else ''
|
|
13286
|
+
|
|
13195
13287
|
# session_model_env starts from LOKI_SESSION_MODEL; track the lever that set it
|
|
13196
13288
|
# so the provenance line names the real source (never a false attribution).
|
|
13197
13289
|
_session_model_source = 'LOKI_SESSION_MODEL'
|
|
13198
|
-
session_model_env =
|
|
13290
|
+
session_model_env = _loki_norm_session_pin(os.environ.get('LOKI_SESSION_MODEL', '')) or 'sonnet'
|
|
13199
13291
|
|
|
13200
13292
|
_fable_override = ''
|
|
13201
13293
|
try:
|
|
@@ -13246,6 +13338,13 @@ def _provider_model_development():
|
|
|
13246
13338
|
return (os.environ.get('LOKI_CLAUDE_MODEL_DEVELOPMENT')
|
|
13247
13339
|
or os.environ.get('LOKI_MODEL_DEVELOPMENT')
|
|
13248
13340
|
or ('sonnet' if _allow_haiku else 'opus'))
|
|
13341
|
+
def _provider_model_planning():
|
|
13342
|
+
# claude.sh:65 -> LOKI_CLAUDE_MODEL_PLANNING > LOKI_MODEL_PLANNING > opus.
|
|
13343
|
+
# CLAUDE_DEFAULT_PLANNING is always opus (LOKI_ALLOW_HAIKU only lowers the
|
|
13344
|
+
# development and fast defaults, not planning).
|
|
13345
|
+
return (os.environ.get('LOKI_CLAUDE_MODEL_PLANNING')
|
|
13346
|
+
or os.environ.get('LOKI_MODEL_PLANNING')
|
|
13347
|
+
or 'opus')
|
|
13249
13348
|
_max_tier = (os.environ.get('LOKI_MAX_TIER', '') or '').strip().lower()
|
|
13250
13349
|
def _loki_clamp_alias(alias):
|
|
13251
13350
|
if not _max_tier:
|
|
@@ -13259,14 +13358,96 @@ def _loki_clamp_alias(alias):
|
|
|
13259
13358
|
if _max_tier == 'opus':
|
|
13260
13359
|
return 'opus' if alias == 'fable' else alias
|
|
13261
13360
|
return alias
|
|
13262
|
-
|
|
13263
|
-
|
|
13264
|
-
|
|
13265
|
-
|
|
13266
|
-
|
|
13267
|
-
|
|
13268
|
-
|
|
13269
|
-
|
|
13361
|
+
|
|
13362
|
+
# Session-pin tier route (the runner's NO-OVERRIDE path). When there is no
|
|
13363
|
+
# mid-flight override file, the runner does NOT feed the session alias straight
|
|
13364
|
+
# to --model. It maps the alias to an abstract TIER (run.sh:12331 -- opus->
|
|
13365
|
+
# planning, sonnet->development, haiku->fast, fable->fable) and resolves that
|
|
13366
|
+
# tier through resolve_model_for_tier (claude.sh:353), which reads
|
|
13367
|
+
# PROVIDER_MODEL_PLANNING/DEVELOPMENT/FAST and then applies
|
|
13368
|
+
# loki_apply_max_tier_clamp(model, REAL_tier). This DIFFERS from the override-
|
|
13369
|
+
# path clamp _loki_clamp_alias above: a 'sonnet' SESSION pin dispatches OPUS
|
|
13370
|
+
# (development tier -> PROVIDER_MODEL_DEVELOPMENT=opus on stock config), whereas
|
|
13371
|
+
# a 'sonnet' OVERRIDE file dispatches sonnet (alias fed straight to --model).
|
|
13372
|
+
# Quoting the alias name on the default session path was the task-568 gap (it
|
|
13373
|
+
# understated cost ~1.7x: Sonnet quote vs Opus dispatch). The estimator must
|
|
13374
|
+
# quote the model the runner actually dispatches.
|
|
13375
|
+
#
|
|
13376
|
+
# SYNC: byte-faithful with run.sh's session-pin case + claude.sh
|
|
13377
|
+
# resolve_model_for_tier + loki_apply_max_tier_clamp. The same resolver lives in
|
|
13378
|
+
# the dashboard (dashboard/server.py _resolve_session_pin). Locked by the
|
|
13379
|
+
# session-pin parity matrix and the no-cap stock cross-route cases in
|
|
13380
|
+
# tests/test-model-override.sh.
|
|
13381
|
+
def _resolve_session_pin(alias):
|
|
13382
|
+
# alias -> abstract tier (run.sh:12331). Unknown -> development (the runner's
|
|
13383
|
+
# '*' arm passes CURRENT_TIER through to resolve_model_for_tier, whose '*'
|
|
13384
|
+
# default is PROVIDER_MODEL_DEVELOPMENT, i.e. the development tier).
|
|
13385
|
+
_pin_tier = {
|
|
13386
|
+
'opus': 'planning',
|
|
13387
|
+
'sonnet': 'development',
|
|
13388
|
+
'haiku': 'fast',
|
|
13389
|
+
'fable': 'fable',
|
|
13390
|
+
# Raw tier-name pins (run.sh:12336 passthrough arm) map to their own
|
|
13391
|
+
# tier, NOT through the alias table. So pin=fast -> fast tier ->
|
|
13392
|
+
# PROVIDER_MODEL_FAST (sonnet stock / haiku ALLOW_HAIKU), matching the
|
|
13393
|
+
# runner's dispatch instead of collapsing onto development.
|
|
13394
|
+
'planning': 'planning',
|
|
13395
|
+
'development': 'development',
|
|
13396
|
+
'fast': 'fast',
|
|
13397
|
+
}.get(alias, 'development')
|
|
13398
|
+
# tier -> model (claude.sh resolve_model_for_tier explicit arms).
|
|
13399
|
+
if _pin_tier == 'planning':
|
|
13400
|
+
_m = _provider_model_planning()
|
|
13401
|
+
elif _pin_tier == 'fast':
|
|
13402
|
+
_m = _provider_model_fast()
|
|
13403
|
+
elif _pin_tier == 'fable':
|
|
13404
|
+
_m = 'fable'
|
|
13405
|
+
else: # development (and the '*' fallthrough)
|
|
13406
|
+
_m = _provider_model_development()
|
|
13407
|
+
# Apply the shared LOKI_MAX_TIER clamp with the REAL tier and resolved model
|
|
13408
|
+
# (loki_apply_max_tier_clamp(model, tier)), NOT the alias==alias override
|
|
13409
|
+
# convention. This is the one place where the two paths legitimately diverge
|
|
13410
|
+
# (e.g. opus pin + sonnet cap + ALLOW_HAIKU: tier route -> sonnet, because the
|
|
13411
|
+
# planning tier downgrades to PROVIDER_MODEL_DEVELOPMENT=sonnet).
|
|
13412
|
+
if not _max_tier:
|
|
13413
|
+
return _m
|
|
13414
|
+
if _max_tier == 'haiku':
|
|
13415
|
+
return _provider_model_fast()
|
|
13416
|
+
if _max_tier == 'sonnet':
|
|
13417
|
+
if _pin_tier in ('planning', 'fable') or _m == 'fable':
|
|
13418
|
+
return _provider_model_development()
|
|
13419
|
+
return _m
|
|
13420
|
+
if _max_tier == 'opus':
|
|
13421
|
+
return 'opus' if _m == 'fable' else _m
|
|
13422
|
+
return _m
|
|
13423
|
+
# Resolve the model the runner will ACTUALLY dispatch for the pinned session,
|
|
13424
|
+
# choosing the correct route:
|
|
13425
|
+
# - OVERRIDE file present: the runner feeds the alias straight to --model via
|
|
13426
|
+
# loki_apply_max_tier_clamp(alias, alias). Use _loki_clamp_alias (the
|
|
13427
|
+
# override-path clamp). A 'sonnet' override dispatches sonnet.
|
|
13428
|
+
# - No override (session pin): the runner maps alias -> tier ->
|
|
13429
|
+
# resolve_model_for_tier -> clamp(model, real_tier). Use _resolve_session_pin.
|
|
13430
|
+
# A 'sonnet' session pin dispatches OPUS (development tier).
|
|
13431
|
+
# This is the task-568 fix: price the actually-dispatched model on BOTH routes.
|
|
13432
|
+
_is_override = (_session_model_source == '.loki/state/model-override')
|
|
13433
|
+
if _is_override:
|
|
13434
|
+
_dispatched_model = _loki_clamp_alias(session_model_env)
|
|
13435
|
+
else:
|
|
13436
|
+
_dispatched_model = _resolve_session_pin(session_model_env)
|
|
13437
|
+
|
|
13438
|
+
# Keep session_model_env (the alias) for token-volume tier mapping and provenance,
|
|
13439
|
+
# but record when the cost ceiling actually changed the dispatched model so the
|
|
13440
|
+
# provenance line is honest about the clamp.
|
|
13441
|
+
if _max_tier and _dispatched_model != session_model_env:
|
|
13442
|
+
_session_model_source = 'LOKI_MAX_TIER (clamped)'
|
|
13443
|
+
# Clear the architect-fable disclosure when the ceiling would clamp the architect
|
|
13444
|
+
# iteration too. This is INDEPENDENT of whether the session model itself changed:
|
|
13445
|
+
# e.g. an opus pin under a sonnet cap leaves the session model opus (no change),
|
|
13446
|
+
# but the iter-0 fable architect tier still clamps down to development. Nesting
|
|
13447
|
+
# this under the session-changed branch would over-quote a Fable iteration the
|
|
13448
|
+
# runner actually dispatches as opus (estimator-vs-runner divergence).
|
|
13449
|
+
if _max_tier and _fable_architect and _loki_clamp_alias('fable') != 'fable':
|
|
13450
|
+
_fable_architect = False
|
|
13270
13451
|
|
|
13271
13452
|
# v7.29.0: Honor LOKI_COMPLEXITY -- the SAME env var the runner honors at
|
|
13272
13453
|
# run.sh:920 -- so a forced-tier run (e.g. 'loki demo' / 'loki start --simple'
|
|
@@ -13282,16 +13463,31 @@ forced_complexity = {'standard': 'moderate'}.get(_forced_complexity_raw, _forced
|
|
|
13282
13463
|
if forced_complexity not in ('simple', 'moderate', 'complex', 'enterprise'):
|
|
13283
13464
|
forced_complexity = ''
|
|
13284
13465
|
|
|
13285
|
-
# Map session model name to tier key used in tokens_per_tier below.
|
|
13286
|
-
#
|
|
13466
|
+
# Map session model name to tier key used in tokens_per_tier below. This keys the
|
|
13467
|
+
# token VOLUME per iteration off the work tier the session pin selects (e.g. a
|
|
13468
|
+
# sonnet pin = the development tier = 80k/15k tokens). It does NOT decide the
|
|
13469
|
+
# priced model: that is _dispatched_model, the model the runner actually invokes.
|
|
13470
|
+
# Unknown models fall through to 'development' as a safe default.
|
|
13287
13471
|
_session_tier_map = {
|
|
13288
13472
|
'fable': 'advisor',
|
|
13289
13473
|
'opus': 'planning',
|
|
13290
13474
|
'sonnet': 'development',
|
|
13291
13475
|
'haiku': 'fast',
|
|
13476
|
+
# Raw tier-name pins key off their own work tier directly (they ARE tier
|
|
13477
|
+
# names), mirroring run.sh's session-pin passthrough arm.
|
|
13478
|
+
'planning': 'planning',
|
|
13479
|
+
'development': 'development',
|
|
13480
|
+
'fast': 'fast',
|
|
13292
13481
|
}
|
|
13293
13482
|
session_tier = _session_tier_map.get(session_model_env, 'development')
|
|
13294
13483
|
|
|
13484
|
+
# Pricing-table key (Fable/Opus/Sonnet/Haiku) for the model the runner dispatches.
|
|
13485
|
+
# The loop below uses tokens_per_tier[tier] for token VOLUME but prices by this
|
|
13486
|
+
# model, so the quote reflects the actually-dispatched model on every route.
|
|
13487
|
+
_PRICED_MODEL_KEY = {'fable': 'Fable', 'opus': 'Opus', 'sonnet': 'Sonnet', 'haiku': 'Haiku'}
|
|
13488
|
+
def _priced_model_for(alias):
|
|
13489
|
+
return _PRICED_MODEL_KEY.get((alias or '').strip().lower(), 'Opus')
|
|
13490
|
+
|
|
13295
13491
|
# Colors (disabled for JSON mode)
|
|
13296
13492
|
if show_json:
|
|
13297
13493
|
RED = GREEN = YELLOW = BLUE = CYAN = BOLD = DIM = NC = ''
|
|
@@ -13524,7 +13720,19 @@ for i in range(estimated_iterations):
|
|
|
13524
13720
|
tier = 'advisor'
|
|
13525
13721
|
|
|
13526
13722
|
info = tokens_per_tier[tier]
|
|
13527
|
-
|
|
13723
|
+
# Token VOLUME comes from the work tier (info), but the priced MODEL is the
|
|
13724
|
+
# model the runner actually dispatches. In legacy rotation the per-tier model
|
|
13725
|
+
# IS the dispatched model. In session-pinned mode (the default) the runner
|
|
13726
|
+
# resolves the pin through provider config (_dispatched_model): a sonnet pin
|
|
13727
|
+
# dispatches opus, so we price Opus, not the tier's static 'Sonnet' label.
|
|
13728
|
+
# The fable-architect iteration 0 genuinely dispatches fable (already cap-
|
|
13729
|
+
# cleared above when it would clamp), so it keeps the advisor tier's Fable.
|
|
13730
|
+
if legacy_tier_switching:
|
|
13731
|
+
model = info['model']
|
|
13732
|
+
elif _fable_architect and i == 0:
|
|
13733
|
+
model = info['model'] # advisor tier -> Fable
|
|
13734
|
+
else:
|
|
13735
|
+
model = _priced_model_for(_dispatched_model)
|
|
13528
13736
|
inp = info['input']
|
|
13529
13737
|
out = info['output']
|
|
13530
13738
|
|
|
@@ -13719,8 +13927,14 @@ else:
|
|
|
13719
13927
|
print(' Model distribution: ' + (' | '.join(pinned_parts) if pinned_parts else '(none)'))
|
|
13720
13928
|
# Provenance: name the lever that actually selected the pinned model, never a
|
|
13721
13929
|
# false attribution. _session_model_source is the real source (env, override
|
|
13722
|
-
# file, or maxTier clamp) tracked at selection time.
|
|
13723
|
-
|
|
13930
|
+
# file, or maxTier clamp) tracked at selection time. When the session pin is a
|
|
13931
|
+
# tier alias that resolves to a DIFFERENT dispatched model (the default: a
|
|
13932
|
+
# 'sonnet' pin -> development tier -> opus), show the resolution so the
|
|
13933
|
+
# distribution above (Opus x4) is legible against the pin name (sonnet).
|
|
13934
|
+
if (not _is_override) and _dispatched_model != session_model_env:
|
|
13935
|
+
print(f' {DIM}(pinned via {_session_model_source}={session_model_env} -> {session_tier} tier -> {_dispatched_model}; set LOKI_LEGACY_TIER_SWITCHING=true to rotate){NC}')
|
|
13936
|
+
else:
|
|
13937
|
+
print(f' {DIM}(pinned via {_session_model_source}={session_model_env}; set LOKI_LEGACY_TIER_SWITCHING=true to rotate){NC}')
|
|
13724
13938
|
if _fable_architect:
|
|
13725
13939
|
print(f' {DIM}(+ 1 architecture iteration on Fable via LOKI_FABLE_ARCHITECT=1){NC}')
|
|
13726
13940
|
if fable_n > 0:
|
|
@@ -14052,7 +14266,9 @@ main() {
|
|
|
14052
14266
|
cmd_memory "$@"
|
|
14053
14267
|
;;
|
|
14054
14268
|
compound)
|
|
14055
|
-
|
|
14269
|
+
# CLI consolidation (Phase B): 'compound' -> 'memory compound'.
|
|
14270
|
+
_deprecated_alias compound "memory compound" "$@"
|
|
14271
|
+
cmd_memory compound "$@"
|
|
14056
14272
|
;;
|
|
14057
14273
|
checkpoint|cp)
|
|
14058
14274
|
# CLI consolidation (Phase A): 'cp' is a deprecated alias of 'checkpoint'.
|
|
@@ -14107,8 +14323,13 @@ main() {
|
|
|
14107
14323
|
optimize)
|
|
14108
14324
|
cmd_optimize "$@"
|
|
14109
14325
|
;;
|
|
14326
|
+
modernize)
|
|
14327
|
+
cmd_modernize "$@"
|
|
14328
|
+
;;
|
|
14110
14329
|
heal)
|
|
14111
|
-
|
|
14330
|
+
# CLI consolidation (Phase B): 'heal' -> 'modernize heal'.
|
|
14331
|
+
_deprecated_alias heal "modernize heal" "$@"
|
|
14332
|
+
cmd_modernize heal "$@"
|
|
14112
14333
|
;;
|
|
14113
14334
|
verify)
|
|
14114
14335
|
cmd_verify "$@"
|
|
@@ -14123,7 +14344,9 @@ main() {
|
|
|
14123
14344
|
cmd_mcp "$@"
|
|
14124
14345
|
;;
|
|
14125
14346
|
migrate)
|
|
14126
|
-
|
|
14347
|
+
# CLI consolidation (Phase B): 'migrate' -> 'modernize migrate'.
|
|
14348
|
+
_deprecated_alias migrate "modernize migrate" "$@"
|
|
14349
|
+
cmd_modernize migrate "$@"
|
|
14127
14350
|
;;
|
|
14128
14351
|
cluster)
|
|
14129
14352
|
cmd_cluster "$@"
|
|
@@ -14182,11 +14405,18 @@ main() {
|
|
|
14182
14405
|
failover)
|
|
14183
14406
|
cmd_failover "$@"
|
|
14184
14407
|
;;
|
|
14408
|
+
analyze)
|
|
14409
|
+
cmd_analyze "$@"
|
|
14410
|
+
;;
|
|
14185
14411
|
onboard)
|
|
14186
|
-
|
|
14412
|
+
# CLI consolidation (Phase B): 'onboard' -> 'analyze onboard'.
|
|
14413
|
+
_deprecated_alias onboard "analyze onboard" "$@"
|
|
14414
|
+
cmd_analyze onboard "$@"
|
|
14187
14415
|
;;
|
|
14188
14416
|
explain)
|
|
14189
|
-
|
|
14417
|
+
# CLI consolidation (Phase B): 'explain' -> 'analyze explain'.
|
|
14418
|
+
_deprecated_alias explain "analyze explain" "$@"
|
|
14419
|
+
cmd_analyze explain "$@"
|
|
14190
14420
|
;;
|
|
14191
14421
|
docs)
|
|
14192
14422
|
cmd_docs "$@"
|
|
@@ -14221,10 +14451,15 @@ main() {
|
|
|
14221
14451
|
cmd_bench "$@"
|
|
14222
14452
|
;;
|
|
14223
14453
|
context|ctx)
|
|
14224
|
-
|
|
14454
|
+
# CLI consolidation (Phase B): 'context' (and short alias 'ctx')
|
|
14455
|
+
# -> 'analyze context'.
|
|
14456
|
+
_deprecated_alias "$command" "analyze context" "$@"
|
|
14457
|
+
cmd_analyze context "$@"
|
|
14225
14458
|
;;
|
|
14226
14459
|
code)
|
|
14227
|
-
|
|
14460
|
+
# CLI consolidation (Phase B): 'code' -> 'analyze code'.
|
|
14461
|
+
_deprecated_alias code "analyze code" "$@"
|
|
14462
|
+
cmd_analyze code "$@"
|
|
14228
14463
|
;;
|
|
14229
14464
|
version|--version|-v)
|
|
14230
14465
|
cmd_version "$@"
|
|
@@ -14233,20 +14468,14 @@ main() {
|
|
|
14233
14468
|
cmd_completions "$@"
|
|
14234
14469
|
;;
|
|
14235
14470
|
kpis)
|
|
14236
|
-
#
|
|
14237
|
-
#
|
|
14238
|
-
#
|
|
14239
|
-
#
|
|
14240
|
-
#
|
|
14241
|
-
#
|
|
14242
|
-
|
|
14243
|
-
|
|
14244
|
-
printf '{"available": false, "reason": "loki kpis requires the Bun runtime; it is not implemented on the bash (LOKI_LEGACY_BASH) route"}\n'
|
|
14245
|
-
else
|
|
14246
|
-
echo "loki kpis requires the Bun runtime and is not available on the bash route." >&2
|
|
14247
|
-
echo "Remove LOKI_LEGACY_BASH=1 (or install Bun: https://bun.sh) to use 'loki kpis'." >&2
|
|
14248
|
-
fi
|
|
14249
|
-
exit 1
|
|
14471
|
+
# CLI consolidation (Phase B): `kpis` is a deprecated alias of the
|
|
14472
|
+
# canonical `report kpis`. Emit the one-line pointer (suppressed
|
|
14473
|
+
# under --json/-q/--quiet by _deprecated_alias), then print the
|
|
14474
|
+
# honest Bun-requirement message via the shared helper. On a machine
|
|
14475
|
+
# WITH Bun, bin/loki routes `kpis` to the Bun runtime before this arm
|
|
14476
|
+
# is ever reached; this arm is the LOKI_LEGACY_BASH / no-Bun path.
|
|
14477
|
+
_deprecated_alias kpis "report kpis" "$@"
|
|
14478
|
+
_kpis_bash_unavailable "$@"
|
|
14250
14479
|
;;
|
|
14251
14480
|
help|--help|-h)
|
|
14252
14481
|
# CLI consolidation (Phase A): `loki help aliases` prints the full
|
|
@@ -16571,6 +16800,7 @@ except Exception as e:
|
|
|
16571
16800
|
echo " export [file] Export to JSON file"
|
|
16572
16801
|
echo " dedupe Remove duplicate entries"
|
|
16573
16802
|
echo " clear [type] Clear learnings (all or specific type)"
|
|
16803
|
+
echo " compound [cmd] Compound-solutions knowledge store (was: loki compound)"
|
|
16574
16804
|
echo ""
|
|
16575
16805
|
echo "Memory System Commands:"
|
|
16576
16806
|
echo " index [rebuild] Show or rebuild the memory index layer"
|
|
@@ -16938,9 +17168,24 @@ print('removed')
|
|
|
16938
17168
|
"
|
|
16939
17169
|
;;
|
|
16940
17170
|
|
|
17171
|
+
compound)
|
|
17172
|
+
# CLI consolidation (Phase B, design item 7): 'compound' is folded
|
|
17173
|
+
# under the 'memory' noun as 'memory compound'. This arm forwards to
|
|
17174
|
+
# the existing cmd_compound handler unchanged (no handler logic
|
|
17175
|
+
# moves). The top-level 'compound' token stays a deprecated
|
|
17176
|
+
# forwarding alias for back-compat. cmd_memory does not shift before
|
|
17177
|
+
# the case, so $@ here is still 'compound <args>'; drop the leading
|
|
17178
|
+
# 'compound' token, then forward the rest verbatim.
|
|
17179
|
+
shift 2>/dev/null || true
|
|
17180
|
+
cmd_compound "$@"
|
|
17181
|
+
;;
|
|
17182
|
+
|
|
16941
17183
|
*)
|
|
16942
|
-
|
|
16943
|
-
|
|
17184
|
+
# Error-channel parity with the consolidated noun family (analyze,
|
|
17185
|
+
# modernize): unknown-subcommand diagnostics go to STDERR so a scripted
|
|
17186
|
+
# consumer capturing stdout is not handed error text. Exit 1 unchanged.
|
|
17187
|
+
echo -e "${RED}Unknown memory command: $subcommand${NC}" >&2
|
|
17188
|
+
echo "Run 'loki memory help' for usage." >&2
|
|
16944
17189
|
exit 1
|
|
16945
17190
|
;;
|
|
16946
17191
|
esac
|
|
@@ -17191,13 +17436,13 @@ COMPOUND_RUN_SCRIPT
|
|
|
17191
17436
|
;;
|
|
17192
17437
|
|
|
17193
17438
|
help|--help|-h)
|
|
17194
|
-
echo -e "${BOLD}loki compound${NC} - Knowledge compounding system"
|
|
17439
|
+
echo -e "${BOLD}loki memory compound${NC} - Knowledge compounding system"
|
|
17195
17440
|
echo ""
|
|
17196
17441
|
echo "Extracts structured solutions from cross-project learnings."
|
|
17197
17442
|
echo "Solutions are stored as markdown files with YAML frontmatter"
|
|
17198
17443
|
echo "at ~/.loki/solutions/{category}/ and fed back into future planning."
|
|
17199
17444
|
echo ""
|
|
17200
|
-
echo "Usage: loki compound <command>"
|
|
17445
|
+
echo "Usage: loki memory compound <command> (alias: loki compound)"
|
|
17201
17446
|
echo ""
|
|
17202
17447
|
echo "Commands:"
|
|
17203
17448
|
echo " list List all solutions by category"
|
|
@@ -20268,6 +20513,41 @@ METRICS_SCRIPT
|
|
|
20268
20513
|
fi
|
|
20269
20514
|
}
|
|
20270
20515
|
|
|
20516
|
+
# CLI consolidation (Phase B, design item 8): the 'analyze' noun groups the
|
|
20517
|
+
# repo-intelligence surface (explain/onboard/code/context) under one entry. It
|
|
20518
|
+
# is a THIN dispatcher: every arm forwards verbatim to the existing cmd_*
|
|
20519
|
+
# handler (no handler logic moves). The four top-level tokens remain deprecated
|
|
20520
|
+
# forwarding aliases for back-compat.
|
|
20521
|
+
cmd_analyze() {
|
|
20522
|
+
local subcommand="${1:-help}"
|
|
20523
|
+
case "$subcommand" in
|
|
20524
|
+
explain) shift; cmd_explain "$@"; return $? ;;
|
|
20525
|
+
onboard) shift; cmd_onboard "$@"; return $? ;;
|
|
20526
|
+
code) shift; cmd_code "$@"; return $? ;;
|
|
20527
|
+
context) shift; cmd_context "$@"; return $? ;;
|
|
20528
|
+
--help|-h|help)
|
|
20529
|
+
echo -e "${BOLD}loki analyze${NC} - Project knowledge and codebase intelligence"
|
|
20530
|
+
echo ""
|
|
20531
|
+
echo "Usage: loki analyze <subcommand> [args]"
|
|
20532
|
+
echo ""
|
|
20533
|
+
echo "Subcommands (grouped knowledge surface):"
|
|
20534
|
+
echo " explain [path] Explain a codebase architecture in prose (was: loki explain)"
|
|
20535
|
+
echo " onboard [path] Analyze a repo and generate CLAUDE.md (was: loki onboard)"
|
|
20536
|
+
echo " code [query] Codebase intelligence queries (was: loki code)"
|
|
20537
|
+
echo " context [cmd] Context-window management (was: loki context)"
|
|
20538
|
+
echo ""
|
|
20539
|
+
echo "Run 'loki analyze <subcommand> --help' for each. The old top-level"
|
|
20540
|
+
echo "names still work; see 'loki help aliases'."
|
|
20541
|
+
return 0
|
|
20542
|
+
;;
|
|
20543
|
+
*)
|
|
20544
|
+
echo -e "${RED}Unknown analyze command: $subcommand${NC}" >&2
|
|
20545
|
+
echo "Run 'loki analyze --help' for usage." >&2
|
|
20546
|
+
return 1
|
|
20547
|
+
;;
|
|
20548
|
+
esac
|
|
20549
|
+
}
|
|
20550
|
+
|
|
20271
20551
|
# Context window management (inspired by Kiro CLI /context command)
|
|
20272
20552
|
# Shows token usage breakdown and context window utilization
|
|
20273
20553
|
cmd_context() {
|
|
@@ -26251,6 +26531,44 @@ _test_gen_bats() {
|
|
|
26251
26531
|
# is emitted at the alias dispatch arm (main()), never here, so `report <sub>`
|
|
26252
26532
|
# stays clean.
|
|
26253
26533
|
cmd_report() {
|
|
26534
|
+
# CLI consolidation (Phase B): `report kpis` is the canonical KPI snapshot
|
|
26535
|
+
# entry. kpis is Bun-only; on a machine WITH Bun, bin/loki two-token-routes
|
|
26536
|
+
# `report kpis` (flag-anywhere) to the Bun runtime before this function is
|
|
26537
|
+
# reached. This is the bash-route (LOKI_LEGACY_BASH / no-Bun) path: print
|
|
26538
|
+
# the honest requirement message, NO deprecation pointer (this IS the
|
|
26539
|
+
# canonical form), exit 1. `kpis` is the report subcommand ONLY when it is the
|
|
26540
|
+
# FIRST non-flag token after `report` (so `report kpis --json` and `report
|
|
26541
|
+
# --json kpis` both route here, mirroring the bin/loki + Bun cli.ts routing),
|
|
26542
|
+
# NOT when it appears anywhere. A `kpis` token that is a positional VALUE of a
|
|
26543
|
+
# different report subcommand -- e.g. `report export json kpis`, where `kpis`
|
|
26544
|
+
# is the export OUTPUT FILENAME -- must NOT be hijacked; it falls through to
|
|
26545
|
+
# the export arm below and behaves exactly as on main (v7.31.0): exit 0, file
|
|
26546
|
+
# `kpis` created. Only the subcommand token is stripped before forwarding to
|
|
26547
|
+
# the helper; flags (e.g. --json) are passed through so it still emits the
|
|
26548
|
+
# structured machine payload.
|
|
26549
|
+
local _report_first_sub="" _kpis_args=() _dropped_kpis=""
|
|
26550
|
+
local _a
|
|
26551
|
+
for _a in "$@"; do
|
|
26552
|
+
case "$_a" in
|
|
26553
|
+
-*) _kpis_args+=("$_a") ;;
|
|
26554
|
+
*)
|
|
26555
|
+
if [ -z "$_report_first_sub" ]; then
|
|
26556
|
+
_report_first_sub="$_a"
|
|
26557
|
+
# Drop only the subcommand token itself, once.
|
|
26558
|
+
if [ "$_a" = "kpis" ]; then
|
|
26559
|
+
_dropped_kpis=1
|
|
26560
|
+
continue
|
|
26561
|
+
fi
|
|
26562
|
+
fi
|
|
26563
|
+
_kpis_args+=("$_a")
|
|
26564
|
+
;;
|
|
26565
|
+
esac
|
|
26566
|
+
done
|
|
26567
|
+
if [ -n "$_dropped_kpis" ]; then
|
|
26568
|
+
# ${arr[@]:-} guards the empty-array expansion under `set -u` on the
|
|
26569
|
+
# bare `report kpis` case (no extra flags) for older bash (3.2/4.2).
|
|
26570
|
+
_kpis_bash_unavailable "${_kpis_args[@]:-}"
|
|
26571
|
+
fi
|
|
26254
26572
|
case "${1:-}" in
|
|
26255
26573
|
session) shift; cmd_stats "$@"; return $? ;;
|
|
26256
26574
|
metrics) shift; cmd_metrics "$@"; return $? ;;
|
|
@@ -26283,6 +26601,7 @@ cmd_report_legacy() {
|
|
|
26283
26601
|
echo " session Session statistics (was: loki stats)"
|
|
26284
26602
|
echo " metrics Efficiency/reward metrics (was: loki metrics)"
|
|
26285
26603
|
echo " cost Token cost breakdown (was: loki cost)"
|
|
26604
|
+
echo " kpis Accuracy + efficiency KPI snapshot (was: loki kpis; Bun runtime only)"
|
|
26286
26605
|
echo " export Export session data (was: loki export) [json|markdown|csv|timeline]"
|
|
26287
26606
|
echo " share Share session assets (was: loki share)"
|
|
26288
26607
|
echo " dogfood Self-development stats (was: loki dogfood)"
|
|
@@ -26319,7 +26638,7 @@ cmd_report_legacy() {
|
|
|
26319
26638
|
--include-gates) include_gates=true; shift ;;
|
|
26320
26639
|
--include-agents) include_agents=true; shift ;;
|
|
26321
26640
|
--include-timeline) include_timeline=true; shift ;;
|
|
26322
|
-
*) echo -e "${RED}Unknown option: $1${NC}"; echo "Run 'loki report --help' for usage."; exit 1 ;;
|
|
26641
|
+
*) echo -e "${RED}Unknown option: $1${NC}" >&2; echo "Run 'loki report --help' for usage." >&2; exit 1 ;; # stderr for noun-family error-channel parity (analyze/modernize)
|
|
26323
26642
|
esac
|
|
26324
26643
|
done
|
|
26325
26644
|
|