loki-mode 7.46.0 → 7.47.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.
Files changed (84) hide show
  1. package/README.md +1 -1
  2. package/SKILL.md +2 -2
  3. package/VERSION +1 -1
  4. package/autonomy/completion-council.sh +113 -0
  5. package/autonomy/run.sh +90 -4
  6. package/autonomy/spec-interrogation.sh +549 -0
  7. package/dashboard/__init__.py +1 -1
  8. package/dashboard/auth.py +117 -2
  9. package/docs/ACKNOWLEDGEMENTS.md +1 -1
  10. package/docs/COMPETITIVE-ANALYSIS.md +1 -1
  11. package/docs/INSTALLATION.md +2 -2
  12. package/docs/OPEN-CORE-BOUNDARY.md +6 -5
  13. package/docs/P2-SPEC-ROBUSTNESS-PLAN.md +192 -0
  14. package/docs/R9-OPEN-CORE-HOOKS-PLAN.md +2 -2
  15. package/docs/auto-claude-comparison.md +2 -2
  16. package/docs/certification/README.md +1 -1
  17. package/docs/competitive/bolt-new-analysis.md +1 -1
  18. package/docs/competitive/emergence-others-analysis.md +6 -6
  19. package/docs/competitive/replit-lovable-analysis.md +4 -4
  20. package/docs/enterprise/security.md +43 -3
  21. package/docs/show-hn-post.md +1 -1
  22. package/loki-ts/dist/loki.js +2 -2
  23. package/mcp/__init__.py +1 -1
  24. package/package.json +1 -1
  25. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  26. package/web-app/dist/assets/{AdminPage-CKUOsWZW.js → AdminPage-CcCJ0Sjt.js} +1 -1
  27. package/web-app/dist/assets/{Avatar-CL9Id9Hi.js → Avatar-DK8kmayw.js} +1 -1
  28. package/web-app/dist/assets/{Badge-B12zwlD7.js → Badge-4uAWnemi.js} +1 -1
  29. package/web-app/dist/assets/{Button-CFLVoduT.js → Button-BBMk33tk.js} +1 -1
  30. package/web-app/dist/assets/ComparePage-bt9rwvST.js +1 -0
  31. package/web-app/dist/assets/{GitHubIssuesPanel-CSitxtAX.js → GitHubIssuesPanel-WDbH47UM.js} +1 -1
  32. package/web-app/dist/assets/{GitHubPRsPanel-BIT06FRo.js → GitHubPRsPanel-C2CiYtTx.js} +1 -1
  33. package/web-app/dist/assets/{HomePage-pU_0fGny.js → HomePage-BQk-MUjn.js} +4 -4
  34. package/web-app/dist/assets/{LoginPage-DTZtt2Yb.js → LoginPage-DMOZVGGL.js} +1 -1
  35. package/web-app/dist/assets/{MagicPage-10zfra8o.js → MagicPage-Bzp2Nt1z.js} +1 -1
  36. package/web-app/dist/assets/{MetricsPage-C-wiKUkv.js → MetricsPage-C39JVdsw.js} +1 -1
  37. package/web-app/dist/assets/{NotFoundPage-BDkcmhYe.js → NotFoundPage-6vT_U9UL.js} +1 -1
  38. package/web-app/dist/assets/{ProjectPage-CiCavQ8n.js → ProjectPage-BfFcZp-E.js} +3 -3
  39. package/web-app/dist/assets/{ProjectsPage-BLCXQwwC.js → ProjectsPage-CPMBf8Wt.js} +1 -1
  40. package/web-app/dist/assets/{SettingsPage-PkxtaMyg.js → SettingsPage-BnNN6ETl.js} +1 -1
  41. package/web-app/dist/assets/{ShowcasePage-iECp8Tha.js → ShowcasePage-WDrMf-cx.js} +1 -1
  42. package/web-app/dist/assets/{SystemSettingsPage-DS6Anno1.js → SystemSettingsPage-DX4jb2e8.js} +1 -1
  43. package/web-app/dist/assets/{TeamsPage-ls6h6bNL.js → TeamsPage-BCfqcXzu.js} +1 -1
  44. package/web-app/dist/assets/{TemplatesPage-Bk0QzlPt.js → TemplatesPage-CZvmimDj.js} +1 -1
  45. package/web-app/dist/assets/{TerminalOutput-4-1hWCtZ.js → TerminalOutput-BlRqFwWV.js} +1 -1
  46. package/web-app/dist/assets/{activity-DH3ih2nS.js → activity-CacZsUyr.js} +1 -1
  47. package/web-app/dist/assets/{bell-Gn17S6uv.js → bell-DK2qtHnk.js} +1 -1
  48. package/web-app/dist/assets/{bot-Cbycc3VE.js → bot-CkcUtHad.js} +1 -1
  49. package/web-app/dist/assets/{check-nIAqa-kf.js → check-CbCPjX3M.js} +1 -1
  50. package/web-app/dist/assets/{chevron-left-D2jcWDll.js → chevron-left-5NUKWw3i.js} +1 -1
  51. package/web-app/dist/assets/{circle-alert-CpL4Bhvt.js → circle-alert-S7uFoxC2.js} +1 -1
  52. package/web-app/dist/assets/{clock-IW4Wq86N.js → clock-CaQRrIrs.js} +1 -1
  53. package/web-app/dist/assets/{cloud-Cn8nNuH2.js → cloud-DBAX6c0r.js} +1 -1
  54. package/web-app/dist/assets/{code-xml-BiJBteXf.js → code-xml-De5-EXv3.js} +1 -1
  55. package/web-app/dist/assets/{copy-CnqkyNsi.js → copy-CUkT6k1v.js} +1 -1
  56. package/web-app/dist/assets/{database-CKSReqa5.js → database-BAWf1Gwt.js} +1 -1
  57. package/web-app/dist/assets/{dollar-sign-CDzDY64R.js → dollar-sign-Ji8zk86R.js} +1 -1
  58. package/web-app/dist/assets/{file-code-corner-Box4IwG1.js → file-code-corner-ChtXoBwS.js} +1 -1
  59. package/web-app/dist/assets/{file-plus-DpGqlXF8.js → file-plus-bFa37P76.js} +1 -1
  60. package/web-app/dist/assets/{folder-open-B57dAoBv.js → folder-open-DhXpXscO.js} +1 -1
  61. package/web-app/dist/assets/{git-commit-horizontal-BVbucmO5.js → git-commit-horizontal-DVPeDQ3j.js} +1 -1
  62. package/web-app/dist/assets/{globe-BkOnKl4x.js → globe-BPZgPeeu.js} +1 -1
  63. package/web-app/dist/assets/{hammer-DRbIQ4QU.js → hammer-jLCaujYH.js} +1 -1
  64. package/web-app/dist/assets/{index-CM_b_EhP.js → index-B-0iHBPO.js} +2 -2
  65. package/web-app/dist/assets/{layers-B78BiFiU.js → layers-B1vsrsFW.js} +1 -1
  66. package/web-app/dist/assets/{lightbulb-B-Itbm9g.js → lightbulb-C-uLoq9Y.js} +1 -1
  67. package/web-app/dist/assets/{loader-circle-Oq6NQhW2.js → loader-circle-JTfD-ZuM.js} +1 -1
  68. package/web-app/dist/assets/{lock-DbJ9zxbw.js → lock-G9rxD4gZ.js} +1 -1
  69. package/web-app/dist/assets/{mail-CzMRod6m.js → mail-BJ0PTN_V.js} +1 -1
  70. package/web-app/dist/assets/{package-WZ5osvej.js → package-CXClfLOO.js} +1 -1
  71. package/web-app/dist/assets/{plus-j08lFR-K.js → plus-EoL5OCB7.js} +1 -1
  72. package/web-app/dist/assets/{refresh-cw-CIr7E-g2.js → refresh-cw-BjREUnVq.js} +1 -1
  73. package/web-app/dist/assets/{rotate-ccw-gwoXxDeE.js → rotate-ccw-DahWX07H.js} +1 -1
  74. package/web-app/dist/assets/{save-B8fV_ZpE.js → save-Dek3gCn1.js} +1 -1
  75. package/web-app/dist/assets/{server-D5dO1paz.js → server-D6V1BAia.js} +1 -1
  76. package/web-app/dist/assets/{shield-alert-Du08zhdg.js → shield-alert-BtTK5Sxb.js} +1 -1
  77. package/web-app/dist/assets/{trash-2-DEKSVae5.js → trash-2-BT5o_g0r.js} +1 -1
  78. package/web-app/dist/assets/{trending-down-DBiXUtxJ.js → trending-down-D4Jk7KF3.js} +1 -1
  79. package/web-app/dist/assets/{trending-up-BgmK_tHq.js → trending-up-EQFTzhEo.js} +1 -1
  80. package/web-app/dist/assets/{upload-IaViyeVD.js → upload-JfI5lCSE.js} +1 -1
  81. package/web-app/dist/assets/{usePolling-PiRLqNu6.js → usePolling-BnhPUuGd.js} +1 -1
  82. package/web-app/dist/assets/{user-BB5J8wAF.js → user-DSUiUYtj.js} +1 -1
  83. package/web-app/dist/index.html +1 -1
  84. package/web-app/dist/assets/ComparePage-Dg0UdZAk.js +0 -1
