specfuse-loop 0.24.0__tar.gz → 0.26.0__tar.gz

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 (634) hide show
  1. {specfuse_loop-0.24.0/specfuse_loop.egg-info → specfuse_loop-0.26.0}/PKG-INFO +1 -1
  2. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/pyproject.toml +1 -1
  3. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/closing_requirements.py +32 -0
  4. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/criteria_state.py +154 -1
  5. specfuse_loop-0.26.0/specfuse/loop/data/VERSION +1 -0
  6. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/docs/methodology.md +68 -3
  7. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/rules/close-discipline.md +11 -0
  8. specfuse_loop-0.26.0/specfuse/loop/data/rules/result-contract.md +143 -0
  9. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/schemas/driver-event.schema.json +3 -2
  10. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/verification.yml.example +37 -0
  11. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/gate_eval.py +17 -0
  12. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/judge.py +113 -2
  13. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/lint_closing.py +35 -0
  14. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/lint_plan.py +1 -1
  15. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/loop.py +1239 -37
  16. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/replay_spin.py +102 -1
  17. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0/specfuse_loop.egg-info}/PKG-INFO +1 -1
  18. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse_loop.egg-info/SOURCES.txt +15 -0
  19. specfuse_loop-0.26.0/tests/test_carried_green_invalidated_by_diff.py +367 -0
  20. specfuse_loop-0.26.0/tests/test_carry_accounting_close_and_judge.py +223 -0
  21. specfuse_loop-0.26.0/tests/test_closing_sessions_on_sonnet.py +28 -0
  22. specfuse_loop-0.26.0/tests/test_dispatch_preamble_rules_pointer.py +32 -0
  23. specfuse_loop-0.26.0/tests/test_dispatch_skills_index.py +105 -0
  24. specfuse_loop-0.26.0/tests/test_failure_signature_names_the_test.py +242 -0
  25. specfuse_loop-0.26.0/tests/test_fix_unit_insertion_bookkeeping.py +193 -0
  26. specfuse_loop-0.26.0/tests/test_fix_unit_insertion_e2e.py +283 -0
  27. specfuse_loop-0.26.0/tests/test_fix_unit_insertion_refused.py +320 -0
  28. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_followups_artifact.py +26 -2
  29. specfuse_loop-0.26.0/tests/test_judge_sees_dropped_produces.py +145 -0
  30. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_gate_proportionality.py +19 -4
  31. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_auto_archive.py +29 -0
  32. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_close_intermediate.py +2 -2
  33. specfuse_loop-0.26.0/tests/test_produces_amendment_e2e.py +247 -0
  34. specfuse_loop-0.26.0/tests/test_produces_repair_note.py +205 -0
  35. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_rearm_clears_stale_criteria_state.py +36 -7
  36. specfuse_loop-0.26.0/tests/test_reclose_carries_narrow_greens_e2e.py +293 -0
  37. specfuse_loop-0.26.0/tests/test_replay_spin_failing_sets.py +110 -0
  38. specfuse_loop-0.26.0/tests/test_spinning_repeat_same_failing_set.py +230 -0
  39. specfuse_loop-0.24.0/specfuse/loop/data/VERSION +0 -1
  40. specfuse_loop-0.24.0/specfuse/loop/data/rules/result-contract.md +0 -132
  41. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/LICENSE +0 -0
  42. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/NOTICE +0 -0
  43. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/README.md +0 -0
  44. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/setup.cfg +0 -0
  45. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/__init__.py +0 -0
  46. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/budget.py +0 -0
  47. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/diagnose_invoke.py +0 -0
  48. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/drafting_answers.py +0 -0
  49. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/drafting_invoke.py +0 -0
  50. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/drafting_questions.py +0 -0
  51. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/driver_command.py +0 -0
  52. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/driver_invoke.py +0 -0
  53. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/invoke.py +0 -0
  54. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/monitoring_read.py +0 -0
  55. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/providers/__init__.py +0 -0
  56. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/providers/answers.py +0 -0
  57. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/providers/bugs.py +0 -0
  58. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/providers/feature.py +0 -0
  59. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/providers/findings_autofix.py +0 -0
  60. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/providers/findings_diagnose.py +0 -0
  61. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/providers/triage.py +0 -0
  62. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/queue_read.py +0 -0
  63. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/repo_detect.py +0 -0
  64. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/run.py +0 -0
  65. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/severity_backfill.py +0 -0
  66. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/state.py +0 -0
  67. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/triage_invoke.py +0 -0
  68. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/agent/worktree.py +0 -0
  69. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/__init__.py +0 -0
  70. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/_filelock.py +0 -0
  71. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/_miniyaml.py +0 -0
  72. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/_wu_sections.py +0 -0
  73. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/adopt_feature.py +0 -0
  74. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/agent_policy.py +0 -0
  75. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/arm_eval.py +0 -0
  76. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/arm_sweep.py +0 -0
  77. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/arm_txn.py +0 -0
  78. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/bug_lane.py +0 -0
  79. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/bug_lane_run.py +0 -0
  80. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/bug_lane_state.py +0 -0
  81. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/build_provenance.py +0 -0
  82. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/caller_check.py +0 -0
  83. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/changelog.py +0 -0
  84. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/cost.py +0 -0
  85. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/CHANGELOG.seed.md +0 -0
  86. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/LEARNINGS.template.md +0 -0
  87. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/docs/concepts/adopting-auto-mode.md +0 -0
  88. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/docs/concepts/architecture-addendum-gates-and-iterative-planning.md +0 -0
  89. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/docs/concepts/autonomy-stop-classes.md +0 -0
  90. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/docs/concepts/ralph-lineage.md +0 -0
  91. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/docs/getting-started.md +0 -0
  92. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/docs/glossary.md +0 -0
  93. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/docs/skills.md +0 -0
  94. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/gitignore.snippet +0 -0
  95. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/monitoring-secrets-checklist.md +0 -0
  96. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/monitoring.overrides.yml.example +0 -0
  97. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/monitoring.yml.example +0 -0
  98. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/roadmap.template.md +0 -0
  99. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/rules/correlation-ids.md +0 -0
  100. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/rules/design-for-diagnosis.md +0 -0
  101. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/rules/human-output.md +0 -0
  102. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/rules/never-touch.md +0 -0
  103. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/rules/operator-escalation.md +0 -0
  104. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/rules/planning-discipline.md +0 -0
  105. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/rules/security-boundaries.md +0 -0
  106. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/rules/verification-discipline.md +0 -0
  107. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/rules-local/README.md +0 -0
  108. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/schemas/event.schema.json +0 -0
  109. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/schemas/events/initiative_created.schema.json +0 -0
  110. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/schemas/events/spec_issue_resolved.schema.json +0 -0
  111. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/schemas/events/spec_issue_routed.schema.json +0 -0
  112. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/schemas/events/spec_validated.schema.json +0 -0
  113. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/templates/DECISIONS.template.md +0 -0
  114. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/templates/GATE.template.md +0 -0
  115. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/templates/LEARNINGS-pending.template.md +0 -0
  116. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/templates/PLAN.template.md +0 -0
  117. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/templates/WU.template.md +0 -0
  118. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/data/workflows/specfuse-monitor.yml +0 -0
  119. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/decisions_format.py +0 -0
  120. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/driver_edit.py +0 -0
  121. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/escalation.py +0 -0
  122. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/events_stats.py +0 -0
  123. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/gate_commands.py +0 -0
  124. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/gh_backend.py +0 -0
  125. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/gh_features.py +0 -0
  126. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/heartbeat.py +0 -0
  127. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/labels.py +0 -0
  128. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/learnings_distil.py +0 -0
  129. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/learnings_query.py +0 -0
  130. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/lint_monitoring.py +0 -0
  131. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/lint_roadmap.py +0 -0
  132. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/notify.py +0 -0
  133. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/notify_escalation.py +0 -0
  134. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/notify_sla.py +0 -0
  135. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/plan_baseline.py +0 -0
  136. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/policy_proposals.py +0 -0
  137. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/policy_review.py +0 -0
  138. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/prerun.py +0 -0
  139. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/prerun_capture.py +0 -0
  140. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/promotion.py +0 -0
  141. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/rearm_migration.py +0 -0
  142. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/red_on_base.py +0 -0
  143. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/roadmap_archive.py +0 -0
  144. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/scaffold.py +0 -0
  145. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/triage.py +0 -0
  146. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/upgrade_merge_gate.py +0 -0
  147. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/loop/validate_event.py +0 -0
  148. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/monitor/__init__.py +0 -0
  149. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/monitor/adapters.py +0 -0
  150. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/monitor/artifact.py +0 -0
  151. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/monitor/autofix.py +0 -0
  152. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/monitor/autofix_invoke.py +0 -0
  153. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/monitor/autofix_run.py +0 -0
  154. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/monitor/autofix_state.py +0 -0
  155. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/monitor/cli.py +0 -0
  156. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/monitor/diagnose_cli.py +0 -0
  157. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/monitor/diagnosis.py +0 -0
  158. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/monitor/fingerprint.py +0 -0
  159. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/monitor/issues.py +0 -0
  160. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/monitor/providers/__init__.py +0 -0
  161. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/monitor/providers/_azure_auth.py +0 -0
  162. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/monitor/providers/azure_app_insights.py +0 -0
  163. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/monitor/providers/azure_service_bus.py +0 -0
  164. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/monitor/redaction.py +0 -0
  165. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse/monitor/schedule.py +0 -0
  166. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse_loop.egg-info/dependency_links.txt +0 -0
  167. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse_loop.egg-info/entry_points.txt +0 -0
  168. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse_loop.egg-info/requires.txt +0 -0
  169. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/specfuse_loop.egg-info/top_level.txt +0 -0
  170. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_abandon_feature_skill.py +0 -0
  171. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_abandoned_work_reported.py +0 -0
  172. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_abandoned_wu_strands_gate.py +0 -0
  173. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_adopt_feature.py +0 -0
  174. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_budget.py +0 -0
  175. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_bug_selection_dedup.py +0 -0
  176. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_default_features_root.py +0 -0
  177. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_driver_command.py +0 -0
  178. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_driver_invoke.py +0 -0
  179. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_driver_restart.py +0 -0
  180. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_escalation_on_issue.py +0 -0
  181. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_escalation_run_state.py +0 -0
  182. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_findings_seam.py +0 -0
  183. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_invoke_timeout.py +0 -0
  184. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_invoke_usage.py +0 -0
  185. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_item_worktree.py +0 -0
  186. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_lock.py +0 -0
  187. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_policy_key_ownership.py +0 -0
  188. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_policy_queue.py +0 -0
  189. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_policy_schema.py +0 -0
  190. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_policy_triage_dial.py +0 -0
  191. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_provider_answers.py +0 -0
  192. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_provider_bugs.py +0 -0
  193. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_provider_feature.py +0 -0
  194. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_provider_findings_autofix.py +0 -0
  195. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_provider_findings_diagnose.py +0 -0
  196. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_provider_isolation.py +0 -0
  197. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_provider_triage.py +0 -0
  198. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_queue_read.py +0 -0
  199. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_relays_driver_output.py +0 -0
  200. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_repo_detect.py +0 -0
  201. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_run.py +0 -0
  202. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_run_progress.py +0 -0
  203. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_seam.py +0 -0
  204. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_snapshot_refresh.py +0 -0
  205. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_agent_state.py +0 -0
  206. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_answer_escalation_skill.py +0 -0
  207. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_app_insights_adapters.py +0 -0
  208. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_archive_ref_reconciliation.py +0 -0
  209. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_arm_eval.py +0 -0
  210. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_arm_eval_lint_class.py +0 -0
  211. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_arm_eval_wiring.py +0 -0
  212. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_arm_gate_edits_uncommitted.py +0 -0
  213. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_arm_sweep.py +0 -0
  214. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_arm_sweep_gate.py +0 -0
  215. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_arm_txn.py +0 -0
  216. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_arm_wiring.py +0 -0
  217. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_artifact_redaction.py +0 -0
  218. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_attempt_note_untracked_files.py +0 -0
  219. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_attempt_outcome_contract.py +0 -0
  220. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_attempt_outcome_emission.py +0 -0
  221. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_attention_nonwriting_guard.py +0 -0
  222. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_attention_silence_section.py +0 -0
  223. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_attention_skill_structure.py +0 -0
  224. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_attribution_halt_claims.py +0 -0
  225. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_autoclose_deferral_visibility.py +0 -0
  226. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_autoclose_gate_note.py +0 -0
  227. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_autoclose_stub_states_what_passed.py +0 -0
  228. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_autofix_invoke.py +0 -0
  229. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_autofix_live.py +0 -0
  230. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_autofix_predicate.py +0 -0
  231. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_autofix_run.py +0 -0
  232. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_autofix_state.py +0 -0
  233. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_autosync.py +0 -0
  234. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_autosync_consent.py +0 -0
  235. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_autosync_firstrun.py +0 -0
  236. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_autosync_no_cwd_leak.py +0 -0
  237. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_autosync_plugin.py +0 -0
  238. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_azure_credential_resolution.py +0 -0
  239. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_backend.py +0 -0
  240. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_baseline_escalation_message.py +0 -0
  241. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_baseline_persistence.py +0 -0
  242. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_baseline_probe.py +0 -0
  243. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_baseline_provenance.py +0 -0
  244. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_baseline_tree_hash_key.py +0 -0
  245. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_bash_routing.py +0 -0
  246. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_bats_suites_gated.py +0 -0
  247. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_binary_verdict.py +0 -0
  248. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_binding_block_advisory.py +0 -0
  249. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_binding_block_allocation.py +0 -0
  250. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_binding_block_budget.py +0 -0
  251. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_blind_run_is_not_drained.py +0 -0
  252. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_bookkeeping_commit_crash_run.py +0 -0
  253. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_bookkeeping_commit_hook_crash.py +0 -0
  254. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_bookkeeping_no_verify.py +0 -0
  255. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_brief_covers_every_unit_escalation.py +0 -0
  256. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_bug_lane_ci_pending.py +0 -0
  257. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_bug_lane_guardrails.py +0 -0
  258. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_bug_lane_label_nonfatal.py +0 -0
  259. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_bug_lane_labels_registered.py +0 -0
  260. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_bug_lane_min_severity.py +0 -0
  261. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_bug_lane_policy_contract.py +0 -0
  262. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_bug_lane_pr_number_carried.py +0 -0
  263. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_bug_lane_preflight_and_dial.py +0 -0
  264. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_bug_lane_run.py +0 -0
  265. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_bug_lane_state.py +0 -0
  266. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_bug_lane_stopped_outcome_pr_number.py +0 -0
  267. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_bug_lane_test_paths.py +0 -0
  268. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_build_provenance.py +0 -0
  269. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_caller_check_ratchet.py +0 -0
  270. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_changed_file_test_selection.py +0 -0
  271. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_changelog_append_only.py +0 -0
  272. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_changelog_collection.py +0 -0
  273. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_changelog_release_wiring.py +0 -0
  274. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_changelog_schema.py +0 -0
  275. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_ci_conclusion_wait.py +0 -0
  276. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_ci_runs_every_gate.py +0 -0
  277. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_claude_resolution.py +0 -0
  278. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_close_b_pending_learnings.py +0 -0
  279. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_close_records_feature_oracle.py +0 -0
  280. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_close_wu_self_reference.py +0 -0
  281. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_closing_deliverable_guard.py +0 -0
  282. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_closing_guard_contracts.py +0 -0
  283. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_closing_guard_prediction.py +0 -0
  284. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_closing_learnings_destination.py +0 -0
  285. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_closing_requirements.py +0 -0
  286. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_coauthor_trailer_allowlist.py +0 -0
  287. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_conditional_reflection.py +0 -0
  288. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_console_encoding.py +0 -0
  289. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_convergent_iteration.py +0 -0
  290. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_convergent_wu_lint.py +0 -0
  291. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_correlation_id_override.py +0 -0
  292. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_correlation_id_two_surfaces.py +0 -0
  293. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_cost_lifetime.py +0 -0
  294. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_cost_tracking.py +0 -0
  295. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_criteria_per_gate_lint.py +0 -0
  296. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_criteria_state.py +0 -0
  297. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_criteria_worklist.py +0 -0
  298. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_decision_citation_lint.py +0 -0
  299. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_decision_followups_discharged.py +0 -0
  300. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_decision_override_lint.py +0 -0
  301. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_decisions_format.py +0 -0
  302. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_default_severity_aliases.py +0 -0
  303. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_degraded_oracle.py +0 -0
  304. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_deliverable_missing_note.py +0 -0
  305. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_deliverable_presence_gate.py +0 -0
  306. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_derive_agent_policy_review_mode.py +0 -0
  307. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_derive_agent_policy_skill.py +0 -0
  308. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_derive_monitoring_discovery.py +0 -0
  309. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_derive_monitoring_skill_registration.py +0 -0
  310. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_design_for_diagnosis_rule.py +0 -0
  311. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_deterministic_refusal_repeat.py +0 -0
  312. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_diagnose_headless.py +0 -0
  313. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_diagnose_issue_skill.py +0 -0
  314. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_diagnosis.py +0 -0
  315. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_diagnosis_roundtrip_live.py +0 -0
  316. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_dispatch_model_from_fix_scope.py +0 -0
  317. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_dispatch_skeleton.py +0 -0
  318. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_distilled_accept_step.py +0 -0
  319. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_doctor.py +0 -0
  320. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_doctor_command_preflight.py +0 -0
  321. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_done_feature_gates.py +0 -0
  322. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_draft_feature_answers_mode.py +0 -0
  323. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_drafting_answer_gate.py +0 -0
  324. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_drafting_invoke.py +0 -0
  325. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_drafting_question_issue.py +0 -0
  326. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_drafting_questions.py +0 -0
  327. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_drafting_reply_shape.py +0 -0
  328. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_driver_edit_detection.py +0 -0
  329. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_driver_event_registry_covers_emitters.py +0 -0
  330. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_driver_integration.py +0 -0
  331. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_driver_lock.py +0 -0
  332. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_driver_module_surface.py +0 -0
  333. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_driver_restart_halt_surfaced.py +0 -0
  334. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_driver_restart_halt_wiring.py +0 -0
  335. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_driver_restart_hold.py +0 -0
  336. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_driver_staleness_gate_summary.py +0 -0
  337. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_driver_staleness_warning.py +0 -0
  338. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_dry_run_no_branch_mutation.py +0 -0
  339. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_duration_tracking.py +0 -0
  340. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_empty_files_escalation.py +0 -0
  341. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_ensure_feature_branch.py +0 -0
  342. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_ensure_feature_branch_base.py +0 -0
  343. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_escalation_assignee_policy.py +0 -0
  344. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_escalation_contract.py +0 -0
  345. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_escalation_crash_containment.py +0 -0
  346. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_escalation_dedup_search.py +0 -0
  347. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_escalation_emit.py +0 -0
  348. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_event_gate_full_envelope.py +0 -0
  349. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_events_redaction.py +0 -0
  350. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_events_stats.py +0 -0
  351. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_extra_gates.py +0 -0
  352. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_failure_artifact_model.py +0 -0
  353. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_failure_signature_fail_prefix.py +0 -0
  354. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_failure_signature_skips_log_noise.py +0 -0
  355. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_feature_branch_auto_sync.py +0 -0
  356. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_feature_branch_squash_merge.py +0 -0
  357. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_feature_branch_stale_base.py +0 -0
  358. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_feature_id_resolution.py +0 -0
  359. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_feature_oracle_e2e.py +0 -0
  360. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_feature_provider_drafting_dispatch.py +0 -0
  361. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_feature_review_accumulation.py +0 -0
  362. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_filelock_portable.py +0 -0
  363. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_files_changed_auto_repair.py +0 -0
  364. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_find_pr_no_search_index.py +0 -0
  365. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_fingerprint.py +0 -0
  366. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_fix_bug_diff_self_check.py +0 -0
  367. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_fix_bug_headless.py +0 -0
  368. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_fix_bug_reads_comments.py +0 -0
  369. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_fold_contract_documented.py +0 -0
  370. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_force_full_close.py +0 -0
  371. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_frontmatter_scalar_quoting.py +0 -0
  372. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_gate_broad_run.py +0 -0
  373. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_gate_budget.py +0 -0
  374. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_gate_budget_post_dispatch.py +0 -0
  375. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_gate_commands_needs.py +0 -0
  376. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_gate_eval.py +0 -0
  377. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_gate_eval_calibration.py +0 -0
  378. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_gate_eval_intermediate_wiring.py +0 -0
  379. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_gate_eval_repo_flag.py +0 -0
  380. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_gate_eval_terminal_wiring.py +0 -0
  381. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_gate_report_verdict.py +0 -0
  382. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_gh_backend.py +0 -0
  383. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_gh_features.py +0 -0
  384. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_git_env_isolation.py +0 -0
  385. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_gitleaks_pinning.py +0 -0
  386. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_groom_backlog_skill.py +0 -0
  387. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_guard_refusal_failure_class.py +0 -0
  388. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_guard_refusal_failure_excerpt.py +0 -0
  389. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_guard_repair_e2e.py +0 -0
  390. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_guard_repair_prompt.py +0 -0
  391. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_hashed_denylist.py +0 -0
  392. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_hashed_denylist_ci.py +0 -0
  393. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_heartbeat.py +0 -0
  394. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_heartbeat_adapter.py +0 -0
  395. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_human_output_rule.py +0 -0
  396. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_human_work_unit.py +0 -0
  397. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_hygiene_boundary_guidance.py +0 -0
  398. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_hyphenated_gate_name.py +0 -0
  399. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_ignored_cleanup_before_probe.py +0 -0
  400. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_init_integration.py +0 -0
  401. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_installed_copy_driver_e2e.py +0 -0
  402. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_interpreter_normalization.py +0 -0
  403. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_judge_close_path.py +0 -0
  404. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_judge_cost.py +0 -0
  405. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_judge_cost_fold_committed.py +0 -0
  406. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_judge_module.py +0 -0
  407. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_judge_path_registry.py +0 -0
  408. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_judge_terminal_flip_state.py +0 -0
  409. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_judged_event_points_at_findings.py +0 -0
  410. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_label_description_length.py +0 -0
  411. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_label_provisioning_runner_contract.py +0 -0
  412. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_label_registry.py +0 -0
  413. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_label_registry_covers_consumers.py +0 -0
  414. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_language_aware_narrow_selection.py +0 -0
  415. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lazy_baseline_e2e.py +0 -0
  416. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_leak_findings_redaction.py +0 -0
  417. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_leak_scan.py +0 -0
  418. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_leak_scan_content.py +0 -0
  419. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_learnings_curate_vendored_promote.py +0 -0
  420. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_learnings_distil_cli.py +0 -0
  421. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_learnings_query.py +0 -0
  422. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_learnings_staging.py +0 -0
  423. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_learnings_suggest_signature_filter.py +0 -0
  424. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_learnings_weights.py +0 -0
  425. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_legacy_4wu_terminal_flips.py +0 -0
  426. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lifecycle_integration.py +0 -0
  427. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lifetime_accounting.py +0 -0
  428. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_ac_observable.py +0 -0
  429. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_bare_produces_path.py +0 -0
  430. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_boundary_consistency.py +0 -0
  431. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_boundary_extraction.py +0 -0
  432. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_close_intermediate.py +0 -0
  433. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_close_verdict_not_predecided.py +0 -0
  434. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_close_wu.py +0 -0
  435. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_closing.py +0 -0
  436. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_closing_criteria.py +0 -0
  437. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_closing_criteria_pristine.py +0 -0
  438. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_correlation_id.py +0 -0
  439. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_correlation_id_close_intermediate.py +0 -0
  440. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_covers_load_wu_invariants.py +0 -0
  441. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_feature_oracle_declared.py +0 -0
  442. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_monitoring.py +0 -0
  443. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_oracle_env.py +0 -0
  444. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_plan_contract_fields.py +0 -0
  445. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_plan_errors.py +0 -0
  446. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_plan_next_draft.py +0 -0
  447. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_plan_relative_import.py +0 -0
  448. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_plan_verdict_exempt.py +0 -0
  449. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_planning_sections.py +0 -0
  450. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_produces_driver_helper.py +0 -0
  451. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_produces_satisfiability.py +0 -0
  452. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_roadmap.py +0 -0
  453. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_sections.py +0 -0
  454. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_task_graph_yaml_selection.py +0 -0
  455. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_lint_verification_reference.py +0 -0
  456. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_live_tests_opt_in.py +0 -0
  457. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_load_bearing_close_lint.py +0 -0
  458. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_attempt_evidence.py +0 -0
  459. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_caveman_preamble.py +0 -0
  460. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_criteria_skeleton.py +0 -0
  461. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_criteria_survival.py +0 -0
  462. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_defaults_by_type.py +0 -0
  463. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_effort.py +0 -0
  464. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_failure_note_cap.py +0 -0
  465. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_files_changed_guard.py +0 -0
  466. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_gate_budget.py +0 -0
  467. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_gate_needs.py +0 -0
  468. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_model_alias.py +0 -0
  469. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_orchestration.py +0 -0
  470. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_post_pass_invariant.py +0 -0
  471. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_reset_preserving_events.py +0 -0
  472. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_smoke_runner.py +0 -0
  473. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_unsandboxed.py +0 -0
  474. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_worklist_injection.py +0 -0
  475. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_loop_zero_token_guard.py +0 -0
  476. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_make_repo_gpgsign_isolation.py +0 -0
  477. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_marker_dual_shape.py +0 -0
  478. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_maven_failure_excerpt.py +0 -0
  479. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_max_attempts_configurable.py +0 -0
  480. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_max_open_prs.py +0 -0
  481. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_migrate_legacy.py +0 -0
  482. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_miniyaml_equivalence.py +0 -0
  483. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_miniyaml_negative.py +0 -0
  484. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_monitor_cli.py +0 -0
  485. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_monitor_issue_lifecycle.py +0 -0
  486. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_monitor_runner_surfaces.py +0 -0
  487. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_monitoring_bootstrap_artifacts.py +0 -0
  488. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_monitoring_cron_dialect.py +0 -0
  489. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_monitoring_example.py +0 -0
  490. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_monitoring_fenced_blocks.py +0 -0
  491. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_monitoring_seed.py +0 -0
  492. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_narrow_fallback_warning.py +0 -0
  493. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_needs_decision_outcome.py +0 -0
  494. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_no_pytest_subprocess.py +0 -0
  495. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_notify.py +0 -0
  496. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_notify_escalation.py +0 -0
  497. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_notify_sla.py +0 -0
  498. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_operator_escalation_rule.py +0 -0
  499. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_oracle_set_declared.py +0 -0
  500. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_oracle_unrunnable_attribution.py +0 -0
  501. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_per_run_item_cap_disclosure.py +0 -0
  502. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_pick_feature_skill.py +0 -0
  503. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_pin_honesty_and_integrity.py +0 -0
  504. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_pin_marker_not_inherited.py +0 -0
  505. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_pin_marker_spawn_sites.py +0 -0
  506. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_plan_baseline.py +0 -0
  507. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_planned_cost_lint.py +0 -0
  508. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_planning_cost_floor.py +0 -0
  509. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_plugin_prose_cross_refs.py +0 -0
  510. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_plugin_qualified_dispatch.py +0 -0
  511. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_policy_budgets_applied.py +0 -0
  512. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_policy_proposals.py +0 -0
  513. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_policy_review.py +0 -0
  514. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_pr_checks_json_field.py +0 -0
  515. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_pr_reference_in_title.py +0 -0
  516. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_pre_existing_claims_cite_evidence.py +0 -0
  517. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_prep_halt_operator_surface.py +0 -0
  518. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_prepare_feature.py +0 -0
  519. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_prepare_scaffold_sync.py +0 -0
  520. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_prerun_capture.py +0 -0
  521. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_prerun_oracles.py +0 -0
  522. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_prerun_wiring.py +0 -0
  523. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_produced_document_verdict_guard.py +0 -0
  524. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_produces_bracket_literal.py +0 -0
  525. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_produces_bracket_wildcard.py +0 -0
  526. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_produces_field.py +0 -0
  527. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_produces_in_diff.py +0 -0
  528. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_produces_justification.py +0 -0
  529. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_produces_recursive_glob.py +0 -0
  530. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_produces_semantics_unified.py +0 -0
  531. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_produces_shape.py +0 -0
  532. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_progress_forward_note.py +0 -0
  533. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_progress_lines_end_to_end.py +0 -0
  534. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_promotion_ledger.py +0 -0
  535. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_provider_escalation_traces.py +0 -0
  536. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_provision_labels.py +0 -0
  537. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_queue_stalled_adapter.py +0 -0
  538. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_rearm_fold_marker.py +0 -0
  539. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_rearm_migration.py +0 -0
  540. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_red_baseline_never_reused.py +0 -0
  541. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_red_on_base_guardrail.py +0 -0
  542. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_red_on_base_probe.py +0 -0
  543. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_redaction_windows_home.py +0 -0
  544. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_reflection_required_signals.py +0 -0
  545. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_replan_end_to_end.py +0 -0
  546. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_replan_event_emission.py +0 -0
  547. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_replan_note_collision.py +0 -0
  548. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_replan_trigger.py +0 -0
  549. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_replan_turn_contract.py +0 -0
  550. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_replay_spin.py +0 -0
  551. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_required_checks.py +0 -0
  552. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_resolve_base.py +0 -0
  553. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_restart_cap_counts_progress.py +0 -0
  554. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_result_block.py +0 -0
  555. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_result_block_audience.py +0 -0
  556. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_resume_command_build.py +0 -0
  557. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_retain_on_guard_refusal_docs.py +0 -0
  558. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_roadmap_add_skill.py +0 -0
  559. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_roadmap_archive_cli.py +0 -0
  560. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_roadmap_archive_shim.py +0 -0
  561. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_roadmap_archive_skill.py +0 -0
  562. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_roadmap_archive_skill_delegates.py +0 -0
  563. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_roadmap_link_gate.py +0 -0
  564. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_roadmap_row_parser.py +0 -0
  565. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_ruff_verdict_lines.py +0 -0
  566. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_rule_import_convergence.py +0 -0
  567. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_run_level_failure_breaker.py +0 -0
  568. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_scaffold_data_in_sync.py +0 -0
  569. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_scaffold_doc_hygiene.py +0 -0
  570. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_scaffold_docs.py +0 -0
  571. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_scaffold_init.py +0 -0
  572. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_scaffold_label_provisioning.py +0 -0
  573. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_scaffold_manifest.py +0 -0
  574. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_scaffold_resources.py +0 -0
  575. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_scaffold_seed_sanity.py +0 -0
  576. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_scaffold_skew_halts.py +0 -0
  577. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_scaffold_upgrade.py +0 -0
  578. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_scaffold_wiring.py +0 -0
  579. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_schedule_dialect.py +0 -0
  580. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_seed_documents_prerun_keys.py +0 -0
  581. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_service_bus_dlq_adapter.py +0 -0
  582. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_session_env_preflight.py +0 -0
  583. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_severity_aliases.py +0 -0
  584. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_severity_backfill_apply.py +0 -0
  585. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_severity_backfill_end_to_end.py +0 -0
  586. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_severity_backfill_limit.py +0 -0
  587. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_severity_backfill_marker.py +0 -0
  588. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_severity_backfill_run.py +0 -0
  589. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_severity_label_projection.py +0 -0
  590. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_severity_reconciliation.py +0 -0
  591. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_severity_rubric.py +0 -0
  592. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_shipped_templates_parse.py +0 -0
  593. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_skill_discovery_links.py +0 -0
  594. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_skills_vendored_in_sync.py +0 -0
  595. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_spec_work_unit_rules.py +0 -0
  596. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_spinning_rearm_gate.py +0 -0
  597. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_spinout_brief_end_to_end.py +0 -0
  598. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_spinout_brief_replan_option.py +0 -0
  599. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_squash_commit_hook_crash.py +0 -0
  600. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_stop_rationale_captured.py +0 -0
  601. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_stranded_halt_cause.py +0 -0
  602. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_surefire_run_level_signature.py +0 -0
  603. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_surefire_verdict_lines.py +0 -0
  604. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_template_closing_shapes.py +0 -0
  605. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_terminal_flip_ownership.py +0 -0
  606. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_terminal_flips.py +0 -0
  607. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_terminal_gate_message.py +0 -0
  608. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_tiered_verification_e2e.py +0 -0
  609. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_timeout_kill_portable.py +0 -0
  610. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_triage.py +0 -0
  611. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_triage_apply.py +0 -0
  612. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_triage_projects_severity_label.py +0 -0
  613. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_triage_severity_classify.py +0 -0
  614. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_triage_severity_end_to_end.py +0 -0
  615. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_triage_severity_write.py +0 -0
  616. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_triage_skill_contract.py +0 -0
  617. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_triage_skips_agent_escalations.py +0 -0
  618. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_tsc_verdict_lines.py +0 -0
  619. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_umbrella_version_resolution.py +0 -0
  620. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_unterminated_frontmatter.py +0 -0
  621. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_untracked_feature_folder.py +0 -0
  622. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_untracked_file_absorption.py +0 -0
  623. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_upgrade_integration.py +0 -0
  624. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_upgrade_merge_gate.py +0 -0
  625. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_validate_event.py +0 -0
  626. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_validate_event_driver_types.py +0 -0
  627. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_verdict_coupling.py +0 -0
  628. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_verify_empty_gate_set.py +0 -0
  629. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_version_consistency.py +0 -0
  630. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_version_skew.py +0 -0
  631. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_windows_gate_exec.py +0 -0
  632. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_worktree_restore.py +0 -0
  633. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_wu_execution_metadata.py +0 -0
  634. {specfuse_loop-0.24.0 → specfuse_loop-0.26.0}/tests/test_wu_template_renders_lintable.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specfuse-loop
