specfuse-loop 0.3.4__tar.gz → 0.3.5__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 (133) hide show
  1. {specfuse_loop-0.3.4/specfuse_loop.egg-info → specfuse_loop-0.3.5}/PKG-INFO +1 -1
  2. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/pyproject.toml +1 -1
  3. specfuse_loop-0.3.5/specfuse/loop/data/VERSION +1 -0
  4. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/loop.py +7 -2
  5. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5/specfuse_loop.egg-info}/PKG-INFO +1 -1
  6. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse_loop.egg-info/SOURCES.txt +1 -0
  7. specfuse_loop-0.3.5/tests/test_lint_plan_relative_import.py +57 -0
  8. specfuse_loop-0.3.4/specfuse/loop/data/VERSION +0 -1
  9. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/LICENSE +0 -0
  10. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/NOTICE +0 -0
  11. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/README.md +0 -0
  12. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/setup.cfg +0 -0
  13. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/__init__.py +0 -0
  14. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/_miniyaml.py +0 -0
  15. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/adopt_feature.py +0 -0
  16. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/data/LEARNINGS.template.md +0 -0
  17. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/data/docs/concepts/architecture-addendum-gates-and-iterative-planning.md +0 -0
  18. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/data/docs/concepts/ralph-lineage.md +0 -0
  19. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/data/docs/getting-started.md +0 -0
  20. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/data/docs/methodology.md +0 -0
  21. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/data/docs/skills.md +0 -0
  22. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/data/gitignore.snippet +0 -0
  23. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/data/roadmap.template.md +0 -0
  24. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/data/rules/correlation-ids.md +0 -0
  25. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/data/rules/never-touch.md +0 -0
  26. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/data/rules/result-contract.md +0 -0
  27. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/data/rules/security-boundaries.md +0 -0
  28. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/data/templates/GATE.template.md +0 -0
  29. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/data/templates/PLAN.template.md +0 -0
  30. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/data/templates/WU.template.md +0 -0
  31. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/data/verification.yml.example +0 -0
  32. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/gate_eval.py +0 -0
  33. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/gh_backend.py +0 -0
  34. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/gh_features.py +0 -0
  35. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/lint_plan.py +0 -0
  36. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/scaffold.py +0 -0
  37. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse/loop/validate_event.py +0 -0
  38. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse_loop.egg-info/dependency_links.txt +0 -0
  39. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse_loop.egg-info/entry_points.txt +0 -0
  40. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse_loop.egg-info/requires.txt +0 -0
  41. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/specfuse_loop.egg-info/top_level.txt +0 -0
  42. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_adopt_feature.py +0 -0
  43. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_arm_gate_edits_uncommitted.py +0 -0
  44. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_attempt_outcome_emission.py +0 -0
  45. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_autosync.py +0 -0
  46. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_autosync_consent.py +0 -0
  47. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_autosync_firstrun.py +0 -0
  48. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_autosync_plugin.py +0 -0
  49. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_backend.py +0 -0
  50. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_bookkeeping_commit_crash_run.py +0 -0
  51. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_bookkeeping_commit_hook_crash.py +0 -0
  52. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_closing_deliverable_guard.py +0 -0
  53. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_cost_tracking.py +0 -0
  54. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_deliverable_presence_gate.py +0 -0
  55. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_doctor.py +0 -0
  56. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_driver_integration.py +0 -0
  57. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_driver_lock.py +0 -0
  58. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_duration_tracking.py +0 -0
  59. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_empty_files_escalation.py +0 -0
  60. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_ensure_feature_branch.py +0 -0
  61. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_extra_gates.py +0 -0
  62. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_force_full_close.py +0 -0
  63. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_gate_eval.py +0 -0
  64. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_gate_eval_calibration.py +0 -0
  65. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_gate_eval_intermediate_wiring.py +0 -0
  66. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_gate_eval_terminal_wiring.py +0 -0
  67. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_gh_backend.py +0 -0
  68. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_gh_features.py +0 -0
  69. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_git_env_isolation.py +0 -0
  70. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_hashed_denylist.py +0 -0
  71. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_hashed_denylist_ci.py +0 -0
  72. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_init_integration.py +0 -0
  73. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_leak_findings_redaction.py +0 -0
  74. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_leak_scan.py +0 -0
  75. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_leak_scan_content.py +0 -0
  76. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_legacy_4wu_terminal_flips.py +0 -0
  77. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_lifecycle_integration.py +0 -0
  78. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_lint_bare_produces_path.py +0 -0
  79. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_lint_close_intermediate.py +0 -0
  80. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_lint_close_wu.py +0 -0
  81. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_lint_correlation_id.py +0 -0
  82. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_lint_correlation_id_close_intermediate.py +0 -0
  83. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_lint_oracle_env.py +0 -0
  84. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_lint_plan_errors.py +0 -0
  85. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_lint_plan_next_draft.py +0 -0
  86. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_lint_produces_driver_helper.py +0 -0
  87. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_lint_sections.py +0 -0
  88. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_lint_task_graph_yaml_selection.py +0 -0
  89. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_loop_auto_archive.py +0 -0
  90. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_loop_caveman_preamble.py +0 -0
  91. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_loop_close_intermediate.py +0 -0
  92. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_loop_defaults_by_type.py +0 -0
  93. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_loop_effort.py +0 -0
  94. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_loop_failure_note_cap.py +0 -0
  95. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_loop_files_changed_guard.py +0 -0
  96. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_loop_gate_budget.py +0 -0
  97. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_loop_model_alias.py +0 -0
  98. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_loop_orchestration.py +0 -0
  99. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_loop_post_pass_invariant.py +0 -0
  100. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_loop_reset_preserving_events.py +0 -0
  101. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_loop_smoke_runner.py +0 -0
  102. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_loop_unsandboxed.py +0 -0
  103. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_loop_zero_token_guard.py +0 -0
  104. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_migrate_legacy.py +0 -0
  105. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_miniyaml_equivalence.py +0 -0
  106. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_miniyaml_negative.py +0 -0
  107. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_planned_cost_lint.py +0 -0
  108. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_prepare_feature.py +0 -0
  109. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_produces_field.py +0 -0
  110. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_result_block.py +0 -0
  111. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_roadmap_add_skill.py +0 -0
  112. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_roadmap_archive_skill.py +0 -0
  113. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_roadmap_row_parser.py +0 -0
  114. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_scaffold_data_in_sync.py +0 -0
  115. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_scaffold_docs.py +0 -0
  116. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_scaffold_init.py +0 -0
  117. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_scaffold_manifest.py +0 -0
  118. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_scaffold_resources.py +0 -0
  119. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_scaffold_seed_sanity.py +0 -0
  120. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_scaffold_upgrade.py +0 -0
  121. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_scaffold_wiring.py +0 -0
  122. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_squash_commit_hook_crash.py +0 -0
  123. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_template_closing_shapes.py +0 -0
  124. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_terminal_flip_ownership.py +0 -0
  125. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_terminal_flips.py +0 -0
  126. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_untracked_feature_folder.py +0 -0
  127. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_upgrade_integration.py +0 -0
  128. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_validate_event.py +0 -0
  129. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_verdict_coupling.py +0 -0
  130. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_verify_empty_gate_set.py +0 -0
  131. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_version_consistency.py +0 -0
  132. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/tests/test_version_skew.py +0 -0
  133. {specfuse_loop-0.3.4 → specfuse_loop-0.3.5}/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.4
