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.
- {specfuse_loop-0.3.23/specfuse_loop.egg-info → specfuse_loop-0.4.0}/PKG-INFO +1 -1
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/pyproject.toml +13 -3
- specfuse_loop-0.4.0/specfuse/loop/data/VERSION +1 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/docs/skills.md +5 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/roadmap.template.md +18 -2
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/templates/PLAN.template.md +1 -1
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/lint_plan.py +1 -1
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/loop.py +450 -81
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/validate_event.py +2 -1
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0/specfuse_loop.egg-info}/PKG-INFO +1 -1
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse_loop.egg-info/SOURCES.txt +3 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_adopt_feature.py +3 -0
- specfuse_loop-0.4.0/tests/test_baseline_escalation_message.py +257 -0
- specfuse_loop-0.4.0/tests/test_baseline_persistence.py +420 -0
- specfuse_loop-0.4.0/tests/test_baseline_probe.py +319 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_bookkeeping_no_verify.py +1 -1
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_ensure_feature_branch.py +2 -2
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_ensure_feature_branch_base.py +1 -1
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_init_integration.py +2 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_learnings_query.py +1 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_correlation_id.py +2 -2
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_plan_relative_import.py +1 -1
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_auto_archive.py +40 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_gate_budget.py +3 -3
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_orchestration.py +27 -2
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_migrate_legacy.py +2 -2
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_prepare_feature.py +2 -2
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_resolve_base.py +2 -2
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_upgrade_integration.py +2 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_validate_event.py +1 -0
- specfuse_loop-0.3.23/specfuse/loop/data/VERSION +0 -1
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/LICENSE +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/NOTICE +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/README.md +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/setup.cfg +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/__init__.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/_filelock.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/_miniyaml.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/adopt_feature.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/LEARNINGS.template.md +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/docs/concepts/architecture-addendum-gates-and-iterative-planning.md +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/docs/concepts/ralph-lineage.md +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/docs/getting-started.md +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/docs/methodology.md +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/gitignore.snippet +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/rules/close-discipline.md +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/rules/correlation-ids.md +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/rules/never-touch.md +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/rules/planning-discipline.md +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/rules/result-contract.md +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/rules/security-boundaries.md +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/rules/verification-discipline.md +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/rules-local/README.md +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/schemas/event.schema.json +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/schemas/events/initiative_created.schema.json +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/schemas/events/spec_issue_resolved.schema.json +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/schemas/events/spec_issue_routed.schema.json +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/schemas/events/spec_validated.schema.json +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/templates/GATE.template.md +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/templates/WU.template.md +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/data/verification.yml.example +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/gate_eval.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/gh_backend.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/gh_features.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse/loop/scaffold.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse_loop.egg-info/dependency_links.txt +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse_loop.egg-info/entry_points.txt +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse_loop.egg-info/requires.txt +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/specfuse_loop.egg-info/top_level.txt +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_arm_gate_edits_uncommitted.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_attempt_outcome_emission.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_autoclose_deferral_visibility.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_autosync.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_autosync_consent.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_autosync_firstrun.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_autosync_plugin.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_backend.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_bash_routing.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_bookkeeping_commit_crash_run.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_bookkeeping_commit_hook_crash.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_claude_resolution.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_close_wu_self_reference.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_closing_deliverable_guard.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_console_encoding.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_cost_tracking.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_degraded_oracle.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_deliverable_presence_gate.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_doctor.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_driver_integration.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_driver_lock.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_duration_tracking.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_empty_files_escalation.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_events_redaction.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_extra_gates.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_filelock_portable.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_force_full_close.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_gate_eval.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_gate_eval_calibration.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_gate_eval_intermediate_wiring.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_gate_eval_terminal_wiring.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_gh_backend.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_gh_features.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_git_env_isolation.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_hashed_denylist.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_hashed_denylist_ci.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_interpreter_normalization.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_leak_findings_redaction.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_leak_scan.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_leak_scan_content.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_legacy_4wu_terminal_flips.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lifecycle_integration.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lifetime_accounting.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_bare_produces_path.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_close_intermediate.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_close_wu.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_correlation_id_close_intermediate.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_oracle_env.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_plan_errors.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_plan_next_draft.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_planning_sections.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_produces_driver_helper.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_sections.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_task_graph_yaml_selection.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_lint_verification_reference.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_attempt_evidence.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_caveman_preamble.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_close_intermediate.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_defaults_by_type.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_effort.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_failure_note_cap.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_files_changed_guard.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_model_alias.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_post_pass_invariant.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_reset_preserving_events.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_smoke_runner.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_unsandboxed.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_loop_zero_token_guard.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_miniyaml_equivalence.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_miniyaml_negative.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_planned_cost_lint.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_prepare_scaffold_sync.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_produces_field.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_produces_in_diff.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_redaction_windows_home.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_result_block.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_roadmap_add_skill.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_roadmap_archive_skill.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_roadmap_row_parser.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_scaffold_data_in_sync.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_scaffold_doc_hygiene.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_scaffold_docs.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_scaffold_init.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_scaffold_manifest.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_scaffold_resources.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_scaffold_seed_sanity.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_scaffold_upgrade.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_scaffold_wiring.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_skills_vendored_in_sync.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_spinning_rearm_gate.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_squash_commit_hook_crash.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_template_closing_shapes.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_terminal_flip_ownership.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_terminal_flips.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_timeout_kill_portable.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_untracked_feature_folder.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_untracked_file_absorption.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_upgrade_merge_gate.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_verdict_coupling.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_verify_empty_gate_set.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_version_consistency.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_version_skew.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_windows_gate_exec.py +0 -0
- {specfuse_loop-0.3.23 → specfuse_loop-0.4.0}/tests/test_wu_execution_metadata.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "specfuse-loop"
|
|
7
|
-
version = "0.
|
|
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
|
-
#
|
|
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
|
|
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):
|