3
- Version: 0.24.0
3
+ Version: 0.26.0
4
4
  Summary: Local-first executor for the Specfuse Plan + Work Unit gate-cycle methodology.
5
5
  Author: Specfuse contributors
6
6
  License: Apache-2.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "specfuse-loop"
7
- version = "0.24.0"
7
+ version = "0.26.0"
8
8
  description = "Local-first executor for the Specfuse Plan + Work Unit gate-cycle methodology."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -155,6 +155,25 @@ FEATURE_ORACLE_VERDICT_RE = re.compile(
155
155
  rf"^###\s+{re.escape(FEATURE_ORACLE_KEY)}:\s*(PASS|FAIL)\s*$", re.MULTILINE,
156
156
  )
157
157
 
158
+ #: A re-close's `## Measurements` carry-accounting line (FEAT-2026-0117/T03),
159
+ #: required only when `GATE-NN-CRITERIA.md` has at least one
160
+ #: `carried_from_attempt` entry — a first close has no new obligation.
161
+ #: `entries` is duck-typed (`criteria_state.CriterionStateEntry`, or anything
162
+ #: with a `carried_from_attempt` attribute): this registry stays a pure-data
163
+ #: module with no import of the artifact schema it describes.
164
+ def carry_summary_is_required(entries) -> bool:
165
+ """True when at least one entry carries a green forward from a prior
166
+ attempt — the trigger for the `## Measurements` carry-accounting line."""
167
+ return any(entry.carried_from_attempt is not None for entry in entries)
168
+
169
+
170
+ def render_carry_summary(entries) -> str:
171
+ """The exact `## Measurements` line a close pastes when `entries` carries
172
+ any criterion forward: `carried forward: N criteria, re-measured: M`."""
173
+ carried = sum(1 for entry in entries if entry.carried_from_attempt is not None)
174
+ return f"carried forward: {carried} criteria, re-measured: {len(entries) - carried}"
175
+
176
+
158
177
  GATE_REVIEW_FILENAME_TEMPLATE = "GATE-{next_gate:02d}-REVIEW.md"
