project-workflow 0.9.0__tar.gz → 0.9.2__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 (161) hide show
  1. {project_workflow-0.9.0 → project_workflow-0.9.2}/CHANGELOG.md +40 -0
  2. {project_workflow-0.9.0 → project_workflow-0.9.2}/MANIFEST.in +1 -1
  3. project_workflow-0.9.2/PKG-INFO +170 -0
  4. project_workflow-0.9.2/README.md +143 -0
  5. {project_workflow-0.9.0 → project_workflow-0.9.2}/pyproject.toml +6 -4
  6. project_workflow-0.9.2/scripts/build_runtime_bundle.py +134 -0
  7. project_workflow-0.9.2/scripts/capture_architecture_snapshot.py +143 -0
  8. project_workflow-0.9.2/scripts/capture_compatibility_baseline.py +126 -0
  9. {project_workflow-0.9.0 → project_workflow-0.9.2}/scripts/capture_dogfood_journey.py +3 -10
  10. project_workflow-0.9.2/scripts/capture_test_inventory.py +80 -0
  11. project_workflow-0.9.2/scripts/check_documentation.py +172 -0
  12. {project_workflow-0.9.0 → project_workflow-0.9.2}/scripts/release_contract.py +22 -12
  13. {project_workflow-0.9.0 → project_workflow-0.9.2}/scripts/run_coordination_evaluations.py +10 -29
  14. {project_workflow-0.9.0 → project_workflow-0.9.2}/scripts/verify_package_journeys.py +69 -80
  15. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/_version.py +1 -1
  16. project_workflow-0.9.2/src/project_workflow/adapter_common.py +181 -0
  17. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/claude_adapter.py +69 -53
  18. project_workflow-0.9.2/src/project_workflow/cli.py +1278 -0
  19. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex/AGENTS.md +2 -2
  20. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex_adapter.py +82 -179
  21. project_workflow-0.9.2/src/project_workflow/commands.py +3290 -0
  22. project_workflow-0.9.2/src/project_workflow/contracts.py +1461 -0
  23. project_workflow-0.9.2/src/project_workflow/coordination.py +3059 -0
  24. project_workflow-0.9.2/src/project_workflow/execution.py +2132 -0
  25. project_workflow-0.9.2/src/project_workflow/execution_config.py +540 -0
  26. project_workflow-0.9.2/src/project_workflow/inspection.py +3513 -0
  27. project_workflow-0.9.2/src/project_workflow/lifecycle.py +4654 -0
  28. project_workflow-0.9.2/src/project_workflow/maintenance.py +2274 -0
  29. project_workflow-0.9.2/src/project_workflow/orchestration.py +3100 -0
  30. project_workflow-0.9.2/src/project_workflow/repository.py +2144 -0
  31. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/templates/workflow.py +18855 -17800
  32. project_workflow-0.9.2/src/project_workflow.egg-info/PKG-INFO +170 -0
  33. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow.egg-info/SOURCES.txt +27 -1
  34. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow.egg-info/requires.txt +2 -0
  35. project_workflow-0.9.2/tests/__init__.py +1 -0
  36. project_workflow-0.9.2/tests/test_architecture.py +163 -0
  37. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_claude_adapter.py +57 -20
  38. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_codex_adapter.py +38 -0
  39. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_continuation_sufficiency.py +12 -6
  40. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_coordination_controls.py +21 -16
  41. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_coordination_evaluations.py +7 -22
  42. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_coordinator_clarify_contract.py +2 -7
  43. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_delegate_epic_mode.py +67 -36
  44. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_delegate_host_assets.py +32 -36
  45. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_delegate_task_mode.py +21 -36
  46. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_delegation.py +35 -28
  47. project_workflow-0.9.2/tests/test_doctor_installation.py +712 -0
  48. project_workflow-0.9.2/tests/test_documentation.py +40 -0
  49. project_workflow-0.9.2/tests/test_epic_planning.py +721 -0
  50. project_workflow-0.9.2/tests/test_evidence_lifecycle.py +1292 -0
  51. project_workflow-0.9.2/tests/test_execution_configuration.py +433 -0
  52. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_execution_control_contract.py +4 -4
  53. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_intent_behavioral_eval.py +18 -20
  54. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_intent_integrity.py +5 -5
  55. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_operational_status.py +14 -3
  56. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_operational_status_actions.py +32 -11
  57. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_operational_status_classification.py +8 -24
  58. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_operational_status_cli.py +36 -51
  59. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_operational_status_inspection.py +10 -13
  60. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_package_journeys.py +5 -14
  61. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_qa_release_control.py +11 -18
  62. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_release_contract.py +15 -8
  63. project_workflow-0.9.2/tests/test_repository_upgrade.py +1413 -0
  64. project_workflow-0.9.2/tests/test_smoke_bomb.py +411 -0
  65. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_user_outcome_journey.py +27 -29
  66. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_verification_campaign.py +19 -0
  67. project_workflow-0.9.2/tests/test_work_items.py +1227 -0
  68. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_workspace_mode.py +18 -21
  69. project_workflow-0.9.2/tests/workflow_test_support.py +409 -0
  70. project_workflow-0.9.0/PKG-INFO +0 -921
  71. project_workflow-0.9.0/README.md +0 -896
  72. project_workflow-0.9.0/src/project_workflow/cli.py +0 -25583
  73. project_workflow-0.9.0/src/project_workflow.egg-info/PKG-INFO +0 -921
  74. project_workflow-0.9.0/tests/test_doctor.py +0 -6085
  75. {project_workflow-0.9.0 → project_workflow-0.9.2}/LICENSE +0 -0
  76. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/README.md +0 -0
  77. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/output-schema.json +0 -0
  78. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-ANALYSIS.md +0 -0
  79. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-001/REPORT.json +0 -0
  80. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-001/baseline-trial-1.json +0 -0
  81. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-001/baseline-trial-2.json +0 -0
  82. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-001/candidate-trial-1.json +0 -0
  83. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-001/candidate-trial-2.json +0 -0
  84. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-002/REPORT.json +0 -0
  85. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-002/baseline-trial-1.json +0 -0
  86. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-002/baseline-trial-2.json +0 -0
  87. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-002/candidate-trial-1.json +0 -0
  88. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-002/candidate-trial-2.json +0 -0
  89. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-003/REPORT.json +0 -0
  90. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-003/candidate-trial-1.json +0 -0
  91. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-003/candidate-trial-2.json +0 -0
  92. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-004/REPORT.json +0 -0
  93. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-004/candidate-trial-1.json +0 -0
  94. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-004/candidate-trial-2.json +0 -0
  95. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-005/REPORT.json +0 -0
  96. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-005/candidate-trial-1.json +0 -0
  97. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/EPIC-016-run-005/candidate-trial-2.json +0 -0
  98. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/results/PROVENANCE-REDACTION.md +0 -0
  99. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/coordination/scenarios.json +0 -0
  100. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/intent_integrity/REPORT.md +0 -0
  101. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/intent_integrity/cases.json +0 -0
  102. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/intent_integrity/continuation-cases.json +0 -0
  103. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/intent_integrity/expectations.json +0 -0
  104. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/intent_integrity/grade_results.py +0 -0
  105. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/intent_integrity/output.schema.json +0 -0
  106. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/intent_integrity/prompts.json +0 -0
  107. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/intent_integrity/results/trial-1.json +0 -0
  108. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/intent_integrity/results/trial-2.json +0 -0
  109. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/intent_integrity/results/trial-3.json +0 -0
  110. {project_workflow-0.9.0 → project_workflow-0.9.2}/evaluations/intent_integrity/runs.json +0 -0
  111. {project_workflow-0.9.0 → project_workflow-0.9.2}/setup.cfg +0 -0
  112. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/__init__.py +0 -0
  113. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/claude_plugin/project-workflow-execution-control/.claude-plugin/plugin.json +0 -0
  114. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/claude_plugin/project-workflow-execution-control/README.md +0 -0
  115. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/claude_plugin/project-workflow-execution-control/hooks/hooks.json +0 -0
  116. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/claude_plugin/project-workflow-execution-control/scripts/project-workflow-claude-hook +0 -0
  117. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex/skills/project-backlog/SKILL.md +0 -0
  118. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex/skills/project-clarify/SKILL.md +0 -0
  119. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex/skills/project-constitution/SKILL.md +0 -0
  120. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex/skills/project-coordinator/SKILL.md +0 -0
  121. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex/skills/project-delegate/SKILL.md +0 -0
  122. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex/skills/project-epic/SKILL.md +0 -0
  123. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex/skills/project-fix/SKILL.md +0 -0
  124. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex/skills/project-implement/SKILL.md +0 -0
  125. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex/skills/project-planner/SKILL.md +0 -0
  126. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex/skills/project-qa-review/SKILL.md +0 -0
  127. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex/skills/project-requirements/SKILL.md +0 -0
  128. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex/skills/project-retro/SKILL.md +0 -0
  129. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex/skills/project-smoke-bomb/SKILL.md +0 -0
  130. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex/skills/project-task/SKILL.md +0 -0
  131. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex_plugin/project-workflow-execution-control/.codex-plugin/plugin.json +0 -0
  132. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex_plugin/project-workflow-execution-control/README.md +0 -0
  133. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/codex_plugin/project-workflow-execution-control/scripts/project-workflow-codex-hook +0 -0
  134. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/cursor/rules/project-workflow.mdc +0 -0
  135. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/prompts/Backlog.prompt.md +0 -0
  136. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/prompts/Clarify.prompt.md +0 -0
  137. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/prompts/Constitution.prompt.md +0 -0
  138. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/prompts/Coordinator.prompt.md +0 -0
  139. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/prompts/Delegate.prompt.md +0 -0
  140. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/prompts/Epic.prompt.md +0 -0
  141. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/prompts/Fix.prompt.md +0 -0
  142. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/prompts/Implement.prompt.md +0 -0
  143. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/prompts/Planner.prompt.md +0 -0
  144. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/prompts/QAReview.prompt.md +0 -0
  145. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/prompts/Requirements.prompt.md +0 -0
  146. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/prompts/Retro.prompt.md +0 -0
  147. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/prompts/SmokeBomb.prompt.md +0 -0
  148. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/prompts/Task.prompt.md +0 -0
  149. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow/templates/workflow +0 -0
  150. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow.egg-info/dependency_links.txt +0 -0
  151. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow.egg-info/entry_points.txt +0 -0
  152. {project_workflow-0.9.0 → project_workflow-0.9.2}/src/project_workflow.egg-info/top_level.txt +0 -0
  153. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/fixtures/legacy-unversioned/.project-workflow/BACKLOG.md +0 -0
  154. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/fixtures/legacy-unversioned/.project-workflow/TRACKER.md +0 -0
  155. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/fixtures/legacy-unversioned/.project-workflow/config.json +0 -0
  156. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/fixtures/legacy-unversioned/.project-workflow/guidance.md +0 -0
  157. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/fixtures/legacy-unversioned/.project-workflow/tasks/TASK-001-Historical-Work/EVIDENCE.json +0 -0
  158. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/fixtures/legacy-unversioned/.project-workflow/tasks/TASK-001-Historical-Work/IMPLEMENTATION.md +0 -0
  159. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/fixtures/legacy-unversioned/.project-workflow/tasks/TASK-001-Historical-Work/REQUIREMENTS.md +0 -0
  160. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/fixtures/legacy-unversioned/USER-NOTES.md +0 -0
  161. {project_workflow-0.9.0 → project_workflow-0.9.2}/tests/test_coordination_subtraction.py +0 -0
