phasegate 0.16.0 → 0.32.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. package/README.ja.md +74 -42
  2. package/README.md +69 -9
  3. package/docs/ADR/ADR-013-story-reflection-gate.md +100 -0
  4. package/docs/guide/configuration.md +244 -7
  5. package/package.json +7 -5
  6. package/scripts/harness/adr-foundation/domain/ports/adr-document-parser-port.ts +1 -0
  7. package/scripts/harness/adr-foundation/domain/ports/adr-frontmatter-parser-port.ts +1 -0
  8. package/scripts/harness/adr-foundation/domain/ports/adr-repository-port.ts +1 -0
  9. package/scripts/harness/adr-foundation/domain/value-objects/adr-status.ts +6 -6
  10. package/scripts/harness/agent-integration/application/dto/handle-pre-tool-use-dto.ts +3 -1
  11. package/scripts/harness/agent-integration/application/usecases/handle-pre-tool-use-usecase.ts +108 -2
  12. package/scripts/harness/agent-integration/domain/ports/config-query-port.ts +2 -0
  13. package/scripts/harness/agent-integration/domain/ports/phase-gate-query-port.ts +1 -1
  14. package/scripts/harness/agent-integration/domain/ports/story-reflection-query-port.ts +8 -0
  15. package/scripts/harness/agent-integration/domain/services/bash-write-target-extractor.ts +258 -0
  16. package/scripts/harness/agent-integration/domain/services/hook-to-cli-translator.ts +21 -4
  17. package/scripts/harness/agent-integration/domain/value-objects/protected-file-list.ts +20 -0
  18. package/scripts/harness/agent-integration/domain/value-objects/story-reflection-query-result.ts +63 -0
  19. package/scripts/harness/agent-integration/infrastructure/adapters/file-system-story-reflection-query-adapter.ts +122 -0
  20. package/scripts/harness/agent-integration/infrastructure/adapters/harness-config-config-query-adapter.ts +20 -0
  21. package/scripts/harness/agent-integration/infrastructure/adapters/phase-gate-query-adapter.ts +17 -3
  22. package/scripts/harness/agent-integration/presentation/pre-tool-use-hook.ts +29 -2
  23. package/scripts/harness/biome-ast-engine/domain/services/lint-runner.ts +24 -0
  24. package/scripts/harness/biome-ast-engine/domain/services/rule-definition-registry.ts +1 -1
  25. package/scripts/harness/biome-ast-engine/domain/value-objects/source-module-snapshot.ts +5 -2
  26. package/scripts/harness/biome-ast-engine/infrastructure/adapters/node-workspace-file-adapter.ts +1 -1
  27. package/scripts/harness/biome-ast-engine/infrastructure/adapters/typescript-source-module-analyzer-adapter.ts +1 -1
  28. package/scripts/harness/biome-ast-engine/infrastructure/parsers/unit-comment-parser.ts +12 -7
  29. package/scripts/harness/ci-governance/composition-root.ts +1 -0
  30. package/scripts/harness/config-foundation/application/mappers/phase-config-section-mapper.ts +44 -0
  31. package/scripts/harness/config-foundation/application/usecases/load-resolved-config-use-case.ts +20 -1
  32. package/scripts/harness/config-foundation/domain/harness-config.ts +2 -1
  33. package/scripts/harness/config-foundation/domain/value-objects/phase-dependencies-config.ts +18 -4
  34. package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v2.schema.json +185 -10
  35. package/scripts/harness/config-foundation/infrastructure/validators/ajv-config-schema-validator.ts +2 -1
  36. package/scripts/harness/harness-api/application/dto/command-dispatch-input.ts +1 -0
  37. package/scripts/harness/harness-api/application/dto/command-dispatch-output.ts +1 -0
  38. package/scripts/harness/harness-api/application/dto/exit-code-decision-input.ts +1 -0
  39. package/scripts/harness/harness-api/application/dto/exit-code-decision-output.ts +1 -0
  40. package/scripts/harness/harness-api/application/dto/harness-api-response-contract.ts +1 -0
  41. package/scripts/harness/harness-api/application/dto/initialize-registry-input.ts +1 -0
  42. package/scripts/harness/harness-api/application/dto/registry-summary-output.ts +1 -0
  43. package/scripts/harness/harness-api/application/dto/status-derivation-input.ts +1 -0
  44. package/scripts/harness/harness-api/application/mappers/harness-api-response-mapper.ts +1 -0
  45. package/scripts/harness/harness-api/application/usecases/decide-exit-code-usecase.ts +1 -0
  46. package/scripts/harness/harness-api/application/usecases/derive-harness-status-usecase.ts +1 -0
  47. package/scripts/harness/harness-api/application/usecases/dispatch-command-usecase.ts +1 -0
  48. package/scripts/harness/harness-api/application/usecases/initialize-command-registry-usecase.ts +1 -0
  49. package/scripts/harness/harness-api/composition-root.ts +1 -0
  50. package/scripts/harness/harness-api/domain/ports/artifact-scanner-port.ts +1 -0
  51. package/scripts/harness/harness-api/domain/ports/biome-lint-port.ts +1 -0
  52. package/scripts/harness/harness-api/domain/ports/config-query-port.ts +1 -0
  53. package/scripts/harness/harness-api/domain/ports/impact-analysis-port.ts +1 -0
  54. package/scripts/harness/harness-api/domain/ports/phase-gate-query-port.ts +1 -0
  55. package/scripts/harness/harness-api/domain/ports/validator-execution-port.ts +1 -0
  56. package/scripts/harness/harness-api/domain/services/command-dispatch-service.ts +1 -0
  57. package/scripts/harness/harness-api/domain/services/command-registry.ts +1 -0
  58. package/scripts/harness/harness-api/domain/services/status-derivation-service.ts +1 -0
  59. package/scripts/harness/harness-api/domain/value-objects/artifact-scan-result.ts +1 -0
  60. package/scripts/harness/harness-api/domain/value-objects/check-ready-result.ts +1 -0
  61. package/scripts/harness/harness-api/domain/value-objects/ci-check-result.ts +1 -0
  62. package/scripts/harness/harness-api/domain/value-objects/cli-command-definition.ts +1 -0
  63. package/scripts/harness/harness-api/domain/value-objects/command-input-spec.ts +1 -0
  64. package/scripts/harness/harness-api/domain/value-objects/drift-report-summary.ts +1 -0
  65. package/scripts/harness/harness-api/domain/value-objects/exit-code-spec.ts +1 -0
  66. package/scripts/harness/harness-api/domain/value-objects/harness-api-response.ts +1 -0
  67. package/scripts/harness/harness-api/domain/value-objects/harness-status-summary.ts +1 -0
  68. package/scripts/harness/harness-api/domain/value-objects/layer-health.ts +1 -0
  69. package/scripts/harness/harness-api/domain/value-objects/phase-info.ts +1 -0
  70. package/scripts/harness/harness-api/index.ts +1 -0
  71. package/scripts/harness/harness-api/infrastructure/adapters/biome-ast-engine-lint-adapter.ts +1 -0
  72. package/scripts/harness/harness-api/infrastructure/adapters/file-system-artifact-scanner-adapter.ts +1 -0
  73. package/scripts/harness/harness-api/infrastructure/adapters/harness-config-query-adapter.ts +1 -0
  74. package/scripts/harness/harness-api/infrastructure/adapters/nyquist-validation-impact-analysis-adapter.ts +1 -0
  75. package/scripts/harness/harness-api/infrastructure/adapters/phase-dependency-model-query-adapter.ts +1 -0
  76. package/scripts/harness/harness-api/infrastructure/adapters/validator-system-execution-adapter.ts +1 -0
  77. package/scripts/harness/harness-api/presentation/dto/cli-output-options.ts +1 -0
  78. package/scripts/harness/harness-api/presentation/formatters/harness-api-json-formatter.ts +1 -0
  79. package/scripts/harness/harness-api/presentation/handlers/check-phase-handler.ts +1 -0
  80. package/scripts/harness/harness-api/presentation/handlers/check-ready-handler.ts +1 -0
  81. package/scripts/harness/harness-api/presentation/handlers/ci-check-handler.ts +1 -0
  82. package/scripts/harness/harness-api/presentation/handlers/complete-check-handler.ts +1 -0
  83. package/scripts/harness/harness-api/presentation/handlers/detect-drift-handler.ts +1 -0
  84. package/scripts/harness/harness-api/presentation/handlers/impact-analysis-handler.ts +1 -0
  85. package/scripts/harness/harness-api/presentation/handlers/lint-handler.ts +1 -0
  86. package/scripts/harness/harness-api/presentation/handlers/status-handler.ts +1 -0
  87. package/scripts/harness/harness-error/infrastructure/adapters/legacy-error-reporter-adapter.ts +7 -1
  88. package/scripts/harness/integrations/pre-commit.ts +1 -0
  89. package/scripts/harness/main.ts +154 -34
  90. package/scripts/harness/phase-dependency-model/application/dto/resolve-gate-result-dto.ts +14 -0
  91. package/scripts/harness/phase-dependency-model/application/services/phase-gate-result-mapper.ts +20 -0
  92. package/scripts/harness/phase-dependency-model/application/usecases/check-story-reflection-usecase.ts +42 -0
  93. package/scripts/harness/phase-dependency-model/application/usecases/resolve-gate-usecase.ts +161 -0
  94. package/scripts/harness/phase-dependency-model/composition-root.ts +57 -1
  95. package/scripts/harness/phase-dependency-model/domain/definitions/{default-phase-dependencies.ts → full-phase-dependencies.ts} +3 -3
  96. package/scripts/harness/phase-dependency-model/domain/definitions/{default-phase-nodes.ts → full-phase-nodes.ts} +1 -1
  97. package/scripts/harness/phase-dependency-model/domain/definitions/full-story-reflection-defaults.ts +28 -0
  98. package/scripts/harness/phase-dependency-model/domain/definitions/minimal-phase-dependencies.ts +32 -0
  99. package/scripts/harness/phase-dependency-model/domain/definitions/minimal-phase-nodes.ts +50 -0
  100. package/scripts/harness/phase-dependency-model/domain/definitions/minimal-story-reflection-defaults.ts +8 -0
  101. package/scripts/harness/phase-dependency-model/domain/definitions/standard-phase-dependencies.ts +39 -0
  102. package/scripts/harness/phase-dependency-model/domain/definitions/standard-phase-nodes.ts +118 -0
  103. package/scripts/harness/phase-dependency-model/domain/definitions/standard-story-reflection-defaults.ts +23 -0
  104. package/scripts/harness/phase-dependency-model/domain/models/phase-structure.ts +95 -23
  105. package/scripts/harness/phase-dependency-model/domain/ports/glob-matcher-port.ts +8 -0
  106. package/scripts/harness/phase-dependency-model/domain/ports/phase-config-provider-port.ts +2 -0
  107. package/scripts/harness/phase-dependency-model/domain/ports/story-annotation-verifier-port.ts +14 -0
  108. package/scripts/harness/phase-dependency-model/domain/ports/story-reflection-file-system-port.ts +16 -0
  109. package/scripts/harness/phase-dependency-model/domain/services/gate-graph.ts +223 -0
  110. package/scripts/harness/phase-dependency-model/domain/services/story-reflection-checker.ts +66 -0
  111. package/scripts/harness/phase-dependency-model/domain/values/gate-definition.ts +127 -0
  112. package/scripts/harness/phase-dependency-model/domain/values/gate-name.ts +40 -0
  113. package/scripts/harness/phase-dependency-model/domain/values/gate-story-annotation.ts +39 -0
  114. package/scripts/harness/phase-dependency-model/domain/values/phase-customization-policy.ts +16 -4
  115. package/scripts/harness/phase-dependency-model/domain/values/story-reflection-config.ts +44 -0
  116. package/scripts/harness/phase-dependency-model/domain/values/story-reflection-mapping.ts +91 -0
  117. package/scripts/harness/phase-dependency-model/domain/values/story-reflection-result.ts +55 -0
  118. package/scripts/harness/phase-dependency-model/infrastructure/adapters/picomatch-glob-matcher.ts +17 -0
  119. package/scripts/harness/phase-dependency-model/infrastructure/adapters/story-annotation-verifier-adapter.ts +46 -0
  120. package/scripts/harness/phase-dependency-model/infrastructure/config/custom-gates-config-parser.ts +22 -0
  121. package/scripts/harness/phase-dependency-model/infrastructure/config/harness-config-phase-config-provider.ts +78 -2
  122. package/scripts/harness/phase-dependency-model/infrastructure/filesystem/file-system-story-reflection-adapter.ts +94 -0
  123. package/scripts/harness/phase-dependency-model/presentation/cli/check-phase-gate-command-handler.ts +12 -4
  124. package/scripts/harness/phase-dependency-model/presentation/cli/story-reflection-status-presenter.ts +87 -0
  125. package/scripts/harness/regression-suite/application/dto/analyze-migration-input.ts +1 -0
  126. package/scripts/harness/regression-suite/application/dto/analyze-migration-output.ts +1 -0
  127. package/scripts/harness/regression-suite/application/dto/configure-ci-gate-input.ts +1 -0
  128. package/scripts/harness/regression-suite/application/dto/configure-ci-gate-output.ts +1 -0
  129. package/scripts/harness/regression-suite/application/dto/migrate-v0-tests-input.ts +1 -0
  130. package/scripts/harness/regression-suite/application/dto/migrate-v0-tests-output.ts +1 -0
  131. package/scripts/harness/regression-suite/application/dto/run-regression-suite-input.ts +1 -0
  132. package/scripts/harness/regression-suite/application/dto/run-regression-suite-output.ts +1 -0
  133. package/scripts/harness/regression-suite/application/mappers/migration-mapping-mapper.ts +1 -0
  134. package/scripts/harness/regression-suite/application/mappers/test-execution-summary-mapper.ts +1 -0
  135. package/scripts/harness/regression-suite/application/usecases/analyze-v0-migration-usecase.ts +1 -0
  136. package/scripts/harness/regression-suite/application/usecases/configure-ci-gate-usecase.ts +1 -0
  137. package/scripts/harness/regression-suite/application/usecases/migrate-v0-tests-usecase.ts +1 -0
  138. package/scripts/harness/regression-suite/application/usecases/run-agent-independence-guard-usecase.ts +1 -0
  139. package/scripts/harness/regression-suite/application/usecases/run-gng-gate-regression-usecase.ts +1 -0
  140. package/scripts/harness/regression-suite/application/usecases/run-k-requirements-regression-usecase.ts +1 -0
  141. package/scripts/harness/regression-suite/application/usecases/run-k14-k15-regression-usecase.ts +1 -0
  142. package/scripts/harness/regression-suite/composition-root.ts +1 -0
  143. package/scripts/harness/regression-suite/domain/aggregates/v0-test-migration.ts +1 -0
  144. package/scripts/harness/regression-suite/domain/ports/ci-gate-result-writer-port.ts +1 -0
  145. package/scripts/harness/regression-suite/domain/ports/config-query-port.ts +1 -0
  146. package/scripts/harness/regression-suite/domain/ports/import-analyzer-port.ts +1 -0
  147. package/scripts/harness/regression-suite/domain/ports/migration-mapping-repository-port.ts +1 -0
  148. package/scripts/harness/regression-suite/domain/ports/suite-registry-port.ts +1 -0
  149. package/scripts/harness/regression-suite/domain/ports/test-runner-port.ts +1 -0
  150. package/scripts/harness/regression-suite/domain/ports/v0-spec-reader-port.ts +1 -0
  151. package/scripts/harness/regression-suite/domain/services/import-guard-service.ts +1 -0
  152. package/scripts/harness/regression-suite/domain/services/migration-analyzer.ts +1 -0
  153. package/scripts/harness/regression-suite/domain/services/regression-runner.ts +1 -0
  154. package/scripts/harness/regression-suite/domain/value-objects/agent-independence-test.ts +1 -0
  155. package/scripts/harness/regression-suite/domain/value-objects/biome-modification-spec.ts +1 -0
  156. package/scripts/harness/regression-suite/domain/value-objects/ci-gate-config.ts +1 -0
  157. package/scripts/harness/regression-suite/domain/value-objects/coverage-rate.ts +1 -0
  158. package/scripts/harness/regression-suite/domain/value-objects/gng-condition-test.ts +1 -0
  159. package/scripts/harness/regression-suite/domain/value-objects/import-violation.ts +1 -0
  160. package/scripts/harness/regression-suite/domain/value-objects/k-requirement-test.ts +1 -0
  161. package/scripts/harness/regression-suite/domain/value-objects/migration-mapping.ts +1 -0
  162. package/scripts/harness/regression-suite/domain/value-objects/regression-suite-definition.ts +1 -0
  163. package/scripts/harness/regression-suite/domain/value-objects/suite-id.ts +1 -0
  164. package/scripts/harness/regression-suite/domain/value-objects/test-execution-summary.ts +1 -0
  165. package/scripts/harness/regression-suite/domain/value-objects/test-failure-detail.ts +1 -0
  166. package/scripts/harness/regression-suite/domain/value-objects/v0-test-id.ts +1 -0
  167. package/scripts/harness/regression-suite/domain/value-objects/v1-test-path.ts +1 -0
  168. package/scripts/harness/regression-suite/infrastructure/adapters/biome-ast-import-analyzer-adapter.ts +1 -0
  169. package/scripts/harness/regression-suite/infrastructure/adapters/file-system-v0-spec-reader-adapter.ts +1 -0
  170. package/scripts/harness/regression-suite/infrastructure/adapters/harness-config-query-adapter.ts +1 -0
  171. package/scripts/harness/regression-suite/infrastructure/adapters/json-ci-gate-result-writer-adapter.ts +1 -0
  172. package/scripts/harness/regression-suite/infrastructure/adapters/markdown-migration-mapping-repository-adapter.ts +1 -0
  173. package/scripts/harness/regression-suite/infrastructure/adapters/static-suite-registry-adapter.ts +1 -0
  174. package/scripts/harness/regression-suite/infrastructure/adapters/vitest-test-runner-adapter.ts +1 -0
  175. package/scripts/harness/regression-suite/infrastructure/registry/agent-independence-suite-definition.ts +1 -0
  176. package/scripts/harness/regression-suite/infrastructure/registry/gng-gate-suite-definition.ts +1 -0
  177. package/scripts/harness/regression-suite/infrastructure/registry/k-requirements-suite-definition.ts +1 -0
  178. package/scripts/harness/regression-suite/infrastructure/registry/v0-migration-suite-definition.ts +1 -0
  179. package/scripts/harness/setup/skill-deployer.ts +82 -5
  180. package/scripts/harness/shared-kernel/harness-api.ts +1 -0
  181. package/scripts/harness/skill-quality/composition-root.ts +1 -0
  182. package/scripts/harness/skill-quality/infrastructure/adapters/ajv-lesson-artifact-schema-adapter.ts +5 -4
  183. package/scripts/harness/traceability-model/domain/services/metadata-validator.ts +12 -10
  184. package/scripts/harness/traceability-model/infrastructure/parsers/source-metadata-parser.ts +16 -2
  185. package/skills/cascade-updater/SKILL.md +16 -3
  186. package/skills/codebase-mapper/SKILL.md +9 -9
  187. package/skills/codex-delegator/SKILL.md +5 -56
  188. package/skills/consistency-checker/SKILL.md +5 -9
  189. package/skills/consistency-checker/references//343/203/201/343/202/247/343/203/203/343/202/257/343/203/252/343/202/271/343/203/210.md +6 -3
  190. package/skills/doc-freshness-checker/SKILL.md +6 -6
  191. package/skills/engineering-perspective/SKILL.md +2 -58
  192. package/skills/engineering-perspective/references/domain-model.md +4 -135
  193. package/skills/implementation-readiness-checker/SKILL.md +18 -72
  194. package/skills/it-test-designer/SKILL.md +25 -161
  195. package/skills/it-test-designer/references/it-test-design-template.md +131 -0
  196. package/skills/it-test-logic-designer/SKILL.md +13 -388
  197. package/skills/it-test-logic-designer/references/controller-test-patterns.md +100 -0
  198. package/skills/it-test-logic-designer/references/repository-test-patterns.md +206 -0
  199. package/skills/it-test-logic-designer/references/usecase-test-patterns.md +87 -0
  200. package/skills/pointer-validator/SKILL.md +4 -4
  201. package/skills/scenario-test-designer/SKILL.md +4 -68
  202. package/skills/scenario-test-designer/references/scenario-test-design-template.md +41 -0
  203. package/skills/scenario-test-designer/references/scenario-test-plan-template.md +35 -0
  204. package/skills/scenario-test-logic-designer/SKILL.md +21 -304
  205. package/skills/scenario-test-logic-designer/references/msw-patterns.md +36 -0
  206. package/skills/scenario-test-logic-designer/references/playwright-patterns.md +237 -0
  207. package/skills/test-coverage-checker/SKILL.md +39 -121
  208. package/skills/test-coverage-checker/references/coverage-report-template.md +99 -0
  209. package/skills/uiux-designer/SKILL.md +27 -92
  210. package/skills/uiux-designer/references/data-testid-convention.md +38 -0
  211. package/skills/uiux-designer/references/uiux-design-template.md +105 -0
  212. package/skills/unit-test-designer/SKILL.md +5 -106
  213. package/skills/unit-test-designer/references/unit-test-design-template.md +127 -0
  214. package/skills/unit-test-logic-designer/SKILL.md +28 -250
  215. package/skills/unit-test-logic-designer/references/test-patterns.md +207 -0
