loki-mode 8.8.1 → 8.9.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 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 v8.8.1
6
+ # Loki Mode v8.9.0
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -469,4 +469,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
469
469
 
470
470
  ---
471
471
 
472
- **v8.8.1 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
472
+ **v8.9.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~410 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 8.8.1
1
+ 8.9.0
package/autonomy/loki CHANGED
@@ -17629,12 +17629,37 @@ else:
17629
17629
  integrations.append(kw)
17630
17630
 
17631
17631
  # Count database mentions
17632
- db_keywords = ['postgresql', 'postgres', 'mysql', 'mongodb', 'sqlite',
17633
- 'dynamodb', 'cassandra', 'redis', 'prisma', 'typeorm',
17634
- 'sequelize', 'drizzle', 'knex', 'database', 'migration']
17635
- for kw in db_keywords:
17636
- if kw in content_lower:
17637
- databases.append(kw)
17632
+ # Count DISTINCT data stores. This feeds a +1-complexity-for-multiple
17633
+ # rule, so what counts as multiple is load-bearing: it pushed a
17634
+ # 322-word issue from moderate to complex, and complex means 18 iterations
17635
+ # instead of 9.
17636
+ #
17637
+ # Three ways the old flat list over-counted a single-database project:
17638
+ # 1. Aliases. 'postgresql' and 'postgres' were separate entries, so one
17639
+ # PostgreSQL app scored TWO data stores by itself. That alone tripped
17640
+ # the rule on a real user's issue.
17641
+ # 2. ORMs. prisma/typeorm/sequelize/drizzle/knex are ACCESS LAYERS, not
17642
+ # stores. Prisma plus PostgreSQL is one database, not two.
17643
+ # 3. Generic words. 'database' and 'migration' matched any PRD that used
17644
+ # the words at all, so a migration-to-the-database line scored two.
17645
+ #
17646
+ # Aliases collapse to one canonical name, ORMs and generic terms are gone.
17647
+ db_aliases = {
17648
+ 'postgresql': 'postgres', 'postgres': 'postgres', 'psql': 'postgres',
17649
+ 'mysql': 'mysql', 'mariadb': 'mysql',
17650
+ 'mongodb': 'mongodb', 'mongo': 'mongodb',
17651
+ 'sqlite': 'sqlite',
17652
+ 'dynamodb': 'dynamodb',
17653
+ 'cassandra': 'cassandra',
17654
+ 'redis': 'redis',
17655
+ 'elasticsearch': 'elasticsearch',
17656
+ 'clickhouse': 'clickhouse',
17657
+ }
17658
+ _seen_db = set()
17659
+ for kw, canonical in db_aliases.items():
17660
+ if kw in content_lower and canonical not in _seen_db:
17661
+ _seen_db.add(canonical)
17662
+ databases.append(canonical)
17638
17663
 
17639
17664
  # Count UI components