159
178
 
160
179
 
@@ -378,6 +397,19 @@ CLOSING_REQUIREMENTS: dict[str, list[Requirement]] = {
378
397
  file=RETROSPECTIVE_FILENAME,
379
398
  enforced_by="check_feature_oracle_verdict_recorded",
380
399
  ),
400
+ Requirement(
401
+ id="close-o", wu_type="close", phase="pre-squash",
402
+ description=(
403
+ "When GATE-NN-CRITERIA.md carries at least one entry forward "
404
+ "from a prior attempt, RETROSPECTIVE.md's Measurements "
405
+ "section records the render_carry_summary(entries) line — "
406
+ "'carried forward: N criteria, re-measured: M' — so the "
407
+ "close states what it inherited (FEAT-2026-0117/T03)"
408
+ ),
409
+ file=RETROSPECTIVE_FILENAME,
410
+ applies_when="criteria_artifact_present",
411
+ enforced_by="check_carry_summary_recorded",
412
+ ),
381
413
  ],
382
414
  "close-intermediate": [
383
415
  Requirement(
@@ -20,7 +20,8 @@ FEAT-2026-0056/PLAN.md and GATE-01.md for the design this module encodes.
20
20
  from __future__ import annotations
21
21
 
22
22
  import re
23
- from dataclasses import dataclass
23
+ from dataclasses import dataclass, field
24
+ from pathlib import Path
24
25
  from typing import Optional
25
26
 
26
27
  #: An oracle's scope classification. `narrow` oracles (a scoped test nodeid,
@@ -41,6 +42,11 @@ _FIELD_PATTERNS = {
41
42
  "state": re.compile(r"^- \*\*state:\*\*\s*`([^`]+)`", re.MULTILINE),
42
43
  "proved_at_sha": re.compile(r"^- \*\*proved_at_sha:\*\*\s*`([^`]+)`", re.MULTILINE),
43
44
  "attempt": re.compile(r"^- \*\*attempt:\*\*\s*`?([^`\n]+)`?", re.MULTILINE),
45
+ "carried_from_attempt": re.compile(
46
+ r"^- \*\*carried_from_attempt:\*\*\s*`?([^`\n]+)`?", re.MULTILINE
47
+ ),
48
+ "covers": re.compile(r"^- \*\*covers:\*\*\s*(.+)$", re.MULTILINE),
49
+ "invalidated_by": re.compile(r"^- \*\*invalidated_by:\*\*\s*(.+)$", re.MULTILINE),
44
50
  }
45
51
 
46
52
 
@@ -55,6 +61,20 @@ class CriterionStateEntry:
55
61
  state: Optional[str]
56
62
  proved_at_sha: Optional[str]
57
63
  attempt: Optional[str]
64
+ #: Set by `reset_stale_criteria_entries` when a re-arm carries this
65
+ #: entry's narrow green past the attempt cycle that proved it — the
66
+ #: attempt number it was carried FROM, not the current attempt.
67
+ carried_from_attempt: Optional[str] = None
68
+ #: Paths this criterion's proof depends on — its producing WU's
69
+ #: `produces:` plus its oracle's test file, when derivable
70
+ #: (`derive_criterion_covers`, FEAT-2026-0117/T02). Empty when never
71
+ #: seeded with a `- **covers:**` line: an entry the skeleton step hasn't
72
+ #: backfilled yet, or one predating this field.
73
+ covers: list = field(default_factory=list)
74
+ #: Set by `invalidate_carried_entries` when a re-close's gate diff
75
+ #: touches a path this (formerly carried) entry `covers` — names that
76
+ #: path, not the whole diff.
77
+ invalidated_by: Optional[str] = None
58
78
 
59
79
 
60
80
  #: Matches `GATE-NN-CRITERIA.md` basenames (any `NN`), and nothing else —
@@ -98,6 +118,8 @@ def parse_criteria_state(text: str) -> list[CriterionStateEntry]:
98
118
  start = m.end()
99
119
  end = headings[i + 1].start() if i + 1 < len(headings) else len(text)
100
120
  block = text[start:end]
121
+ covers_raw = _extract_field(block, "covers")
122
+ covers = [c.strip() for c in covers_raw.split(",") if c.strip()] if covers_raw else []
101
123
  entries.append(
102
124
  CriterionStateEntry(
103
125
  criterion_id=criterion_id,
@@ -107,11 +129,77 @@ def parse_criteria_state(text: str) -> list[CriterionStateEntry]:
107
129
  state=_extract_field(block, "state"),
108
130
  proved_at_sha=_extract_field(block, "proved_at_sha"),
109
131
  attempt=_extract_field(block, "attempt"),
132
+ carried_from_attempt=_extract_field(block, "carried_from_attempt"),
133
+ covers=covers,
134
+ invalidated_by=_extract_field(block, "invalidated_by"),
110
135
  )
111
136
  )
112
137
  return entries
113
138
 
114
139
 
140
+ def resolve_carry_forward_narrow_greens(cfg: "dict | None") -> bool:
141
+ """Whether a re-armed close carries a `narrow`/`pass` entry's green
142
+ forward past the attempt cycle that proved it (FEAT-2026-0117/T01).
143
+
144
+ Reads `verification.yml` `defaults.carry_forward_narrow_greens` — default
145
+ True, same project-default precedence tier as `loop.py`'s other
146
+ `resolve_*` readers. *cfg* is the already-loaded `verification.yml` dict;
147
+ this module does no file I/O of its own.
148
+ """
149
+ if not cfg:
150
+ return True
151
+ return (cfg.get("defaults") or {}).get("carry_forward_narrow_greens", True) is not False
152
+
153
+
154
+ def reset_stale_criteria_entries(
155
+ entries: list[CriterionStateEntry], current_attempt: int, carry_narrow: bool,
156
+ ) -> list[CriterionStateEntry]:
157
+ """Reset entries left behind by a superseded attempt cycle (#3279).
158
+
159
+ An entry whose recorded `attempt` exceeds *current_attempt* was measured
160
+ in a cycle a re-arm has since superseded. With *carry_narrow* true, an
161
+ entry that is also `kind: narrow` and `state: pass` is provably safe to
162
+ keep — its oracle's scope was knowable, so a re-arm does not invalidate
163
+ what it proved — and keeps every field, gaining `carried_from_attempt`
164
+ set to the attempt it was proved on. Every other stale entry resets to
165
+ `unverified` with its per-attempt fields cleared, exactly as if it had
166
+ never been verified. Entries at or below the current attempt, and
167
+ entries with no recorded attempt, are returned unchanged.
168
+ """
169
+ refreshed: list[CriterionStateEntry] = []
170
+ for entry in entries:
171
+ recorded = entry.attempt
172
+ try:
173
+ is_stale = recorded is not None and int(str(recorded).strip()) > current_attempt
174
+ except (TypeError, ValueError):
175
+ is_stale = False # unparseable attempt: leave it for the close
176
+ if is_stale:
177
+ if carry_narrow and entry.kind == "narrow" and entry.state == "pass":
178
+ entry = CriterionStateEntry(
179
+ criterion_id=entry.criterion_id,
180
+ criterion=entry.criterion,
181
+ oracle=entry.oracle,
182
+ kind=entry.kind,
183
+ state=entry.state,
184
+ proved_at_sha=entry.proved_at_sha,
185
+ attempt=entry.attempt,
186
+ carried_from_attempt=str(recorded).strip(),
187
+ )
188
+ else:
189
+ entry = CriterionStateEntry(
190
+ criterion_id=entry.criterion_id,
191
+ criterion=entry.criterion,
192
+ oracle=None,
193
+ kind=None,
194
+ state="unverified",
195
+ proved_at_sha=None,
196
+ attempt=None,
197
+ carried_from_attempt=None,
198
+ )
199
+ refreshed.append(entry)
200
+ return refreshed
201
+
202
+
115
203
  @dataclass(frozen=True)
116
204
  class ReverificationWorklist:
117
205
  """Partition of a gate's recorded entries for a re-dispatched close attempt.
@@ -138,6 +226,11 @@ def build_reverification_worklist(
138
226
  fail` or `state: unverified`, and every `broad` entry regardless of
139
227
  state — goes to `reverify`. Fail-safe default: unclassifiable entries
140
228
  land in `reverify`, never in `carry_forward`.
229
+
230
+ `covers` plays no part in this partition — a `carried_from_attempt`
231
+ entry with an empty `covers` is kept out of `carry_forward` by
232
+ `loop.invalidate_carried_entries` resetting it to `unverified` before
233
+ this runs (FEAT-2026-0117/T02), not by a check here.
141
234
  """
142
235
  carry_forward: list[CriterionStateEntry] = []
143
236
  reverify: list[CriterionStateEntry] = []
@@ -191,5 +284,65 @@ def render_criteria_state(entries: list[CriterionStateEntry]) -> str:
191
284
  lines.append(f"- **proved_at_sha:** `{entry.proved_at_sha}`")
192
285
  if entry.attempt is not None:
193
286
  lines.append(f"- **attempt:** `{entry.attempt}`")
287
+ if entry.carried_from_attempt is not None:
288
+ lines.append(f"- **carried_from_attempt:** `{entry.carried_from_attempt}`")
289
+ if entry.covers:
290
+ lines.append(f"- **covers:** {', '.join(entry.covers)}")
291
+ if entry.invalidated_by is not None:
292
+ lines.append(f"- **invalidated_by:** {entry.invalidated_by}")
194
293
  blocks.append("\n".join(lines) + "\n")
195
294
  return "\n".join(blocks)
295
+
296
+
297
+ _UNITTEST_ORACLE_RE = re.compile(r"-m\s+unittest\s+([\w.]+)")
298
+ _MAVEN_DTEST_RE = re.compile(r"-Dtest=([A-Za-z_][A-Za-z0-9_]*)")
299
+
300
+
301
+ def _unittest_module_path(oracle_command: str) -> "Optional[str]":
302
+ """`tests.foo_bar[.TestX.test_y]` -> `tests/foo_bar.py`, the file the
303
+ unittest oracle actually runs regardless of which class/method suffix it
304
+ names. Tries the longest dotted prefix that exists on disk first, so a
305
+ package (`tests/foo_bar/__init__` style) is not required; falls back to
306
+ the full dotted-to-slash mapping when nothing on disk matches yet."""
307
+ m = _UNITTEST_ORACLE_RE.search(oracle_command)
308
+ if not m:
309
+ return None
310
+ parts = m.group(1).split(".")
311
+ for i in range(len(parts), 0, -1):
312
+ candidate = "/".join(parts[:i]) + ".py"
313
+ if Path(candidate).is_file():
314
+ return candidate
315
+ return "/".join(parts) + ".py"
316
+
317
+
318
+ def _maven_test_class_path(oracle_command: str) -> "Optional[str]":
319
+ """`-Dtest=FooBarTest` -> its `src/test/**/FooBarTest.java`, only when
320
+ one actually exists — unlike the unittest case, a Maven class name gives
321
+ no reliable package-to-path mapping without a filesystem lookup."""
322
+ m = _MAVEN_DTEST_RE.search(oracle_command)
323
+ if not m:
324
+ return None
325
+ root = Path("src/test")
326
+ if not root.is_dir():
327
+ return None
328
+ matches = sorted(root.rglob(f"{m.group(1)}.java"))
329
+ return str(matches[0]) if matches else None
330
+
331
+
332
+ def derive_criterion_covers(wu, oracle_command: "Optional[str]") -> list:
333
+ """Paths a criterion's proof depends on (FEAT-2026-0117/T02): its
334
+ producing WU's `produces:` plus the test file its oracle command names,
335
+ when derivable. Feeds a seeded entry's `- **covers:**` line so a re-close
336
+ can tell whether a later diff touched what a carried green actually
337
+ measured — see `invalidate_carried_entries` in `loop.py`.
338
+
339
+ *wu* is anything with a `.produces` list (a `WorkUnit`, or a duck-typed
340
+ stand-in built from a WU read off disk); *oracle_command* is the entry's
341
+ recorded `oracle`, or `None` before a close has run it.
342
+ """
343
+ covers = list(getattr(wu, "produces", None) or [])
344
+ if oracle_command:
345
+ test_path = _unittest_module_path(oracle_command) or _maven_test_class_path(oracle_command)
346
+ if test_path and test_path not in covers:
347
+ covers.append(test_path)
348
+ return covers
@@ -0,0 +1 @@
1
+ 0.26.0
@@ -127,6 +127,22 @@ it mostly does not need. Author-set unless marked driver-owned.
127
127
  `attempts`, `cost_usd`, `input_tokens`, `output_tokens`, `duration_seconds`,
128
128
  `cumulative_*`, `re_arm_count`, `re_arm_history`, `folded_through_re_arm`,
129
129
  `model`/`effort` as resolved, `gate_set`, `driver_version`, `started_at`.
130
+ - `produces_dropped` — driver-owned. Written when a RESULT's `produces_amended:`
131
+ entries are accepted (`defaults.produces_amendable: true`): the paths dropped
132
+ from this unit's recorded `produces:` (`.specfuse/rules/result-contract.md`).
133
+ - `covers` — driver-seeded, on a `GATE-NN-CRITERIA.md` entry, not WU frontmatter.
134
+ The path(s) that criterion's oracle actually exercises; absent when no path is
135
+ derivable, in which case the criterion is never carried forward.
136
+ - `carried_from_attempt` — driver-owned, on a carried `GATE-NN-CRITERIA.md`
137
+ entry. The attempt number whose run proved the green being carried.
138
+ - `invalidated_by` — driver-owned, on a `GATE-NN-CRITERIA.md` entry whose
139
+ carried green was invalidated. Names the path in `covers:` the gate diff
140
+ touched since `proved_at_sha`.
141
+
142
+ `defaults.carry_forward_narrow_greens` (`verification.yml`, default `true`) —
143
+ whether a re-close may carry forward a prior attempt's `narrow` green at all;
144
+ see `.specfuse/verification.yml.example` and
145
+ `.specfuse/rules/close-discipline.md` §5.
130
146
 
131
147
  ## 3. Work unit types
132
148
 
@@ -388,12 +404,19 @@ after v2+ revisions ship.
388
404
  Every dispatched attempt emits exactly one `attempt_outcome` event to
389
405
  `events.jsonl`. The payload carries a standardized set of fields:
390
406
  `outcome`, `failure_class`, `failure_signature`, `failure_excerpt`,
391
- `cost_usd`, `duration_seconds`, `attempt`, and `re_arm_count`. For
392
- the field-by-field schema see
407
+ `failing_tests`, `cost_usd`, `duration_seconds`, `attempt`, and
408
+ `re_arm_count`. For the field-by-field schema see
393
409
  `.specfuse/features/FEAT-2026-0016-attempt-outcome-rearm-contract/PLAN.md`
394
410
  § "Event payload shape — `attempt_outcome` v1". The full payload is
395
411
  not restated here (one fact, one home).
396
412
 
413
+ `failing_tests` is the sorted, de-duplicated list of failing test ids
414
+ `extract_failing_tests` recognised in the gate report (empty when no
415
+ runner-recognised per-test id was found); for `failure_class: tests`,
416
+ `detect_spinning_signature_repeat` treats two non-empty `failing_tests`
417
+ sets as the same failure iff they are equal as sets, ahead of the
418
+ `(failure_class, failure_signature)` comparison (FEAT-2026-0116).
419
+
397
420
  `outcome` taxonomy, as `loop.py` actually emits it — thirteen values,
398
421
  bound to the emitter by `tests/test_attempt_outcome_contract.py`:
399
422
 
@@ -454,6 +477,41 @@ separately carry `auto_repaired_files_changed` in `extras`: the list of
454
477
  declared-but-unchanged `files_changed` paths the driver dropped on the
455
478
  WU's behalf rather than failing the attempt over.
456
479
 
480
+ **Dispatch without the skills index (#3423).** A dispatched session runs
481
+ `claude -p --disable-slash-commands` by default: a work unit invokes no
482
+ skill, and the project's skills index (34 skills, 1,534 words of descriptions
483
+ in the loop repository) is fixed context carried in every turn's cache read.
484
+ `defaults.dispatch_skills: true` in `verification.yml` restores the index for
485
+ a project whose units do call `/skill-name` in-session.
486
+
487
+ **The post-merge checklist travels with the archive (#3424).** A `met`
488
+ terminal close no longer files PLAN.md's `## Post-merge checklist` as a
489
+ `specfuse:post-merge` issue (ten filed across two repositories, eight never
490
+ actioned); `auto_archive_feature` appends it under the feature's archived
491
+ detail section in `roadmap-archive.md`. `defaults.post_merge_issue: true` in
492
+ `verification.yml` restores the issue.
493
+
494
+ **A RESULT may amend the plan, never add to it (FEAT-2026-0114).** A session's
495
+ `produces_amended:` entry claims a planned `produces:` path the solution did
496
+ not need; `defaults.produces_amendable: true` in `verification.yml` lets the
497
+ driver accept it, dropping the path into `produces_dropped` on the unit.
498
+ Default `false` — an unrecognized amendment is judged as an unjustified
499
+ unchanged deliverable (`.specfuse/rules/result-contract.md`).
500
+
501
+ **A block may name its own fix (FEAT-2026-0115).** A `blocked` RESULT's
502
+ `blocked_next:` names a drafted fix unit; once the arm checks clear, the
503
+ driver inserts it ahead of the blocked unit and emits `fix_unit_inserted` to
504
+ `events.jsonl` on re-arm. `defaults.fix_unit_insertion: true` in
505
+ `verification.yml` gates the feature accepting one at all;
506
+ `defaults.max_fix_units_per_unit: 2` caps insertions per blocked unit.
507
+
508
+ **Closing sessions run on sonnet (#3425).** `close`, `close-intermediate`
509
+ and `plan-next` default to `sonnet` at effort `high`, the same model as the
510
+ judge that checks them (lower-only, about $0.46 per close). Opus was 56% of
511
+ all spend while implementation ran on sonnet. A unit's own
512
+ `model:` still overrides the default, and every `judged` event carries
513
+ `close_model` so judge agreement can be read per close model.
514
+
457
515
  Retention interacts with spinning detection, not around it:
458
516
  `detect_deterministic_refusal_repeat` (#1415) escalates a WU to
459
517
  `blocked_human` when two consecutive attempts emit an identical refusal
@@ -579,7 +637,7 @@ completion.
579
637
 
580
638
  Closing ceremony cost should scale with feature size. A feature whose
581
639
  **planned substantive** WU count (types `implementation`, `qa_authoring`,
582
- `qa_execution`, `qa_curation`) is **≤ 8** drafts as a **single gate** with
640
+ `qa_execution`, `qa_curation`) is **≤ 12** drafts as a **single gate** with
583
641
  a **single terminal `close` WU** — no `close-intermediate`, no `plan-next`.
584
642
  This is the proportional shape: small features do not pay multi-WU closing
585
643
  overhead sized for large ones.
@@ -597,6 +655,13 @@ reflective session. Ceremony proportionality trades reflection only on
597
655
  features that stay small **and** on-plan. The `gate_eval.py` predicate is
598
656
  the safety net; this rule does not replace it.
599
657
 
658
+ The line moved from 8 to 12 on 2026-09-26 (#3426): post-review features
659
+ average 10.7 substantive units, every extra gate costs a `plan-next` plus a
660
+ `close-intermediate` and an `awaiting_review` wait, and the arm predicate
661
+ would have armed only 18 of 74 gate boundaries it evaluated — the wait was a
662
+ human redraft, not a review. A feature goes multi-gate when a human decision
663
+ sits between its gates, not because it is large.
664
+
600
665
  **Reflective prose is conditional too (FEAT-2026-0106).** The roadmap once
601
666
  asked for a retrospective "only on `not_met` or on request" — superseded,
602
667
  for an ordering reason: the close writes `RETROSPECTIVE.md` before the judge
@@ -222,6 +222,17 @@ green would be an unsound coverage claim; it re-runs on every close attempt.
222
222
  inferred by a reader, the same posture §2 already takes on the hedged-record
223
223
  `kind:`. `specfuse lint --closing` is the check.
224
224
 
225
+ **A carried `narrow` green is invalidated when the criterion's covered paths
226
+ changed since it was proved.** Each entry may carry a driver-seeded `covers:`
227
+ — the path(s) its oracle actually exercises. On a re-close, a carried entry's
228
+ `narrow` green is invalidated (re-measured, not trusted) when the gate diff
229
+ since that entry's `proved_at_sha` touches a path in its `covers:`. A
230
+ criterion with no derivable `covers:` is never carried — it re-measures on
231
+ every close attempt, the same as a `broad` entry. A carried entry also
232
+ carries `carried_from_attempt`, the attempt number whose run proved it. A
233
+ re-close's `## Measurements` states how much of the gate's state was inherited
234
+ versus fresh: `carried forward: N criteria, re-measured: M`.
235
+
225
236
  ## Split with project-local rules
226
237
 
227
238
  These are the generic obligations. The concrete grounding — which command is
@@ -0,0 +1,143 @@
1
+ <!--
2
+ Copyright 2026 Specfuse Contributors
3
+ Licensed under the Apache License, Version 2.0. See LICENSE.
4
+ -->
5
+
6
+ # Rule: the RESULT block contract
7
+
8
+ A dispatched work-unit session ends with one fenced `result` block as the last
9
+ thing in its output; the driver reads it, and a session emitting none is a
10
+ failed attempt. The RESULT is **advisory** — the driver re-runs verification
11
+ itself, and that decides done.
12
+
13
+ ## Who reads it — emit it only when something does
14
+
15
+ This block is a **machine interface**, not a report. Emit it only when a
16
+ program is on the other end: a dispatched work-unit session (always), or a
17
+ skill invoked **non-interactively** from a calling program parsing the
18
+ outcome (`fix-bug` under `autofix_invoke`).
19
+
20
+ Do **not** emit it on an interactive run — a human typing `/pick-feature` has
21
+ no parser, and the block becomes a slab to scroll past, the verbosity
22
+ [`human-output.md`](human-output.md) prevents. Report per that rule instead.
23
+ Rule of thumb: a person-typed slash command is interactive; a `claude -p`
24
+ dispatch is not.
25
+
26
+ ## The cycle: state intent, act, verify, report
27
+
28
+ [`verification-discipline.md`](verification-discipline.md) is normative on the
29
+ cycle; this file is normative on how the loop surface reports step 4.
30
+
31
+ 1. **State intent.** One sentence on what you are about to do and why it is the
32
+ next right step. If it disagrees with the work unit's acceptance criteria,
33
+ the unit is not what you thought it was.
34
+ 2. **Act.** Stay inside that scope. "While I was here I also fixed X" is drift;
35
+ the work unit's **Do not touch** section is binding.
36
+ 3. **Verify.** Re-read what you produced — Write/Edit reports the action taken,
37
+ not the property you wanted — and run the unit's own verification commands,
38
+ in declared order, with full output. On the loop that set is the
39
+ **per-attempt (narrow) tier**: the unit type's gates minus any declaring
40
+ `tier: broad`, with `tests` through its `narrow_command` over the unit's
41
+ `produces:` test modules. The full suite, coverage and every `tier: broad`
42
+ gate are the driver's, once per gate — running them in-session buys
43
+ nothing. "I assume the tests still pass" is not verification. A
44
+ behavioural claim needs a run, not a source reading; a rule-or-severity
45
+ claim needs a **negative observation** — the rule seen rejecting a
46
+ purpose-built bad input.
47
+ 4. **Report.** Report only what verification confirmed.
48
+
49
+ A failing check leaves you in one of three situations: correctable locally
50
+ (fix the cause, re-run the **whole narrow tier** from the top), spinning
51
+ (three fresh attempts is the driver's budget — emit `status: blocked` with
52
+ evidence rather than guessing), or fundamentally blocked (spec ambiguity,
53
+ generated code that must change, a missing dependency — emit `status: blocked`
54
+ naming the boundary).
55
+
56
+ ## Format
57
+
58
+ ````markdown
59
+ ```result
60
+ status: complete | blocked # complete = "I believe acceptance criteria are met"
61
+ summary: <one sentence on what changed>
62
+ forward_note: <optional — one sentence on what the NEXT unit should know>
63
+ files_changed:
64
+ - path/to/file
65
+ acceptance_criteria:
66
+ - text: <criterion, copied from the work unit>
67
+ met: true | false
68
+ evidence: <how you know — a test name, a behavior, a line reference>
69
+ blocked_reason: <present only when status is blocked>
70
+ blocked_next: # optional — a drafted fix unit
71
+ kind: fix_unit
72
+ file: <path to the drafted WU>
73
+ id: <the drafted WU's id>
74
+ produces_unchanged: # optional — obligation 1 below
75
+ - path: <a produces: entry, verbatim>
76
+ justification: <the command you ran and its output showing the deliverable already holds>
77
+ produces_amended: # optional — obligation 1 below
78
+ - path: <a produces: entry, verbatim>
79
+ justification: <why the plan named it but the solution didn't need it>
80
+ ```
81
+ ````
82
+
83
+ `summary` is backward-looking by this contract's own definition — one sentence
84
+ on what changed. `forward_note` is the other half: what surprised you, or what
85
+ the next unit should know, that `summary` misses. Optional, never required by
86
+ any guard — omit it and the driver's `PROGRESS.md` entry is unchanged
87
+ (FEAT-2026-0106/T02).
88
+
89
+ ## Rules
90
+
91
+ 1. **No git.** Edit files only. The driver stages, squashes, and commits one
92
+ trailer-carrying commit per unit.
93
+ 2. **Verify before reporting.** Do not report success you have not checked.
94
+ 3. **Blocked is a valid, respectable outcome.** A precise `blocked_reason`
95
+ after one honest attempt beats three attempts chasing a `complete`
96
+ verification keeps rejecting.
97
+ 4. **Stop at a boundary rather than working around it.** Generated
98
+ directories, secrets, and `.git/` internals are off-limits
99
+ ([`never-touch.md`](never-touch.md),
100
+ [`security-boundaries.md`](security-boundaries.md)); weakening a failing
101
+ gate to pass is the same failure class. Silence at a boundary is not
102
+ permission.
103
+ 5. **No secret-looking values in evidence.** The driver reads and may archive
104
+ this block.
105
+ 6. **Never mint or rewrite a correlation ID to make it fit.** A well-formed
106
+ ID disagreeing across surfaces is `blocked`, not a rename
107
+ ([`correlation-ids.md`](correlation-ids.md)).
108
+ 7. **A "pre-existing" failure claim cites the commit it was measured on.**
109
+ Calling a failure pre-existing is a claim about a *different* commit,
110
+ typically the merge-base, that nothing on your own branch establishes.
111
+ Name the command and commit, give the numbers from both sides, and emit
112
+ `status: blocked` rather than asserting an unmeasured baseline: a mass of
113
+ errors sharing one signature (network refused, unresolvable build
114
+ dependencies) reports where the suite ran, not the repository (#2075).
115
+ 8. **A block may name its own fix.** `blocked_next:` points at a drafted work
116
+ unit — `provenance: agent`, `status: draft`, the five WU sections filled —
117
+ the driver inserts ahead of this one and re-arms it, when the feature runs
118
+ `auto` and the draft passes the arm checks; no `blocked_next` escalates
119
+ unchanged.
120
+
121
+ ## Closing obligations for implementation WUs (FEAT-2026-0049)
122
+
123
+ 1. **Diff against `produces:` first.** Every path in the WU's `produces:` list
124
+ must show a working-tree change, or the RESULT must justify each unchanged
125
+ path under `produces_unchanged:` (deliverable already held) or
126
+ `produces_amended:` (the plan named a path the solution didn't need — drop
127
+ only, never add) — spelled as `produces:` spells it, plus the proving
128
+ command and output. The driver reads that list: a justified entry passes
129
+ and is recorded as `produces_justified`; an unjustified one, or a blank
130
+ justification, is refused (#198, #3268, outcome `produces_not_in_diff`).
131
+ Silence on an unchanged deliverable is not valid.
132
+ 2. **A plan-level contradiction is `blocked`, not `complete`.** Put the
133
+ finding in `blocked_reason`; never bury it in a gate document and close
134
+ `complete`.
135
+ 3. **Every `evidence:` cites an executed command** and its observed exit
136
+ code/output. Reading source or citing another WU's RESULT is not
137
+ verification.
138
+ 4. **Analysis without edits is not a silent attempt.** Say so; end `blocked`
139
+ rather than spend the attempt on prose.
140
+
141
+ The driver's whole cycle — re-verify, commit, advance the dependency
142
+ frontier, dispatch next — runs on this block being an honest claim. State
143
+ intent. Act. Verify. Report. Every time.
@@ -3,7 +3,7 @@
3
3
  "$id": "https://specfuse.dev/loop/schemas/driver-event.schema.json",
4
4
  "title": "Driver-local envelope registry",
5
5
  "description": "Additive to the vendored orchestrator envelope (event.schema.json): shapes the loop driver emits with no orchestrator-side counterpart. validate_event.py resolves each shape against the vendored envelope first; only when absent there does it fall through to this registry. `event_types` (FEAT-2026-0060) widens the event_type enum; task_started, task_completed, and human_escalation are already sanctioned in the vendored enum and must not be duplicated here. `correlation_id` (FEAT-2026-0073) widens the correlation_id pattern to admit the closing-sequence and hygiene shapes `.specfuse/rules/correlation-ids.md` documents; `closing_names` and `hygiene_suffix_pattern` here must state the same set of shapes as that rules file's combined pattern (and as specfuse/loop/lint_plan.py's CORRELATION_ID_RE, which independently enforces the same contract on PLAN.md graphs).",
6
- "$comment": "FEAT-2026-0060/T01: event_types derived from the union of every build_event(...) call site in specfuse/loop/loop.py and a corpus sweep of every .specfuse/features/*/events.jsonl, subtracting the vendored envelope enum. attempt_outcome and gate_reached were already-known precedent (loop.py's build_arm_predicate_event docstring); auto_close_decision, arm_predicate_evaluated, re_arm_dispatched, plan_next_draft_lint, and unsandboxed_dispatch are additional driver-local mechanics the orchestrator has no concept of. gate_auto_armed (loop.py build_event call under gate_events.append) and re_arm_rejected (loop.py build_event call under the spinning_reproduction_missing re-arm check) are emitted by real code paths that have never fired in a recorded run, so a corpus-only sweep cannot see them; they are included because call-site derivation does. FEAT-2026-0073/T01: correlation_id added — closing_names and hygiene_suffix_pattern mirror correlation-ids.md's documented shapes and lint_plan.py's CORRELATION_ID_RE verbatim, so the envelope, the rules file, and the PLAN-graph linter state one contract. FEAT-2026-0075/T03: driver_staleness_detected added — emitted at gate completion when a work unit's squash diff touched the driver's own importable surface, naming the editing unit, the driver paths it touched, and the IDs of units this process dispatched afterward (which ran the pre-edit module). FEAT-2026-0100/T02: judged added — emitted once per terminal close after the closing-deliverable guards, carrying the close's own verdict, the judge session's verdict (null when the judge was disabled, timed out, or returned nothing parseable, with the reason beside it), and whether the judge lowered it. FEAT-2026-0109/T01: baseline_attribution added — emitted when the retroactive per-attempt-failure baseline probe (attribute_failure_to_baseline) runs fresh, carrying the gate, the failing-gate set, and the unit whose failed attempt triggered the probe. FEAT-2026-0109/T06: broad_run_result added — emitted whenever the once-per-gate broad verification pass (gate_broad_run_check) actually runs (never on a tree-unchanged dedup skip), carrying the gate, the tree it was measured on, and its pass/fail outcome; a failing broad run additionally raises the existing human_escalation event type with reason: broad_run_gate_failure, which needs no schema addition since human_escalation is already sanctioned in the vendored envelope enum. FEAT-2026-0109/T08: driver_build_pinned added — emitted once per process, before any work unit is dispatched, when this process is itself a materialized pin (`_reexec_pinned`); carries the pin's tree hash and its path so an operator or test can read what build actually ran without inferring it from `ps` output. `driver_staleness_detected` needed no addition here: this unit reuses it with `halted: false` for the pinned, non-halting case (the registry constrains the type list, not the payload), adding `pinned_tree` / `next_pin_tree` fields alongside the existing `halted: true` shape. FEAT-2026-0104/T04: replan added — emitted once a re-plan turn (T03's run_replan_turn) rewrites a unit's body ahead of its last permitted attempt, so gate_eval.py's evaluate_auto_close (check 2, already reading this event_type since FEAT-2026-0018/T02) can disable auto-close for a gate that needed one.",
6
+ "$comment": "FEAT-2026-0060/T01: event_types derived from the union of every build_event(...) call site in specfuse/loop/loop.py and a corpus sweep of every .specfuse/features/*/events.jsonl, subtracting the vendored envelope enum. attempt_outcome and gate_reached were already-known precedent (loop.py's build_arm_predicate_event docstring); auto_close_decision, arm_predicate_evaluated, re_arm_dispatched, plan_next_draft_lint, and unsandboxed_dispatch are additional driver-local mechanics the orchestrator has no concept of. gate_auto_armed (loop.py build_event call under gate_events.append) and re_arm_rejected (loop.py build_event call under the spinning_reproduction_missing re-arm check) are emitted by real code paths that have never fired in a recorded run, so a corpus-only sweep cannot see them; they are included because call-site derivation does. FEAT-2026-0073/T01: correlation_id added — closing_names and hygiene_suffix_pattern mirror correlation-ids.md's documented shapes and lint_plan.py's CORRELATION_ID_RE verbatim, so the envelope, the rules file, and the PLAN-graph linter state one contract. FEAT-2026-0075/T03: driver_staleness_detected added — emitted at gate completion when a work unit's squash diff touched the driver's own importable surface, naming the editing unit, the driver paths it touched, and the IDs of units this process dispatched afterward (which ran the pre-edit module). FEAT-2026-0100/T02: judged added — emitted once per terminal close after the closing-deliverable guards, carrying the close's own verdict, the judge session's verdict (null when the judge was disabled, timed out, or returned nothing parseable, with the reason beside it), and whether the judge lowered it. FEAT-2026-0109/T01: baseline_attribution added — emitted when the retroactive per-attempt-failure baseline probe (attribute_failure_to_baseline) runs fresh, carrying the gate, the failing-gate set, and the unit whose failed attempt triggered the probe. FEAT-2026-0109/T06: broad_run_result added — emitted whenever the once-per-gate broad verification pass (gate_broad_run_check) actually runs (never on a tree-unchanged dedup skip), carrying the gate, the tree it was measured on, and its pass/fail outcome; a failing broad run additionally raises the existing human_escalation event type with reason: broad_run_gate_failure, which needs no schema addition since human_escalation is already sanctioned in the vendored envelope enum. FEAT-2026-0109/T08: driver_build_pinned added — emitted once per process, before any work unit is dispatched, when this process is itself a materialized pin (`_reexec_pinned`); carries the pin's tree hash and its path so an operator or test can read what build actually ran without inferring it from `ps` output. `driver_staleness_detected` needed no addition here: this unit reuses it with `halted: false` for the pinned, non-halting case (the registry constrains the type list, not the payload), adding `pinned_tree` / `next_pin_tree` fields alongside the existing `halted: true` shape. FEAT-2026-0104/T04: replan added — emitted once a re-plan turn (T03's run_replan_turn) rewrites a unit's body ahead of its last permitted attempt, so gate_eval.py's evaluate_auto_close (check 2, already reading this event_type since FEAT-2026-0018/T02) can disable auto-close for a gate that needed one. FEAT-2026-0115/T01: fix_unit_inserted added — emitted once a blocked RESULT's `blocked_next:` names a drafted fix unit that `insert_fix_unit` validated and inserted ahead of the blocked unit, carrying the fix unit's id, its file, the gate, and the insertion count; the blocked unit's own re-arm (an existing `re_arm_dispatched`, reason `fix_unit_inserted`) rides alongside it, so this is the only genuinely new event_type the mechanic needs.",
7
7
  "event_types": [
8
8
  "attempt_outcome",
9
9
  "gate_reached",
@@ -20,7 +20,8 @@
20
20
  "baseline_attribution",
21
21
  "broad_run_result",
22
22
  "driver_build_pinned",
23
- "replan"
23
+ "replan",
24
+ "fix_unit_inserted"
24
25
  ],
25
26
  "correlation_id": {
26
27
  "closing_names": [
@@ -118,9 +118,46 @@
118
118
  # # attempt repairs the retained tree in place
119
119
  # # instead of re-authoring from scratch. Set to
120
120
  # # false to restore the pre-0.18 discard behaviour.
121
+ # dispatch_skills: false # whether a dispatched session loads the
122
+ # # project's skills index. Defaults to false:
123
+ # # a work unit invokes no skill, and the index
124
+ # # is fixed context paid on every turn (#3423).
125
+ # # Set true for a project whose units call
126
+ # # `/skill-name` in-session.
127
+ # post_merge_issue: false # whether a `met` terminal close files PLAN.md's
128
+ # # `## Post-merge checklist` as a tracked issue.
129
+ # # Defaults to false (#3424): the checklist is
130
+ # # appended under the feature's archived detail
131
+ # # section in roadmap-archive.md instead.
132
+ # produces_amendable: false # whether the driver accepts a RESULT's
133
+ # # `produces_amended:` entries, dropping those
134
+ # # paths from the unit's recorded `produces:`.
135
+ # # Defaults to false: an amendment claim is
136
+ # # ignored and the path is judged as an
137
+ # # unjustified unchanged deliverable instead
138
+ # # (FEAT-2026-0114).
139
+ # fix_unit_insertion: true # whether a blocked RESULT's `blocked_next:`
140
+ # # may insert its drafted fix unit instead of
141
+ # # escalating. Defaults to true (FEAT-2026-0115).
142
+ # max_fix_units_per_unit: 2 # cap on `fix_unit_inserted` insertions per
143
+ # # blocked unit before it escalates instead
144
+ # # (FEAT-2026-0115). Defaults to 2.
145
+ # carry_forward_narrow_greens: true # whether a re-close may carry forward a
146
+ # # prior attempt's `narrow` GATE-NN-CRITERIA.md
147
+ # # green instead of re-measuring it. Defaults to
148
+ # # true. A carried green still invalidates when
149
+ # # the gate diff since its `proved_at_sha`
150
+ # # touches a path in its `covers:` — see
151
+ # # `.specfuse/rules/close-discipline.md` §5.
121
152
  # defaults:
122
153
  # max_attempts: 3
123
154
  # retain_on_guard_refusal: true
155
+ # dispatch_skills: false
156
+ # post_merge_issue: false
157
+ # produces_amendable: false
158
+ # fix_unit_insertion: true
159
+ # max_fix_units_per_unit: 2
160
+ # carry_forward_narrow_greens: true
124
161
  #
125
162
  # The re-plan-after-two-failures behaviour (FEAT-2026-0104) reads this same
126
163
  # `max_attempts` resolution and adds no config key of its own — a unit's