specfuse-loop 0.3.23__tar.gz → 0.4.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 (173) hide show
  1. {specfuse_loop-0.3.23/specfuse_loop.egg-info → specfuse_loop-0.4.0}/PKG-INFO +1 -1
  2. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/pyproject.toml +13 -3
  3. specfuse_loop-0.4.0/specfuse/loop/data/VERSION +1 -0
  4. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/docs/skills.md +5 -0
  5. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/roadmap.template.md +18 -2
  6. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/templates/PLAN.template.md +1 -1
  7. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/lint_plan.py +1 -1
  8. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/loop.py +450 -81
  9. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/validate_event.py +2 -1
  10. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0/specfuse_loop.egg-info}/PKG-INFO +1 -1
  11. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse_loop.egg-info/SOURCES.txt +3 -0
  12. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_adopt_feature.py +3 -0
  13. specfuse_loop-0.4.0/tests/test_baseline_escalation_message.py +257 -0
  14. specfuse_loop-0.4.0/tests/test_baseline_persistence.py +420 -0
  15. specfuse_loop-0.4.0/tests/test_baseline_probe.py +319 -0
  16. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_bookkeeping_no_verify.py +1 -1
  17. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_ensure_feature_branch.py +2 -2
  18. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_ensure_feature_branch_base.py +1 -1
  19. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_init_integration.py +2 -0
  20. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_learnings_query.py +1 -0
  21. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_correlation_id.py +2 -2
  22. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_plan_relative_import.py +1 -1
  23. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_auto_archive.py +40 -0
  24. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_gate_budget.py +3 -3
  25. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_orchestration.py +27 -2
  26. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_migrate_legacy.py +2 -2
  27. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_prepare_feature.py +2 -2
  28. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_resolve_base.py +2 -2
  29. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_upgrade_integration.py +2 -0
  30. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_validate_event.py +1 -0
  31. specfuse_loop-0.3.23/specfuse/loop/data/VERSION +0 -1
  32. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/LICENSE +0 -0
  33. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/NOTICE +0 -0
  34. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/README.md +0 -0
  35. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/setup.cfg +0 -0
  36. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/__init__.py +0 -0
  37. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/_filelock.py +0 -0
  38. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/_miniyaml.py +0 -0
  39. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/adopt_feature.py +0 -0
  40. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/LEARNINGS.template.md +0 -0
  41. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/docs/concepts/architecture-addendum-gates-and-iterative-planning.md +0 -0
  42. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/docs/concepts/ralph-lineage.md +0 -0
  43. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/docs/getting-started.md +0 -0
  44. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/docs/methodology.md +0 -0
  45. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/gitignore.snippet +0 -0
  46. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/rules/close-discipline.md +0 -0
  47. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/rules/correlation-ids.md +0 -0
  48. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/rules/never-touch.md +0 -0
  49. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/rules/planning-discipline.md +0 -0
  50. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/rules/result-contract.md +0 -0
  51. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/rules/security-boundaries.md +0 -0
  52. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/rules/verification-discipline.md +0 -0
  53. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/rules-local/README.md +0 -0
  54. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/schemas/event.schema.json +0 -0
  55. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/schemas/events/initiative_created.schema.json +0 -0
  56. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/schemas/events/spec_issue_resolved.schema.json +0 -0
  57. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/schemas/events/spec_issue_routed.schema.json +0 -0
  58. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/schemas/events/spec_validated.schema.json +0 -0
  59. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/templates/GATE.template.md +0 -0
  60. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/templates/WU.template.md +0 -0
  61. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/verification.yml.example +0 -0
  62. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/gate_eval.py +0 -0
  63. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/gh_backend.py +0 -0
  64. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/gh_features.py +0 -0
  65. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/scaffold.py +0 -0
  66. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse_loop.egg-info/dependency_links.txt +0 -0
  67. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse_loop.egg-info/entry_points.txt +0 -0
  68. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse_loop.egg-info/requires.txt +0 -0
  69. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse_loop.egg-info/top_level.txt +0 -0
  70. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_arm_gate_edits_uncommitted.py +0 -0
  71. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_attempt_outcome_emission.py +0 -0
  72. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_autoclose_deferral_visibility.py +0 -0
  73. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_autosync.py +0 -0
  74. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_autosync_consent.py +0 -0
  75. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_autosync_firstrun.py +0 -0
  76. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_autosync_plugin.py +0 -0
  77. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_backend.py +0 -0
  78. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_bash_routing.py +0 -0
  79. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_bookkeeping_commit_crash_run.py +0 -0
  80. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_bookkeeping_commit_hook_crash.py +0 -0
  81. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_claude_resolution.py +0 -0
  82. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_close_wu_self_reference.py +0 -0
  83. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_closing_deliverable_guard.py +0 -0
  84. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_console_encoding.py +0 -0
  85. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_cost_tracking.py +0 -0
  86. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_degraded_oracle.py +0 -0
  87. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_deliverable_presence_gate.py +0 -0
  88. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_doctor.py +0 -0
  89. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_driver_integration.py +0 -0
  90. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_driver_lock.py +0 -0
  91. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_duration_tracking.py +0 -0
  92. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_empty_files_escalation.py +0 -0
  93. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_events_redaction.py +0 -0
  94. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_extra_gates.py +0 -0
  95. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_filelock_portable.py +0 -0
  96. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_force_full_close.py +0 -0
  97. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_gate_eval.py +0 -0
  98. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_gate_eval_calibration.py +0 -0
  99. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_gate_eval_intermediate_wiring.py +0 -0
  100. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_gate_eval_terminal_wiring.py +0 -0
  101. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_gh_backend.py +0 -0
  102. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_gh_features.py +0 -0
  103. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_git_env_isolation.py +0 -0
  104. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_hashed_denylist.py +0 -0
  105. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_hashed_denylist_ci.py +0 -0
  106. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_interpreter_normalization.py +0 -0
  107. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_leak_findings_redaction.py +0 -0
  108. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_leak_scan.py +0 -0
  109. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_leak_scan_content.py +0 -0
  110. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_legacy_4wu_terminal_flips.py +0 -0
  111. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lifecycle_integration.py +0 -0
  112. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lifetime_accounting.py +0 -0
  113. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_bare_produces_path.py +0 -0
  114. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_close_intermediate.py +0 -0
  115. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_close_wu.py +0 -0
  116. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_correlation_id_close_intermediate.py +0 -0
  117. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_oracle_env.py +0 -0
  118. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_plan_errors.py +0 -0
  119. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_plan_next_draft.py +0 -0
  120. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_planning_sections.py +0 -0
  121. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_produces_driver_helper.py +0 -0
  122. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_sections.py +0 -0
  123. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_task_graph_yaml_selection.py +0 -0
  124. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_verification_reference.py +0 -0
  125. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_attempt_evidence.py +0 -0
  126. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_caveman_preamble.py +0 -0
  127. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_close_intermediate.py +0 -0
  128. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_defaults_by_type.py +0 -0
  129. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_effort.py +0 -0
  130. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_failure_note_cap.py +0 -0
  131. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_files_changed_guard.py +0 -0
  132. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_model_alias.py +0 -0
  133. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_post_pass_invariant.py +0 -0
  134. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_reset_preserving_events.py +0 -0
  135. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_smoke_runner.py +0 -0
  136. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_unsandboxed.py +0 -0
  137. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_zero_token_guard.py +0 -0
  138. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_miniyaml_equivalence.py +0 -0
  139. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_miniyaml_negative.py +0 -0
  140. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_planned_cost_lint.py +0 -0
  141. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_prepare_scaffold_sync.py +0 -0
  142. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_produces_field.py +0 -0
  143. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_produces_in_diff.py +0 -0
  144. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_redaction_windows_home.py +0 -0
  145. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_result_block.py +0 -0
  146. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_roadmap_add_skill.py +0 -0
  147. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_roadmap_archive_skill.py +0 -0
  148. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_roadmap_row_parser.py +0 -0
  149. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_scaffold_data_in_sync.py +0 -0
  150. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_scaffold_doc_hygiene.py +0 -0
  151. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_scaffold_docs.py +0 -0
  152. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_scaffold_init.py +0 -0
  153. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_scaffold_manifest.py +0 -0
  154. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_scaffold_resources.py +0 -0
  155. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_scaffold_seed_sanity.py +0 -0
  156. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_scaffold_upgrade.py +0 -0
  157. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_scaffold_wiring.py +0 -0
  158. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_skills_vendored_in_sync.py +0 -0
  159. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_spinning_rearm_gate.py +0 -0
  160. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_squash_commit_hook_crash.py +0 -0
  161. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_template_closing_shapes.py +0 -0
  162. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_terminal_flip_ownership.py +0 -0
  163. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_terminal_flips.py +0 -0
  164. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_timeout_kill_portable.py +0 -0
  165. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_untracked_feature_folder.py +0 -0
  166. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_untracked_file_absorption.py +0 -0
  167. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_upgrade_merge_gate.py +0 -0
  168. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_verdict_coupling.py +0 -0
  169. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_verify_empty_gate_set.py +0 -0
  170. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_version_consistency.py +0 -0
  171. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_version_skew.py +0 -0
  172. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_windows_gate_exec.py +0 -0
  173. {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_wu_execution_metadata.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specfuse-loop
3
- Version: 0.3.23
3
+ Version: 0.4.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.3.23"
7
+ version = "0.4.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"
@@ -45,11 +45,21 @@ dev = [
45
45
  Homepage = "https://github.com/specfuse/loop"
46
46
  Source = "https://github.com/specfuse/loop"
47
47
 
48
- # Minimal ruff config — keep defaults (E + F). Target the loop's actual
49
- # minimum Python (matches pyproject's `requires-python`).
48
+ # Target the loop's actual minimum Python (matches `requires-python`).
50
49
  [tool.ruff]
51
50
  target-version = "py310"
52
51
 
52
+ [tool.ruff.lint]
53
+ # Pin the ruleset EXPLICITLY rather than relying on ruff's implicit default.
54
+ # ruff 0.16 broadened its default `select` to a large opinionated set
55
+ # (B/SIM/PLW/RUF/I/…); a bare config inherited that overnight and flagged ~300
56
+ # findings across code that had been clean for months — breaking CI on every PR
57
+ # purely from a version bump. This repo intends only the classic default
58
+ # (pyflakes + the core pycodestyle subset); pinning it here makes that intent
59
+ # version-independent. Adopting the broader ruleset is a separate, deliberate
60
+ # decision (see the roadmap), never an implicit consequence of upgrading ruff.
61
+ select = ["E4", "E7", "E9", "F", "PLW1510", "B", "BLE001", "S110", "TRY004"]
62
+
53
63
  [project.scripts]
54
64
  specfuse-loop = "specfuse.loop.loop:main"
55
65
  specfuse-lint = "specfuse.loop.lint_plan:main"
@@ -0,0 +1 @@
1
+ 0.4.0
@@ -48,6 +48,11 @@ roadmap ──/pick-feature──▶ active ──/draft-feature──▶ gate 1
48
48
  `/draft-feature`.
49
49
  - **`/roadmap-add`** — add a new feature row to the roadmap before it's ready to
50
50
  pick.
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
53
+ FEAT-ID that must complete first. Writes the row status, the detail block, and
54
+ PLAN frontmatter, keeping intra-page feature links resolvable.
55
+ `/block-feature FEAT-ID --unblock` clears the block and restores the status.
51
56
 
52
57
  ### 2. Draft — turn a picked feature into a runnable gate
53
58
 
@@ -23,8 +23,24 @@ the canonical column order below.
23
23
  |----------------|-------|--------|--------|--------|
24
24
 
25
25
  Status: `planned` → `active` → `done` (or `abandoned`). `deferred` = parked
26
- pending an external decision/dependency; resumable (a human flips it back to
27
- `active` when the blocker clears), distinct from `abandoned` (dead).
26
+ by choice pending an external decision/dependency; resumable (a human flips it
27
+ back to `active` when the blocker clears), distinct from `abandoned` (dead).
28
+ `blocked` = cannot proceed because a *named* dependency is unmet — an ADR
29
+ awaiting approval, or an upstream feature that must complete first. Resumable
30
+ like `deferred`, but where `deferred` is a voluntary park with no named blocker,
31
+ `blocked` always names its blocker so the roadmap shows what it waits on and
32
+ links to it.
33
+
34
+ A `blocked` feature's detail section carries a `**Blocked by.**` block — blank
35
+ line above it, one linked blocker per clause:
36
+
37
+ **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
+ Each blocker is a Markdown link: an ADR points at its `.md` file (kept under
40
+ `docs/adr/` by convention, so from `.specfuse/roadmap.md` the link is
41
+ `../docs/adr/…`); a feature dependency points at the blocking
42
+ feature's roadmap anchor (`#feat-yyyy-nnnn`). When every blocker clears, a human
43
+ flips `blocked` → `active` (or `planned`) and removes the `**Blocked by.**` block.
28
44
 
29
45
  ## Notes
30
46
 
@@ -7,7 +7,7 @@ roadmap_goal: <one line copied from the roadmap — the north star this feature
7
7
  plan-next anchors every drafted gate to this and flags if a retrospective implies
8
8
  it should change>
9
9
  autonomy_default: review # auto | review | supervised
10
- status: active # active | deferred | done | abandoned
10
+ status: active # active | blocked | deferred | done | abandoned
11
11
  # deferred = parked pending an external decision/dependency; resumable, non-dispatchable
12
12
  # planned_cost_usd: 0.00 # OPTIONAL — sum of WU planned costs; lint warns when missing or when delta from WU sum > 10%
13
13
  ---
@@ -46,7 +46,7 @@ VALID_STATUS = {"draft", "pending", "ready", "in_progress", "in_review", "done",
46
46
  # unrecognized status that passes lint and then behaves differently at dispatch
47
47
  # is the class #183 (deferred) and #185 exist to close. Keep in sync with
48
48
  # find_feature / the gate-status transitions in loop.py.
49
- VALID_FEATURE_STATUS = {"planned", "active", "deferred", "done", "abandoned"}
49
+ VALID_FEATURE_STATUS = {"planned", "active", "blocked", "deferred", "done", "abandoned"}
50
50
  VALID_GATE_STATUS = {"open", "awaiting_review", "passed"}
51
51
  CLOSING_SEQUENCE = ["retrospective", "lessons", "docs", "plan-next"]
52
52
  # New compact closing shapes (FEAT-2026-0015):