@@ -27,9 +27,14 @@ This file is the **Single Source of Truth** for all quality configuration in a P
27
27
  "relaxedGates": ["phase-gate", "2-phase-execution"]
28
28
  },
29
29
  "phaseDependencies": {
30
- "preset": "default", // "default" | "custom"
30
+ "preset": "standard", // "full" | "standard" | "minimal" | "custom" ("default" -> "full")
31
31
  "override": false,
32
- "customRules": []
32
+ "customRules": [],
33
+ "gates": [], // Optional. Custom phase gates (preset: "custom"). See gates[] reference below.
34
+ "storyReflection": { // Optional. Defaults per preset when omitted.
35
+ "enabled": true,
36
+ "mappings": [] // Omit to use the preset's built-in mappings.
37
+ }
33
38
  },
34
39
  "planningMode": {
35
40
  "default": "interactive", // "interactive" | "embedded-qa"
@@ -108,11 +113,243 @@ The five layers are:
108
113
 
109
114
  #### `phaseDependencies`
110
115
 
111
- | Sub-field | Type | Default | Description |
112
- |---------------|------------|-------------|--------------------------------------------------------------------|
113
- | `preset` | `string` | `"default"` | `"default"` uses the built-in AIDLC phase dependency graph. `"custom"` enables `customRules`. |
114
- | `override` | `boolean` | `false` | When `true`, custom rules fully replace the default graph instead of extending it. |
115
- | `customRules` | `array` | `[]` | Array of custom phase dependency rules. Only used when `preset` is `"custom"`. |
116
+ | Sub-field | Type | Default | Description |
117
+ |--------------------|------------|--------------|--------------------------------------------------------------------|
118
+ | `preset` | `string` | `"standard"` | One of `"full"`, `"standard"`, `"minimal"`, `"custom"`. `"default"` is accepted for backward compatibility and falls back to `"full"`. |
119
+ | `override` | `boolean` | `false` | When `true`, custom rules fully replace the default graph instead of extending it. Required when `preset` is `"custom"`. |
120
+ | `customRules` | `array` | `[]` | Array of custom phase dependency rules. Only used when `preset` is `"custom"`. |
121
+ | `gates` | `array` | `[]` | Array of custom phase gate definitions. See [gates\[\]](#gates-custom-phase-gates) below. Optional; defaults to empty. |
122
+ | `storyReflection` | `object` | preset-based | See [storyReflection](#storyreflection-inception--product-gate) below. Omit entirely for zero-config defaults per preset. |
123
+
124
+ ##### Phase Dependency Presets
125
+
126
+ | Preset | Phase 3 Gates | storyReflection default | Use Case |
127
+ |------------|---------------|-------------------------------------------------------------------------|----------------------------------------------------|
128
+ | `full` | All gates | **Enabled** -- `logical_design.md` + `domain_model.md` required, `uiux_design.md` optional | AIDLC full ceremony; mission-critical systems |
129
+ | `standard` | Core gates | **Enabled** -- `logical_design.md` required, `domain_model.md` optional | Production development with moderate rigor |
130
+ | `minimal` | None | **Disabled** | Prototyping / exploration (trade-off: no reflection enforcement) |
131
+ | `custom` | User-defined | User-defined (zero or explicit `mappings`) | Full control via `customRules` and `storyReflection.mappings` |
132
+
133
+ > `"default"` is accepted as an alias for `"full"` so existing `phasegate.config.json` files keep working after the upgrade.
134
+
135
+ #### `gates[]` (custom phase gates)
136
+
137
+ `gates[]` lets a project declare **additional phase gates** that fire when a write targets specific file globs. Each gate is checked at the pre-tool-use hook (and via `check-phase-gate` CLI) and blocks the write if its preconditions are not met.
138
+
139
+ `gates[]` is typically combined with `preset: "custom"` and `override: true` when the project wants full control over the phase dependency graph. It is also valid to layer a small number of gates on top of `preset: "custom"` without replacing the full graph.
140
+
141
+ **Validation is fail-fast**: a malformed `gates[]` entry (e.g. `level: 99`, unknown dependency) causes `loadResolvedConfig()` to exit with code `2` and prints `Invalid phasegate.config.json: ...` to stderr. The same error surfaces as a `blocker` in the hook path.
142
+
143
+ ##### Gate definition schema
144
+
145
+ Each entry in `gates[]` is an object with:
146
+
147
+ | Field | Type | Required | Description |
148
+ |-------------------|------------|----------|-------------------------------------------------------------------------------------------------------------------|
149
+ | `name` | `string` | yes | Unique gate identifier. Must match `^[a-z][a-z0-9-]*$`. |
150
+ | `level` | `integer` | yes | Phase level this gate belongs to. One of `1`, `2`, `3`. |
151
+ | `requires` | `object[]` | yes | Required artifacts. Each entry is `{ "path": "<glob or path>", "required": <boolean> }`. |
152
+ | `blocks` | `string[]` | yes | Glob patterns of files the gate guards. A write targeting any matching file triggers this gate. |
153
+ | `dependsOn` | `string[]` | yes | Names of other gates that must pass first. Forms a DAG; cycles are rejected at load time. |
154
+ | `storyAnnotation` | `object` | no | `{ "required": <boolean>, "tag": "<tag-name>" }`. When `required: true`, matched files must contain the tag (e.g. `@story-id H01-01`). Only valid when `level: 3`. |
155
+
156
+ **Rules:**
157
+
158
+ - `name` must be unique across the whole `gates[]` array.
159
+ - `level` is restricted to `1`, `2`, or `3`. `level: 99` or similar is a schema violation.
160
+ - `dependsOn` must reference existing gate names and must not form a cycle.
161
+ - `storyAnnotation` may only appear on `level: 3` gates (schema-enforced).
162
+ - `blocks` uses picomatch glob syntax (e.g. `"src/**/*.ts"`, `"scripts/harness/order/**"`).
163
+
164
+ ##### Example 1 — single level-3 story gate
165
+
166
+ Enforce that any write under `scripts/harness/order/**` carries an `@story-id` annotation:
167
+
168
+ ```jsonc
169
+ {
170
+ "phaseDependencies": {
171
+ "preset": "custom",
172
+ "override": true,
173
+ "customRules": [],
174
+ "gates": [
175
+ {
176
+ "name": "order-story-impl",
177
+ "level": 3,
178
+ "requires": [
179
+ { "path": "docs/product/user_stories.md", "required": true }
180
+ ],
181
+ "blocks": ["scripts/harness/order/**/*.ts"],
182
+ "dependsOn": [],
183
+ "storyAnnotation": { "required": true, "tag": "@story-id" }
184
+ }
185
+ ]
186
+ }
187
+ }
188
+ ```
189
+
190
+ ##### Example 2 — diamond DAG with multiple chains
191
+
192
+ Two level-1 gates feed into a level-2 aggregate, which gates a level-3 implementation:
193
+
194
+ ```jsonc
195
+ {
196
+ "phaseDependencies": {
197
+ "preset": "custom",
198
+ "override": true,
199
+ "customRules": [],
200
+ "gates": [
201
+ {
202
+ "name": "logical-design",
203
+ "level": 1,
204
+ "requires": [
205
+ { "path": "docs/product/construction/{unit}/logical_design.md", "required": true }
206
+ ],
207
+ "blocks": [],
208
+ "dependsOn": []
209
+ },
210
+ {
211
+ "name": "domain-model",
212
+ "level": 1,
213
+ "requires": [
214
+ { "path": "docs/product/construction/{unit}/domain_model.md", "required": true }
215
+ ],
216
+ "blocks": [],
217
+ "dependsOn": []
218
+ },
219
+ {
220
+ "name": "tdd-plan",
221
+ "level": 2,
222
+ "requires": [
223
+ { "path": "docs/inception/{unit}/{storyId}/tdd_implementation_plan.md", "required": true }
224
+ ],
225
+ "blocks": [],
226
+ "dependsOn": ["logical-design", "domain-model"]
227
+ },
228
+ {
229
+ "name": "story-impl",
230
+ "level": 3,
231
+ "requires": [],
232
+ "blocks": ["scripts/harness/**/*.ts"],
233
+ "dependsOn": ["tdd-plan"],
234
+ "storyAnnotation": { "required": true, "tag": "@story-id" }
235
+ }
236
+ ]
237
+ }
238
+ }
239
+ ```
240
+
241
+ ##### Example 3 — minimal level-1 gate (no storyAnnotation)
242
+
243
+ Block commits that touch a protected path unless a design artifact exists — no story-id enforcement:
244
+
245
+ ```jsonc
246
+ {
247
+ "phaseDependencies": {
248
+ "preset": "custom",
249
+ "override": true,
250
+ "customRules": [],
251
+ "gates": [
252
+ {
253
+ "name": "schema-guard",
254
+ "level": 1,
255
+ "requires": [
256
+ { "path": "docs/schema/migration-notes.md", "required": true }
257
+ ],
258
+ "blocks": ["db/migrations/**/*.sql"],
259
+ "dependsOn": []
260
+ }
261
+ ]
262
+ }
263
+ }
264
+ ```
265
+
266
+ #### `storyReflection` (inception -> product gate)
267
+
268
+ `storyReflection` enforces that every US / issue under `docs/inception/{unit}/{storyId}/` has been **cascaded into the accumulating product design documents** (`docs/product/construction/{unit}/`) before source code under `src/{unit}/` or `scripts/harness/{unit}/` can be written or edited.
269
+
270
+ The check fires at the pre-tool-use hook and blocks `Write`/`Edit` (and their Bash equivalents such as `cat > file`, `tee`, heredoc, `sed -i`, `cp`, `mv`, `touch`) whenever an inception design exists but its `@story-id` is not reflected in the corresponding product file.
271
+
272
+ **Zero-config**: omitting the `storyReflection` block, or specifying it without `mappings`, applies the preset's built-in mappings automatically.
273
+
274
+ | Sub-field | Type | Default | Description |
275
+ |-------------|------------|-------------------------|------------------------------------------------------------------------------|
276
+ | `enabled` | `boolean` | preset-dependent | Master switch. `full` / `standard` default to `true`; `minimal` defaults to `false`. |
277
+ | `mappings` | `array` | preset-dependent | Array of inception -> product file mappings. Omit to use the preset default. |
278
+
279
+ Each mapping entry:
280
+
281
+ | Field | Type | Description |
282
+ |-------------|-----------|-----------------------------------------------------------------------------|
283
+ | `inception` | `string` | Template path, e.g. `"docs/inception/{unit}/{storyId}/logical_design.md"`. |
284
+ | `product` | `string` | Template path, e.g. `"docs/product/construction/{unit}/logical_design.md"`.|
285
+ | `required` | `boolean` | When `true`, missing reflection blocks the write. When `false`, it is tolerated (optional mapping). |
286
+
287
+ ##### Preset defaults (hard-coded)
288
+
289
+ **`full`** -- AIDLC recommended (product-accumulated design documents only; test designs are out of scope because they live per-US inside `inception/`):
290
+
291
+ ```jsonc
292
+ [
293
+ { "inception": "docs/inception/{unit}/{storyId}/logical_design.md",
294
+ "product": "docs/product/construction/{unit}/logical_design.md",
295
+ "required": true },
296
+ { "inception": "docs/inception/{unit}/{storyId}/domain_model.md",
297
+ "product": "docs/product/construction/{unit}/domain_model.md",
298
+ "required": true },
299
+ { "inception": "docs/inception/{unit}/{storyId}/uiux_design.md",
300
+ "product": "docs/product/construction/{unit}/uiux_design.md",
301
+ "required": false }
302
+ ]
303
+ ```
304
+
305
+ **`standard`**:
306
+
307
+ ```jsonc
308
+ [
309
+ { "inception": "docs/inception/{unit}/{storyId}/logical_design.md",
310
+ "product": "docs/product/construction/{unit}/logical_design.md",
311
+ "required": true },
312
+ { "inception": "docs/inception/{unit}/{storyId}/domain_model.md",
313
+ "product": "docs/product/construction/{unit}/domain_model.md",
314
+ "required": false }
315
+ ]
316
+ ```
317
+
318
+ **`minimal`**: `enabled: false`. No storyReflection checking.
319
+
320
+ ##### Custom mappings example
321
+
322
+ Override the preset defaults only when your project needs a different policy:
323
+
324
+ ```jsonc
325
+ {
326
+ "phaseDependencies": {
327
+ "preset": "standard",
328
+ "storyReflection": {
329
+ "enabled": true,
330
+ "mappings": [
331
+ { "inception": "docs/inception/{unit}/{storyId}/logical_design.md",
332
+ "product": "docs/product/construction/{unit}/logical_design.md",
333
+ "required": true }
334
+ ]
335
+ }
336
+ }
337
+ }
338
+ ```
339
+
340
+ ##### How the check fires
341
+
342
+ 1. `Write` / `Edit` (or a Bash write such as `cat > src/order/foo.ts`) targets a source file under a Unit.
343
+ 2. `WriteTargetScope` resolves the `@unit` annotation (comma-separated and multi-line `@unit` are both supported; **all** listed units are checked).
344
+ 3. For each unit, every `storyId` directory under `docs/inception/{unit}/` is enumerated.
345
+ 4. For each required mapping, the pre-tool-use hook checks that the target product document contains `@story-id {storyId}`.
346
+ 5. Any missing reflection produces a `STORY_REFLECTION` block reason with a fix hint that points to the `cascade-updater` skill and [ADR-013](../ADR/ADR-013-story-reflection-gate.md).
347
+
348
+ ##### Passing the gate
349
+
350
+ `cascade-updater` is the **standard means of passing the storyReflection gate**: run it to propagate the new US / issue design into the accumulating product documents. Manual editing of the product file with an appended `@story-id` tag is also accepted.
351
+
352
+ Quick Mode with `relaxedGates: ["phase-gate"]` relaxes `storyReflection` as well (see [Quick Mode](#quick-mode)). L1 and L2 `metadata` / `test-quality` checks remain fully enforced.
116
353
 
117
354
  #### `planningMode`
118
355
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "phasegate",
3
- "version": "0.16.0",
3
+ "version": "0.32.0",
4
4
  "packageManager": "pnpm@10.30.1",
5
5
  "description": "Phasegate — AI-agnostic quality defense toolkit. Enforces structural integrity between design intent and code.",
6
6
  "license": "Apache-2.0",
@@ -44,19 +44,21 @@
44
44
  },
45
45
  "scripts": {
46
46
  "phasegate": "npx tsx scripts/harness/main.ts",
47
- "phasegate:status": "npx tsx scripts/harness/main.ts harness:status",
47
+ "phasegate:status": "npx tsx scripts/harness/main.ts phasegate:status",
48
48
  "phasegate:enable": "npx tsx scripts/harness/main.ts enable-feature",
49
49
  "phasegate:disable": "npx tsx scripts/harness/main.ts disable-feature",
50
- "phasegate:check-phase": "npx tsx scripts/harness/main.ts harness:check-phase",
51
- "phasegate:check-ready": "npx tsx scripts/harness/main.ts harness:check-ready",
52
- "test": "vitest run --config scripts/harness/__tests__/vitest.config.ts"
50
+ "phasegate:check-phase": "npx tsx scripts/harness/main.ts phasegate:check-phase",
51
+ "phasegate:check-ready": "npx tsx scripts/harness/main.ts phasegate:check-ready",
52
+ "test": "vitest run --config scripts/harness/__tests__/vitest.config.forks.ts && vitest run --config scripts/harness/__tests__/vitest.config.ts"
53
53
  },
54
54
  "dependencies": {
55
55
  "ajv": "^8.18.0",
56
+ "picomatch": "^4.0.4",
56
57
  "tsx": "^4.0.0"
57
58
  },
58
59
  "devDependencies": {
59
60
  "@biomejs/biome": "^2.4.7",
61
+ "@types/picomatch": "^4.0.0",
60
62
  "@types/node": "^25.3.5",
61
63
  "typescript": "^5.0.0",
62
64
  "vitest": "^3.0.0"
@@ -1,3 +1,4 @@
1
+ // @layer domain
1
2
  import type { ADR } from '../aggregates/adr.js';
2
3
  import type { AdrBody } from '../value-objects/adr-body.js';
3
4
  import type { AdrFrontmatter } from '../value-objects/adr-frontmatter.js';
@@ -1,3 +1,4 @@
1
+ // @layer domain
1
2
  import type { AdrFrontmatter } from '../value-objects/adr-frontmatter.js';
2
3
 
3
4
  export interface AdrFrontmatterParserPort {
@@ -1,3 +1,4 @@
1
+ // @layer domain
1
2
  import type { ADR } from '../aggregates/adr.js';
2
3
  import type { AdrId } from '../value-objects/adr-id.js';
3
4
  import type { AdrStatus } from '../value-objects/adr-status.js';
@@ -5,11 +5,11 @@
5
5
  const ALLOWED_STATUSES = ['Proposed', 'Accepted', 'Deprecated', 'Superseded'] as const;
6
6
  type AdrStatusValue = (typeof ALLOWED_STATUSES)[number];
7
7
 
8
- const TRANSITIONS: Readonly<Record<AdrStatusValue, readonly AdrStatusValue[]>> = Object.freeze({
9
- Proposed: Object.freeze(['Accepted', 'Deprecated']),
10
- Accepted: Object.freeze(['Deprecated', 'Superseded']),
11
- Deprecated: Object.freeze(['Proposed']),
12
- Superseded: Object.freeze([]),
8
+ const TRANSITIONS = Object.freeze({
9
+ Proposed: Object.freeze(['Accepted', 'Deprecated'] as const),
10
+ Accepted: Object.freeze(['Deprecated', 'Superseded'] as const),
11
+ Deprecated: Object.freeze(['Proposed'] as const),
12
+ Superseded: Object.freeze([] as const),
13
13
  });
14
14
 
15
15
  export class InvalidAdrStatusError extends Error {
@@ -52,7 +52,7 @@ export class AdrStatus {
52
52
  }
53
53
 
54
54
  canTransitionTo(target: AdrStatus): boolean {
55
- return TRANSITIONS[this.value].includes(target.value);
55
+ return (TRANSITIONS[this.value] as readonly string[]).includes(target.value);
56
56
  }
57
57
 
58
58
  equals(other: AdrStatus): boolean {
@@ -11,8 +11,10 @@ export interface HandlePreToolUseInput {
11
11
  export interface HandlePreToolUseOutput {
12
12
  shouldBlock: boolean;
13
13
  blockedFilePath?: string;
14
- blockReason?: 'PROTECTED_FILE' | 'PHASE_GATE';
14
+ blockReason?: 'PROTECTED_FILE' | 'PHASE_GATE' | 'STORY_REFLECTION';
15
15
  error?: { message: string };
16
16
  phaseGateBlockers?: string[];
17
+ storyReflectionBlockers?: string[];
18
+ storyReflectionWarnings?: string[];
17
19
  nextAction?: string;
18
20
  }
@@ -9,15 +9,17 @@
9
9
 
10
10
  import { AsyncHookToCliTranslator } from '../../domain/services/hook-to-cli-translator.js';
11
11
  import { HookEvent } from '../../domain/value-objects/hook-event.js';
12
- import { ProtectedFileList } from '../../domain/value-objects/protected-file-list.js';
13
12
  import type { BlockMetadata } from '../../domain/value-objects/hook-translation-result.js';
14
13
  import type { ConfigQueryPort } from '../../domain/ports/config-query-port.js';
15
14
  import type { PhaseGateQueryPort } from '../../domain/ports/phase-gate-query-port.js';
15
+ import type { StoryReflectionQueryPort } from '../../domain/ports/story-reflection-query-port.js';
16
+ import { WriteTargetScope } from '../../domain/value-objects/write-target-scope.js';
16
17
  import type { HandlePreToolUseInput, HandlePreToolUseOutput } from '../dto/handle-pre-tool-use-dto.js';
17
18
 
18
19
  export interface HandlePreToolUseUseCasePorts {
19
20
  configQueryPort: ConfigQueryPort;
20
21
  phaseGateQueryPort: PhaseGateQueryPort;
22
+ storyReflectionQueryPort?: StoryReflectionQueryPort;
21
23
  }
22
24
 
23
25
  export class HandlePreToolUseInputValidationError extends Error {
@@ -29,11 +31,17 @@ export class HandlePreToolUseInputValidationError extends Error {
29
31
  }
30
32
 
31
33
  export class HandlePreToolUseUseCase {
34
+ private static readonly WRITE_TOOLS: ReadonlySet<string> = new Set([
35
+ 'Write', 'Edit', 'NotebookEdit', 'str_replace_editor',
36
+ ]);
37
+
32
38
  private readonly translator: AsyncHookToCliTranslator;
33
39
  private readonly configQueryPort: ConfigQueryPort;
40
+ private readonly storyReflectionQueryPort?: StoryReflectionQueryPort;
34
41
 
35
42
  constructor(ports: HandlePreToolUseUseCasePorts) {
36
43
  this.configQueryPort = ports.configQueryPort;
44
+ this.storyReflectionQueryPort = ports.storyReflectionQueryPort;
37
45
  this.translator = new AsyncHookToCliTranslator({
38
46
  configQueryPort: ports.configQueryPort,
39
47
  reentryGuard: { isActive: () => false } as never,
@@ -71,7 +79,39 @@ export class HandlePreToolUseUseCase {
71
79
  };
72
80
  }
73
81
 
74
- return { shouldBlock: false };
82
+ const scope = this.resolveStoryReflectionScope(input);
83
+ if (scope === null || this.storyReflectionQueryPort === undefined) {
84
+ return { shouldBlock: false };
85
+ }
86
+
87
+ const reflectionResult = await this.storyReflectionQueryPort.checkReflection(scope.unitId!);
88
+
89
+ if (reflectionResult.skipped || reflectionResult.passed) {
90
+ return { shouldBlock: false };
91
+ }
92
+
93
+ return HandlePreToolUseUseCase.buildStoryReflectionBlockOutput(
94
+ input.targetFilePaths[0],
95
+ reflectionResult.blockers,
96
+ reflectionResult.warnings,
97
+ );
98
+ }
99
+
100
+ private resolveStoryReflectionScope(input: HandlePreToolUseInput): WriteTargetScope | null {
101
+ if (!HandlePreToolUseUseCase.WRITE_TOOLS.has(input.toolName)) {
102
+ return null;
103
+ }
104
+
105
+ const projectPaths = this.configQueryPort.getProjectPaths();
106
+
107
+ for (const targetFilePath of input.targetFilePaths) {
108
+ const scope = WriteTargetScope.fromPath(targetFilePath, projectPaths);
109
+ if (scope?.level === 3 && scope.unitId !== undefined) {
110
+ return scope;
111
+ }
112
+ }
113
+
114
+ return null;
75
115
  }
76
116
 
77
117
  private static readonly LEVEL_LABELS: Record<number, string> = {
@@ -161,4 +201,70 @@ export class HandlePreToolUseUseCase {
161
201
  error: { message },
162
202
  };
163
203
  }
204
+
205
+ private static buildStoryReflectionBlockOutput(
206
+ blockedFilePath: string | undefined,
207
+ blockers: readonly string[],
208
+ warnings: readonly string[],
209
+ ): HandlePreToolUseOutput {
210
+ return {
211
+ shouldBlock: true,
212
+ blockedFilePath,
213
+ blockReason: 'STORY_REFLECTION',
214
+ error: {
215
+ message: HandlePreToolUseUseCase.buildStoryReflectionErrorMessage(blockers),
216
+ },
217
+ storyReflectionBlockers: [...blockers],
218
+ storyReflectionWarnings: [...warnings],
219
+ };
220
+ }
221
+
222
+ private static buildStoryReflectionErrorMessage(blockers: readonly string[]): string {
223
+ const firstBlocker = blockers[0];
224
+ const details = firstBlocker === undefined
225
+ ? null
226
+ : HandlePreToolUseUseCase.extractStoryReflectionDetails(firstBlocker);
227
+ const lines: string[] = [];
228
+
229
+ if (details !== null) {
230
+ lines.push(`[L2-STORY-REFLECTION] ${details.productPath} に`);
231
+ lines.push(`@story-id ${details.storyId} が反映されていません。`);
232
+ lines.push('');
233
+ } else {
234
+ lines.push('[L2-STORY-REFLECTION] product 文書に @story-id が反映されていません。');
235
+ lines.push('');
236
+ }
237
+
238
+ for (const blocker of blockers) {
239
+ lines.push(`- ${blocker}`);
240
+ }
241
+
242
+ lines.push('');
243
+ lines.push('修正方法:');
244
+ lines.push(' 1. cascade-updater を実行して product 文書を更新');
245
+ lines.push(
246
+ ` 2. または手動で該当 product 文書に @story-id ${details?.storyId ?? '<STORY-ID>'} を追加`,
247
+ );
248
+ lines.push('');
249
+ lines.push('参照: ADR-XXX');
250
+
251
+ return lines.join('\n');
252
+ }
253
+
254
+ private static extractStoryReflectionDetails(
255
+ blocker: string,
256
+ ): { productPath: string; storyId: string } | null {
257
+ const productPathMatch = blocker.match(/docs\/product\/construction\/[^\s]+\.md/);
258
+ const storyIdMatch = blocker.match(/@story-id\s+([A-Z][\w-]*-\d+)|\b([A-Z][\w-]*-\d+)\b/);
259
+ const storyId = storyIdMatch?.[1] ?? storyIdMatch?.[2];
260
+
261
+ if (productPathMatch === null || storyId === undefined) {
262
+ return null;
263
+ }
264
+
265
+ return {
266
+ productPath: productPathMatch[0],
267
+ storyId,
268
+ };
269
+ }
164
270
  }
@@ -8,5 +8,7 @@ export type HookType = 'pre-tool-use' | 'post-tool-use' | 'stop';
8
8
  export interface ConfigQueryPort {
9
9
  isHookEnabled(hookType: HookType): Promise<boolean>;
10
10
  getProtectedFilePatterns(): Promise<string[]>;
11
+ getProtectedFileExclusions(): Promise<string[]>;
12
+ getRelaxedGates(): Promise<readonly string[]>;
11
13
  getProjectPaths(): ProjectPaths;
12
14
  }
@@ -5,5 +5,5 @@ import type { WriteTargetScope } from '../value-objects/write-target-scope.js';
5
5
  import type { PhaseGateQueryResult } from '../value-objects/phase-gate-query-result.js';
6
6
 
7
7
  export interface PhaseGateQueryPort {
8
- checkGate(scope: WriteTargetScope): Promise<PhaseGateQueryResult>;
8
+ checkGate(scope: WriteTargetScope, targetFilePath?: string): Promise<PhaseGateQueryResult>;
9
9
  }
@@ -0,0 +1,8 @@
1
+ // @unit agent-integration
2
+ // @layer domain
3
+
4
+ import type { StoryReflectionQueryResult } from '../value-objects/story-reflection-query-result.js';
5
+
6
+ export interface StoryReflectionQueryPort {
7
+ checkReflection(unitId: string): Promise<StoryReflectionQueryResult>;
8
+ }