3
+ Version: 0.3.5
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.4"
7
+ version = "0.3.5"
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"
@@ -0,0 +1 @@
1
+ 0.3.5
@@ -62,7 +62,7 @@ SPECFUSE_DIR = Path(".specfuse")
62
62
  REPO_ROOT = SPECFUSE_DIR.parent
63
63
  FEATURES_DIR = SPECFUSE_DIR / "features"
64
64
  VERIFICATION_PATH = SPECFUSE_DIR / "verification.yml"
65
- DRIVER_VERSION = "0.3.4"
65
+ DRIVER_VERSION = "0.3.5"
66
66
  # Oldest scaffold layout this driver can drive. init.sh stamps the scaffold's own
67
67
  # version into `.specfuse/VERSION`; check_scaffold_version() fails loud at startup if
68
68
  # the consumer's scaffold is older than this, pointing at `specfuse upgrade`. Bump
@@ -3531,7 +3531,12 @@ def run(
3531
3531
  # FEAT-2026-0018/T07 — plan-next-draft lint hook (warn-only v1)
3532
3532
  if wu.type == "plan-next":
3533
3533
  try:
3534
- from lint_plan import lint_plan_next_draft
3534
+ # Package-relative + function-local: lint_plan
3535
+ # imports `from .loop import VERDICT_VALUES`, so a
3536
+ # module-top import would be circular; the old
3537
+ # flat (top-level) form broke once the driver
3538
+ # ships as a pip package (#100).
3539
+ from .lint_plan import lint_plan_next_draft
3535
3540
  _warns = lint_plan_next_draft(feature_dir, gate.number)
3536
3541
  except Exception as _exc:
3537
3542
  _warns = [f"lint_plan_next_draft raised: {_exc}"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specfuse-loop
3
- Version: 0.3.4
3
+ Version: 0.3.5
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
@@ -79,6 +79,7 @@ tests/test_lint_correlation_id_close_intermediate.py
79
79
  tests/test_lint_oracle_env.py
80
80
  tests/test_lint_plan_errors.py
81
81
  tests/test_lint_plan_next_draft.py
82
+ tests/test_lint_plan_relative_import.py
82
83
  tests/test_lint_produces_driver_helper.py
83
84
  tests/test_lint_sections.py
84
85
  tests/test_lint_task_graph_yaml_selection.py
@@ -0,0 +1,57 @@
1
+ #
2
+ # Copyright 2026 Specfuse contributors
3
+ # Licensed under the Apache License, Version 2.0. See LICENSE.
4
+ #
5
+ """Regression test for #100 — the plan-next-draft lint hook must use a
6
+ package-relative import.
7
+
8
+ `loop.py`'s plan-next hook imported `from lint_plan import lint_plan_next_draft`
9
+ (flat). That only resolved when the scripts were copied side-by-side (pre-pip);
10
+ in the installed package it raises `No module named 'lint_plan'`, so the
11
+ plan-next gate logs a warning and the draft lint never runs. The import is
12
+ function-local on purpose (lint_plan imports `from .loop import VERDICT_VALUES`,
13
+ so a module-top import would be circular) — the fix is to make the local import
14
+ package-relative, not to hoist it.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ import subprocess
20
+ import sys
21
+ import tempfile
22
+ import unittest
23
+ from pathlib import Path
24
+
25
+ REPO_ROOT = Path(__file__).resolve().parent.parent
26
+ LOOP_SRC = REPO_ROOT / "specfuse" / "loop" / "loop.py"
27
+
28
+
29
+ class TestLintPlanRelativeImport(unittest.TestCase):
30
+
31
+ def test_loop_uses_package_relative_lint_plan_import(self):
32
+ src = LOOP_SRC.read_text(encoding="utf-8")
33
+ self.assertNotIn(
34
+ "from lint_plan import", src,
35
+ "flat `from lint_plan import` breaks in the installed package (#100)",
36
+ )
37
+ self.assertIn(
38
+ "from .lint_plan import lint_plan_next_draft", src,
39
+ "the plan-next hook must import lint_plan_next_draft package-relative",
40
+ )
41
+
42
+ def test_lint_plan_next_draft_importable_outside_repo_root(self):
43
+ """Resolvable as a package member even when CWD is not the repo root
44
+ (so a flat `lint_plan.py` on the path can't mask the bug)."""
45
+ with tempfile.TemporaryDirectory() as tmp:
46
+ r = subprocess.run(
47
+ [sys.executable, "-c",
48
+ "from specfuse.loop.lint_plan import lint_plan_next_draft; "
49
+ "print('ok')"],
50
+ capture_output=True, text=True, cwd=tmp,
51
+ )
52
+ self.assertEqual(r.returncode, 0, r.stderr)
53
+ self.assertIn("ok", r.stdout)
54
+
55
+
56
+ if __name__ == "__main__":
57
+ unittest.main()
@@ -1 +0,0 @@
1
- 0.3.4
File without changes
File without changes
File without changes
File without changes