@@ -4,6 +4,46 @@ All notable changes to this project are documented in this file.
4
4
 
5
5
  ## Unreleased
6
6
 
7
+ ## 0.9.2 - 2026-08-31
8
+
9
+ ### Added
10
+
11
+ - Added public `project execution configure`, `status`, and `disable` commands so operators can
12
+ create and inspect exact host-neutral sealed authority without fabricating internal coordination
13
+ JSON or hashes. Successor envelopes retain previous controls and receipts.
14
+
15
+ ### Changed
16
+
17
+ - Documented Codex installation as repository-local skills plus a package-owned ephemeral per-run
18
+ hook. A persistent marketplace-plugin listing is neither required nor treated as activation or
19
+ runtime proof.
20
+
21
+ ### Known proof boundary
22
+
23
+ - Sealed runtime execution is certified for Codex only in this release. The Claude Code adapter and
24
+ managed assets remain packaged and fail closed, but no real authenticated Claude Code canary has
25
+ passed; this release makes no Claude runtime or dual-host certification claim.
26
+
27
+ ## 0.9.1 - 2026-08-29
28
+
29
+ ### Changed
30
+
31
+ - Replaced the authored 25,583-line CLI monolith with cohesive, acyclic runtime domains, a bounded
32
+ compatibility facade, and one deterministic manifest-driven standalone runtime without changing
33
+ the public v0.9 command or schema contract.
34
+ - Split the catch-all Doctor tests into product-boundary suites, centralized only shared fixtures,
35
+ and made locked Ruff, Ruff format, mypy, architecture, documentation, full-suite, and package
36
+ journey checks part of both CI and release validation.
37
+ - Replaced the oversized README and stale release guidance with a small authority-led documentation
38
+ hierarchy covering architecture, use, contribution, maintenance, and release ownership.
39
+
40
+ ### Fixed
41
+
42
+ - Kept a completed Task or Epic's retained verification campaign inspectable from terminal global
43
+ tracker state so Doctor and delivery projection do not lose exact-candidate proof after closeout.
44
+ - Removed dead distribution globs and stale current-version guidance while retaining historical
45
+ workflow records, exact release artifacts, blocked proof obligations, and unique work.
46
+
7
47
  ## 0.9.0 - 2026-08-29