package/README.md CHANGED
@@ -502,4 +502,4 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
502
502
 
503
503
  ## Star History
504
504
 
505
- [![Star History Chart](https://api.star-history.com/chart?repos=asklokesh/loki-mode&type=timeline&logscale&legend=bottom-right)](https://www.star-history.com/?repos=asklokesh%2Floki-mode&type=timeline&logscale=&legend=bottom-right)
505
+ [![Star History Chart](https://api.star-history.com/chart?repos=asklokesh/loki-mode&type=timeline&legend=bottom-right)](https://www.star-history.com/?repos=asklokesh%2Floki-mode&type=timeline&legend=bottom-right)
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.46.0
6
+ # Loki Mode v7.47.0
7
7
 
8
8
  **You are an autonomous agent. You make decisions. You do not ask questions. You do not stop.**
9
9
 
@@ -407,4 +407,4 @@ See `CHANGELOG.md` entries [7.5.7], [7.5.8], [7.5.13] for the per-fix list and r
407
407
 
408
408
  ---
409
409
 
410
- **v7.46.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
410
+ **v7.47.0 | [Autonomi](https://www.autonomi.dev/) flagship product | ~260 lines core**
package/VERSION CHANGED
@@ -1 +1 @@
1
- 7.46.0
1
+ 7.47.0
@@ -1721,6 +1721,111 @@ EVIDENCE_EOF
1721
1721
  return 1
1722
1722
  }
1723
1723
 
1724
+ #===============================================================================
1725
+ # P2-2 Assumption ledger gate (spec-robustness).
1726
+ #
1727
+ # Blocks completion while any high-severity assumption is unresolved, where
1728
+ # unresolved means: severity=high AND confirmed=false AND acknowledged=false.
1729
+ # This is the completion-side teeth for the spec-interrogation feature: when the
1730
+ # spec was ambiguous and Loki had to assume something high-impact, "done" cannot
1731
+ # be declared until that assumption has at least been acknowledged (auto-ack
1732
+ # lifecycle in run.sh, default-on) or human-confirmed
1733
+ # (LOKI_ASSUMPTIONS_REQUIRE_CONFIRM=1).
1734
+ #
1735
+ # By-design timing: in DEFAULT autonomous mode run.sh auto-acknowledges entries
1736
+ # every iteration right after injecting them into the build prompt, so by the
1737
+ # time the council reaches this gate (>= COUNCIL_MIN_ITERATIONS) they are already
1738
+ # acknowledged and the gate passes. That is intentional: a permanent block on
1739
+ # "unconfirmed" in a non-TTY run would just die at max-iterations and never reach
1740
+ # the proof-of-done. The PERSISTENT block lives in the
1741
+ # LOKI_ASSUMPTIONS_REQUIRE_CONFIRM=1 path (auto-ack disabled, only human
1742
+ # confirmed=true clears it). In BOTH modes the assumptions are unconditionally
1743
+ # SURFACED in proof-of-done (build_completion_summary reads counts ignoring
1744
+ # ack/confirm state), so "done" always means "done, plus here is what I assumed."
1745
+ #
1746
+ # The block COUNT comes from spec_ledger_high_unresolved_count() in
1747
+ # autonomy/spec-interrogation.sh. The gate sources that module if it is not
1748
+ # already loaded, so it works both inside run.sh (already sourced) and in
1749
+ # standalone tests (sources it here). When the module / ledger is absent the
1750
+ # count is 0 and the gate passes -- a project with no recorded assumptions is
1751
+ # never blocked (no spurious block on clean specs).
1752
+ #
1753
+ # Mirrors council_evidence_gate: opt-out knob first, defensive COUNCIL_STATE_DIR
1754
+ # default, writes .loki/council/assumption-block.json on block (removed on pass).
1755
+ #
1756
+ # Returns 0 (pass / OK to complete) or 1 (block / CONTINUE).
1757
+ #===============================================================================
1758
+ council_assumption_ledger_gate() {
1759
+ # Knob first: opt-out is exact-as-today, before any file read or write.
1760
+ [ "${LOKI_ASSUMPTION_GATE:-1}" = "0" ] && return 0
1761
+
1762
+ if [ -z "${COUNCIL_STATE_DIR:-}" ]; then
1763
+ COUNCIL_STATE_DIR="${TARGET_DIR:-.}/.loki/council"
1764
+ fi
1765
+
1766
+ # Source the spec-interrogation module if its counter is not already defined
1767
+ # (standalone tests / completion-promise route). Best-effort.
1768
+ if ! type spec_ledger_high_unresolved_count >/dev/null 2>&1; then
1769
+ local _si_helper
1770
+ _si_helper="$(dirname "${BASH_SOURCE[0]}")/spec-interrogation.sh"
1771
+ if [ -f "$_si_helper" ]; then
1772
+ # shellcheck disable=SC1090
1773
+ . "$_si_helper" 2>/dev/null || true
1774
+ fi
1775
+ fi
1776
+
1777
+ # No module => no ledger => nothing to block on (pass-through).
1778
+ if ! type spec_ledger_high_unresolved_count >/dev/null 2>&1; then
1779
+ if [ -f "$COUNCIL_STATE_DIR/assumption-block.json" ]; then
1780
+ rm -f "$COUNCIL_STATE_DIR/assumption-block.json"
1781
+ fi
1782
+ return 0
1783
+ fi
1784
+
1785
+ local unresolved
1786
+ unresolved="$(spec_ledger_high_unresolved_count 2>/dev/null || echo 0)"
1787
+ # Defensive: coerce to an integer.
1788
+ case "$unresolved" in
1789
+ ''|*[!0-9]*) unresolved=0 ;;
1790
+ esac
1791
+
1792
+ if [ "$unresolved" -eq 0 ]; then
1793
+ # Gate passes: remove any stale block report.
1794
+ if [ -f "$COUNCIL_STATE_DIR/assumption-block.json" ]; then
1795
+ rm -f "$COUNCIL_STATE_DIR/assumption-block.json"
1796
+ fi
1797
+ return 0
1798
+ fi
1799
+
1800
+ log_warn "[Council] Assumption ledger gate BLOCKED: ${unresolved} high-severity spec assumption(s) unresolved (the spec was ambiguous in ${unresolved} high-impact place(s))."
1801
+ log_warn "[Council] Resolve by confirming them in .loki/assumptions/ (set confirmed=true), or opt out with LOKI_ASSUMPTION_GATE=0."
1802
+
1803
+ mkdir -p "$COUNCIL_STATE_DIR" 2>/dev/null || true
1804
+ local ab_file="$COUNCIL_STATE_DIR/assumption-block.json"
1805
+ local ab_tmp="${ab_file}.tmp"
1806
+ local timestamp
1807
+ timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
1808
+ cat > "$ab_tmp" << ASSUMPTION_EOF
1809
+ {
1810
+ "status": "blocked",
1811
+ "blocked": true,
1812
+ "blocked_at": "$timestamp",
1813
+ "iteration": ${ITERATION_COUNT:-0},
1814
+ "reason": "high_severity_assumptions_unresolved",
1815
+ "high_unresolved": $unresolved
1816
+ }
1817
+ ASSUMPTION_EOF
1818
+ mv "$ab_tmp" "$ab_file" 2>/dev/null || rm -f "$ab_tmp" 2>/dev/null || true
1819
+
1820
+ if type record_trust_event_bash &>/dev/null; then
1821
+ record_trust_event_bash "assumption_block" \
1822
+ "high_unresolved=$unresolved" \
1823
+ >/dev/null 2>&1 || true
1824
+ fi
1825
+
1826
+ return 1
1827
+ }
1828
+
1724
1829
  #===============================================================================
1725
1830
  # Council Member Review - Individual member evaluation
1726
1831
  #===============================================================================
@@ -2512,6 +2617,14 @@ council_evaluate() {
2512
2617
  return 1 # CONTINUE - cannot complete without real evidence
2513
2618
  fi
2514
2619
 
2620
+ # P2-2: assumption ledger gate - block completion while high-severity spec
2621
+ # assumptions are unresolved (the spec was ambiguous in a high-impact place
2622
+ # and Loki had to assume something that has not been acknowledged/confirmed).
2623
+ if ! council_assumption_ledger_gate; then
2624
+ log_info "[Council] Completion blocked by assumption ledger gate"
2625
+ return 1 # CONTINUE - cannot complete with unresolved high-sev assumptions
2626
+ fi
2627
+
2515
2628
  # Compute threshold using the same ceiling(2/3) formula as council_vote and council_aggregate_votes
2516
2629
  local _eval_threshold=$(( (COUNCIL_SIZE * 2 + 2) / 3 ))
2517
2630
 
package/autonomy/run.sh CHANGED
@@ -2634,6 +2634,27 @@ except Exception:
2634
2634
  fi
2635
2635
  fi
2636
2636
 
2637
+ # P2-2: assumption-ledger summary for proof-of-done. "done" means "done, plus
2638
+ # here are the N places your spec was ambiguous and what Loki assumed."
2639
+ # spec_ledger_counts echoes "<total> <high>"; defined when spec-interrogation.sh
2640
+ # is sourced (run.sh sources it in DISCOVERY). Guarded for safety.
2641
+ local assumptions_total=0 assumptions_high=0 assumption_lines=""
2642
+ if type spec_ledger_counts &>/dev/null; then
2643
+ local _ac
2644
+ _ac="$(spec_ledger_counts 2>/dev/null || echo '0 0')"
2645
+ assumptions_total="${_ac%% *}"
2646
+ assumptions_high="${_ac##* }"
2647
+ case "$assumptions_total" in ''|*[!0-9]*) assumptions_total=0 ;; esac
2648
+ case "$assumptions_high" in ''|*[!0-9]*) assumptions_high=0 ;; esac
2649
+ if [ "$assumptions_total" != "0" ]; then
2650
+ local _ledger_md="$loki_dir/assumptions/ledger.md"
2651
+ if [ -f "$_ledger_md" ]; then
2652
+ # Pull just the "## <id> ..." headings as a terse one-per-line list.
2653
+ assumption_lines="$(grep '^## ' "$_ledger_md" 2>/dev/null | sed 's/^## / - /' || true)"
2654
+ fi
2655
+ fi
2656
+ fi
2657
+
2637
2658
  # ---- Durable human-readable file: .loki/COMPLETION.txt --------------------
2638
2659
  {
2639
2660
  echo "Loki Mode run summary"
@@ -2668,6 +2689,14 @@ except Exception:
2668
2689
  echo "$evidence_inconclusive_line"
2669
2690
  echo ""
2670
2691
  fi
2692
+ if [ "$assumptions_total" != "0" ]; then
2693
+ echo "Spec assumptions recorded: $assumptions_total ($assumptions_high high-severity)"
2694
+ echo " These are places your spec was ambiguous and what Loki assumed. See .loki/assumptions/ledger.md"
2695
+ if [ -n "$assumption_lines" ]; then
2696
+ echo "$assumption_lines"
2697
+ fi
2698
+ echo ""
2699
+ fi
2671
2700
  echo "Review the work:"
2672
2701
  echo " $review_cmd"
2673
2702
  echo ""
@@ -2691,6 +2720,8 @@ except Exception:
2691
2720
  _LOKI_CS_DELEGATE_BRANCH="$delegate_branch" \
2692
2721
  _LOKI_CS_PR_URL="$pr_url" \
2693
2722
  _LOKI_CS_TS="$ts" \
2723
+ _LOKI_CS_ASSUMPTIONS_TOTAL="$assumptions_total" \
2724
+ _LOKI_CS_ASSUMPTIONS_HIGH="$assumptions_high" \
2694
2725
  _LOKI_CS_OUT_FILE="$loki_dir/state/completion.json" \
2695
2726
  python3 -c "
2696
2727
  import json, os, tempfile
@@ -2710,6 +2741,8 @@ rec = {
2710
2741
  'delegate_branch': os.environ.get('_LOKI_CS_DELEGATE_BRANCH', ''),
2711
2742
  'pr_url': os.environ.get('_LOKI_CS_PR_URL', ''),
2712
2743
  'timestamp': os.environ.get('_LOKI_CS_TS', ''),
2744
+ 'assumptions_total': i(os.environ.get('_LOKI_CS_ASSUMPTIONS_TOTAL')),
2745
+ 'assumptions_high': i(os.environ.get('_LOKI_CS_ASSUMPTIONS_HIGH')),
2713
2746
  }
2714
2747
  d = os.path.dirname(out)
2715
2748
  fd, tmp = tempfile.mkstemp(dir=d, suffix='.json')
@@ -11581,6 +11614,17 @@ build_prompt() {
11581
11614
  gate_failure_context="${gate_failure_context}FIX THESE ISSUES BEFORE PROCEEDING WITH NEW WORK."
11582
11615
  fi
11583
11616
 
11617
+ # P2-2: high-severity spec-assumption context. When DISCOVERY recorded any
11618
+ # high-severity assumption (the spec was ambiguous in a high-impact place),
11619
+ # surface it to the build agent so it implements with the gap in view (or
11620
+ # fixes the spec) instead of obliviously coding past it. spec_ledger_prompt_block
11621
+ # is defined when spec-interrogation.sh is sourced (run.sh sources it in
11622
+ # DISCOVERY); guarded so build_prompt is safe when the module is absent.
11623
+ local assumption_context=""
11624
+ if type spec_ledger_prompt_block &>/dev/null; then
11625
+ assumption_context="$(spec_ledger_prompt_block 2>/dev/null || true)"
11626
+ fi
11627
+
11584
11628
  # Human directive injection (from HUMAN_INPUT.md)
11585
11629
  # NOTE: Do NOT unset LOKI_HUMAN_INPUT here - build_prompt runs in a subshell
11586
11630
  # (command substitution) so unset would not affect the parent shell.
@@ -11833,15 +11877,15 @@ except Exception:
11833
11877
  else
11834
11878
  if [ $retry -eq 0 ]; then
11835
11879
  if [ -n "$prd" ]; then
11836
- echo "Loki Mode with PRD at $prd. $update_instruction $human_directive $gate_failure_context $queue_tasks $bmad_context $openspec_context $mirofish_context $magic_context $checklist_status $app_runner_info $playwright_info $memory_context_section $rarv_instruction $memory_instruction $usage_doc_instruction $compose_instruction $lsp_grounding_instruction $agents_md_instruction $completion_instruction $sdlc_instruction $autonomous_suffix"
11880
+ echo "Loki Mode with PRD at $prd. $update_instruction $human_directive $gate_failure_context $assumption_context $queue_tasks $bmad_context $openspec_context $mirofish_context $magic_context $checklist_status $app_runner_info $playwright_info $memory_context_section $rarv_instruction $memory_instruction $usage_doc_instruction $compose_instruction $lsp_grounding_instruction $agents_md_instruction $completion_instruction $sdlc_instruction $autonomous_suffix"
11837
11881
  else
11838
- echo "Loki Mode. $human_directive $gate_failure_context $queue_tasks $bmad_context $openspec_context $mirofish_context $magic_context $checklist_status $app_runner_info $playwright_info $memory_context_section $analysis_instruction $rarv_instruction $memory_instruction $usage_doc_instruction $compose_instruction $lsp_grounding_instruction $agents_md_instruction $completion_instruction $sdlc_instruction $autonomous_suffix"
11882
+ echo "Loki Mode. $human_directive $gate_failure_context $assumption_context $queue_tasks $bmad_context $openspec_context $mirofish_context $magic_context $checklist_status $app_runner_info $playwright_info $memory_context_section $analysis_instruction $rarv_instruction $memory_instruction $usage_doc_instruction $compose_instruction $lsp_grounding_instruction $agents_md_instruction $completion_instruction $sdlc_instruction $autonomous_suffix"
11839
11883
  fi
11840
11884
  else
11841
11885
  if [ -n "$prd" ]; then
11842
- echo "Loki Mode - Resume iteration #$iteration (retry #$retry). PRD: $prd. $human_directive $gate_failure_context $queue_tasks $bmad_context $openspec_context $mirofish_context $magic_context $checklist_status $app_runner_info $playwright_info $memory_context_section $rarv_instruction $memory_instruction $usage_doc_instruction $compose_instruction $lsp_grounding_instruction $agents_md_instruction $completion_instruction $sdlc_instruction $autonomous_suffix"
11886
+ echo "Loki Mode - Resume iteration #$iteration (retry #$retry). PRD: $prd. $human_directive $gate_failure_context $assumption_context $queue_tasks $bmad_context $openspec_context $mirofish_context $magic_context $checklist_status $app_runner_info $playwright_info $memory_context_section $rarv_instruction $memory_instruction $usage_doc_instruction $compose_instruction $lsp_grounding_instruction $agents_md_instruction $completion_instruction $sdlc_instruction $autonomous_suffix"
11843
11887
  else
11844
- echo "Loki Mode - Resume iteration #$iteration (retry #$retry). $human_directive $gate_failure_context $queue_tasks $bmad_context $openspec_context $mirofish_context $magic_context $checklist_status $app_runner_info $playwright_info $memory_context_section Use .loki/generated-prd.md if exists. $rarv_instruction $memory_instruction $usage_doc_instruction $compose_instruction $lsp_grounding_instruction $agents_md_instruction $completion_instruction $sdlc_instruction $autonomous_suffix"
11888
+ echo "Loki Mode - Resume iteration #$iteration (retry #$retry). $human_directive $gate_failure_context $assumption_context $queue_tasks $bmad_context $openspec_context $mirofish_context $magic_context $checklist_status $app_runner_info $playwright_info $memory_context_section Use .loki/generated-prd.md if exists. $rarv_instruction $memory_instruction $usage_doc_instruction $compose_instruction $lsp_grounding_instruction $agents_md_instruction $completion_instruction $sdlc_instruction $autonomous_suffix"
11845
11889
  fi
11846
11890
  fi
11847
11891
  fi
@@ -11946,6 +11990,7 @@ except Exception:
11946
11990
  fi
11947
11991
  [ -n "$human_directive" ] && printf '%s\n' "$human_directive"
11948
11992
  [ -n "$gate_failure_context" ] && printf '%s\n' "$gate_failure_context"
11993
+ [ -n "$assumption_context" ] && printf '%s\n' "$assumption_context"
11949
11994
  [ -n "$queue_tasks" ] && printf '%s\n' "$queue_tasks"
11950
11995
  [ -n "$bmad_context" ] && printf '%s\n' "$bmad_context"
11951
11996
  [ -n "$openspec_context" ] && printf '%s\n' "$openspec_context"
@@ -13066,6 +13111,22 @@ except Exception:
13066
13111
  fi
13067
13112
  fi
13068
13113
 
13114
+ # P2-1: Spec interrogation (DISCOVERY phase, BEFORE iteration 1 begins
13115
+ # coding). Auto-detects spec ambiguities/contradictions/underspecification
13116
+ # via the Devil's-Advocate grill + prd-analyzer, classifies them with a
13117
+ # deterministic severity, and records every gap as a first-class assumption
13118
+ # under .loki/assumptions/. Default-on; LOKI_SPEC_GRILL=0 opts out.
13119
+ # Provider-aware and degrades cleanly (no provider -> prd-analyzer
13120
+ # assumptions only, no fabricated questions). Best-effort: never blocks the
13121
+ # run. The completion-side teeth are council_assumption_ledger_gate.
13122
+ if [ -f "${SCRIPT_DIR}/spec-interrogation.sh" ]; then
13123
+ # shellcheck disable=SC1090
13124
+ . "${SCRIPT_DIR}/spec-interrogation.sh" 2>/dev/null || true
13125
+ if type spec_interrogation_run &>/dev/null; then
13126
+ spec_interrogation_run "$prd_path" || true
13127
+ fi
13128
+ fi
13129
+
13069
13130
  # Auto-derive completion promise from PRD (v6.10.0)
13070
13131
  # When PRD exists but no explicit promise, auto-derive one and switch to checkpoint mode
13071
13132
  if [ -n "$prd_path" ] && [ -f "$prd_path" ] && [ -z "$COMPLETION_PROMISE" ]; then
@@ -13227,6 +13288,18 @@ except Exception as exc:
13227
13288
  local prompt
13228
13289
  prompt=$(build_prompt "$retry" "$prd_path" "$ITERATION_COUNT")
13229
13290
 
13291
+ # P2-2 auto-acknowledgment lifecycle: build_prompt just injected the
13292
+ # high-severity spec assumptions into the prompt (assumption_context), so
13293
+ # the agent has now SEEN them. Mark them acknowledged so the completion
13294
+ # gate is not a permanent dead-end in autonomous (non-TTY) mode where no
13295
+ # human can ever set confirmed=true. This is the opposite of silent
13296
+ # autocorrect: the gap was recorded, prompt-injected, and is surfaced in
13297
+ # proof-of-done. LOKI_ASSUMPTIONS_REQUIRE_CONFIRM=1 disables auto-ack so
13298
+ # only a human confirmation clears the block (the helper checks the knob).
13299
+ if type spec_ledger_acknowledge_all &>/dev/null; then
13300
+ spec_ledger_acknowledge_all 2>/dev/null || true
13301
+ fi
13302
+
13230
13303
  # BUG #5 fix: Clear LOKI_HUMAN_INPUT in the parent shell after build_prompt
13231
13304
  # consumed it. build_prompt runs in a subshell (command substitution), so
13232
13305
  # any unset inside it does not affect the parent. Clear here to prevent
@@ -14539,6 +14612,17 @@ if __name__ == "__main__":
14539
14612
  log_warn "Completion claim rejected: held-out spec-eval gate found failing held-out acceptance check(s)."
14540
14613
  log_warn " Details under .loki/council/heldout-block.json ; opt out with LOKI_HELDOUT_GATE=0"
14541
14614
  # Fall through; keep iterating until the held-out checks pass.
14615
+ # P2-2: the assumption ledger gate must also guard the DEFAULT
14616
+ # completion-promise route, not only the interval-gated council path.
14617
+ # Otherwise an agent can self-assert "done" while a high-severity spec
14618
+ # assumption is still unresolved, bypassing the spec-robustness gate.
14619
+ # Mirrors the evidence/held-out gate arms above. Opt-out: the gate's
14620
+ # own LOKI_ASSUMPTION_GATE=0 (returns 0 immediately when disabled, so
14621
+ # this branch never fires). Gate output is printed by the gate itself.
14622
+ elif [ "$_completion_claimed" = 1 ] && type council_assumption_ledger_gate &>/dev/null && ! council_assumption_ledger_gate; then
14623
+ log_warn "Completion claim rejected: assumption ledger gate found unresolved high-severity spec assumption(s)."
14624
+ log_warn " Details under .loki/council/assumption-block.json ; opt out with LOKI_ASSUMPTION_GATE=0"
14625
+ # Fall through; keep iterating until high-sev assumptions resolve.
14542
14626
  elif [ "$_completion_claimed" = 1 ]; then
14543
14627
  echo ""
14544
14628
  if [ -n "$COMPLETION_PROMISE" ]; then
@@ -15014,6 +15098,8 @@ check_human_intervention() {
15014
15098
  log_info "Council force-review: blocked by evidence hard gate"
15015
15099
  elif type council_heldout_gate &>/dev/null && ! council_heldout_gate; then
15016
15100
  log_info "Council force-review: blocked by held-out spec-eval hard gate"
15101
+ elif type council_assumption_ledger_gate &>/dev/null && ! council_assumption_ledger_gate; then
15102
+ log_info "Council force-review: blocked by assumption ledger hard gate"
15017
15103
  elif type council_vote &>/dev/null && council_vote; then
15018
15104
  log_header "COMPLETION COUNCIL: FORCE REVIEW - PROJECT COMPLETE"
15019
15105
  # BUG #17 fix: Write COMPLETED marker, generate council report, and