specfuse-loop 0.29.0__tar.gz → 0.30.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 (693) hide show
  1. {specfuse_loop-0.29.0/specfuse_loop.egg-info → specfuse_loop-0.30.0}/PKG-INFO +1 -1
  2. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/pyproject.toml +1 -1
  3. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/invoke.py +14 -3
  4. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/providers/triage.py +13 -6
  5. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/run.py +45 -2
  6. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/triage_invoke.py +25 -0
  7. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/arm_eval.py +3 -0
  8. specfuse_loop-0.30.0/specfuse/loop/data/VERSION +1 -0
  9. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/docs/concepts/autonomy-stop-classes.md +7 -0
  10. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/docs/methodology.md +8 -5
  11. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/docs/skills.md +1 -1
  12. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/roadmap.template.md +2 -0
  13. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/escalation.py +65 -0
  14. specfuse_loop-0.30.0/specfuse/loop/gen_contract.py +654 -0
  15. specfuse_loop-0.30.0/specfuse/loop/layout.py +335 -0
  16. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/lint_roadmap.py +72 -3
  17. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/loop.py +59 -6
  18. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/scaffold.py +12 -2
  19. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/triage.py +34 -13
  20. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0/specfuse_loop.egg-info}/PKG-INFO +1 -1
  21. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse_loop.egg-info/SOURCES.txt +18 -0
  22. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_invoke_usage.py +2 -2
  23. specfuse_loop-0.30.0/tests/test_block_feature_layout.py +95 -0
  24. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bug_lane_spend.py +3 -3
  25. specfuse_loop-0.30.0/tests/test_closed_escalation_labels.py +148 -0
  26. specfuse_loop-0.30.0/tests/test_floor_skip_summary.py +94 -0
  27. specfuse_loop-0.30.0/tests/test_gate_log_size_budget.py +67 -0
  28. specfuse_loop-0.30.0/tests/test_gen_contract.py +461 -0
  29. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_init_integration.py +9 -1
  30. specfuse_loop-0.30.0/tests/test_judge_editing_terminal_docs.py +58 -0
  31. specfuse_loop-0.30.0/tests/test_layout.py +75 -0
  32. specfuse_loop-0.30.0/tests/test_layout_end_to_end.py +174 -0
  33. specfuse_loop-0.30.0/tests/test_layout_link.py +68 -0
  34. specfuse_loop-0.30.0/tests/test_layout_no_layout_goldens.py +186 -0
  35. specfuse_loop-0.30.0/tests/test_layout_validation.py +117 -0
  36. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_roadmap.py +57 -0
  37. specfuse_loop-0.30.0/tests/test_narrow_non_py_produces.py +73 -0
  38. specfuse_loop-0.30.0/tests/test_rearm_retained_new_files.py +118 -0
  39. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_scaffold_init.py +5 -1
  40. specfuse_loop-0.30.0/tests/test_spend_counts_cache_tokens.py +62 -0
  41. specfuse_loop-0.30.0/tests/test_triage_reads_comments.py +111 -0
  42. specfuse_loop-0.30.0/tests/test_triage_severity_label_conflict.py +165 -0
  43. specfuse_loop-0.29.0/specfuse/loop/data/VERSION +0 -1
  44. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/LICENSE +0 -0
  45. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/NOTICE +0 -0
  46. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/README.md +0 -0
  47. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/setup.cfg +0 -0
  48. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/__init__.py +0 -0
  49. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/budget.py +0 -0
  50. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/diagnose_invoke.py +0 -0
  51. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/drafting_answers.py +0 -0
  52. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/drafting_invoke.py +0 -0
  53. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/drafting_questions.py +0 -0
  54. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/driver_command.py +0 -0
  55. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/driver_invoke.py +0 -0
  56. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/monitoring_read.py +0 -0
  57. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/providers/__init__.py +0 -0
  58. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/providers/answers.py +0 -0
  59. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/providers/bugs.py +0 -0
  60. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/providers/feature.py +0 -0
  61. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/providers/findings_autofix.py +0 -0
  62. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/providers/findings_diagnose.py +0 -0
  63. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/queue_read.py +0 -0
  64. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/repo_detect.py +0 -0
  65. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/severity_backfill.py +0 -0
  66. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/state.py +0 -0
  67. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/agent/worktree.py +0 -0
  68. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/__init__.py +0 -0
  69. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/_filelock.py +0 -0
  70. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/_miniyaml.py +0 -0
  71. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/_wu_sections.py +0 -0
  72. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/adopt_feature.py +0 -0
  73. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/agent_policy.py +0 -0
  74. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/arm_sweep.py +0 -0
  75. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/arm_txn.py +0 -0
  76. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/bug_lane.py +0 -0
  77. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/bug_lane_run.py +0 -0
  78. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/bug_lane_state.py +0 -0
  79. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/build_provenance.py +0 -0
  80. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/caller_check.py +0 -0
  81. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/changelog.py +0 -0
  82. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/closing_requirements.py +0 -0
  83. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/cost.py +0 -0
  84. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/criteria_state.py +0 -0
  85. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/CHANGELOG.seed.md +0 -0
  86. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/LEARNINGS.template.md +0 -0
  87. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/docs/concepts/adopting-auto-mode.md +0 -0
  88. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/docs/concepts/architecture-addendum-gates-and-iterative-planning.md +0 -0
  89. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/docs/concepts/monitoring-runners.md +0 -0
  90. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/docs/concepts/monitoring-schema.md +0 -0
  91. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/docs/concepts/monitoring-to-fix.md +0 -0
  92. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/docs/concepts/ralph-lineage.md +0 -0
  93. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/docs/flows.html +0 -0
  94. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/docs/getting-started.md +0 -0
  95. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/docs/glossary.md +0 -0
  96. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/docs/lifecycles.md +0 -0
  97. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/gitignore.snippet +0 -0
  98. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/monitoring-secrets-checklist.md +0 -0
  99. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/monitoring.overrides.yml.example +0 -0
  100. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/monitoring.yml.example +0 -0
  101. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/rules/close-discipline.md +0 -0
  102. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/rules/correlation-ids.md +0 -0
  103. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/rules/design-for-diagnosis.md +0 -0
  104. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/rules/human-output.md +0 -0
  105. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/rules/never-touch.md +0 -0
  106. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/rules/operator-escalation.md +0 -0
  107. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/rules/planning-discipline.md +0 -0
  108. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/rules/result-contract.md +0 -0
  109. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/rules/security-boundaries.md +0 -0
  110. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/rules/verification-discipline.md +0 -0
  111. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/rules-local/README.md +0 -0
  112. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/schemas/driver-event.schema.json +0 -0
  113. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/schemas/event.schema.json +0 -0
  114. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/schemas/events/initiative_created.schema.json +0 -0
  115. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/schemas/events/spec_issue_resolved.schema.json +0 -0
  116. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/schemas/events/spec_issue_routed.schema.json +0 -0
  117. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/schemas/events/spec_validated.schema.json +0 -0
  118. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/templates/DECISIONS.template.md +0 -0
  119. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/templates/GATE.template.md +0 -0
  120. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/templates/LEARNINGS-pending.template.md +0 -0
  121. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/templates/PLAN.template.md +0 -0
  122. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/templates/WU.template.md +0 -0
  123. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/verification.yml.example +0 -0
  124. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/data/workflows/specfuse-monitor.yml +0 -0
  125. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/decisions_format.py +0 -0
  126. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/driver_edit.py +0 -0
  127. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/events_stats.py +0 -0
  128. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/gate_commands.py +0 -0
  129. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/gate_eval.py +0 -0
  130. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/gh_backend.py +0 -0
  131. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/gh_features.py +0 -0
  132. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/heartbeat.py +0 -0
  133. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/judge.py +0 -0
  134. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/labels.py +0 -0
  135. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/learnings_distil.py +0 -0
  136. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/learnings_query.py +0 -0
  137. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/lint_closing.py +0 -0
  138. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/lint_monitoring.py +0 -0
  139. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/lint_plan.py +0 -0
  140. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/notify.py +0 -0
  141. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/notify_escalation.py +0 -0
  142. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/notify_sla.py +0 -0
  143. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/plan_baseline.py +0 -0
  144. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/policy_proposals.py +0 -0
  145. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/policy_review.py +0 -0
  146. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/prerun.py +0 -0
  147. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/prerun_capture.py +0 -0
  148. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/promotion.py +0 -0
  149. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/rearm_migration.py +0 -0
  150. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/red_on_base.py +0 -0
  151. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/replay_spin.py +0 -0
  152. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/roadmap_archive.py +0 -0
  153. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/upgrade_merge_gate.py +0 -0
  154. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/loop/validate_event.py +0 -0
  155. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/__init__.py +0 -0
  156. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/adapters.py +0 -0
  157. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/artifact.py +0 -0
  158. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/autofix.py +0 -0
  159. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/autofix_invoke.py +0 -0
  160. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/autofix_run.py +0 -0
  161. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/autofix_state.py +0 -0
  162. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/cli.py +0 -0
  163. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/diagnose_cli.py +0 -0
  164. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/diagnosis.py +0 -0
  165. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/durations.py +0 -0
  166. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/fingerprint.py +0 -0
  167. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/issues.py +0 -0
  168. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/providers/__init__.py +0 -0
  169. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/providers/_azure_auth.py +0 -0
  170. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/providers/azure_app_insights.py +0 -0
  171. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/providers/azure_service_bus.py +0 -0
  172. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/redaction.py +0 -0
  173. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse/monitor/schedule.py +0 -0
  174. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse_loop.egg-info/dependency_links.txt +0 -0
  175. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse_loop.egg-info/entry_points.txt +0 -0
  176. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse_loop.egg-info/requires.txt +0 -0
  177. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/specfuse_loop.egg-info/top_level.txt +0 -0
  178. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_abandon_feature_skill.py +0 -0
  179. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_abandoned_work_reported.py +0 -0
  180. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_abandoned_wu_strands_gate.py +0 -0
  181. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_adopt_feature.py +0 -0
  182. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_budget.py +0 -0
  183. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_bug_selection_dedup.py +0 -0
  184. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_default_features_root.py +0 -0
  185. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_driver_command.py +0 -0
  186. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_driver_invoke.py +0 -0
  187. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_driver_restart.py +0 -0
  188. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_escalation_on_issue.py +0 -0
  189. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_escalation_run_state.py +0 -0
  190. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_findings_seam.py +0 -0
  191. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_invoke_timeout.py +0 -0
  192. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_item_worktree.py +0 -0
  193. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_lock.py +0 -0
  194. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_policy_key_ownership.py +0 -0
  195. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_policy_queue.py +0 -0
  196. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_policy_schema.py +0 -0
  197. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_policy_triage_dial.py +0 -0
  198. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_provider_answers.py +0 -0
  199. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_provider_bugs.py +0 -0
  200. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_provider_feature.py +0 -0
  201. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_provider_findings_autofix.py +0 -0
  202. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_provider_findings_diagnose.py +0 -0
  203. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_provider_isolation.py +0 -0
  204. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_provider_triage.py +0 -0
  205. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_queue_read.py +0 -0
  206. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_relays_driver_output.py +0 -0
  207. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_repo_detect.py +0 -0
  208. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_run.py +0 -0
  209. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_run_progress.py +0 -0
  210. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_seam.py +0 -0
  211. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_snapshot_refresh.py +0 -0
  212. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_agent_state.py +0 -0
  213. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_answer_escalation_skill.py +0 -0
  214. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_app_insights_adapters.py +0 -0
  215. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_app_insights_harvest_window.py +0 -0
  216. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_app_insights_query_schema_check.py +0 -0
  217. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_app_insights_workspace_schema.py +0 -0
  218. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_archive_ref_reconciliation.py +0 -0
  219. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_arm_eval.py +0 -0
  220. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_arm_eval_lint_class.py +0 -0
  221. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_arm_eval_wiring.py +0 -0
  222. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_arm_gate_edits_uncommitted.py +0 -0
  223. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_arm_sweep.py +0 -0
  224. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_arm_sweep_gate.py +0 -0
  225. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_arm_txn.py +0 -0
  226. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_arm_wiring.py +0 -0
  227. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_artifact_redaction.py +0 -0
  228. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_attempt_note_untracked_files.py +0 -0
  229. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_attempt_outcome_contract.py +0 -0
  230. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_attempt_outcome_emission.py +0 -0
  231. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_attention_nonwriting_guard.py +0 -0
  232. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_attention_silence_section.py +0 -0
  233. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_attention_skill_structure.py +0 -0
  234. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_attribution_halt_claims.py +0 -0
  235. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_autoclose_deferral_visibility.py +0 -0
  236. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_autoclose_gate_note.py +0 -0
  237. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_autoclose_stub_states_what_passed.py +0 -0
  238. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_autofix_invoke.py +0 -0
  239. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_autofix_live.py +0 -0
  240. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_autofix_predicate.py +0 -0
  241. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_autofix_run.py +0 -0
  242. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_autofix_state.py +0 -0
  243. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_autosync.py +0 -0
  244. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_autosync_consent.py +0 -0
  245. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_autosync_firstrun.py +0 -0
  246. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_autosync_no_cwd_leak.py +0 -0
  247. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_autosync_plugin.py +0 -0
  248. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_azure_credential_resolution.py +0 -0
  249. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_backend.py +0 -0
  250. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_baseline_escalation_message.py +0 -0
  251. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_baseline_persistence.py +0 -0
  252. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_baseline_probe.py +0 -0
  253. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_baseline_provenance.py +0 -0
  254. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_baseline_tree_hash_key.py +0 -0
  255. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bash_routing.py +0 -0
  256. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bats_suites_gated.py +0 -0
  257. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_binary_verdict.py +0 -0
  258. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_binding_block_advisory.py +0 -0
  259. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_binding_block_allocation.py +0 -0
  260. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_binding_block_budget.py +0 -0
  261. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_blind_run_is_not_drained.py +0 -0
  262. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bookkeeping_commit_crash_run.py +0 -0
  263. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bookkeeping_commit_hook_crash.py +0 -0
  264. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bookkeeping_no_verify.py +0 -0
  265. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_brief_covers_every_unit_escalation.py +0 -0
  266. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bug_lane_ci_pending.py +0 -0
  267. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bug_lane_guardrails.py +0 -0
  268. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bug_lane_label_nonfatal.py +0 -0
  269. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bug_lane_labels_registered.py +0 -0
  270. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bug_lane_min_severity.py +0 -0
  271. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bug_lane_no_checks_pending.py +0 -0
  272. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bug_lane_policy_contract.py +0 -0
  273. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bug_lane_pr_number_carried.py +0 -0
  274. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bug_lane_preflight_and_dial.py +0 -0
  275. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bug_lane_run.py +0 -0
  276. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bug_lane_state.py +0 -0
  277. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bug_lane_stopped_outcome_pr_number.py +0 -0
  278. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bug_lane_superseded.py +0 -0
  279. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_bug_lane_test_paths.py +0 -0
  280. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_build_provenance.py +0 -0
  281. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_caller_check_ratchet.py +0 -0
  282. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_carried_green_invalidated_by_diff.py +0 -0
  283. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_carry_accounting_close_and_judge.py +0 -0
  284. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_changed_file_test_selection.py +0 -0
  285. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_changelog_append_only.py +0 -0
  286. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_changelog_collection.py +0 -0
  287. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_changelog_release_wiring.py +0 -0
  288. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_changelog_schema.py +0 -0
  289. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_ci_conclusion_wait.py +0 -0
  290. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_ci_runs_every_gate.py +0 -0
  291. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_claude_resolution.py +0 -0
  292. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_close_b_pending_learnings.py +0 -0
  293. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_close_records_feature_oracle.py +0 -0
  294. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_close_wu_self_reference.py +0 -0
  295. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_closing_deliverable_guard.py +0 -0
  296. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_closing_guard_contracts.py +0 -0
  297. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_closing_guard_prediction.py +0 -0
  298. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_closing_learnings_destination.py +0 -0
  299. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_closing_requirements.py +0 -0
  300. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_closing_sessions_on_sonnet.py +0 -0
  301. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_coauthor_trailer_allowlist.py +0 -0
  302. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_conditional_reflection.py +0 -0
  303. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_console_encoding.py +0 -0
  304. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_convergent_iteration.py +0 -0
  305. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_convergent_wu_lint.py +0 -0
  306. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_correlation_id_override.py +0 -0
  307. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_correlation_id_two_surfaces.py +0 -0
  308. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_cost_lifetime.py +0 -0
  309. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_cost_tracking.py +0 -0
  310. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_criteria_per_gate_lint.py +0 -0
  311. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_criteria_state.py +0 -0
  312. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_criteria_worklist.py +0 -0
  313. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_decision_citation_lint.py +0 -0
  314. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_decision_followups_discharged.py +0 -0
  315. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_decision_override_lint.py +0 -0
  316. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_decisions_format.py +0 -0
  317. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_default_severity_aliases.py +0 -0
  318. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_degraded_oracle.py +0 -0
  319. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_deliverable_missing_note.py +0 -0
  320. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_deliverable_presence_gate.py +0 -0
  321. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_derive_agent_policy_review_mode.py +0 -0
  322. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_derive_agent_policy_skill.py +0 -0
  323. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_derive_monitoring_discovery.py +0 -0
  324. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_derive_monitoring_skill_registration.py +0 -0
  325. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_design_for_diagnosis_rule.py +0 -0
  326. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_deterministic_refusal_repeat.py +0 -0
  327. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_diagnose_fenced_analysis.py +0 -0
  328. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_diagnose_headless.py +0 -0
  329. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_diagnose_issue_skill.py +0 -0
  330. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_diagnosis.py +0 -0
  331. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_diagnosis_roundtrip_live.py +0 -0
  332. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_diagnosis_severity_end_to_end.py +0 -0
  333. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_diagnosis_severity_rubric.py +0 -0
  334. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_dispatch_model_from_fix_scope.py +0 -0
  335. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_dispatch_preamble_rules_pointer.py +0 -0
  336. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_dispatch_skeleton.py +0 -0
  337. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_dispatch_skills_index.py +0 -0
  338. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_distilled_accept_step.py +0 -0
  339. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_doctor.py +0 -0
  340. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_doctor_command_preflight.py +0 -0
  341. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_done_feature_gates.py +0 -0
  342. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_draft_feature_answers_mode.py +0 -0
  343. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_drafting_answer_gate.py +0 -0
  344. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_drafting_invoke.py +0 -0
  345. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_drafting_question_issue.py +0 -0
  346. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_drafting_questions.py +0 -0
  347. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_drafting_reply_shape.py +0 -0
  348. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_driver_edit_detection.py +0 -0
  349. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_driver_event_registry_covers_emitters.py +0 -0
  350. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_driver_integration.py +0 -0
  351. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_driver_lock.py +0 -0
  352. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_driver_module_surface.py +0 -0
  353. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_driver_restart_halt_surfaced.py +0 -0
  354. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_driver_restart_halt_wiring.py +0 -0
  355. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_driver_restart_hold.py +0 -0
  356. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_driver_staleness_gate_summary.py +0 -0
  357. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_driver_staleness_warning.py +0 -0
  358. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_dry_run_no_branch_mutation.py +0 -0
  359. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_duration_tracking.py +0 -0
  360. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_empty_files_escalation.py +0 -0
  361. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_ensure_feature_branch.py +0 -0
  362. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_ensure_feature_branch_base.py +0 -0
  363. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_escalation_assignee_policy.py +0 -0
  364. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_escalation_contract.py +0 -0
  365. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_escalation_crash_containment.py +0 -0
  366. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_escalation_dedup_search.py +0 -0
  367. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_escalation_emit.py +0 -0
  368. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_event_gate_full_envelope.py +0 -0
  369. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_events_redaction.py +0 -0
  370. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_events_stats.py +0 -0
  371. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_extra_gates.py +0 -0
  372. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_failure_artifact_model.py +0 -0
  373. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_failure_signature_fail_prefix.py +0 -0
  374. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_failure_signature_names_the_test.py +0 -0
  375. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_failure_signature_skips_log_noise.py +0 -0
  376. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_feature_branch_auto_sync.py +0 -0
  377. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_feature_branch_squash_merge.py +0 -0
  378. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_feature_branch_stale_base.py +0 -0
  379. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_feature_id_resolution.py +0 -0
  380. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_feature_oracle_e2e.py +0 -0
  381. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_feature_provider_drafting_dispatch.py +0 -0
  382. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_feature_review_accumulation.py +0 -0
  383. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_filelock_portable.py +0 -0
  384. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_files_changed_auto_repair.py +0 -0
  385. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_find_pr_no_search_index.py +0 -0
  386. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_fingerprint.py +0 -0
  387. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_fix_bug_cwd_worktree.py +0 -0
  388. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_fix_bug_diff_self_check.py +0 -0
  389. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_fix_bug_headless.py +0 -0
  390. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_fix_bug_reads_comments.py +0 -0
  391. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_fix_unit_insertion_bookkeeping.py +0 -0
  392. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_fix_unit_insertion_e2e.py +0 -0
  393. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_fix_unit_insertion_refused.py +0 -0
  394. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_flows_page.py +0 -0
  395. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_fold_contract_documented.py +0 -0
  396. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_followups_artifact.py +0 -0
  397. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_force_full_close.py +0 -0
  398. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_frontmatter_scalar_quoting.py +0 -0
  399. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_gate_broad_run.py +0 -0
  400. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_gate_budget.py +0 -0
  401. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_gate_budget_post_dispatch.py +0 -0
  402. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_gate_commands_needs.py +0 -0
  403. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_gate_eval.py +0 -0
  404. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_gate_eval_calibration.py +0 -0
  405. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_gate_eval_intermediate_wiring.py +0 -0
  406. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_gate_eval_repo_flag.py +0 -0
  407. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_gate_eval_terminal_wiring.py +0 -0
  408. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_gate_report_verdict.py +0 -0
  409. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_gh_backend.py +0 -0
  410. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_gh_features.py +0 -0
  411. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_git_env_isolation.py +0 -0
  412. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_gitleaks_pinning.py +0 -0
  413. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_groom_backlog_skill.py +0 -0
  414. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_guard_refusal_failure_class.py +0 -0
  415. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_guard_refusal_failure_excerpt.py +0 -0
  416. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_guard_repair_e2e.py +0 -0
  417. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_guard_repair_prompt.py +0 -0
  418. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_hashed_denylist.py +0 -0
  419. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_hashed_denylist_ci.py +0 -0
  420. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_headless_no_background_tasks.py +0 -0
  421. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_heartbeat.py +0 -0
  422. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_heartbeat_adapter.py +0 -0
  423. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_heartbeat_emission_contract.py +0 -0
  424. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_http_status_regression_adapter.py +0 -0
  425. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_http_status_regression_end_to_end.py +0 -0
  426. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_human_output_rule.py +0 -0
  427. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_human_work_unit.py +0 -0
  428. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_hygiene_boundary_guidance.py +0 -0
  429. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_hyphenated_gate_name.py +0 -0
  430. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_ignored_cleanup_before_probe.py +0 -0
  431. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_installed_copy_driver_e2e.py +0 -0
  432. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_interpreter_normalization.py +0 -0
  433. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_judge_close_path.py +0 -0
  434. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_judge_cost.py +0 -0
  435. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_judge_cost_fold_committed.py +0 -0
  436. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_judge_module.py +0 -0
  437. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_judge_path_registry.py +0 -0
  438. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_judge_sees_dropped_produces.py +0 -0
  439. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_judge_terminal_flip_state.py +0 -0
  440. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_judged_event_points_at_findings.py +0 -0
  441. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_label_description_length.py +0 -0
  442. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_label_provisioning_runner_contract.py +0 -0
  443. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_label_registry.py +0 -0
  444. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_label_registry_covers_consumers.py +0 -0
  445. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_language_aware_narrow_selection.py +0 -0
  446. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lazy_baseline_e2e.py +0 -0
  447. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_leak_findings_redaction.py +0 -0
  448. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_leak_scan.py +0 -0
  449. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_leak_scan_content.py +0 -0
  450. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_learnings_curate_vendored_promote.py +0 -0
  451. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_learnings_distil_cli.py +0 -0
  452. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_learnings_query.py +0 -0
  453. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_learnings_staging.py +0 -0
  454. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_learnings_suggest_signature_filter.py +0 -0
  455. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_learnings_weights.py +0 -0
  456. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_legacy_4wu_terminal_flips.py +0 -0
  457. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lifecycle_integration.py +0 -0
  458. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lifetime_accounting.py +0 -0
  459. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_ac_observable.py +0 -0
  460. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_bare_produces_path.py +0 -0
  461. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_boundary_consistency.py +0 -0
  462. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_boundary_extraction.py +0 -0
  463. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_close_intermediate.py +0 -0
  464. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_close_verdict_not_predecided.py +0 -0
  465. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_close_wu.py +0 -0
  466. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_closing.py +0 -0
  467. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_closing_criteria.py +0 -0
  468. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_closing_criteria_pristine.py +0 -0
  469. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_correlation_id.py +0 -0
  470. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_correlation_id_close_intermediate.py +0 -0
  471. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_covers_load_wu_invariants.py +0 -0
  472. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_feature_oracle_declared.py +0 -0
  473. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_gate_proportionality.py +0 -0
  474. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_monitoring.py +0 -0
  475. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_oracle_env.py +0 -0
  476. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_plan_contract_fields.py +0 -0
  477. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_plan_errors.py +0 -0
  478. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_plan_next_draft.py +0 -0
  479. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_plan_relative_import.py +0 -0
  480. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_plan_verdict_exempt.py +0 -0
  481. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_planning_sections.py +0 -0
  482. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_produces_driver_helper.py +0 -0
  483. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_produces_satisfiability.py +0 -0
  484. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_sections.py +0 -0
  485. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_task_graph_yaml_selection.py +0 -0
  486. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_lint_verification_reference.py +0 -0
  487. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_live_tests_opt_in.py +0 -0
  488. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_load_bearing_close_lint.py +0 -0
  489. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_attempt_evidence.py +0 -0
  490. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_auto_archive.py +0 -0
  491. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_caveman_preamble.py +0 -0
  492. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_close_intermediate.py +0 -0
  493. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_criteria_skeleton.py +0 -0
  494. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_criteria_survival.py +0 -0
  495. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_defaults_by_type.py +0 -0
  496. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_effort.py +0 -0
  497. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_failure_note_cap.py +0 -0
  498. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_files_changed_guard.py +0 -0
  499. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_gate_budget.py +0 -0
  500. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_gate_needs.py +0 -0
  501. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_model_alias.py +0 -0
  502. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_orchestration.py +0 -0
  503. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_post_pass_invariant.py +0 -0
  504. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_reset_preserving_events.py +0 -0
  505. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_smoke_runner.py +0 -0
  506. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_unsandboxed.py +0 -0
  507. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_worklist_injection.py +0 -0
  508. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_loop_zero_token_guard.py +0 -0
  509. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_make_repo_gpgsign_isolation.py +0 -0
  510. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_marker_dual_shape.py +0 -0
  511. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_maven_failure_excerpt.py +0 -0
  512. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_max_attempts_configurable.py +0 -0
  513. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_max_open_prs.py +0 -0
  514. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_migrate_legacy.py +0 -0
  515. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_miniyaml_equivalence.py +0 -0
  516. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_miniyaml_negative.py +0 -0
  517. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_monitor_check_isolation.py +0 -0
  518. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_monitor_cli.py +0 -0
  519. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_monitor_diagnose_auto_warning.py +0 -0
  520. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_monitor_durations.py +0 -0
  521. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_monitor_finding_context_end_to_end.py +0 -0
  522. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_monitor_finding_lifecycle_end_to_end.py +0 -0
  523. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_monitor_finding_meta.py +0 -0
  524. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_monitor_issue_lifecycle.py +0 -0
  525. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_monitor_one_issue_per_fingerprint.py +0 -0
  526. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_monitor_quiet_annotation.py +0 -0
  527. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_monitor_runner_surfaces.py +0 -0
  528. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_monitoring_bootstrap_artifacts.py +0 -0
  529. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_monitoring_cron_dialect.py +0 -0
  530. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_monitoring_example.py +0 -0
  531. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_monitoring_fenced_blocks.py +0 -0
  532. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_monitoring_seed.py +0 -0
  533. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_narrow_fallback_warning.py +0 -0
  534. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_needs_decision_outcome.py +0 -0
  535. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_no_pytest_subprocess.py +0 -0
  536. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_notify.py +0 -0
  537. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_notify_escalation.py +0 -0
  538. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_notify_sla.py +0 -0
  539. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_operator_escalation_rule.py +0 -0
  540. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_oracle_set_declared.py +0 -0
  541. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_oracle_unrunnable_attribution.py +0 -0
  542. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_per_run_item_cap_disclosure.py +0 -0
  543. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_pick_feature_skill.py +0 -0
  544. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_pin_honesty_and_integrity.py +0 -0
  545. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_pin_marker_not_inherited.py +0 -0
  546. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_pin_marker_spawn_sites.py +0 -0
  547. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_plan_baseline.py +0 -0
  548. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_planned_cost_lint.py +0 -0
  549. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_planning_cost_floor.py +0 -0
  550. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_plugin_prose_cross_refs.py +0 -0
  551. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_plugin_qualified_dispatch.py +0 -0
  552. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_policy_budgets_applied.py +0 -0
  553. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_policy_proposals.py +0 -0
  554. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_policy_review.py +0 -0
  555. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_pr_checks_json_field.py +0 -0
  556. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_pr_reference_in_title.py +0 -0
  557. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_pre_existing_claims_cite_evidence.py +0 -0
  558. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_prep_halt_operator_surface.py +0 -0
  559. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_prepare_feature.py +0 -0
  560. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_prepare_scaffold_sync.py +0 -0
  561. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_prerun_capture.py +0 -0
  562. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_prerun_oracles.py +0 -0
  563. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_prerun_wiring.py +0 -0
  564. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_produced_document_verdict_guard.py +0 -0
  565. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_produces_amendment_e2e.py +0 -0
  566. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_produces_bracket_literal.py +0 -0
  567. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_produces_bracket_wildcard.py +0 -0
  568. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_produces_field.py +0 -0
  569. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_produces_in_diff.py +0 -0
  570. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_produces_justification.py +0 -0
  571. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_produces_recursive_glob.py +0 -0
  572. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_produces_repair_note.py +0 -0
  573. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_produces_semantics_unified.py +0 -0
  574. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_produces_shape.py +0 -0
  575. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_progress_forward_note.py +0 -0
  576. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_progress_lines_end_to_end.py +0 -0
  577. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_promoted_issue_not_redispatched.py +0 -0
  578. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_promotion_ledger.py +0 -0
  579. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_provider_escalation_traces.py +0 -0
  580. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_provision_labels.py +0 -0
  581. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_queue_stalled_adapter.py +0 -0
  582. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_rearm_clears_stale_criteria_state.py +0 -0
  583. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_rearm_close_broad_run.py +0 -0
  584. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_rearm_fold_marker.py +0 -0
  585. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_rearm_migration.py +0 -0
  586. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_reclose_carries_narrow_greens_e2e.py +0 -0
  587. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_red_baseline_never_reused.py +0 -0
  588. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_red_on_base_fetch_and_reason.py +0 -0
  589. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_red_on_base_guardrail.py +0 -0
  590. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_red_on_base_overlay.py +0 -0
  591. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_red_on_base_probe.py +0 -0
  592. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_red_on_base_real_runner.py +0 -0
  593. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_redaction_windows_home.py +0 -0
  594. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_rediagnose_on_reopen.py +0 -0
  595. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_reescalation_posts_comment.py +0 -0
  596. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_reflection_required_signals.py +0 -0
  597. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_replan_end_to_end.py +0 -0
  598. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_replan_event_emission.py +0 -0
  599. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_replan_note_collision.py +0 -0
  600. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_replan_trigger.py +0 -0
  601. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_replan_turn_contract.py +0 -0
  602. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_replay_spin.py +0 -0
  603. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_replay_spin_failing_sets.py +0 -0
  604. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_required_checks.py +0 -0
  605. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_resolve_base.py +0 -0
  606. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_restart_cap_counts_progress.py +0 -0
  607. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_result_block.py +0 -0
  608. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_result_block_audience.py +0 -0
  609. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_result_block_near_miss.py +0 -0
  610. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_result_block_scalar.py +0 -0
  611. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_resume_command_build.py +0 -0
  612. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_retain_on_guard_refusal_docs.py +0 -0
  613. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_roadmap_add_skill.py +0 -0
  614. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_roadmap_archive_cli.py +0 -0
  615. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_roadmap_archive_shim.py +0 -0
  616. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_roadmap_archive_skill.py +0 -0
  617. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_roadmap_archive_skill_delegates.py +0 -0
  618. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_roadmap_link_gate.py +0 -0
  619. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_roadmap_row_parser.py +0 -0
  620. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_ruff_verdict_lines.py +0 -0
  621. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_rule_import_convergence.py +0 -0
  622. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_run_level_failure_breaker.py +0 -0
  623. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_scaffold_data_in_sync.py +0 -0
  624. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_scaffold_doc_hygiene.py +0 -0
  625. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_scaffold_docs.py +0 -0
  626. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_scaffold_label_provisioning.py +0 -0
  627. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_scaffold_manifest.py +0 -0
  628. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_scaffold_resources.py +0 -0
  629. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_scaffold_seed_sanity.py +0 -0
  630. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_scaffold_skew_halts.py +0 -0
  631. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_scaffold_upgrade.py +0 -0
  632. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_scaffold_wiring.py +0 -0
  633. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_schedule_dialect.py +0 -0
  634. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_seed_documents_prerun_keys.py +0 -0
  635. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_service_bus_dlq_adapter.py +0 -0
  636. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_session_env_preflight.py +0 -0
  637. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_severity_aliases.py +0 -0
  638. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_severity_backfill_apply.py +0 -0
  639. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_severity_backfill_bugs_only.py +0 -0
  640. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_severity_backfill_end_to_end.py +0 -0
  641. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_severity_backfill_limit.py +0 -0
  642. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_severity_backfill_marker.py +0 -0
  643. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_severity_backfill_run.py +0 -0
  644. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_severity_label_projection.py +0 -0
  645. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_severity_reconciliation.py +0 -0
  646. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_severity_rubric.py +0 -0
  647. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_shipped_templates_parse.py +0 -0
  648. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_skill_discovery_links.py +0 -0
  649. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_skills_vendored_in_sync.py +0 -0
  650. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_spec_work_unit_rules.py +0 -0
  651. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_spinning_rearm_gate.py +0 -0
  652. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_spinning_repeat_same_failing_set.py +0 -0
  653. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_spinout_brief_end_to_end.py +0 -0
  654. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_spinout_brief_replan_option.py +0 -0
  655. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_squash_commit_hook_crash.py +0 -0
  656. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_stop_rationale_captured.py +0 -0
  657. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_stranded_halt_cause.py +0 -0
  658. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_surefire_run_level_signature.py +0 -0
  659. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_surefire_verdict_lines.py +0 -0
  660. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_template_closing_shapes.py +0 -0
  661. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_terminal_auto_close_changelog.py +0 -0
  662. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_terminal_flip_ownership.py +0 -0
  663. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_terminal_flips.py +0 -0
  664. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_terminal_gate_message.py +0 -0
  665. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_tiered_verification_e2e.py +0 -0
  666. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_timeout_kill_portable.py +0 -0
  667. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_triage.py +0 -0
  668. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_triage_apply.py +0 -0
  669. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_triage_projects_severity_label.py +0 -0
  670. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_triage_severity_classify.py +0 -0
  671. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_triage_severity_end_to_end.py +0 -0
  672. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_triage_severity_write.py +0 -0
  673. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_triage_skill_contract.py +0 -0
  674. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_triage_skips_agent_escalations.py +0 -0
  675. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_tsc_verdict_lines.py +0 -0
  676. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_umbrella_version_resolution.py +0 -0
  677. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_unreadable_pr_listing_holds_pr_work.py +0 -0
  678. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_unterminated_frontmatter.py +0 -0
  679. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_untracked_feature_folder.py +0 -0
  680. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_untracked_file_absorption.py +0 -0
  681. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_upgrade_gitignore_lines.py +0 -0
  682. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_upgrade_integration.py +0 -0
  683. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_upgrade_merge_gate.py +0 -0
  684. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_validate_event.py +0 -0
  685. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_validate_event_driver_types.py +0 -0
  686. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_verdict_coupling.py +0 -0
  687. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_verify_empty_gate_set.py +0 -0
  688. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_version_consistency.py +0 -0
  689. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_version_skew.py +0 -0
  690. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_windows_gate_exec.py +0 -0
  691. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_worktree_restore.py +0 -0
  692. {specfuse_loop-0.29.0 → specfuse_loop-0.30.0}/tests/test_wu_execution_metadata.py +0 -0
  693. {specfuse_loop-0.29.0 → specfuse_loop-0.30.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.29.0
3
+ Version: 0.30.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.29.0"
7
+ version = "0.30.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"
@@ -112,13 +112,24 @@ def _parse_envelope(raw: str) -> tuple:
112
112
  return result_text, (usage if usage else None)
113
113
 
114
114
 
115
+ #: Every token field `budgets.max_tokens_per_run` is compared against (#3522).
116
+ SPEND_TOKEN_FIELDS = (
117
+ "input_tokens",
118
+ "output_tokens",
119
+ "cache_read_input_tokens",
120
+ "cache_creation_input_tokens",
121
+ )
122
+
123
+
115
124
  def usage_spend(usage: Optional[dict]) -> int:
116
- """`spend` for `ActionOutcome`: input + output tokens, cache reads
117
- excluded -- matching the driver's own cost line (`loop.py:7300-7302`).
125
+ """`spend` for `ActionOutcome`: all four usage token fields, cache reads
126
+ and cache creation included (#3522). With prompt caching nearly all of a
127
+ headless session's input is cache traffic, so leaving it out reported a
128
+ small fraction of the real volume and `max_tokens_per_run` never bound.
118
129
  Zero for a `None` usage, never a `KeyError`."""
119
130
  if not usage:
120
131
  return 0
121
- return int(usage.get("input_tokens", 0)) + int(usage.get("output_tokens", 0))
132
+ return sum(int(usage.get(key, 0)) for key in SPEND_TOKEN_FIELDS)
122
133
 
123
134
 
124
135
  def run_claude(
@@ -303,7 +303,8 @@ class TriageProvider:
303
303
 
304
304
  rubric = self._rubric_for_run()
305
305
  argv, prompt = build_invocation(
306
- number, title, body, self._repo, self._working_dir, rubric=rubric
306
+ number, title, body, self._repo, self._working_dir, rubric=rubric,
307
+ comments=row.get("comments") or [],
307
308
  )
308
309
  invoked = run_claude(argv, prompt, runner=self._runner)
309
310
  spend = usage_spend(invoked.usage)
@@ -368,6 +369,9 @@ class TriageProvider:
368
369
  "category": category,
369
370
  "confidence": confidence,
370
371
  "severity": severity,
372
+ # #3521: without the issue's labels `apply_triage` cannot see
373
+ # a person's `severity:*` label, and adds a second one beside it.
374
+ "labels": row.get("labels") or [],
371
375
  }
372
376
  ]
373
377
  results = apply_triage(
@@ -391,11 +395,14 @@ class TriageProvider:
391
395
  spend=spend,
392
396
  )
393
397
 
394
- return ActionOutcome(
395
- status=STATUS_COMPLETED,
396
- detail=f"issue #{number} triaged as {row_result.get('category')}",
397
- spend=spend,
398
- )
398
+ detail = f"issue #{number} triaged as {row_result.get('category')}"
399
+ if row_result.get("severity_conflict"):
400
+ detail += (
401
+ f"; severity label left as "
402
+ f"{', '.join(row_result['severity_conflict'])} "
403
+ f"(triage judged {severity})"
404
+ )
405
+ return ActionOutcome(status=STATUS_COMPLETED, detail=detail, spend=spend)
399
406
 
400
407
  def reconcile(self, item: ActionItem, outcome: ActionOutcome) -> None:
401
408
  return None
@@ -62,6 +62,7 @@ from specfuse.loop.build_provenance import warn_if_out_of_tree
62
62
  from specfuse.loop.escalation import (
63
63
  CREATED_NUMBER_UNKNOWN,
64
64
  annotate_escalation,
65
+ clear_closed_escalation_labels,
65
66
  emit_escalation,
66
67
  )
67
68
 
@@ -198,8 +199,8 @@ class ActionOutcome:
198
199
  `spend` is real tokens, not a proxy — a provider that dispatches a
199
200
  headless `claude` session reports it through
200
201
  `specfuse.agent.invoke.usage_spend(invoke_result.usage)`
201
- (FEAT-2026-0108/T01): input plus output tokens, cache reads excluded, so
202
- it lines up with the driver's own cost line. It defaults to zero so a
202
+ (FEAT-2026-0108/T01): all four usage token fields, cache reads and cache
203
+ creation included (#3522). It defaults to zero so a
203
204
  provider that dispatches nothing, or whose session reported no usage
204
205
  envelope, leaves the run's total spend untouched. `escalation`, when set
205
206
  on a `STATUS_ESCALATED` outcome, is recorded — on `target_issue` when the
@@ -299,6 +300,10 @@ class RunSummary:
299
300
  #: re-run, because a triage-only run otherwise looks like a bug lane that
300
301
  #: declined everything.
301
302
  newly_triaged_bugs_undispatched: tuple = ()
303
+ #: `(number, reason)` for bugs this run triaged that the severity floor
304
+ #: holds back (#3521). Kept apart from the re-run list above: a re-run
305
+ #: would not dispatch them either, so the summary names the floor instead.
306
+ newly_triaged_bugs_below_floor: tuple = ()
302
307
 
303
308
 
304
309
  def _bug_marked_numbers(snapshot: AgentSnapshot) -> set:
@@ -306,6 +311,30 @@ def _bug_marked_numbers(snapshot: AgentSnapshot) -> set:
306
311
  return {issue.number for issue in snapshot.issues if issue.triage_category == "bug"}
307
312
 
308
313
 
314
+ def _split_by_severity_floor(numbers, snapshot: AgentSnapshot,
315
+ policy_path: Optional[str]) -> tuple:
316
+ """`(re-runnable, [(number, reason), ...])` for bugs triaged and never
317
+ dispatched (#3521).
318
+
319
+ Reads the floor exactly as `BugsProvider.advertise` does, so a bug this
320
+ returns as held back is one the next run's lane would skip too -- telling
321
+ the operator to re-run for it was a promise the lane would not keep.
322
+ """
323
+ floor = agent_policy.resolve_min_severity(policy_path)
324
+ aliases = agent_policy.resolve_severity_aliases(policy_path)
325
+ labels_by_number = {issue.number: issue.labels for issue in snapshot.issues}
326
+ rerun, held = [], []
327
+ for number in numbers:
328
+ severity, via = agent_policy.read_severity_label(
329
+ labels_by_number.get(number), aliases)
330
+ ok, why = agent_policy.meets_severity_floor(severity, floor, via=via)
331
+ if ok:
332
+ rerun.append(number)
333
+ else:
334
+ held.append((number, why))
335
+ return rerun, held
336
+
337
+
309
338
  def _refresh_snapshot(
310
339
  previous: AgentSnapshot,
311
340
  *,
@@ -838,6 +867,13 @@ def run_agent(
838
867
  policy_path=policy_path,
839
868
  features_root=features_root,
840
869
  )
870
+ # #3523: a closed issue keeps no escalation labels the lane wrote.
871
+ cleared = clear_closed_escalation_labels(runner, repo)
872
+ if cleared:
873
+ report(
874
+ "cleared needs-human from closed escalated issue(s): "
875
+ + ", ".join(f"#{number}" for number in cleared)
876
+ )
841
877
  bugs_preempt = _resolve_bugs_preempt(policy_path)
842
878
  report(
843
879
  f"snapshot: {len(snapshot.issues)} open issues, "
@@ -1179,6 +1215,10 @@ def run_agent(
1179
1215
  for number in _bug_marked_numbers(snapshot) - bugs_marked_at_start
1180
1216
  if f"bug-{number}" not in handled_ids
1181
1217
  )
1218
+ newly_triaged, below_floor = _split_by_severity_floor(
1219
+ newly_triaged, snapshot, policy_path)
1220
+ for number, why in below_floor:
1221
+ report(f"#{number} newly triaged as bug, not dispatched — {why}")
1182
1222
  if newly_triaged:
1183
1223
  report(
1184
1224
  f"{len(newly_triaged)} issue(s) newly triaged as bug and not "
@@ -1200,6 +1240,7 @@ def run_agent(
1200
1240
  escalations=tuple(escalations),
1201
1241
  wip_refs=tuple(wip_refs),
1202
1242
  newly_triaged_bugs_undispatched=tuple(newly_triaged),
1243
+ newly_triaged_bugs_below_floor=tuple(below_floor),
1203
1244
  )
1204
1245
  finally:
1205
1246
  lock_fd.close()
@@ -1229,6 +1270,8 @@ def _format_summary(summary: RunSummary) -> str:
1229
1270
  f" {len(summary.newly_triaged_bugs_undispatched)} newly triaged "
1230
1271
  f"as bug, not dispatched — re-run to fix them: {numbers}"
1231
1272
  )
1273
+ for number, why in summary.newly_triaged_bugs_below_floor:
1274
+ lines.append(f" #{number} newly triaged as bug, not dispatched — {why}")
1232
1275
  return "\n".join(lines)
1233
1276
 
1234
1277
 
@@ -47,6 +47,7 @@ def build_invocation(
47
47
  model: str = "sonnet",
48
48
  effort: str = "medium",
49
49
  rubric: Optional[dict] = None,
50
+ comments: Optional[list] = None,
50
51
  ):
51
52
  """Build argv and prompt text for a headless triage-classification
52
53
  session against one issue. Returns a `(argv, prompt)` tuple; runs
@@ -60,6 +61,12 @@ def build_invocation(
60
61
  session -- and the marker instruction grows a third `severity=` field.
61
62
  The prompt is built from `rubric`'s own mapping alone; it holds no copy
62
63
  of any shipped default definitions.
64
+
65
+ `comments` is the issue's comment list as `gh issue list --json comments`
66
+ returns it (#3520): a maintainer often routes an issue -- folds it into a
67
+ feature, marks it a duplicate -- in a comment, and a classifier reading
68
+ the body alone labels it `bug` anyway. No comments leaves the prompt
69
+ byte-identical to the one built without them.
63
70
  """
64
71
  argv = build_claude_argv(model, effort)
65
72
  if rubric:
@@ -88,6 +95,7 @@ def build_invocation(
88
95
  f"Issue number: {issue_number}\n"
89
96
  f"Issue title: {title}\n\n"
90
97
  f"Issue body:\n{body}\n\n"
98
+ f"{_comments_block(comments)}"
91
99
  "Classify this issue into exactly one of the categories: "
92
100
  f"{', '.join(CATEGORIES)}.\n\n"
93
101
  f"{marker_instruction}"
@@ -95,6 +103,23 @@ def build_invocation(
95
103
  return argv, prompt
96
104
 
97
105
 
106
+ def _comments_block(comments: Optional[list]) -> str:
107
+ if not comments:
108
+ return ""
109
+ rendered = []
110
+ for comment in comments:
111
+ author = (comment.get("author") or {}).get("login") or "unknown"
112
+ association = comment.get("authorAssociation") or "NONE"
113
+ rendered.append(f"--- @{author} ({association}):\n{comment.get('body') or ''}")
114
+ return (
115
+ "Issue comments, oldest first:\n"
116
+ + "\n\n".join(rendered)
117
+ + "\n\nIf a maintainer comment already routes this issue -- folds it "
118
+ "into a feature or another issue, or marks it a duplicate -- classify "
119
+ "it by that decision, not by the body alone.\n\n"
120
+ )
121
+
122
+
98
123
  def classify_result(result_text: str) -> Optional[tuple]:
99
124
  """Return the `(category, confidence)` pair a classification session's
100
125
  output names, or `None` if the output carries no parseable triage
@@ -104,6 +104,7 @@ JUDGE_MODULES = tuple(
104
104
  "agent_policy.py", # automerge dial, diff/merge caps, test paths
105
105
  "cost.py", # spend, read by budget_projection
106
106
  "gate_commands.py", # resolves which commands a gate must pass
107
+ "gen_contract.py", # IS a `code` gate in component repos; an edit can turn a red contract green
107
108
  # What a work unit or a close must satisfy.
108
109
  "closing_requirements.py",
109
110
  "criteria_state.py",
@@ -157,6 +158,8 @@ NON_JUDGE_MODULES = {
157
158
  "learnings_query.py": "reads LEARNINGS.md for planning context",
158
159
  "lint_monitoring.py": "lints monitoring.yml, which no arm/close/merge "
159
160
  "verdict reads",
161
+ "layout.py": "resolves layout.yml for lint_roadmap and skills; no arm/"
162
+ "close/merge verdict reads it",
160
163
  "lint_roadmap.py": "lints roadmap.md, which no arm/close/merge verdict reads",
161
164
  "notify.py": "delivery of a message about a decision already made",
162
165
  "notify_escalation.py": "as notify.py",
@@ -0,0 +1 @@
1
+ 0.30.0
@@ -48,6 +48,13 @@ cleared by editing driver code; it clears by changing the plan's numbers.
48
48
  file under a judge-path surface — paths that would let a work unit edit its
49
49
  own verification.
50
50
 
51
+ **Does not cover the terminal gate.** The class reads only the successor
52
+ gate's drafted units. A terminal gate has no successor, so what its own units
53
+ change is never checked; a single-gate feature is never checked at all. The
54
+ terminal close goes straight to the judge, and no judge-path check sits on
55
+ that path (#3542). A feature that edits a judge surface in its last gate should
56
+ run under `review`.
57
+
51
58
  **Fires when:** a drafted WU's `produces:` list contains a path matching one
52
59
  of `JUDGE_PATHS` — `.specfuse/verification.yml`, `.specfuse/hooks/`,
53
60
  `.specfuse/rules/`, `.github/workflows/`, or `pyproject.toml` (matched
@@ -26,8 +26,8 @@ on both surfaces.
26
26
  both stay resumable: a human flips the feature back to `active` when the
27
27
  obstacle clears. Both are distinct from `abandoned` (dead) and `done`
28
28
  (complete).
29
- - `blocked` — cannot proceed because a **named** dependency is unmet: an ADR
30
- awaiting approval, or an upstream `FEAT-YYYY-NNNN` that must complete first.
29
+ - `blocked` — cannot proceed because a **named** dependency is unmet: a decision
30
+ awaiting approval (ADR or decision entry, per `layout.yml`), or an upstream `FEAT-YYYY-NNNN` that must complete first.
31
31
  A blocked feature always names and links its blocker, so the roadmap shows
32
32
  the dependency at a glance. Only `planned` or `active` may be blocked.
33
33
  - `deferred` — a *voluntary* park with no named blocker, pending an external
@@ -795,9 +795,12 @@ untouched** — the same eight stop classes, the same `would_arm`, the same
795
795
  single flip site. What changed is what an armed gate is armed *on*. Before the
796
796
  judge, an `auto` feature let the session that did the work write the verdict
797
797
  that advanced the feature; now a fresh evaluator that never sees that session's
798
- prose writes it, and can only lower it. The `judge_editing` stop class still
799
- vetoes any gate that edited the loop's own driver, so a feature that changes
800
- the machinery keeps its human checkpoint regardless of this default.
798
+ prose writes it, and can only lower it. The `judge_editing` stop class vetoes
799
+ arming a successor gate whose drafted units would edit a judge surface. It
800
+ does **not** cover the terminal gate's own units, so a single-gate feature,
801
+ or the last gate of any feature, that edits the loop's verdict machinery
802
+ reaches its close with no human checkpoint under `auto` (#3542). Choose
803
+ `review` for such a feature.
801
804
 
802
805
  Tighten to `review` when the judge cannot do its job — a feature whose criteria
803
806
  are not judgeable from the evidence bundle (see `judge_disabled` in §3), or one
@@ -49,7 +49,7 @@ roadmap ──/pick-feature──▶ active ──/draft-feature──▶ gate 1
49
49
  - **`/roadmap-add`** — add a new feature row to the roadmap before it's ready to
50
50
  pick.
51
51
  - **`/block-feature`** — flip a roadmap feature to `blocked` (or clear it) with a
52
- linked `**Blocked by.**` blocker — an ADR awaiting approval or an upstream
52
+ linked `**Blocked by.**` blocker — a decision awaiting approval (ADR or decision entry, per `layout.yml`) or an upstream
53
53
  FEAT-ID that must complete first. Writes the row status, the detail block, and
54
54
  PLAN frontmatter, keeping intra-page feature links resolvable.
55
55
  `/block-feature FEAT-ID --unblock` clears the block and restores the status.
@@ -34,6 +34,7 @@ links to it.
34
34
  A `blocked` feature's detail section carries a `**Blocked by.**` block — blank
35
35
  line above it, one linked blocker per clause:
36
36
 
37
+ <!-- layout:decisions-example -->
37
38
  **Blocked by.** [ADR-0007: event-schema versioning](../docs/adr/0007-event-schema-versioning.md) — awaiting approval; [FEAT-2026-0011](#feat-2026-0011) — scoring data must land first.
38
39
 
39
40
  Each blocker is a Markdown link: an ADR points at its `.md` file (kept under
@@ -41,6 +42,7 @@ Each blocker is a Markdown link: an ADR points at its `.md` file (kept under
41
42
  `../docs/adr/…`); a feature dependency points at the blocking
42
43
  feature's roadmap anchor (`#feat-yyyy-nnnn`). When every blocker clears, a human
43
44
  flips `blocked` → `active` (or `planned`) and removes the `**Blocked by.**` block.
45
+ <!-- /layout:decisions-example -->
44
46
 
45
47
  ## Notes
46
48
 
@@ -523,6 +523,71 @@ def annotate_escalation(
523
523
  return issue_number
524
524
 
525
525
 
526
+ #: How many closed `needs-human` issues one sweep reads. Cleared issues drop
527
+ #: the label, so the set stays small once a repository has been swept once.
528
+ _CLOSED_SWEEP_LIMIT = 100
529
+
530
+
531
+ def clear_closed_escalation_labels(
532
+ runner: Callable, repo: str, *, limit: int = _CLOSED_SWEEP_LIMIT
533
+ ) -> list:
534
+ """Remove the lane's escalation labels from closed issues (#3523).
535
+
536
+ An escalated issue that a person then fixed and closed kept
537
+ ``needs-human`` and its category label: it looked parked to anyone
538
+ filtering by label, and reopened, the bug lane would skip it. Only an
539
+ issue carrying this module's escalation marker (body or comment) is
540
+ touched -- the labels on it are the lane's own -- and only
541
+ ``needs-human`` plus ``CATEGORY_LABELS`` are removed. Best-effort like
542
+ every other label projection here: an unreadable listing or a failed edit
543
+ clears nothing and never raises. Returns the numbers cleared.
544
+ """
545
+ try:
546
+ result = runner(
547
+ [
548
+ "gh", "issue", "list",
549
+ "--repo", repo,
550
+ "--label", NEEDS_HUMAN_LABEL,
551
+ "--state", "closed",
552
+ "--limit", str(limit),
553
+ "--json", "number,body,comments,labels",
554
+ ],
555
+ check=False,
556
+ )
557
+ except Exception: # noqa: BLE001 - a sweep failure must not stop the run
558
+ return []
559
+ if getattr(result, "returncode", 1) != 0 or not getattr(result, "stdout", None):
560
+ return []
561
+ try:
562
+ issues = json.loads(result.stdout)
563
+ except ValueError:
564
+ return []
565
+ marker_prefix = _CORRELATION_MARKER_TEMPLATE.split("{", 1)[0]
566
+ cleared = []
567
+ for issue in issues if isinstance(issues, list) else ():
568
+ if not isinstance(issue, dict) or "number" not in issue:
569
+ continue
570
+ texts = [issue.get("body") or ""] + [
571
+ comment.get("body") or ""
572
+ for comment in issue.get("comments") or []
573
+ if isinstance(comment, dict)
574
+ ]
575
+ if not any(marker_prefix in text for text in texts):
576
+ continue
577
+ names = {
578
+ label.get("name")
579
+ for label in issue.get("labels") or []
580
+ if isinstance(label, dict)
581
+ }
582
+ to_remove = sorted(names & (CATEGORY_LABELS | {NEEDS_HUMAN_LABEL}))
583
+ argv = ["gh", "issue", "edit", str(issue["number"]), "--repo", repo]
584
+ for label in to_remove:
585
+ argv += ["--remove-label", label]
586
+ if _try_run(runner, argv):
587
+ cleared.append(issue["number"])
588
+ return cleared
589
+
590
+
526
591
  def _try_run(runner: Callable, argv: list) -> bool:
527
592
  """Run *argv*, swallowing any failure. Returns whether it succeeded.
528
593