8
48
 
9
49
  ### Added
@@ -5,4 +5,4 @@ recursive-include scripts *.py
5
5
  recursive-include tests *.py
6
6
  recursive-include tests/fixtures *
7
7
  recursive-include evaluations/intent_integrity *.json *.md *.py
8
- recursive-include evaluations/coordination *.json *.md *.py
8
+ recursive-include evaluations/coordination *.json *.md
@@ -0,0 +1,170 @@
1
+ Metadata-Version: 2.4
2
+ Name: project-workflow
3
+ Version: 0.9.2
4
+ Summary: Spec-driven development with GitHub Copilot, Claude Code, OpenAI Codex, and Cursor: workflow scaffolding, QA review, retro, and task management CLI
5
+ Author-email: John Detlefs <john@example.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/johndetlefs/project-workflow
8
+ Project-URL: Repository, https://github.com/johndetlefs/project-workflow.git
9
+ Project-URL: Issues, https://github.com/johndetlefs/project-workflow/issues
10
+ Keywords: workflow,spec-driven,ai,github-copilot,claude-code,codex,cursor,task-management
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Requires-Python: >=3.10
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENSE
20
+ Provides-Extra: dev
21
+ Requires-Dist: build>=1.2; extra == "dev"
22
+ Requires-Dist: mypy>=1.15; extra == "dev"
23
+ Requires-Dist: pytest>=7.0; extra == "dev"
24
+ Requires-Dist: ruff>=0.11; extra == "dev"
25
+ Requires-Dist: setuptools>=65.0; extra == "dev"
26
+ Dynamic: license-file
27
+
28
+ # project-workflow
29
+
30
+ Project Workflow is a repository-native delivery system for turning owner intent into planned,
31
+ implemented, evidenced, reviewed work. Its state is plain Markdown and JSON beside the code, so
32
+ people and coding agents can inspect the same requirements, status, decisions, and proof.
33
+
34
+ Its repository guidance supports GitHub Copilot, Claude Code, OpenAI Codex, and Cursor. Sealed
35
+ runtime enforcement has a narrower, versioned proof boundary: v0.9.2 is runtime-certified for
36
+ Codex only. The packaged Claude Code adapter remains fail-closed and uncertified until its real
37
+ authenticated host canary passes; Cursor and GitHub Copilot are not sealed-runtime targets. Project
38
+ Workflow complements issue trackers, Git hosts, CI, registries, and deployment platforms; it does
39
+ not replace their authority.
40
+
41
+ ## Quick Start
42
+
43
+ From the root of an existing Git repository:
44
+
45
+ ```bash
46
+ uvx --from project-workflow==0.9.2 project init --agent codex
47
+ ```
48
+
49
+ Choose `github-copilot`, `claude-code`, `codex`, or `cursor` to match the agent that will operate
50
+ the repository. For an existing installation, use upgrade—not init:
51
+
52
+ ```bash
53
+ uvx --from project-workflow==0.9.2 project upgrade --agent codex
54
+ ```
55
+
56
+ Then describe the outcome in ordinary language. The installed guidance routes it to the smallest
57
+ sufficient record:
58
+
59
+ | Route | Use it for | Durable record |
60
+ | --- | --- | --- |
61
+ | Backlog | Optional future intent not ready for execution | `BL-*` row in `BACKLOG.md` |
62
+ | Fix | One bounded correction to a delivered or accepted baseline | `FIX-*` folder and global tracker row |
63
+ | Task | One new independently reviewable outcome | `TASK-*` requirements and implementation |
64
+ | Epic | Coordinated workstreams with shared parent outcomes | `EPIC-*` contract, decomposition, children, audit, and retro |
65
+
66
+ An in-scope correction stays in its active work item. Completed history is not rewritten to make a
67
+ later defect look original.
68
+
69
+ ## See What Is True
70
+
71
+ Start with the read-only status projection:
72
+
73
+ ```bash
74
+ ./.project-workflow/cli/workflow status
75
+ ./.project-workflow/cli/workflow status --id TASK-001
76
+ ./.project-workflow/cli/workflow status --strict
77
+ ./.project-workflow/cli/workflow status --format json
78
+ ```
79
+
80
+ Status reports sourced lifecycle, proof, blockers, delivery state, and the next safe action. It
81
+ does not execute that action. Use Doctor for workflow diagnosis:
82
+
83
+ ```bash
84
+ ./.project-workflow/cli/workflow doctor
85
+ ./.project-workflow/cli/workflow doctor --strict
86
+ ```
87
+
88
+ Tests, a passing Doctor, `Complete`, merge, release, deployment, adoption, and owner acceptance are
89
+ separate evidence layers. Project Workflow reports the strongest layer actually proved.
90
+
91
+ ## How Work Moves
92
+
93
+ The owner confirms the plain-language Intent and outcome boundary once. The Coordinator then plans,
94
+ clarifies, implements, validates, and commissions QA autonomously inside that approved envelope.
95
+ Material drift, missing authority, or a changed proof obligation returns to the owner.
96
+
97
+ The normal Task path is:
98
+
99
+ ```text
100
+ Analysing -> Ready -> In Progress -> Testing -> Review -> Complete
101
+ ```
102
+
103
+ Epics use the same outcome discipline plus a contract, authoritative decomposition, child tracker,
104
+ intent audit, parent acceptance map, closeout audit, and retro. Fixes stay deliberately lighter.
105
+
106
+ For detailed commands and examples, read [Using Project Workflow](docs/using-project-workflow.md)
107
+ or run `./.project-workflow/cli/workflow --help`.
108
+
109
+ Approved material work can optionally use [Sealed Host Execution](docs/execution-control.md). Codex
110
+ uses repository-local skills plus an ephemeral per-run hook; a permanent marketplace-plugin entry
111
+ is neither required nor accepted as activation proof.
112
+
113
+ ## What Is Installed
114
+
115
+ Initialization creates:
116
+
117
+ - `.project-workflow/` configuration, manifest, backlog, trackers, tasks, guidance, and a
118
+ dependency-free local CLI;
119
+ - host-specific agent guidance for the selected mode;
120
+ - managed instruction blocks that point the agent at repository-local workflow truth.
121
+
122
+ Tracked requirements, plans, approvals, evidence, and local guidance remain repository-owned.
123
+ Managed helpers and installed host assets are generated derivatives; update their canonical source
124
+ or use the supported generator/upgrade path instead of editing copies.
125
+
126
+ See [Documentation and Source Authority](docs/authority.md) for the complete hierarchy and
127
+ [Compatibility](COMPATIBILITY.md) for versioned repository support.
128
+
129
+ ## Contributing
130
+
131
+ Project Workflow is one Python package, one public `project` command, and one generated
132
+ dependency-free helper. Canonical runtime code is split by domain under `src/project_workflow/`;
133
+ `src/project_workflow/templates/workflow.py` and `.project-workflow/cli/workflow.py` are generated.
134
+
135
+ ```bash
136
+ uv sync --locked --extra dev
137
+ uv run --locked ruff check src/project_workflow/*.py scripts tests
138
+ uv run --locked ruff format --check src/project_workflow/*.py scripts tests
139
+ uv run --locked mypy src/project_workflow/*.py
140
+ PATH="/opt/homebrew/bin:$PATH" uv run --locked pytest -q
141
+ ```
142
+
143
+ Read [Contributing](docs/contributing.md) before changing source and
144
+ [Architecture](docs/architecture.md) before moving responsibilities. Maintainers should also read
145
+ [Maintenance](docs/maintenance.md); public release authority is isolated in
146
+ [RELEASING.md](RELEASING.md).
147
+
148
+ ## Documentation Map
149
+
150
+ | Need | Authority |
151
+ | --- | --- |
152
+ | Product mission and stable outcomes | [Constitution](.project-workflow/CONSTITUTION.md) |
153
+ | Repository operating rules | [AGENTS.md](AGENTS.md) and [local guidance](.project-workflow/guidance.md) |
154
+ | Orientation and first commands | This README |
155
+ | Work-item operation | [Using Project Workflow](docs/using-project-workflow.md) |
156
+ | Codex-certified sealed execution and Claude Code limitations | [Sealed Host Execution](docs/execution-control.md) |
157
+ | Source boundaries and generated ownership | [Architecture](docs/architecture.md) |
158
+ | Development and validation | [Contributing](docs/contributing.md) |
159
+ | Upgrade, hygiene, and generated assets | [Maintenance](docs/maintenance.md) |
160
+ | Compatibility policy | [COMPATIBILITY.md](COMPATIBILITY.md) |
161
+ | Public release procedure | [RELEASING.md](RELEASING.md) |
162
+ | Current command syntax | `project --help` and the [local CLI guide](.project-workflow/cli/README.md) |
163
+
164
+ Workflow task folders are durable state and audit history, not competing current product
165
+ instructions.
166
+
167
+ ## License And Support
168
+
169
+ Project Workflow is available under the [MIT License](LICENSE). Report defects and proposals through
170
+ [GitHub Issues](https://github.com/johndetlefs/project-workflow/issues).
@@ -0,0 +1,143 @@
1
+ # project-workflow
2
+
3
+ Project Workflow is a repository-native delivery system for turning owner intent into planned,
4
+ implemented, evidenced, reviewed work. Its state is plain Markdown and JSON beside the code, so
5
+ people and coding agents can inspect the same requirements, status, decisions, and proof.
6
+
7
+ Its repository guidance supports GitHub Copilot, Claude Code, OpenAI Codex, and Cursor. Sealed
8
+ runtime enforcement has a narrower, versioned proof boundary: v0.9.2 is runtime-certified for
9
+ Codex only. The packaged Claude Code adapter remains fail-closed and uncertified until its real
10
+ authenticated host canary passes; Cursor and GitHub Copilot are not sealed-runtime targets. Project
11
+ Workflow complements issue trackers, Git hosts, CI, registries, and deployment platforms; it does
12
+ not replace their authority.
13
+
14
+ ## Quick Start
15
+
16
+ From the root of an existing Git repository:
17
+
18
+ ```bash
19
+ uvx --from project-workflow==0.9.2 project init --agent codex
20
+ ```
21
+
22
+ Choose `github-copilot`, `claude-code`, `codex`, or `cursor` to match the agent that will operate
23
+ the repository. For an existing installation, use upgrade—not init:
24
+
25
+ ```bash
26
+ uvx --from project-workflow==0.9.2 project upgrade --agent codex
27
+ ```
28
+
29
+ Then describe the outcome in ordinary language. The installed guidance routes it to the smallest
30
+ sufficient record:
31
+
32
+ | Route | Use it for | Durable record |
33
+ | --- | --- | --- |
34
+ | Backlog | Optional future intent not ready for execution | `BL-*` row in `BACKLOG.md` |
35
+ | Fix | One bounded correction to a delivered or accepted baseline | `FIX-*` folder and global tracker row |
36
+ | Task | One new independently reviewable outcome | `TASK-*` requirements and implementation |
37
+ | Epic | Coordinated workstreams with shared parent outcomes | `EPIC-*` contract, decomposition, children, audit, and retro |
38
+
39
+ An in-scope correction stays in its active work item. Completed history is not rewritten to make a
40
+ later defect look original.
41
+
42
+ ## See What Is True
43
+
44
+ Start with the read-only status projection:
45
+
46
+ ```bash
47
+ ./.project-workflow/cli/workflow status
48
+ ./.project-workflow/cli/workflow status --id TASK-001
49
+ ./.project-workflow/cli/workflow status --strict
50
+ ./.project-workflow/cli/workflow status --format json
51
+ ```
52
+
53
+ Status reports sourced lifecycle, proof, blockers, delivery state, and the next safe action. It
54
+ does not execute that action. Use Doctor for workflow diagnosis:
55
+
56
+ ```bash
57
+ ./.project-workflow/cli/workflow doctor
58
+ ./.project-workflow/cli/workflow doctor --strict
59
+ ```
60
+
61
+ Tests, a passing Doctor, `Complete`, merge, release, deployment, adoption, and owner acceptance are
62
+ separate evidence layers. Project Workflow reports the strongest layer actually proved.
63
+
64
+ ## How Work Moves
65
+
66
+ The owner confirms the plain-language Intent and outcome boundary once. The Coordinator then plans,
67
+ clarifies, implements, validates, and commissions QA autonomously inside that approved envelope.
68
+ Material drift, missing authority, or a changed proof obligation returns to the owner.
69
+
70
+ The normal Task path is:
71
+
72
+ ```text
73
+ Analysing -> Ready -> In Progress -> Testing -> Review -> Complete
74
+ ```
75
+
76
+ Epics use the same outcome discipline plus a contract, authoritative decomposition, child tracker,
77
+ intent audit, parent acceptance map, closeout audit, and retro. Fixes stay deliberately lighter.
78
+
79
+ For detailed commands and examples, read [Using Project Workflow](docs/using-project-workflow.md)
80
+ or run `./.project-workflow/cli/workflow --help`.
81
+
82
+ Approved material work can optionally use [Sealed Host Execution](docs/execution-control.md). Codex
83
+ uses repository-local skills plus an ephemeral per-run hook; a permanent marketplace-plugin entry
84
+ is neither required nor accepted as activation proof.
85
+
86
+ ## What Is Installed
87
+
88
+ Initialization creates:
89
+
90
+ - `.project-workflow/` configuration, manifest, backlog, trackers, tasks, guidance, and a
91
+ dependency-free local CLI;
92
+ - host-specific agent guidance for the selected mode;
93
+ - managed instruction blocks that point the agent at repository-local workflow truth.
94
+
95
+ Tracked requirements, plans, approvals, evidence, and local guidance remain repository-owned.
96
+ Managed helpers and installed host assets are generated derivatives; update their canonical source
97
+ or use the supported generator/upgrade path instead of editing copies.
98
+
99
+ See [Documentation and Source Authority](docs/authority.md) for the complete hierarchy and
100
+ [Compatibility](COMPATIBILITY.md) for versioned repository support.
101
+
102
+ ## Contributing
103
+
104
+ Project Workflow is one Python package, one public `project` command, and one generated
105
+ dependency-free helper. Canonical runtime code is split by domain under `src/project_workflow/`;
106
+ `src/project_workflow/templates/workflow.py` and `.project-workflow/cli/workflow.py` are generated.
107
+
108
+ ```bash
109
+ uv sync --locked --extra dev
110
+ uv run --locked ruff check src/project_workflow/*.py scripts tests
111
+ uv run --locked ruff format --check src/project_workflow/*.py scripts tests
112
+ uv run --locked mypy src/project_workflow/*.py
113
+ PATH="/opt/homebrew/bin:$PATH" uv run --locked pytest -q
114
+ ```
115
+
116
+ Read [Contributing](docs/contributing.md) before changing source and
117
+ [Architecture](docs/architecture.md) before moving responsibilities. Maintainers should also read
118
+ [Maintenance](docs/maintenance.md); public release authority is isolated in
119
+ [RELEASING.md](RELEASING.md).
120
+
121
+ ## Documentation Map
122
+
123
+ | Need | Authority |
124
+ | --- | --- |
125
+ | Product mission and stable outcomes | [Constitution](.project-workflow/CONSTITUTION.md) |
126
+ | Repository operating rules | [AGENTS.md](AGENTS.md) and [local guidance](.project-workflow/guidance.md) |
127
+ | Orientation and first commands | This README |
128
+ | Work-item operation | [Using Project Workflow](docs/using-project-workflow.md) |
129
+ | Codex-certified sealed execution and Claude Code limitations | [Sealed Host Execution](docs/execution-control.md) |
130
+ | Source boundaries and generated ownership | [Architecture](docs/architecture.md) |
131
+ | Development and validation | [Contributing](docs/contributing.md) |
132
+ | Upgrade, hygiene, and generated assets | [Maintenance](docs/maintenance.md) |
133
+ | Compatibility policy | [COMPATIBILITY.md](COMPATIBILITY.md) |
134
+ | Public release procedure | [RELEASING.md](RELEASING.md) |
135
+ | Current command syntax | `project --help` and the [local CLI guide](.project-workflow/cli/README.md) |
136
+
137
+ Workflow task folders are durable state and audit history, not competing current product
138
+ instructions.
139
+
140
+ ## License And Support
141
+
142
+ Project Workflow is available under the [MIT License](LICENSE). Report defects and proposals through
143
+ [GitHub Issues](https://github.com/johndetlefs/project-workflow/issues).
@@ -30,7 +30,9 @@ Issues = "https://github.com/johndetlefs/project-workflow/issues"
30
30
  [project.optional-dependencies]
31
31
  dev = [
32
32
  "build>=1.2",
33
+ "mypy>=1.15",
33
34
  "pytest>=7.0",
35
+ "ruff>=0.11",
34
36
  "setuptools>=65.0",
35
37
  ]
36
38
 
@@ -64,15 +66,14 @@ project_workflow = [
64
66
  "cursor/rules/*.mdc",
65
67
  ]
66
68
 
67
- [tool.black]
68
- line-length = 100
69
- target-version = ["py310"]
70
-
71
69
  [tool.ruff]
72
70
  line-length = 100
73
71
  target-version = "py310"
74
72
 
75
73
  [tool.ruff.lint]
74
+ ignore = [
75
+ "E501", # The formatter is the line-layout authority; exact fixture strings may exceed it.
76
+ ]
76
77
  select = [
77
78
  "E", # pycodestyle errors
78
79
  "W", # pycodestyle warnings
@@ -86,6 +87,7 @@ python_version = "3.10"
86
87
  warn_return_any = true
87
88
  warn_unused_configs = true
88
89
  disallow_untyped_defs = false
90
+ exclude = ["src/project_workflow/templates/"]
89
91
 
90
92
  [tool.pytest.ini_options]
91
93
  testpaths = ["tests"]
@@ -0,0 +1,134 @@
1
+ #!/usr/bin/env python3
2
+ """Build the dependency-free repository-local workflow runtime deterministically."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import ast
8
+ import hashlib
9
+ import sys
10
+ from pathlib import Path
11
+
12
+ ROOT = Path(__file__).resolve().parents[1]
13
+ MANIFEST = ROOT / "scripts/runtime-modules.txt"
14
+ TEMPLATE = ROOT / "src/project_workflow/templates/workflow.py"
15
+ SOURCE_MIRROR = ROOT / ".project-workflow/cli/workflow.py"
16
+ GENERATED_MARKER = "# project-workflow:generated"
17
+ PROVENANCE = "# source-manifest: scripts/runtime-modules.txt"
18
+
19
+
20
+ def manifest_paths() -> tuple[Path, ...]:
21
+ entries = []
22
+ for raw in MANIFEST.read_text(encoding="utf-8").splitlines():
23
+ value = raw.strip()
24
+ if not value or value.startswith("#"):
25
+ continue
26
+ path = ROOT / value
27
+ if not path.is_file():
28
+ raise ValueError(f"Runtime manifest entry does not exist: {value}")
29
+ entries.append(path)
30
+ if not entries:
31
+ raise ValueError("Runtime manifest must contain at least one source module.")
32
+ return tuple(entries)
33
+
34
+
35
+ def _top_level_removals(source: str) -> set[int]:
36
+ tree = ast.parse(source)
37
+ removals: set[int] = set()
38
+ for index, node in enumerate(tree.body):
39
+ remove = False
40
+ if (
41
+ index == 0
42
+ and isinstance(node, ast.Expr)
43
+ and isinstance(node.value, ast.Constant)
44
+ and isinstance(node.value.value, str)
45
+ ):
46
+ remove = True
47
+ elif isinstance(node, ast.ImportFrom) and node.module == "__future__":
48
+ remove = True
49
+ elif isinstance(node, ast.ImportFrom) and (
50
+ node.level > 0 or (node.module or "").startswith("project_workflow")
51
+ ):
52
+ remove = True
53
+ if remove:
54
+ removals.update(range(node.lineno, node.end_lineno + 1))
55
+ return removals
56
+
57
+
58
+ def canonical_module_text(path: Path) -> str:
59
+ source = path.read_text(encoding="utf-8")
60
+ removals = _top_level_removals(source)
61
+ lines = source.splitlines()
62
+ kept = [
63
+ line
64
+ for number, line in enumerate(lines, start=1)
65
+ if number not in removals and not (number == 1 and line.startswith("#!"))
66
+ ]
67
+ while kept and not kept[0].strip():
68
+ kept.pop(0)
69
+ while kept and not kept[-1].strip():
70
+ kept.pop()
71
+ return "\n".join(kept) + "\n"
72
+
73
+
74
+ def build_bundle() -> str:
75
+ paths = manifest_paths()
76
+ manifest_hash = hashlib.sha256(MANIFEST.read_bytes()).hexdigest()
77
+ sections = [
78
+ "#!/usr/bin/env python3\n",
79
+ '"""Generated dependency-free Project Workflow runtime. Do not edit directly."""\n',
80
+ "from __future__ import annotations\n\n",
81
+ f"{GENERATED_MARKER}\n",
82
+ f"{PROVENANCE}\n",
83
+ f"# manifest-sha256: {manifest_hash}\n\n",
84
+ ]
85
+ for path in paths:
86
+ relative = path.relative_to(ROOT).as_posix()
87
+ sections.append(f"# --- begin {relative} ---\n")
88
+ sections.append(canonical_module_text(path))
89
+ sections.append(f"# --- end {relative} ---\n\n")
90
+ return "".join(sections).rstrip("\n") + "\n"
91
+
92
+
93
+ def expected_outputs() -> tuple[Path, Path]:
94
+ return TEMPLATE, SOURCE_MIRROR
95
+
96
+
97
+ def check() -> int:
98
+ expected = build_bundle()
99
+ stale = [
100
+ path.relative_to(ROOT).as_posix()
101
+ for path in expected_outputs()
102
+ if not path.is_file() or path.read_text(encoding="utf-8") != expected
103
+ ]
104
+ if stale:
105
+ print("Generated runtime is stale:")
106
+ for path in stale:
107
+ print(f"- {path}")
108
+ return 1
109
+ print("Generated runtime is current.")
110
+ return 0
111
+
112
+
113
+ def write() -> int:
114
+ content = build_bundle()
115
+ for path in expected_outputs():
116
+ path.parent.mkdir(parents=True, exist_ok=True)
117
+ path.write_text(content, encoding="utf-8")
118
+ SOURCE_MIRROR.chmod(SOURCE_MIRROR.stat().st_mode | 0o111)
119
+ print(f"Wrote {TEMPLATE.relative_to(ROOT)}")
120
+ print(f"Wrote {SOURCE_MIRROR.relative_to(ROOT)}")
121
+ return 0
122
+
123
+
124
+ def main() -> int:
125
+ parser = argparse.ArgumentParser(description=__doc__)
126
+ mode = parser.add_mutually_exclusive_group(required=True)
127
+ mode.add_argument("--check", action="store_true")
128
+ mode.add_argument("--write", action="store_true")
129
+ args = parser.parse_args()
130
+ return check() if args.check else write()
131
+
132
+
133
+ if __name__ == "__main__":
134
+ sys.exit(main())
@@ -0,0 +1,143 @@
1
+ #!/usr/bin/env python3
2
+ """Capture canonical module and adapter ownership evidence as deterministic JSON."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import argparse
7
+ import ast
8
+ import hashlib
9
+ import json
10
+ from pathlib import Path
11
+
12
+ ROOT = Path(__file__).resolve().parents[1]
13
+ MANIFEST = ROOT / "scripts/runtime-modules.txt"
14
+
15
+
16
+ def sha256(path: Path) -> str:
17
+ return "sha256:" + hashlib.sha256(path.read_bytes()).hexdigest()
18
+
19
+
20
+ def runtime_paths() -> list[Path]:
21
+ return [
22
+ ROOT / line.strip()
23
+ for line in MANIFEST.read_text(encoding="utf-8").splitlines()
24
+ if line.strip() and not line.lstrip().startswith("#")
25
+ ]
26
+
27
+
28
+ def internal_dependencies(path: Path, names: set[str]) -> list[str]:
29
+ dependencies: set[str] = set()
30
+ for node in ast.walk(ast.parse(path.read_text(encoding="utf-8"))):
31
+ if isinstance(node, ast.ImportFrom):
32
+ if node.level and node.module:
33
+ dependency = node.module.split(".", 1)[0]
34
+ if dependency in names:
35
+ dependencies.add(dependency)
36
+ elif (node.module or "").startswith("project_workflow."):
37
+ dependency = (node.module or "").split(".")[1]
38
+ if dependency in names:
39
+ dependencies.add(dependency)
40
+ elif isinstance(node, ast.Import):
41
+ for alias in node.names:
42
+ if alias.name.startswith("project_workflow."):
43
+ dependency = alias.name.split(".")[1]
44
+ if dependency in names:
45
+ dependencies.add(dependency)
46
+ return sorted(dependencies)
47
+
48
+
49
+ def top_level_definitions(path: Path) -> list[str]:
50
+ return sorted(
51
+ node.name
52
+ for node in ast.parse(path.read_text(encoding="utf-8")).body
53
+ if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef))
54
+ )
55
+
56
+
57
+ def adapter_common_imports(path: Path) -> list[str]:
58
+ imported = []
59
+ for node in ast.walk(ast.parse(path.read_text(encoding="utf-8"))):
60
+ if isinstance(node, ast.ImportFrom) and (node.module or "").endswith("adapter_common"):
61
+ imported.extend(alias.name for alias in node.names)
62
+ return sorted(set(imported))
63
+
64
+
65
+ def payload() -> dict[str, object]:
66
+ paths = runtime_paths()
67
+ names = {path.stem for path in paths}
68
+ order = {path.stem: index for index, path in enumerate(paths)}
69
+ modules = []
70
+ definition_owners: dict[str, list[str]] = {}
71
+ for path in paths:
72
+ definitions = top_level_definitions(path)
73
+ for name in definitions:
74
+ definition_owners.setdefault(name, []).append(path.stem)
75
+ dependencies = internal_dependencies(path, names)
76
+ modules.append(
77
+ {
78
+ "name": path.stem,
79
+ "path": path.relative_to(ROOT).as_posix(),
80
+ "line_count": len(path.read_text(encoding="utf-8").splitlines()),
81
+ "top_level_definition_count": len(definitions),
82
+ "dependencies": dependencies,
83
+ "dependencies_precede_module": all(
84
+ order[dependency] < order[path.stem] for dependency in dependencies
85
+ ),
86
+ "sha256": sha256(path),
87
+ }
88
+ )
89
+ duplicates = {name: owners for name, owners in definition_owners.items() if len(owners) > 1}
90
+ package = ROOT / "src/project_workflow"
91
+ common = package / "adapter_common.py"
92
+ codex = package / "codex_adapter.py"
93
+ claude = package / "claude_adapter.py"
94
+ template = package / "templates/workflow.py"
95
+ helper = ROOT / ".project-workflow/cli/workflow.py"
96
+ adapter_records = []
97
+ for path in (common, codex, claude):
98
+ installed = ROOT / ".project-workflow/cli" / path.name
99
+ adapter_records.append(
100
+ {
101
+ "name": path.stem,
102
+ "line_count": len(path.read_text(encoding="utf-8").splitlines()),
103
+ "sha256": sha256(path),
104
+ "installed_sha256": sha256(installed),
105
+ "installed_matches_source": path.read_bytes() == installed.read_bytes(),
106
+ "common_imports": adapter_common_imports(path),
107
+ }
108
+ )
109
+ return {
110
+ "schema_version": 1,
111
+ "runtime_manifest": MANIFEST.relative_to(ROOT).as_posix(),
112
+ "runtime_module_count": len(modules),
113
+ "runtime_modules": modules,
114
+ "duplicate_top_level_definitions": duplicates,
115
+ "dependency_order_valid": all(record["dependencies_precede_module"] for record in modules),
116
+ "entry_module_under_2000_lines": modules[-1]["line_count"] < 2_000,
117
+ "domain_modules_under_5000_lines": all(
118
+ record["line_count"] < 5_000 for record in modules[:-1]
119
+ ),
120
+ "generated_runtime": {
121
+ "template_sha256": sha256(template),
122
+ "installed_helper_sha256": sha256(helper),
123
+ "byte_identical": template.read_bytes() == helper.read_bytes(),
124
+ },
125
+ "adapters": adapter_records,
126
+ }
127
+
128
+
129
+ def main() -> int:
130
+ parser = argparse.ArgumentParser(description=__doc__)
131
+ parser.add_argument("--output", type=Path, required=True)
132
+ args = parser.parse_args()
133
+ args.output.parent.mkdir(parents=True, exist_ok=True)
134
+ args.output.write_text(
135
+ json.dumps(payload(), indent=2, sort_keys=True) + "\n",
136
+ encoding="utf-8",
137
+ )
138
+ print(args.output)
139
+ return 0
140
+
141
+
142
+ if __name__ == "__main__":
143
+ raise SystemExit(main())