17640
17665
  ui_keywords = ['dashboard', 'form', 'table', 'modal', 'navbar',
@@ -17717,6 +17742,34 @@ iteration_map = {
17717
17742
  }
17718
17743
  min_iter, max_iter = iteration_map[complexity]
17719
17744
 
17745
+ # --- Capability-aware iteration budget ---------------------------------------
17746
+ # The map above was written when a model could not hold a whole feature in one
17747
+ # pass, so work was chopped into many small iterations. On a frontier tier that
17748
+ # is now actively harmful: each iteration boundary is a context reset, and
17749
+ # re-planning mid-feature is where a run loses the thread and burns money.
17750
+ #
17751
+ # A frontier model should be handed the whole job and left to finish it. So the
17752
+ # budget is divided by the capability tier the run will actually dispatch,
17753
+ # rather than assuming the weakest case for everyone. The floor is 1, never 0.
17754
+ #
17755
+ # This scales the ESTIMATE and the ceiling, not the work. A run that genuinely
17756
+ # needs more iterations still takes them; nothing here forces an early stop.
17757
+ _tier_raw = (os.environ.get('LOKI_SESSION_MODEL') or '').strip().lower()
17758
+ _frontier = ('high', 'planning', 'opus', 'sol')
17759
+ _small = ('small', 'fast', 'haiku', 'luna')
17760
+ if _tier_raw in _frontier:
17761
+ # Frontier: one pass for anything short of enterprise scope.
17762
+ min_iter = 1
17763
+ max_iter = max(1, max_iter // 4)
17764
+ elif _tier_raw in _small:
17765
+ # Small models genuinely benefit from more, smaller steps.
17766
+ pass
17767
+ else:
17768
+ # medium / unset: the common default. Halve the legacy budget -- current
17769
+ # workhorse models complete in far fewer passes than this map assumed.
17770
+ min_iter = max(1, min_iter // 2)
17771
+ max_iter = max(min_iter, max_iter // 2)
17772
+
17720
17773
  # Adjust based on specific counts
17721
17774
  if endpoint_count > 10:
17722
17775
  max_iter = max(max_iter, max_iter + endpoint_count // 5)
package/autonomy/run.sh CHANGED
@@ -630,6 +630,70 @@ PY
630
630
  export LOKI_SPEC_SHA256
631
631
  }
632
632
 
633
+ # Scoped-change profile: a bug fix or a single feature in an EXISTING repo.
634
+ #
635
+ # Measured on a real user's run: a 322-word GitHub issue against an existing
636
+ # codebase spent 25+ minutes still inside iteration 1. The work itself was
637
+ # genuine, but the build was also running competitor web research, load and
638
+ # performance testing, regression simulation and UAT -- all of which default to
639
+ # true, and none of which a scoped issue fix needs. That is the difference
640
+ # between a 5-minute fix and a 30-minute one.
641
+ #
642
+ # What this NEVER touches: code review, security, tests, E2E, and the
643
+ # completion council all stay on. Speed here comes from not running phases that
644
+ # are irrelevant to the change, never from skipping verification. A greenfield
645
+ # build or a whole-repo refactor does not match this profile and keeps the full
646
+ # suite.
647
+ #
648
+ # Auto-detected rather than another flag the user has to know: an existing git
649
+ # repo with real history, plus a spec that reads as a scoped change. Set
650
+ # LOKI_SCOPED_CHANGE=0 to force the full suite, or =1 to force this profile.
651
+ loki_detect_scoped_change() {
652
+ # Explicit operator intent always wins, in both directions.
653
+ case "${LOKI_SCOPED_CHANGE:-}" in
654
+ 0|false) return 1 ;;
655
+ 1|true) return 0 ;;
656
+ esac
657
+
658
+ # Greenfield is not a scoped change: no repo, or a repo with almost no
659
+ # history, means we are building something new.
660
+ local target="${TARGET_DIR:-.}"
661
+ [ -d "$target/.git" ] || return 1
662
+ local commits
663
+ commits="$(git -C "$target" rev-list --count HEAD 2>/dev/null || echo 0)"
664
+ [ "${commits:-0}" -ge 5 ] || return 1
665
+
666
+ # An issue-sourced spec is the canonical scoped change: someone filed a
667
+ # discrete request against code that already exists.
668
+ [ -n "${LOKI_ISSUE_REF:-}" ] && return 0
669
+ case "${LOKI_PRD_FILE:-}" in
670
+ *prd-issue-*) return 0 ;;
671
+ esac
672
+
673
+ return 1
674
+ }
675
+
676
+ loki_apply_scoped_change_profile() {
677
+ loki_detect_scoped_change || return 0
678
+
679
+ # Off: cannot affect the correctness of a scoped change to existing code.
680
+ : "${LOKI_PHASE_WEB_RESEARCH:=false}"
681
+ : "${LOKI_PHASE_PERFORMANCE:=false}"
682
+ : "${LOKI_PHASE_REGRESSION:=false}"
683
+ : "${LOKI_PHASE_UAT:=false}"
684
+
685
+ # On: every trust gate, unchanged. These are the moat.
686
+ : "${LOKI_PHASE_CODE_REVIEW:=true}"
687
+ : "${LOKI_PHASE_SECURITY:=true}"
688
+ : "${LOKI_PHASE_UNIT_TESTS:=true}"
689
+ : "${LOKI_PHASE_E2E_TESTS:=true}"
690
+
691
+ export LOKI_PHASE_WEB_RESEARCH LOKI_PHASE_PERFORMANCE LOKI_PHASE_REGRESSION
692
+ export LOKI_PHASE_UAT LOKI_PHASE_CODE_REVIEW LOKI_PHASE_SECURITY
693
+ export LOKI_PHASE_UNIT_TESTS LOKI_PHASE_E2E_TESTS
694
+ export LOKI_SCOPED_CHANGE_ACTIVE=1
695
+ }
696
+
633
697
  loki_apply_build_profile() {
634
698
  [ "${LOKI_BUILD_PROFILE:-}" = "simple-web" ] || return 0
635
699
  : "${LOKI_PHASE_API_TESTS:=false}"
@@ -772,6 +836,7 @@ print(catalog["providers"]["claude"]["cli_aliases"].get(os.environ["_LOKI_SELECT
772
836
  export LOKI_SDK_JUDGE_MODEL LOKI_SDK_PRD_ENRICH_MODEL LOKI_SDK_REVIEW_MODEL
773
837
  }
774
838
  loki_apply_build_profile
839
+ loki_apply_scoped_change_profile
775
840
 
776
841
  # Default hang guard for EVERY build, not just simple-web.
777
842
  #
@@ -7,7 +7,7 @@ Modules:
7
7
  control: Session control API (start/stop/pause/resume)
8
8
  """
9
9
 
10
- __version__ = "8.8.1"
10
+ __version__ = "8.9.0"
11
11
 
12
12
  # Expose the control app for easy import
13
13
  try: