pactkit 2.18.0__tar.gz → 2.19.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.
- pactkit-2.19.0/.coverage +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/CHANGELOG.md +9 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/PKG-INFO +2 -2
- {pactkit-2.18.0 → pactkit-2.19.0}/README.md +1 -1
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/architecture/governance/archive/lessons_archive_202603.md +1 -0
- pactkit-2.19.0/docs/architecture/governance/archive/lessons_archive_202604.md +5 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/architecture/governance/lessons.md +2 -2
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/architecture/governance/rules.md +1 -1
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/product/archive/archive_202608.md +19 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/product/context.md +3 -3
- pactkit-2.19.0/docs/specs/STORY-slim-143.md +178 -0
- pactkit-2.19.0/docs/specs/STORY-slim-144.md +169 -0
- pactkit-2.19.0/docs/test_cases/STORY-slim-143_case.md +43 -0
- pactkit-2.19.0/docs/test_cases/STORY-slim-144_case.md +37 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/pyproject.toml +1 -1
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/__init__.py +1 -1
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/cli.py +27 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/prompts/commands.py +1 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/prompts/workflows.py +13 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/schemas.py +26 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/skills/scaffold.py +9 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/skills/spec_linter.py +57 -0
- pactkit-2.19.0/src/pactkit/spec_graph.py +296 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_sprint_command.py +3 -2
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story042_spec_linter.py +9 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story063_prompt_slimming.py +6 -3
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim026.py +1 -1
- pactkit-2.19.0/tests/unit/test_story_slim143_spec_graph.py +273 -0
- pactkit-2.19.0/tests/unit/test_story_slim144_wave_mode.py +147 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/.codegraph/.gitignore +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/.github/workflows/pactkit.yml +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/.github/workflows/publish.yml +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/.gitignore +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/AGENTS.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/CODE_OF_CONDUCT.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/CONTRIBUTING.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/LICENSE +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/SECURITY.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/architecture/governance/archive/lessons_archive_202602.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/architecture/governance/harness_audit.json +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/architecture/governance/philosophy.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/assets/logo.png +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/e2e/journey.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/guides/codex-integration-preresearch.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/guides/tool-integration-checklist.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/product/archive/archive_202602.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/product/archive/archive_202603.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/product/archive/archive_202604.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/product/archive/archive_202605.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/product/archive/archive_202606.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/product/archive/archive_202607.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/product/friction-log.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/product/prd.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/product/sprint_board.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-001.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-002.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-003.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-004.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-005.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-006.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-007.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-008.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-009.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-010.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-011.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-012.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-013.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-014.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-015.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-016.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-017.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-018.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-019.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-020.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-021.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-022.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-023.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-024.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-025.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-026.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-027.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-028.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-029.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-030.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-031.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-032.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-033.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-034.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-035.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-slim-001.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-slim-002.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-slim-003.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-slim-004.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-slim-005.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-slim-006.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-slim-089.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/BUG-slim-107.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-023.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-049.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-050.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-051.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-052.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-061.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-062.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-067.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-069.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-070.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-085.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-087.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-096.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-099.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-107.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-117.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-122.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-123.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-126.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-127.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-130.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-131.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/HOTFIX-slim-132.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-001.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-002.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-003.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-004.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-005.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-006.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-007.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-008.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-009.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-010.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-011.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-012.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-013.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-014.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-015.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-016.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-017.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-018.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-019.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-020.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-021.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-022.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-023.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-024.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-025.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-026.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-027.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-028.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-029.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-030.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-031.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-032.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-033.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-034.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-035.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-036.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-037.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-038.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-039.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-040.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-041.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-042.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-043.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-044.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-045.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-046.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-047.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-048.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-049.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-050.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-051.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-052.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-053.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-054.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-055.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-056.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-057.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-058.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-059.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-060.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-061.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-062.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-063.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-064.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-065.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-069.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-070.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-071.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-072.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-073.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-001.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-005.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-006.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-007.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-009.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-010.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-011.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-012.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-013.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-014.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-015.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-016.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-017.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-018.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-019.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-020.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-021.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-022.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-023.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-024.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-028.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-029.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-030.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-031.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-032.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-033.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-034.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-035.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-036.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-037.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-038.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-039.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-040.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-041.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-042.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-043.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-044.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-045.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-046.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-047.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-048.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-049.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-050.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-051.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-052.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-053.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-054.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-055.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-056.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-057.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-058.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-059.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-060.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-063.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-066.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-067.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-068.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-069.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-070.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-071.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-072.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-073.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-074.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-075.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-076.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-077.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-078.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-079.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-080.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-081.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-082.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-083.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-084.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-086.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-088.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-089.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-090.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-091.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-092.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-093.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-094.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-095.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-097.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-098.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-099.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-100.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-101.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-102.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-103.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-104.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-105.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-106.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-107.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-108.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-109.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-110.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-111.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-112.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-113.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-114.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-115.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-116.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-118.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-119.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-120.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-121.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-124.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-125.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-126.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-127.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-128.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-129.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-132.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-133.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-134.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-135.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-136.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-137.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-138.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-139.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-140.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-141.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/specs/STORY-slim-142.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/test_cases/BUG-001_case.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/test_cases/BUG-002_case.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/test_cases/STORY-slim-028_case.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/test_cases/STORY-slim-029_case.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/test_cases/STORY-slim-031_case.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/test_cases/STORY-slim-032_case.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/test_cases/STORY-slim-033_case.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/test_cases/STORY-slim-034_case.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/test_cases/STORY-slim-135_case.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/test_cases/STORY-slim-136_case.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/test_cases/STORY-slim-137_case.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/test_cases/STORY-slim-138_case.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/test_cases/STORY-slim-139_case.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/test_cases/STORY-slim-140_case.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/test_cases/STORY-slim-141_case.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/docs/test_cases/STORY-slim-142_case.md +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/opencode.json +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/__main__.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/audit.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/backfill.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/cleaners.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/commit_gate.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/config.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/context_gen.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/coverage_gate.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/deploy_manifest.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/deps.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/doctor.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/done_verify.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/garden.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/generators/__init__.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/generators/adapter.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/generators/deploy_base.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/generators/deployer.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/guards.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/id_generator.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/invariants.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/issue_sync.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/lazy_visualize.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/lessons.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/lint_runner.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/observe.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/profiles.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/prompts/__init__.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/prompts/agents.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/prompts/guides.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/prompts/references.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/prompts/rules.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/prompts/skills.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/regression.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/scripts.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/sec_scope.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/skills/__init__.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/skills/analyzers/__init__.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/skills/analyzers/go_analyzer.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/skills/analyzers/java_analyzer.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/skills/analyzers/python_analyzer.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/skills/analyzers/ts_analyzer.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/skills/board.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/skills/interface_summary.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/skills/report.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/skills/visualize.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/spec_status.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/test_mapper.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/utils.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/src/pactkit/validators.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/conftest.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/e2e/__init__.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/e2e/cli/__init__.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/e2e/cli/test_cli_e2e.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/agent_parser/agents_dir/researcher.yaml +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/agent_parser/agents_dir/writer.yaml +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/agent_parser/langgraph_app.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/agent_parser/mcp_settings.json +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/api_call_parser/axios_style.tsx +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/api_call_parser/dynamic.tsx +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/api_call_parser/page.tsx +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/config_golden/copy_claude.json +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/config_golden/copy_claude.yaml +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/config_golden/copy_codex.json +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/config_golden/copy_codex.yaml +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/config_golden/copy_github.json +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/config_golden/copy_github.yaml +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/config_golden/empty.json +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/config_golden/empty.yaml +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/config_golden/full_legacy.json +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/config_golden/full_legacy.yaml +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/config_golden/minimal.json +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/config_golden/minimal.yaml +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/config_golden/unknown_keys.json +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/fixtures/config_golden/unknown_keys.yaml +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/integration/__init__.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/integration/test_deploy_classic.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_agent_features.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_agent_frontmatter.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_agents_enrichment.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_audit.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_blast_radius.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_board_bug027.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_board_sections.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug001_skill_path.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug002_plugin_paths.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug003_multi_import.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug004_dead_set.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug005_archive_taskless.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug006_scan_excludes.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug007_stale_trace_refs.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug008_stale_command_refs.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug009_project_config_backfill.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug010_rewrite_yaml.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug011_stale_refs.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug012_call_graph_filter.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug013_config_single_source.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug014_version_hygiene.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug017_project_init_playbook.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug018_issue_tracker_verification.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug019_venv_deployment.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug020_claude_md_backup.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug025_release_delegation.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug026_version_sync.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug028_ghost_refs.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug029_stack_detection_fallback.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug030_spec_lint_cli.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug031_docstring_accuracy.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug034_plan_metadata_template.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug_021.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug_022.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug_023.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug_024.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug_slim001_env_detection.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug_slim002_instruction_collision.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug_slim003.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug_slim004.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug_slim005.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug_slim006.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_bug_slim089_global_claude_md.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_check_command.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_check_extensions_072_073.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_check_playbook_072_073.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_command_frontmatter.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_command_visualize_modes.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_commit_gate.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_complexity.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_config.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_config_auto_merge.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_constitution_sharpening.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_context_gen.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_create_skill.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_cross_flow_matrix.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_deploy_base.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_deployer_cleanup.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_deployer_plugin.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_deps.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_design_command.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_done_gates.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_done_verify.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_draw_prompt.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_draw_references.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_drawio_mcp.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_garden.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_home_path_fix.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_hotfix_command.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_init_guard.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_init_playbook_074.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_interface_summary.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_lang_profiles.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_layer_violations.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_lessons_rotation_075.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_list_stories.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_mcp_integration.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_model_config.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_modular_constitution.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_monorepo_detect.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_multi_prefix.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_observe.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_pdca_slim.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_profiles.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_project_visibility.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_prompt_cli_refs.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_prompt_quality_075.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_prompt_structural_invariants.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_prompts_package.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_release.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_release_field.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_release_v110.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_render_prompt.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_report_parser.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_report_unified.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_review_command.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_rules_enrichment.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_scaffold.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_scaffold_developer_prefix.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_schemas.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_script_extraction.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_selective_deploy.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_session_context.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_skill_structure.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_skills_enrichment.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_slim_deps_088.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_smart_regression.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_solution_design_rule.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_stack_references.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_status_command.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_statusline.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story014_release.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story015_ci_lint_gate.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story016_claude_md.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story017_init_claude_md.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story018_arch_staleness.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story019_bailout.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story020_horizon.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story021_rfc.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story022_decision_tree.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story023_test_quality.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story024_native_agent.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story025_ci_pipeline.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story026_issue_tracker.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story028_rule_scoping.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story029_doctor.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story030_lint.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story031_git_init_guard.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story032_greenfield_redirect.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story033_config_backfill.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story034_plan_config_refresh.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story035_readme_docs.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story037_regression_fix.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story038_call_graph_update.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story039_venv_config.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story040_layered_claude_md.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story043_active_clarify.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story044_consistency_check.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story045_auto_pr.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story046_agent_adapter.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story047_enterprise_flags.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story048_worktree_isolation.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story049_community_standards.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story050_doc_only_shortcut.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story051_workflow_streamlining.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story052_conditional_github_release.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story053_impact_regression.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story055_commands.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story055_config.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story055_spec_linter.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story056_commands.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story056_config.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story057_implicit_cleanup.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story058_opencode_extraction.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story058_routing_fix.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story059_codex_removal.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story060_init_hang.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story061_remove_thinking.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story062_mcp_recommendations.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story064_venv_local_md.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story065_sprint_model.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story072_developer_prefix.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story106_lateral_scan.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story133_debug_skill.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim009_lazy_rules.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim010_dry_refactor.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim011_command_rules.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim012_ci.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim014_clean.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim014_context.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim014_guard.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim014_lazy_viz.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim014_next_id.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim014_regression.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim014_sec_scope.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim014_validators.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim015_doctor.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim016_testmap_lint.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim017.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim018.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim019_plan_subphases.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim020_explore_stall_fix.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim021.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim022.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim023.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim024.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim025.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim027.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim028.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim029.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim030.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim031.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim032.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim033.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim034.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim035.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim036.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim037.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim038.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim039.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim040.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim041.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim042.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim043.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim044.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim045.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim046.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim047.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim048.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim049.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim051.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim052.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim053.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim054.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim055.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim056.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim060_codex_profile.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim063.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim065.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim076_multistack.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim077_monorepo_stack.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim078.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim079.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim080.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim081.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim082.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim083.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim084.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim095.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim098_pdca_nudge.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim099_act_context_ref.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim102_version_marker.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim104_should_semantics.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim107.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim109_journey_spec.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim111_playwright_assertion.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim112_rules_split.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim114_journey_sync.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim119.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim120.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim121.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim125.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim126.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim127_managed_block.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim128_engineering_concerns.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim132.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim134_no_model_in_frontmatter.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim135_config_schema.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim139_skill_manifest.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim141_manifest_hash.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_story_slim142_all_target_isolation.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_tools.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_topology_parsers_066.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_update_task.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_visualize_call_nested.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_visualize_chain_fix.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_visualize_modes.py +0 -0
- {pactkit-2.18.0 → pactkit-2.19.0}/tests/unit/test_visualize_multilang_chain.py +0 -0
pactkit-2.19.0/.coverage
ADDED
|
Binary file
|
|
@@ -4,6 +4,15 @@ All notable changes to PactKit will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
Format follows [Keep a Changelog](https://keepachangelog.com/).
|
|
6
6
|
|
|
7
|
+
## [2.19.0] - 2026-08-17
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- **Spec Dependency Surface** (STORY-slim-143) — every scaffolded Spec now carries a machine-readable `## Dependency Surface` table (`Depends on` / `Provides` / `Touches` / `Conflict risk`). Story dependencies and file-level conflict surface are no longer implicit in the architect's head — they're data.
|
|
11
|
+
- **`pactkit spec-graph`** (STORY-slim-143) — deterministic story dependency DAG from all Specs: topological **execution waves** (wave N depends only on waves < N; same-wave stories are parallelizable), a **file-overlap conflict matrix** (same-wave overlaps flagged unsafe-parallel), cycle detection with non-zero exit, and Mermaid output to `docs/architecture/graphs/story_graph.mmd`. Stdlib only (`graphlib`, `fnmatch`), zero new dependencies.
|
|
12
|
+
- **Spec linter rules E010/W011** (STORY-slim-143) — dangling `Depends on` references (story ID with no Spec file) are now an Act-blocking ERROR; missing Dependency Surface is a WARNING. Reuses spec_linter's section-parsing helpers (newly public: `strip_code_blocks` / `section_text`).
|
|
13
|
+
- **Sprint Wave Mode** (STORY-slim-144) — `/project-sprint` with empty arguments scans the backlog, consumes `pactkit spec-graph --json` (new flag), and runs conflict-free same-wave stories as parallel worktree subagents (cap `sprint.max_parallel`, default 3). Stories with same-wave conflicts or undeclared Touches are serialized safe-by-default. Wave gate: wave N+1 starts only after wave N is fully merged green; fail-fast with no auto-retry; resume by re-running (idempotent). Single-story mode with arguments is byte-for-byte unchanged.
|
|
14
|
+
- **Plan playbook Dependency Surface step** (STORY-slim-143) — `/project-plan` Phase 3.2a now fills the table from Phase 1 trace findings, so every new Spec ships scheduling data.
|
|
15
|
+
|
|
7
16
|
## [2.18.0] - 2026-08-17
|
|
8
17
|
|
|
9
18
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: pactkit
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.19.0
|
|
4
4
|
Summary: Spec-driven agentic DevOps toolkit for AI coding assistants
|
|
5
5
|
Project-URL: Homepage, https://pactkit.dev
|
|
6
6
|
Project-URL: Repository, https://github.com/pactkit/pactkit-public
|
|
@@ -289,7 +289,7 @@ PactKit ships 36 deterministic CLI subcommands — operations that were previous
|
|
|
289
289
|
| `pactkit upgrade` | Upgrade with format selection |
|
|
290
290
|
| `pactkit version` | Show installed version |
|
|
291
291
|
| `pactkit schema` | Print document schemas |
|
|
292
|
-
| `pactkit doctor` | Diagnose project health (HLD drift, board, config) |
|
|
292
|
+
| `pactkit doctor` | Diagnose project health (HLD drift, board, config, deployment content parity, adapter skew) |
|
|
293
293
|
| `pactkit spec-lint` | Validate spec structure (14 rules: E001-E008, W001-W006) |
|
|
294
294
|
| `pactkit spec-status` | Update spec Status field (Draft/In Progress/Done) |
|
|
295
295
|
| `pactkit guard` | Check project init markers |
|
|
@@ -244,7 +244,7 @@ PactKit ships 36 deterministic CLI subcommands — operations that were previous
|
|
|
244
244
|
| `pactkit upgrade` | Upgrade with format selection |
|
|
245
245
|
| `pactkit version` | Show installed version |
|
|
246
246
|
| `pactkit schema` | Print document schemas |
|
|
247
|
-
| `pactkit doctor` | Diagnose project health (HLD drift, board, config) |
|
|
247
|
+
| `pactkit doctor` | Diagnose project health (HLD drift, board, config, deployment content parity, adapter skew) |
|
|
248
248
|
| `pactkit spec-lint` | Validate spec structure (14 rules: E001-E008, W001-W006) |
|
|
249
249
|
| `pactkit spec-status` | Update spec Status field (Draft/In Progress/Done) |
|
|
250
250
|
| `pactkit guard` | Check project init markers |
|
{pactkit-2.18.0 → pactkit-2.19.0}/docs/architecture/governance/archive/lessons_archive_202603.md
RENAMED
|
@@ -73,3 +73,4 @@
|
|
|
73
73
|
| 2026-03-31 | tree-sitter comment nodes are direct children of function body nodes (block/statement_block), enabling scoped dispatch hint queries without parent traversal. Per-language comment query needed: Go/TS use (comment), Java uses [(line_comment)(block_comment)]. | visualize.py:_extract_calls_from_body |
|
|
74
74
|
| 2026-03-31 | config.py load_config() deep merge was single-level; adding check.pactguard (nested dict inside check) required upgrading to two-level merge to preserve sub-dict defaults like mode and blocking | src/pactkit/config.py:load_config |
|
|
75
75
|
| 2026-03-31 | Adding pactkit-garden to VALID_SKILLS broke 5 hardcoded count assertions in test_config.py, test_pdca_slim.py, test_selective_deploy.py, test_prompt_structural_invariants.py, test_story_slim063.py — grep == 21 and == 10 in tests before releasing a new skill | tests/unit/test_pdca_slim.py:test_valid_skills_count |
|
|
76
|
+
| 2026-03-31 | DETECTED_ENV in commands.py init playbook was unnecessary — _render_prompt(template, profile) already resolves per-format at deploy time. Added FORMAT_NAME to deployer.py var_map to enable pactkit init --format {FORMAT_NAME}. | deployer.py:_render_prompt |
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# Lessons Archive (2026-04)
|
|
2
|
+
|
|
3
|
+
| Date | Lesson | Context |
|
|
4
|
+
|------|--------|---------|
|
|
5
|
+
| 2026-04-01 | Graduated safety language: retire MANDATORY keyword across prompts/commands.py, workflows.py, skills.py — use CRITICAL for safety gates (T1) and MUST for required steps (T2). Consistency prevents AI from treating all-caps keywords as equally urgent. | prompts/commands.py:MANDATORY→MUST/CRITICAL |
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
| Date | Lesson | Context |
|
|
4
4
|
|------|--------|---------|
|
|
5
|
-
| 2026-03-31 | DETECTED_ENV in commands.py init playbook was unnecessary — _render_prompt(template, profile) already resolves per-format at deploy time. Added FORMAT_NAME to deployer.py var_map to enable pactkit init --format {FORMAT_NAME}. | deployer.py:_render_prompt |
|
|
6
|
-
| 2026-04-01 | Graduated safety language: retire MANDATORY keyword across prompts/commands.py, workflows.py, skills.py — use CRITICAL for safety gates (T1) and MUST for required steps (T2). Consistency prevents AI from treating all-caps keywords as equally urgent. | prompts/commands.py:MANDATORY→MUST/CRITICAL |
|
|
7
5
|
| 2026-04-01 | Multi-stack visualize: _detect_stack() returning single str masks Go/TS/Java files in mixed projects; _build_class_graph hardcoded ast.parse() silently skips non-Python via except. Fix: _detect_stacks() returns list, extract_classes() ABC on all 4 analyzers. | visualize.py:_detect_stacks,_build_class_graph |
|
|
8
6
|
| 2026-04-01 | Monorepo stack detection requires depth-1 subdir scan; cleaners.py and visualize.py _STACK_MARKERS must scan root/* not just root | cleaners.py:detect_stacks |
|
|
9
7
|
| 2026-04-01 | When splitting a monolithic file into submodules with deploy-time inlining via load_script(), relative imports (from .foo) in exec() context raise KeyError not ImportError — guard with except (ImportError, KeyError) | skills/__init__.py:load_script |
|
|
@@ -53,3 +51,5 @@
|
|
|
53
51
|
| 2026-08-13 | 门禁词表扫描须先剥离 code fence/inline code span(done_verify.py:_strip_code_spans),否则词表元讨论自身误报 | done_verify.py:_strip_code_spans |
|
|
54
52
|
| 2026-08-17 | check_deploy_parity 新增 hash 路径漏了 SEC-7 降级守卫(PermissionError/AttributeError 穿透 doctor)——Spec Security Scope 逐条自查 + 独立评审实重现能抓作者盲区 | doctor.py:check_deploy_parity |
|
|
55
53
|
| 2026-08-17 | deploy(format=all) 的 adapter 分支无视 target 直写真实 home——跨环境副作用必须显式审查 target/HOME 语义;测试通过 subprocess 调 CLI 时 HOME 未隔离即真实机器 | deployer.py:deploy |
|
|
54
|
+
| 2026-08-17 | Baseline budget tests (test_story063_prompt_slimming.py BASELINE_TOTAL_CHARS) leave <100 chars headroom — new playbook instructions must compress hard or bump baseline with justification comment | pactkit/prompts/commands.py |
|
|
55
|
+
| 2026-08-17 | pactkit update only deploys to ~/.claude — in-repo pactkit-plugin/commands copies need manual sync from prompts/ source (verified by normalized diff) | pactkit/prompts/workflows.py:SPRINT_PROMPT |
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
|
|
16
16
|
## Invariants
|
|
17
17
|
|
|
18
|
-
1. All
|
|
18
|
+
1. All 4183+ tests must pass before any commit to `main`.
|
|
19
19
|
2. Specs (`docs/specs/`) are the source of truth — code conforms to specs, not the reverse.
|
|
20
20
|
3. CLI entry point is `pactkit` via `src/pactkit/cli.py:main`.
|
|
21
21
|
4. No runtime dependencies beyond `pyyaml`.
|
|
@@ -65,3 +65,22 @@
|
|
|
65
65
|
- [x] doctor.py: adapter 版本偏斜 warning
|
|
66
66
|
- [x] 运维: 本机 adapter 升级 2.17.0
|
|
67
67
|
- [x] AC3 双跑全量套件验证
|
|
68
|
+
|
|
69
|
+
### [STORY-slim-143] Spec Dependency Surface & Story DAG (spec-graph)
|
|
70
|
+
> Spec: docs/specs/STORY-slim-143.md
|
|
71
|
+
|
|
72
|
+
- [x] schemas.py Dependency Surface constants+template
|
|
73
|
+
- [x] spec_linter dangling-ref/missing-section rules
|
|
74
|
+
- [x] spec_graph.py DAG+waves+conflict matrix
|
|
75
|
+
- [x] cli.py spec-graph subcommand
|
|
76
|
+
- [x] TDD tests AC1-AC7
|
|
77
|
+
- [x] plan playbook Phase 3.2 step
|
|
78
|
+
|
|
79
|
+
### [STORY-slim-144] Sprint Wave Mode: conflict-aware parallel orchestration
|
|
80
|
+
> Spec: docs/specs/STORY-slim-144.md
|
|
81
|
+
|
|
82
|
+
- [x] spec-graph --json serializer
|
|
83
|
+
- [x] TDD json tests AC1-AC2
|
|
84
|
+
- [x] SPRINT_PROMPT wave mode section R2-R5
|
|
85
|
+
- [x] regenerate deployed sprint playbook
|
|
86
|
+
- [x] prompt content tests AC3-AC6
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# Project Context (Auto-generated)
|
|
2
|
-
> Last updated: 2026-08-
|
|
2
|
+
> Last updated: 2026-08-17T17:57:13+08:00 by pactkit context
|
|
3
3
|
|
|
4
4
|
## Sprint Status
|
|
5
5
|
Backlog: 5 | In Progress: 0 | Done: 0 stories
|
|
@@ -16,11 +16,11 @@ None
|
|
|
16
16
|
* main
|
|
17
17
|
|
|
18
18
|
## Key Decisions
|
|
19
|
-
- guardrail 测试(行数/字符数上限)触线时,优先把组装逻辑上移到 CLI 组合层而不是抬阈值——deployer 保持精简,init/update 的副作用归 cli 编排
|
|
20
|
-
- 配置副本同步 canonical 不能用键数启发式(默认值墙副本键数多但意图少,会覆盖手工配置),必须用显式优先级——见 config.py:sync_config_copies 的 CANONICAL_PREFERENCE
|
|
21
19
|
- 门禁词表扫描须先剥离 code fence/inline code span(done_verify.py:_strip_code_spans),否则词表元讨论自身误报
|
|
22
20
|
- check_deploy_parity 新增 hash 路径漏了 SEC-7 降级守卫(PermissionError/AttributeError 穿透 doctor)——Spec Security Scope 逐条自查 + 独立评审实重现能抓作者盲区
|
|
23
21
|
- deploy(format=all) 的 adapter 分支无视 target 直写真实 home——跨环境副作用必须显式审查 target/HOME 语义;测试通过 subprocess 调 CLI 时 HOME 未隔离即真实机器
|
|
22
|
+
- Baseline budget tests (test_story063_prompt_slimming.py BASELINE_TOTAL_CHARS) leave <100 chars headroom — new playbook instructions must compress hard or bump baseline with justification comment
|
|
23
|
+
- pactkit update only deploys to ~/.claude — in-repo pactkit-plugin/commands copies need manual sync from prompts/ source (verified by normalized diff)
|
|
24
24
|
|
|
25
25
|
## Next Recommended Action
|
|
26
26
|
`/project-plan`
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# STORY-slim-143: Spec Dependency Surface & Story DAG (spec-graph)
|
|
2
|
+
|
|
3
|
+
| Field | Value |
|
|
4
|
+
|-------|-------|
|
|
5
|
+
| ID | STORY-slim-143 |
|
|
6
|
+
| Status | Done |
|
|
7
|
+
| Priority | P1 |
|
|
8
|
+
| Release | 2.19.0 |
|
|
9
|
+
|
|
10
|
+
## Background
|
|
11
|
+
|
|
12
|
+
/project-plan currently writes each Spec in isolation — there is no structured record of *what a story depends on*, *what public surface it provides*, or *which files it will touch*. Plan Phase 3.3 only suggests "record story dependencies if applicable" via Memory MCP (optional, unstructured). Consequences:
|
|
13
|
+
|
|
14
|
+
1. When multiple stories are implemented in parallel (multiple agents / worktrees), file-level conflicts are only discovered at merge time.
|
|
15
|
+
2. Story execution order (先后顺序) is implicit in the architect's head, not computable — nothing can topologically sort the board.
|
|
16
|
+
3. `/project-sprint` today runs strictly one story at a time; safe parallel scheduling requires machine-readable dependency data.
|
|
17
|
+
|
|
18
|
+
This story adds a **Dependency Surface** section to the Spec schema, lints it, and introduces `pactkit spec-graph` — a deterministic CLI that parses all Specs and emits a story dependency DAG, topological execution waves, and a file-overlap conflict matrix. Downstream stories (sprint wave orchestration, interface-first contract staging, merge-preflight) consume this data but are out of scope here.
|
|
19
|
+
|
|
20
|
+
## Requirements
|
|
21
|
+
|
|
22
|
+
### R1: Dependency Surface Schema (MUST)
|
|
23
|
+
|
|
24
|
+
`schemas.py` MUST define a new optional Spec section `## Dependency Surface` (added to `SPEC_TEMPLATE` and `SPEC_OPTIONAL_SECTIONS`, registered in `SCHEMA_REGISTRY`) with exactly four pipe-table fields:
|
|
25
|
+
|
|
26
|
+
| Field | Value |
|
|
27
|
+
|-------|-------|
|
|
28
|
+
| Depends on | comma-separated story IDs this story consumes, each with a `needs:` note (e.g. `STORY-143 (needs: spec-graph CLI)`), or `None` |
|
|
29
|
+
| Provides | public surface this story adds (CLI commands, exported functions, schema constants), or `None` |
|
|
30
|
+
| Touches | glob-level file paths this story expects to modify (e.g. `src/pactkit/cli.py`, `src/pactkit/skills/*.py`) |
|
|
31
|
+
| Conflict risk | `LOW` / `MEDIUM` / `HIGH` + free-text reason |
|
|
32
|
+
|
|
33
|
+
Schema constants (section name, field names, risk levels) MUST live in `schemas.py` as named constants — no magic strings in parser/linter/CLI.
|
|
34
|
+
|
|
35
|
+
### R2: Linter Rules for Dependency Surface (MUST)
|
|
36
|
+
|
|
37
|
+
`spec_linter.py` MUST add checks, invoked from `validate_spec()` following the existing `_check_*` call-sequence pattern:
|
|
38
|
+
|
|
39
|
+
- **New ERROR rule**: a `Depends on` entry references a story ID that has no corresponding file in the specs dir (dangling dependency) — typo protection, since ordering decisions rely on these edges.
|
|
40
|
+
- **New WARNING rule**: `## Dependency Surface` section is missing or its table lacks any of the four required fields.
|
|
41
|
+
|
|
42
|
+
Both rules MUST reuse the existing `_find_section` / `_section_text` parsing helpers — no fourth copy of section-parsing regexes.
|
|
43
|
+
|
|
44
|
+
### R3: `pactkit spec-graph` CLI (MUST)
|
|
45
|
+
|
|
46
|
+
New module `src/pactkit/spec_graph.py` + `spec-graph` subcommand in `cli.py` (argparse subparser + dispatch chain, same pattern as `spec-lint`). Given `--specs-dir docs/specs` (default), it MUST:
|
|
47
|
+
|
|
48
|
+
1. Parse every Spec's Dependency Surface table (reusing spec_linter parsing helpers).
|
|
49
|
+
2. Build the story DAG from `Depends on` edges (excluding edges to stories already `Status | Done`, which are satisfied).
|
|
50
|
+
3. Topologically sort into **execution waves**: wave N contains all stories whose remaining dependencies are all in waves < N. Stories in the same wave are parallelizable.
|
|
51
|
+
4. Compute a **conflict matrix**: pairs of stories whose `Touches` globs overlap (same literal path or glob intersection) are flagged; pairs in the same wave with overlap MUST be highlighted as unsafe-parallel.
|
|
52
|
+
5. Detect dependency cycles and MUST report them as an error (non-zero exit) with the cycle path — a cycle means the Specs themselves are contradictory.
|
|
53
|
+
6. Emit a Mermaid graph to `docs/architecture/graphs/story_graph.mmd` (`--write-graph` flag) and print the wave list + conflict matrix to stdout.
|
|
54
|
+
|
|
55
|
+
### R4: Deterministic Scheduling Semantics (MUST)
|
|
56
|
+
|
|
57
|
+
Wave assignment, overlap detection, and cycle detection MUST be computed entirely in code (LLM ≠ Calculator). The CLI output MUST be stable for identical Spec inputs — same input, same waves, same matrix ordering (sorted output, no dict-iteration nondeterminism).
|
|
58
|
+
|
|
59
|
+
### R5: Plan Playbook Integration (SHOULD)
|
|
60
|
+
|
|
61
|
+
`pactkit-plugin/commands/project-plan.md` Phase 3.2 SHOULD gain a step instructing the architect to fill the Dependency Surface from Phase 1 trace findings (touches = traced files; depends-on = stories whose Provides it consumes). Sprint parallel orchestration itself is explicitly NOT changed by this story.
|
|
62
|
+
|
|
63
|
+
## Technical Design
|
|
64
|
+
|
|
65
|
+
### Lateral Scan Results
|
|
66
|
+
|
|
67
|
+
- Operation: parse Spec metadata/section structure
|
|
68
|
+
- Existing implementations: 3 (`spec_linter.py` `_find_section`/`_section_text`, `done_verify.py` requirement parsing, `audit.py` status check)
|
|
69
|
+
- Assessment: **Reuse existing** — `spec_graph.py` and the new lint rules import spec_linter's helpers; no new regex parser is written.
|
|
70
|
+
|
|
71
|
+
### Capability Assessment
|
|
72
|
+
|
|
73
|
+
| Need | Source | Decision |
|
|
74
|
+
|------|--------|----------|
|
|
75
|
+
| Spec section/metadata parsing | `pactkit.skills.spec_linter` (project) | Reuse |
|
|
76
|
+
| Topological sort / cycle detection | stdlib (`graphlib.TopologicalSorter`, Python ≥ 3.9) | Enable — no new dependency |
|
|
77
|
+
| Glob overlap check | stdlib `fnmatch` + path normalization | Enable |
|
|
78
|
+
| CLI registration | `cli.py` subparser chain (project) | Reuse |
|
|
79
|
+
|
|
80
|
+
### New Implementation Required
|
|
81
|
+
|
|
82
|
+
- `pactkit/spec_graph.py`: Dependency Surface parsing → DAG → waves → conflict matrix → Mermaid emit. Single responsibility, pure functions over parsed data (testable without filesystem fixtures beyond temp specs).
|
|
83
|
+
|
|
84
|
+
### Concurrency Decision (Engineering Concern: concurrency)
|
|
85
|
+
|
|
86
|
+
No runtime concurrency in this story. The *scheduling* semantics are deterministic data: waves are computed by `graphlib`, and any future parallel executor (sprint story) consumes the wave list rather than re-deriving it. This keeps the "can these two stories run in parallel?" judgment in code, not in an LLM prompt.
|
|
87
|
+
|
|
88
|
+
## Acceptance Criteria
|
|
89
|
+
|
|
90
|
+
### AC1: Scaffolded Spec carries Dependency Surface (R1)
|
|
91
|
+
|
|
92
|
+
- **Given** a project with pactkit initialized and the new schema deployed
|
|
93
|
+
- **When** `scaffold.py create_spec "STORY-x-999" "demo"` is run
|
|
94
|
+
- **Then** the generated Spec contains `## Dependency Surface` with all four fields (Depends on / Provides / Touches / Conflict risk) and `pactkit spec-lint` on it reports 0 errors and 0 warnings for the new rules.
|
|
95
|
+
|
|
96
|
+
### AC2: Dangling dependency is rejected (R2)
|
|
97
|
+
|
|
98
|
+
- **Given** a Spec whose `Depends on` includes `STORY-slim-999` and no such file exists in the specs dir
|
|
99
|
+
- **When** `pactkit spec-lint` runs on that Spec
|
|
100
|
+
- **Then** it reports the new ERROR rule naming the dangling ID, and exits non-zero.
|
|
101
|
+
|
|
102
|
+
### AC3: Missing section is a warning (R2)
|
|
103
|
+
|
|
104
|
+
- **Given** an otherwise-valid Spec with no `## Dependency Surface` section (e.g. all pre-2.19 Specs)
|
|
105
|
+
- **When** `pactkit spec-lint` runs on it
|
|
106
|
+
- **Then** the new WARNING fires but existing rules are unaffected.
|
|
107
|
+
|
|
108
|
+
### AC4: Waves and conflict matrix from real Specs (R3, R4)
|
|
109
|
+
|
|
110
|
+
- **Given** three Specs: A (Depends on: None, Touches: `a.py`), B (Depends on: A, Touches: `b.py`), C (Depends on: None, Touches: `a.py`)
|
|
111
|
+
- **When** `pactkit spec-graph` runs
|
|
112
|
+
- **Then** output shows wave 1 = {A, C}, wave 2 = {B}, and flags A↔C as a same-wave file conflict on `a.py` (unsafe-parallel).
|
|
113
|
+
|
|
114
|
+
### AC5: Cycle detection (R3, R4)
|
|
115
|
+
|
|
116
|
+
- **Given** two Specs that depend on each other
|
|
117
|
+
- **When** `pactkit spec-graph` runs
|
|
118
|
+
- **Then** it exits non-zero and prints the cycle path (e.g. `A -> B -> A`).
|
|
119
|
+
|
|
120
|
+
### AC6: Deterministic output (R4)
|
|
121
|
+
|
|
122
|
+
- **Given** any fixed set of Specs
|
|
123
|
+
- **When** `pactkit spec-graph` runs twice
|
|
124
|
+
- **Then** wave lists and conflict matrix are byte-identical (sorted, stable ordering).
|
|
125
|
+
|
|
126
|
+
### AC7: Plan playbook documents the step (R5)
|
|
127
|
+
|
|
128
|
+
- **Given** the updated `project-plan.md` playbook
|
|
129
|
+
- **When** reading Phase 3.2
|
|
130
|
+
- **Then** it contains a step instructing the architect to fill the Dependency Surface (touches from Phase 1 trace, depends-on from consumed Provides), with a pointer to the field semantics in R1.
|
|
131
|
+
|
|
132
|
+
## Target Call Chain
|
|
133
|
+
|
|
134
|
+
- CLI: `pactkit spec-graph` → `cli.py` (subparser + dispatch) → `pactkit.spec_graph.main(argv)`
|
|
135
|
+
- Core: `spec_graph.main` → `parse_dependency_surfaces(specs_dir)` (reuses `spec_linter._find_section` / `_section_text`) → `build_dag()` → `graphlib.TopologicalSorter` (waves) → `conflict_matrix()` (fnmatch overlap) → stdout / `story_graph.mmd`
|
|
136
|
+
- Lint: `pactkit spec-lint` → `spec_linter.validate_spec()` → new `_check_dependency_surface()` (dangling-ref ERROR, missing-section WARNING)
|
|
137
|
+
- Scaffold: `scaffold.py create_spec` → `schemas.SPEC_TEMPLATE` (now includes Dependency Surface)
|
|
138
|
+
|
|
139
|
+
## Dependency Surface
|
|
140
|
+
|
|
141
|
+
| Field | Value |
|
|
142
|
+
|-------|-------|
|
|
143
|
+
| Depends on | None |
|
|
144
|
+
| Provides | `pactkit spec-graph` CLI; `pactkit.spec_graph` module; `DEP_SURFACE_*` schema constants; 2 new spec-lint rules |
|
|
145
|
+
| Touches | `src/pactkit/schemas.py`, `src/pactkit/skills/spec_linter.py`, `src/pactkit/spec_graph.py` (new), `src/pactkit/cli.py`, `pactkit-plugin/commands/project-plan.md`, `tests/unit/test_story_slim143_spec_graph.py` (new), `tests/unit/test_story042_spec_linter.py` |
|
|
146
|
+
| Conflict risk | LOW — schemas.py and cli.py are frequently touched, but changes are append-only (new section constant, new subparser), minimal overlap with typical feature stories |
|
|
147
|
+
|
|
148
|
+
## Implementation Steps
|
|
149
|
+
|
|
150
|
+
| Step | File | Action | Dependencies | Risk |
|
|
151
|
+
|------|------|--------|-------------|------|
|
|
152
|
+
| 1 | `src/pactkit/schemas.py` | Add `DEP_SURFACE_*` constants + section in SPEC_TEMPLATE + SCHEMA_REGISTRY | None | Low |
|
|
153
|
+
| 2 | `src/pactkit/skills/spec_linter.py` | Add `_check_dependency_surface` (dangling-ref ERROR, missing-section WARNING) | Step 1 | Low |
|
|
154
|
+
| 3 | `src/pactkit/spec_graph.py` | New module: parse → DAG → waves (graphlib) → conflict matrix → Mermaid | Step 1 | Medium (glob-overlap edge cases) |
|
|
155
|
+
| 4 | `src/pactkit/cli.py` | Register `spec-graph` subparser + dispatch | Step 3 | Low |
|
|
156
|
+
| 5 | `tests/unit/` | TDD tests for AC1–AC6 | Steps 1–4 | Low |
|
|
157
|
+
| 6 | `pactkit-plugin/commands/project-plan.md` | Phase 3.2 step: fill Dependency Surface from trace findings | Step 1 | Low |
|
|
158
|
+
|
|
159
|
+
## Security Scope
|
|
160
|
+
|
|
161
|
+
| Check | Applicable | Reason |
|
|
162
|
+
|-------|------------|--------|
|
|
163
|
+
| SEC-1 | Yes | new source module spec_graph.py — code quality standards apply |
|
|
164
|
+
| SEC-2 | Yes | parses user-authored Spec markdown + glob paths — must tolerate malformed tables/globs without crashing |
|
|
165
|
+
| SEC-3 | N/A | no database/ORM (auto-detect false positive: no SQL involved) |
|
|
166
|
+
| SEC-4 | N/A | no frontend files |
|
|
167
|
+
| SEC-5 | N/A | no auth patterns |
|
|
168
|
+
| SEC-6 | N/A | no API/route files |
|
|
169
|
+
| SEC-7 | Yes | cycle detection and dangling refs must fail with clear errors, non-zero exit, no stack traces |
|
|
170
|
+
| SEC-8 | N/A | no new dependencies — stdlib only (graphlib, fnmatch) |
|
|
171
|
+
|
|
172
|
+
## Out of Scope
|
|
173
|
+
|
|
174
|
+
- `/project-sprint` wave-based parallel orchestration (depends on this story's Provides; separate story)
|
|
175
|
+
- Interface-first contract staging for depended-upon stories
|
|
176
|
+
- Merge-preflight conflict check (`--check-conflicts`) at agent completion time
|
|
177
|
+
- Auto-fixing file conflicts (spec-graph only *reports* them)
|
|
178
|
+
- Board format changes (board.py untouched)
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# STORY-slim-144: Sprint Wave Mode: conflict-aware parallel orchestration
|
|
2
|
+
|
|
3
|
+
| Field | Value |
|
|
4
|
+
|-------|-------|
|
|
5
|
+
| ID | STORY-slim-144 |
|
|
6
|
+
| Status | Done |
|
|
7
|
+
| Priority | P1 |
|
|
8
|
+
| Release | 2.19.0 |
|
|
9
|
+
|
|
10
|
+
## Background
|
|
11
|
+
|
|
12
|
+
`/project-sprint` (v1.5.0) orchestrates exactly ONE story per invocation: Plan → Act → Check → Close, strictly sequential in worktrees. STORY-slim-143 delivered the missing data layer — every Spec now declares a Dependency Surface, and `pactkit spec-graph` computes execution waves (topological layers) and a file-overlap conflict matrix. What remains is the **consumer**: a wave mode in sprint that runs multiple backlog stories concurrently when the data proves it safe.
|
|
13
|
+
|
|
14
|
+
Design constraints from the existing architecture:
|
|
15
|
+
- Backward compatible: `$ARGUMENTS` present → current single-story mode, unchanged.
|
|
16
|
+
- LLM ≠ Calculator: wave membership, parallel/serialize decisions, and conflict checks come from `spec-graph` output, never from orchestrator judgment.
|
|
17
|
+
- Safe by default: stories without a declared `Touches` (legacy/placeholder) MUST NOT be parallelized — unknown conflict surface means serialize.
|
|
18
|
+
|
|
19
|
+
## Requirements
|
|
20
|
+
|
|
21
|
+
### R1: `spec-graph --json` Machine-Readable Output (MUST)
|
|
22
|
+
|
|
23
|
+
`pactkit spec-graph` MUST accept a `--json` flag emitting `{waves: [[ids]], conflicts: [{story_a, story_b, shared, same_wave}]}` with sorted, deterministic ordering. The sprint orchestrator consumes this instead of parsing human output. Cycle errors MUST still exit non-zero (JSON or not).
|
|
24
|
+
|
|
25
|
+
### R2: Wave Mode Entry (MUST)
|
|
26
|
+
|
|
27
|
+
`commands/project-sprint.md` (source: `src/pactkit/prompts/workflows.py` SPRINT_PROMPT) MUST gain a wave mode with this entry rule:
|
|
28
|
+
|
|
29
|
+
- `$ARGUMENTS` non-empty → existing single-story mode, byte-for-byte behavior preserved.
|
|
30
|
+
- `$ARGUMENTS` empty → wave mode:
|
|
31
|
+
1. `board.py list_stories` → BACKLOG story IDs.
|
|
32
|
+
2. `pactkit spec-graph --json` → waves + conflicts, filtered to backlog IDs with existing Specs.
|
|
33
|
+
3. If no parallelizable stories exist (all serialized), log and fall back to single-story suggestion.
|
|
34
|
+
|
|
35
|
+
### R3: Conflict-Aware Scheduling Policy (MUST)
|
|
36
|
+
|
|
37
|
+
Within each wave, the orchestrator MUST partition stories into:
|
|
38
|
+
|
|
39
|
+
- **Parallel batch**: stories whose Touches are all declared (no placeholder/missing) AND pairwise non-conflicting per the matrix. Batch size MUST NOT exceed `sprint.max_parallel` from pactkit.yaml (default 3, named constant — no magic value); excess stories spill to a following sub-batch.
|
|
40
|
+
- **Serialized tail**: stories flagged same-wave-conflict, or with undeclared Touches, run one-at-a-time after the parallel batch.
|
|
41
|
+
|
|
42
|
+
Each story (parallel or serialized) runs the EXISTING per-story PDCA chain (Plan→Act→Check→Close) in its own worktree, reusing current Stage A/B/C dispatch logic — no duplicated stage definitions (DRY).
|
|
43
|
+
|
|
44
|
+
### R4: Wave Gate & Failure Policy (MUST)
|
|
45
|
+
|
|
46
|
+
- Wave N+1 MUST NOT start until every wave-N story is merged green (worktree merged, tests passing per each story's Close stage).
|
|
47
|
+
- Any story failure → STOP the wave immediately (fail-fast, consistent with current single-story semantics), report which stories completed/merged vs pending, and leave remaining stories on the board. NEVER auto-retry a failed story in the same run.
|
|
48
|
+
- Merge conflict on worktree merge → STOP + suggest `git merge --abort` (existing error contract preserved).
|
|
49
|
+
|
|
50
|
+
### R5: Observability (SHOULD)
|
|
51
|
+
|
|
52
|
+
The orchestrator SHOULD print a wave plan before dispatching (wave N: parallel=[...], serialized=[...], skipped=[...] with reasons) so the user can abort before any subagent spawns.
|
|
53
|
+
|
|
54
|
+
## Technical Design
|
|
55
|
+
|
|
56
|
+
### Lateral Scan Results
|
|
57
|
+
|
|
58
|
+
- Operation: subagent orchestration with dependency ordering
|
|
59
|
+
- Existing implementations: 1 (`SPRINT_PROMPT` single-story chain) — no existing parallel scheduler
|
|
60
|
+
- Assessment: **New is justified** — wave mode extends the single existing orchestrator; per-story chain is reused verbatim, not copied.
|
|
61
|
+
|
|
62
|
+
### Capability Assessment
|
|
63
|
+
|
|
64
|
+
| Need | Source | Decision |
|
|
65
|
+
|------|--------|----------|
|
|
66
|
+
| Waves + conflict matrix | `pactkit spec-graph` (STORY-slim-143) | Reuse — add `--json` consumer interface |
|
|
67
|
+
| Backlog enumeration | `board.py list_stories` | Reuse |
|
|
68
|
+
| Worktree isolation | existing sprint Stage A/B/C pattern | Reuse |
|
|
69
|
+
| Parallel cap config | pactkit.yaml `sprint.max_parallel` (new optional key, default 3) | New config key |
|
|
70
|
+
|
|
71
|
+
### New Implementation Required
|
|
72
|
+
|
|
73
|
+
- `spec_graph.py`: `--json` flag + `to_json()` serializer (~30 lines).
|
|
74
|
+
- `SPRINT_PROMPT`: Wave Mode section (Phase 0.5: Mode Detection; Phase 1W: Wave loop). Deployed copy `pactkit-plugin/commands/project-sprint.md` regenerated via `pactkit update`.
|
|
75
|
+
|
|
76
|
+
### Concurrency Decision (Engineering Concern: concurrency)
|
|
77
|
+
|
|
78
|
+
Parallelism is at the **subagent/team level** (Claude Code Task agents with worktree isolation), not threads/processes in pactkit code — pactkit itself stays single-threaded. The cap (`sprint.max_parallel`, default 3) bounds concurrent worktrees. Merging is always sequential (one worktree at a time), which is the serialization point that keeps git state sane. Conflict avoidance is precomputed by `spec-graph`, not detected at merge time.
|
|
79
|
+
|
|
80
|
+
### Error-Recovery Decision (Engineering Concern: error-recovery)
|
|
81
|
+
|
|
82
|
+
Fail-fast per wave; no auto-retry; partial progress is always safe because every completed story merged through its own green PDCA chain. Resume = re-run `/project-sprint` — remaining backlog stories re-enter wave computation (idempotent, since completed stories are Done and excluded by spec-graph).
|
|
83
|
+
|
|
84
|
+
### Backwards-Compatibility Decision (Engineering Concern: backwards-compatibility)
|
|
85
|
+
|
|
86
|
+
Single-story mode is the default when args are present — zero behavior change for existing users. Wave mode is opt-in via empty args. `sprint.max_parallel` absent from pactkit.yaml → default 3, no config migration needed.
|
|
87
|
+
|
|
88
|
+
## Acceptance Criteria
|
|
89
|
+
|
|
90
|
+
### AC1: JSON output shape (R1)
|
|
91
|
+
|
|
92
|
+
- **Given** specs forming 2 waves with one same-wave conflict
|
|
93
|
+
- **When** `pactkit spec-graph --json` runs
|
|
94
|
+
- **Then** stdout parses as JSON with `waves` (list of sorted ID lists) and `conflicts` (list of objects with story_a/story_b/shared/same_wave), and two runs are byte-identical.
|
|
95
|
+
|
|
96
|
+
### AC2: Cycle still errors under --json (R1)
|
|
97
|
+
|
|
98
|
+
- **Given** two mutually dependent specs
|
|
99
|
+
- **When** `pactkit spec-graph --json` runs
|
|
100
|
+
- **Then** exit code is non-zero and stderr names the cycle.
|
|
101
|
+
|
|
102
|
+
### AC3: Mode detection (R2)
|
|
103
|
+
|
|
104
|
+
- **Given** the updated SPRINT_PROMPT / project-sprint.md
|
|
105
|
+
- **When** reading the entry phase
|
|
106
|
+
- **Then** it specifies: non-empty `$ARGUMENTS` → single-story mode (unchanged path); empty → wave mode with board scan + `spec-graph --json` + fallback when nothing is parallelizable.
|
|
107
|
+
|
|
108
|
+
### AC4: Scheduling policy documented and deterministic (R3)
|
|
109
|
+
|
|
110
|
+
- **Given** the updated playbook
|
|
111
|
+
- **When** reading the wave-mode section
|
|
112
|
+
- **Then** it encodes all of: parallel batch requires declared Touches AND pairwise non-conflict; `sprint.max_parallel` cap with default 3; serialized tail for conflicted/undeclared stories; per-story worktree PDCA chain reuse (reference, not copy).
|
|
113
|
+
|
|
114
|
+
### AC5: Wave gate & failure policy (R4, R5)
|
|
115
|
+
|
|
116
|
+
- **Given** the updated playbook
|
|
117
|
+
- **When** reading the wave-mode section
|
|
118
|
+
- **Then** it states: wave N+1 blocked until wave N fully merged; fail-fast STOP with completed/pending report; no auto-retry; merge-conflict → STOP + `git merge --abort` suggestion; wave plan printed before dispatch.
|
|
119
|
+
|
|
120
|
+
### AC6: Prompt hygiene (R2-R5)
|
|
121
|
+
|
|
122
|
+
- **Given** the implemented changes
|
|
123
|
+
- **When** running `pytest tests/unit/test_prompt_cli_refs.py tests/unit/test_story063_prompt_slimming.py` and full suite
|
|
124
|
+
- **Then** all pass (prompt baselines bumped per project convention if needed, with justification comments).
|
|
125
|
+
|
|
126
|
+
## Target Call Chain
|
|
127
|
+
|
|
128
|
+
- Wave mode: `/project-sprint` (empty args) → SPRINT_PROMPT Mode Detection → `board.py list_stories` + `pactkit spec-graph --json` → wave plan → per-story existing Stage A/B/C dispatch (worktree) → sequential merges → wave gate → next wave
|
|
129
|
+
- JSON: `cli.py spec-graph` → `spec_graph.main(["--json"])` → `to_json(graph)` (waves via `compute_waves`, conflicts via `compute_conflicts`)
|
|
130
|
+
|
|
131
|
+
## Dependency Surface
|
|
132
|
+
|
|
133
|
+
| Field | Value |
|
|
134
|
+
|-------|-------|
|
|
135
|
+
| Depends on | STORY-slim-143 (needs: `pactkit spec-graph` waves + conflict matrix, `spec_graph.compute_waves`/`compute_conflicts`) |
|
|
136
|
+
| Provides | `pactkit spec-graph --json`; sprint wave mode; `sprint.max_parallel` config key |
|
|
137
|
+
| Touches | `src/pactkit/spec_graph.py`, `src/pactkit/prompts/workflows.py`, `pactkit-plugin/commands/project-sprint.md`, `tests/unit/test_story_slim144_wave_mode.py` (new) |
|
|
138
|
+
| Conflict risk | LOW — workflows.py SPRINT_PROMPT and spec_graph.py append-only changes; no overlap with typical feature stories |
|
|
139
|
+
|
|
140
|
+
## Implementation Steps
|
|
141
|
+
|
|
142
|
+
| Step | File | Action | Dependencies | Risk |
|
|
143
|
+
|------|------|--------|-------------|------|
|
|
144
|
+
| 1 | `src/pactkit/spec_graph.py` | Add `--json` + `to_json()` | None | Low |
|
|
145
|
+
| 2 | `tests/unit/test_story_slim144_wave_mode.py` | TDD tests for AC1/AC2 | Step 1 | Low |
|
|
146
|
+
| 3 | `src/pactkit/prompts/workflows.py` | SPRINT_PROMPT wave mode section (R2-R5) | Step 1 | Medium (prompt size budget) |
|
|
147
|
+
| 4 | `pactkit-plugin/commands/project-sprint.md` | Regenerate via `pactkit update` | Step 3 | Low |
|
|
148
|
+
| 5 | `tests/unit/` | Prompt content assertions for AC3-AC5 | Step 3 | Low |
|
|
149
|
+
|
|
150
|
+
## Security Scope
|
|
151
|
+
|
|
152
|
+
| Check | Applicable | Reason |
|
|
153
|
+
|-------|------------|--------|
|
|
154
|
+
| SEC-1 | Yes | spec_graph.py source change — code quality standards apply |
|
|
155
|
+
| SEC-2 | Yes | --json serializer consumes spec-derived data — output must be valid JSON for any malformed surface input |
|
|
156
|
+
| SEC-3 | N/A | no database |
|
|
157
|
+
| SEC-4 | N/A | no frontend |
|
|
158
|
+
| SEC-5 | N/A | auto-detect false positive: no auth/session code touched (prompt text only) |
|
|
159
|
+
| SEC-6 | N/A | no API endpoints |
|
|
160
|
+
| SEC-7 | Yes | cycle error under --json must stay a clean single-line stderr + non-zero exit |
|
|
161
|
+
| SEC-8 | N/A | no new dependencies (stdlib json) |
|
|
162
|
+
|
|
163
|
+
## Out of Scope
|
|
164
|
+
|
|
165
|
+
- Interface-first contract staging (separate downstream story)
|
|
166
|
+
- Merge-preflight conflict check at agent completion time
|
|
167
|
+
- Auto-retry / self-healing of failed stories
|
|
168
|
+
- Parallelism inside pactkit code itself (threads/async) — orchestration-level only
|
|
169
|
+
- Changing single-story mode behavior in any way
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Test Cases: STORY-slim-143 — Spec Dependency Surface & Story DAG (spec-graph)
|
|
2
|
+
|
|
3
|
+
## TC-1: Scaffolded spec carries Dependency Surface (AC1)
|
|
4
|
+
|
|
5
|
+
- **Given** pactkit 项目已初始化且新 schema 已部署
|
|
6
|
+
- **When** 运行 `scaffold.py create_spec "STORY-x-999" "demo"`
|
|
7
|
+
- **Then** 生成的 Spec 含 `## Dependency Surface` 及全部四个字段(Depends on / Provides / Touches / Conflict risk),且 `pactkit spec-lint` 无 E010/W011
|
|
8
|
+
|
|
9
|
+
## TC-2: Dangling dependency rejected (AC2)
|
|
10
|
+
|
|
11
|
+
- **Given** 某 Spec 的 Depends on 引用不存在的 `STORY-slim-999`
|
|
12
|
+
- **When** 运行 `pactkit spec-lint`
|
|
13
|
+
- **Then** 报告 E010(含该 ID)并以非零码退出
|
|
14
|
+
|
|
15
|
+
## TC-3: Missing section is a warning (AC3)
|
|
16
|
+
|
|
17
|
+
- **Given** 一个无 `## Dependency Surface` 的旧 Spec(其余部分合法)
|
|
18
|
+
- **When** 运行 `pactkit spec-lint`
|
|
19
|
+
- **Then** 报告 W011 但整体 PASS,既有规则不受影响
|
|
20
|
+
|
|
21
|
+
## TC-4: Waves and conflict matrix (AC4)
|
|
22
|
+
|
|
23
|
+
- **Given** A(Depends on: None, Touches: `a.py`)、B(Depends on: A, Touches: `b.py`)、C(Depends on: None, Touches: `a.py`)
|
|
24
|
+
- **When** 运行 `pactkit spec-graph`
|
|
25
|
+
- **Then** wave 1 = {A, C}、wave 2 = {B},且 A↔C 被标记为同 wave 文件冲突(unsafe-parallel)
|
|
26
|
+
|
|
27
|
+
## TC-5: Cycle detection (AC5)
|
|
28
|
+
|
|
29
|
+
- **Given** 两个互相依赖的 Spec
|
|
30
|
+
- **When** 运行 `pactkit spec-graph`
|
|
31
|
+
- **Then** 以非零码退出并输出 cycle 路径
|
|
32
|
+
|
|
33
|
+
## TC-6: Deterministic output (AC6)
|
|
34
|
+
|
|
35
|
+
- **Given** 任意固定 Spec 集合
|
|
36
|
+
- **When** `pactkit spec-graph` 连续运行两次
|
|
37
|
+
- **Then** wave 列表与冲突矩阵字节一致
|
|
38
|
+
|
|
39
|
+
## TC-7: Plan playbook documents the step (AC7)
|
|
40
|
+
|
|
41
|
+
- **Given** 更新后的 project-plan 命令内容
|
|
42
|
+
- **When** 阅读 Phase 3.2a
|
|
43
|
+
- **Then** 存在 Dependency Surface 填写指引,且包含 E010 与 `pactkit spec-graph` 引用
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Test Cases: STORY-slim-144 — Sprint Wave Mode: conflict-aware parallel orchestration
|
|
2
|
+
|
|
3
|
+
## TC-1: JSON output shape (AC1)
|
|
4
|
+
|
|
5
|
+
- **Given** 两个 wave + 一个同 wave 冲突的 Spec 集合
|
|
6
|
+
- **When** 运行 `pactkit spec-graph --json`
|
|
7
|
+
- **Then** 输出合法 JSON 含 `waves`(排序的 ID 列表的列表)与 `conflicts`(含 story_a/story_b/shared/same_wave),两次运行字节一致
|
|
8
|
+
|
|
9
|
+
## TC-2: Cycle under --json (AC2)
|
|
10
|
+
|
|
11
|
+
- **Given** 两个互相依赖的 Spec
|
|
12
|
+
- **When** 运行 `pactkit spec-graph --json`
|
|
13
|
+
- **Then** 以非零码退出且 stderr 含 cycle 路径
|
|
14
|
+
|
|
15
|
+
## TC-3: Mode detection (AC3)
|
|
16
|
+
|
|
17
|
+
- **Given** 更新后的 SPRINT_PROMPT / project-sprint.md
|
|
18
|
+
- **When** 阅读入口 Phase
|
|
19
|
+
- **Then** 非空 `$ARGUMENTS` → 单 story 模式(行为不变);空 → wave 模式(board 扫描 + `spec-graph --json` + 无可并行 story 时回退建议)
|
|
20
|
+
|
|
21
|
+
## TC-4: Scheduling policy (AC4)
|
|
22
|
+
|
|
23
|
+
- **Given** 更新后的 playbook
|
|
24
|
+
- **When** 阅读 Wave Mode section
|
|
25
|
+
- **Then** 编码全部策略:声明 Touches 且两两无冲突才并行 / `sprint.max_parallel` 默认 3 / 冲突或未声明者串行 / 按引用复用 Stage A-C(不复制定义)
|
|
26
|
+
|
|
27
|
+
## TC-5: Wave gate & failure policy (AC5)
|
|
28
|
+
|
|
29
|
+
- **Given** 更新后的 playbook
|
|
30
|
+
- **When** 阅读 Wave Mode section
|
|
31
|
+
- **Then** 编码:wave N+1 阻塞至 N 全部 merge 绿 / fail-fast 且 NEVER auto-retry / merge 冲突提示 `git merge --abort` / dispatch 前打印 wave plan 并等用户确认
|
|
32
|
+
|
|
33
|
+
## TC-6: Prompt hygiene (AC6)
|
|
34
|
+
|
|
35
|
+
- **Given** 实现完成
|
|
36
|
+
- **When** 运行全量测试
|
|
37
|
+
- **Then** 全部通过(prompt 基线 bump 均带 justification 注释)
|
|
@@ -249,6 +249,23 @@ def main():
|
|
|
249
249
|
sec_scope_parser = subparsers.add_parser("sec-scope", help="Auto-detect security scope")
|
|
250
250
|
sec_scope_parser.add_argument("files", nargs="*", help="Changed file paths")
|
|
251
251
|
|
|
252
|
+
# pactkit spec-graph (STORY-slim-143)
|
|
253
|
+
spec_graph_parser = subparsers.add_parser(
|
|
254
|
+
"spec-graph", help="Story dependency graph: execution waves + conflict matrix"
|
|
255
|
+
)
|
|
256
|
+
spec_graph_parser.add_argument(
|
|
257
|
+
"--specs-dir", default="docs/specs", help="Directory containing spec files"
|
|
258
|
+
)
|
|
259
|
+
spec_graph_parser.add_argument(
|
|
260
|
+
"--write-graph", action="store_true", help="Write Mermaid graph to --graph-path"
|
|
261
|
+
)
|
|
262
|
+
spec_graph_parser.add_argument(
|
|
263
|
+
"--graph-path", default="docs/architecture/graphs/story_graph.mmd", help="Mermaid output path"
|
|
264
|
+
)
|
|
265
|
+
spec_graph_parser.add_argument(
|
|
266
|
+
"--json", action="store_true", help="Emit machine-readable JSON (waves + conflicts)"
|
|
267
|
+
)
|
|
268
|
+
|
|
252
269
|
# pactkit lint-context (STORY-slim-014 R2)
|
|
253
270
|
lint_ctx_parser = subparsers.add_parser("lint-context", help="Validate context.md structure")
|
|
254
271
|
lint_ctx_parser.add_argument("path", nargs="?", default="docs/product/context.md", help="Path to context.md")
|
|
@@ -574,6 +591,16 @@ def main():
|
|
|
574
591
|
ctx_path.write_text(content, encoding="utf-8")
|
|
575
592
|
print(f"Generated {ctx_path}")
|
|
576
593
|
|
|
594
|
+
elif args.command == "spec-graph":
|
|
595
|
+
from pactkit.spec_graph import main as spec_graph_main
|
|
596
|
+
|
|
597
|
+
argv = ["--specs-dir", args.specs_dir, "--graph-path", args.graph_path]
|
|
598
|
+
if args.write_graph:
|
|
599
|
+
argv.append("--write-graph")
|
|
600
|
+
if args.json:
|
|
601
|
+
argv.append("--json")
|
|
602
|
+
raise SystemExit(spec_graph_main(argv))
|
|
603
|
+
|
|
577
604
|
elif args.command == "sec-scope":
|
|
578
605
|
from pathlib import Path
|
|
579
606
|
|
|
@@ -124,6 +124,7 @@ allowed-tools: [Read, Write, Edit, Bash, Glob, Grep]
|
|
|
124
124
|
- Edit `(Description of the problem or feature)` → actual Background content from your Trace findings
|
|
125
125
|
- Edit `## Target Call Chain` placeholder → actual call chain from Phase 1
|
|
126
126
|
- Edit `### R1: (Requirement Name) (MUST)` → actual requirements using RFC 2119 keywords (MUST/SHOULD/MAY). Add more R{N} sections as needed.
|
|
127
|
+
- Edit `## Dependency Surface` fields (dangling ID = E010; feeds `pactkit spec-graph`)
|
|
127
128
|
4. **Journey Segment (Conditional)**: If `docs/e2e/journey.md` exists in the project:
|
|
128
129
|
- Read `docs/e2e/journey.md` to identify defined journeys and their steps.
|
|
129
130
|
- Assess whether this Story's scope touches any journey step (e.g., modifies a UI flow, changes an API endpoint used in a journey).
|