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
@@ -0,0 +1,42 @@
1
+ /**
2
+ * @layer application
3
+ * @unit phase-dependency-model
4
+ *
5
+ * CheckStoryReflectionUseCase
6
+ * StoryReflectionChecker をオーケストレーションし、inception → product への
7
+ * storyId 反映状況を検証するユースケース。
8
+ *
9
+ * 入力: unitId, StoryReflectionConfig
10
+ * 出力: StoryReflectionResult(pass/fail + violations/warnings)
11
+ *
12
+ * enabled=false の場合は即座に pass を返す。
13
+ */
14
+
15
+ import type { StoryReflectionChecker } from '../../domain/services/story-reflection-checker.js';
16
+ import type { StoryReflectionConfig } from '../../domain/values/story-reflection-config.js';
17
+ import { StoryReflectionResult } from '../../domain/values/story-reflection-result.js';
18
+
19
+ export interface CheckStoryReflectionInput {
20
+ readonly unitId: string;
21
+ readonly config: StoryReflectionConfig;
22
+ }
23
+
24
+ export interface CheckStoryReflectionUseCaseDeps {
25
+ readonly checker: StoryReflectionChecker;
26
+ }
27
+
28
+ export class CheckStoryReflectionUseCase {
29
+ private readonly checker: StoryReflectionChecker;
30
+
31
+ constructor(deps: CheckStoryReflectionUseCaseDeps) {
32
+ this.checker = deps.checker;
33
+ }
34
+
35
+ async execute(input: CheckStoryReflectionInput): Promise<StoryReflectionResult> {
36
+ if (!input.config.enabled) {
37
+ return StoryReflectionResult.pass();
38
+ }
39
+
40
+ return this.checker.check(input.unitId, input.config);
41
+ }
42
+ }
@@ -0,0 +1,161 @@
1
+ // @unit phase-dependency-model
2
+ // @layer application
3
+
4
+ import type { ResolveGateResultDto, ResolveGateFindingDto } from '../dto/resolve-gate-result-dto.js';
5
+ import { GateGraph } from '../../domain/services/gate-graph.js';
6
+ import type { ArtifactExistenceCheckerPort } from '../../domain/ports/artifact-existence-checker-port.js';
7
+ import type { GlobMatcherPort } from '../../domain/ports/glob-matcher-port.js';
8
+ import type { StoryAnnotationVerifierPort } from '../../domain/ports/story-annotation-verifier-port.js';
9
+ import { Artifact } from '../../domain/values/artifact.js';
10
+ import type { GateDefinition, GateRequirement } from '../../domain/values/gate-definition.js';
11
+
12
+ export interface ResolveGateInput {
13
+ readonly targetFilePath: string;
14
+ readonly gates: readonly GateDefinition[];
15
+ readonly scope?: {
16
+ readonly unitId?: string;
17
+ readonly storyId?: string;
18
+ };
19
+ }
20
+
21
+ export interface ResolveGateUseCaseDeps {
22
+ readonly globMatcher: GlobMatcherPort;
23
+ readonly artifactExistenceChecker: ArtifactExistenceCheckerPort;
24
+ readonly storyAnnotationVerifier?: StoryAnnotationVerifierPort;
25
+ }
26
+
27
+ interface RequirementEvaluation {
28
+ readonly gateName: string;
29
+ readonly requirement: GateRequirement;
30
+ readonly resolvedPath: string;
31
+ }
32
+
33
+ export class ResolveGateUseCase {
34
+ private readonly globMatcher: GlobMatcherPort;
35
+ private readonly artifactExistenceChecker: ArtifactExistenceCheckerPort;
36
+ private readonly storyAnnotationVerifier?: StoryAnnotationVerifierPort;
37
+
38
+ constructor(deps: ResolveGateUseCaseDeps) {
39
+ this.globMatcher = deps.globMatcher;
40
+ this.artifactExistenceChecker = deps.artifactExistenceChecker;
41
+ this.storyAnnotationVerifier = deps.storyAnnotationVerifier;
42
+ }
43
+
44
+ async execute(input: ResolveGateInput): Promise<ResolveGateResultDto> {
45
+ const graph = GateGraph.build([...input.gates]);
46
+ const matchedGates = input.gates.filter((gate) =>
47
+ gate.blocks.some((pattern) => this.globMatcher.match(pattern, input.targetFilePath)),
48
+ );
49
+
50
+ if (matchedGates.length === 0) {
51
+ return Object.freeze({
52
+ matchedGates: Object.freeze([]),
53
+ blockers: Object.freeze([]),
54
+ warnings: Object.freeze([]),
55
+ });
56
+ }
57
+
58
+ const evaluationOrder = new Map<string, GateDefinition>();
59
+ for (const gate of matchedGates) {
60
+ for (const ancestorName of graph.resolveAncestors(gate.name)) {
61
+ const ancestor = graph.gates.get(ancestorName.value);
62
+ if (ancestor && !evaluationOrder.has(ancestor.name.value)) {
63
+ evaluationOrder.set(ancestor.name.value, ancestor);
64
+ }
65
+ }
66
+
67
+ if (!evaluationOrder.has(gate.name.value)) {
68
+ evaluationOrder.set(gate.name.value, gate);
69
+ }
70
+ }
71
+
72
+ const evaluations = [...evaluationOrder.values()].flatMap((gate) =>
73
+ gate.requires.map((requirement) => ({
74
+ gateName: gate.name.value,
75
+ requirement,
76
+ resolvedPath: this.expandPlaceholders(requirement.path, input.scope),
77
+ })),
78
+ );
79
+ const artifacts = evaluations.map((evaluation, index) =>
80
+ Artifact.create({
81
+ name: `${evaluation.gateName}-${index + 1}`,
82
+ path: evaluation.resolvedPath,
83
+ required: evaluation.requirement.required,
84
+ }),
85
+ );
86
+ const statuses = await this.artifactExistenceChecker.checkAll(artifacts, input.scope ?? {});
87
+
88
+ const blockers: ResolveGateFindingDto[] = [];
89
+ const warnings: ResolveGateFindingDto[] = [];
90
+
91
+ for (const evaluation of evaluations) {
92
+ if (statuses.get(evaluation.resolvedPath) === true) {
93
+ continue;
94
+ }
95
+
96
+ const finding = Object.freeze({
97
+ gateName: evaluation.gateName,
98
+ path: evaluation.resolvedPath,
99
+ reason: evaluation.requirement.required
100
+ ? '必須アーティファクトが不足しています'
101
+ : '推奨アーティファクトが不足しています',
102
+ });
103
+
104
+ if (evaluation.requirement.required) {
105
+ blockers.push(finding);
106
+ } else {
107
+ warnings.push(finding);
108
+ }
109
+ }
110
+
111
+ if (this.storyAnnotationVerifier) {
112
+ for (const gate of matchedGates) {
113
+ if (!gate.storyAnnotation) {
114
+ continue;
115
+ }
116
+
117
+ const verification = await this.storyAnnotationVerifier.verify(
118
+ input.targetFilePath,
119
+ gate.storyAnnotation.tag,
120
+ );
121
+
122
+ if (verification.hasAnnotation) {
123
+ continue;
124
+ }
125
+
126
+ const finding = Object.freeze({
127
+ gateName: gate.name.value,
128
+ path: input.targetFilePath,
129
+ reason: gate.storyAnnotation.required
130
+ ? `${gate.storyAnnotation.tag} 注釈が必要です`
131
+ : `${gate.storyAnnotation.tag} 注釈を推奨します`,
132
+ });
133
+
134
+ if (gate.storyAnnotation.required) {
135
+ blockers.push(finding);
136
+ continue;
137
+ }
138
+
139
+ warnings.push(finding);
140
+ }
141
+ }
142
+
143
+ return Object.freeze({
144
+ matchedGates: Object.freeze(matchedGates.map((gate) => gate.name.value)),
145
+ blockers: Object.freeze(blockers),
146
+ warnings: Object.freeze(warnings),
147
+ });
148
+ }
149
+
150
+ private expandPlaceholders(
151
+ path: string,
152
+ scope?: {
153
+ readonly unitId?: string;
154
+ readonly storyId?: string;
155
+ },
156
+ ): string {
157
+ return path
158
+ .replaceAll('{unit}', scope?.unitId ?? '{unit}')
159
+ .replaceAll('{storyId}', scope?.storyId ?? '{storyId}');
160
+ }
161
+ }
@@ -7,13 +7,19 @@
7
7
  */
8
8
  import { FileSystemArtifactExistenceChecker } from './infrastructure/filesystem/file-system-artifact-existence-checker.js';
9
9
  import { MarkdownPlanDocumentReader } from './infrastructure/filesystem/markdown-plan-document-reader.js';
10
+ import { PicomatchGlobMatcher } from './infrastructure/adapters/picomatch-glob-matcher.js';
11
+ import { StoryAnnotationVerifierAdapter } from './infrastructure/adapters/story-annotation-verifier-adapter.js';
12
+ import { CustomGatesConfigParser } from './infrastructure/config/custom-gates-config-parser.js';
13
+ import { MarkdownDesignDocumentGateway } from '../traceability-model/infrastructure/gateways/markdown-design-document-gateway.js';
10
14
  import {
11
15
  HarnessConfigPhaseConfigProvider,
12
16
  type PhaseConfigSection,
13
17
  } from './infrastructure/config/harness-config-phase-config-provider.js';
14
18
  import { PhaseOverrideAuditLogger } from './infrastructure/logging/phase-override-audit-logger.js';
15
19
  import { EvidenceBundleAssembler } from './application/services/evidence-bundle-assembler.js';
20
+ import { PhaseGateResultMapper } from './application/services/phase-gate-result-mapper.js';
16
21
  import { CheckPhaseGateUseCase } from './application/usecases/check-phase-gate-usecase.js';
22
+ import { ResolveGateUseCase } from './application/usecases/resolve-gate-usecase.js';
17
23
  import { CheckPhaseGateCommandHandler } from './presentation/cli/check-phase-gate-command-handler.js';
18
24
 
19
25
  const DEFAULT_REPORT_OUTPUT_DIR = '.harness/reports';
@@ -35,6 +41,16 @@ export function createPhaseDependencyModelModule(
35
41
  ) {
36
42
  const phaseConfig = (config.phaseConfig as PhaseConfigSection | undefined) ?? defaultPhaseConfig;
37
43
  const reportOutputDir = config.reportOutputDir ?? DEFAULT_REPORT_OUTPUT_DIR;
44
+ const rawCustomGates =
45
+ ((config.phaseConfig as {
46
+ readonly gates?: readonly unknown[];
47
+ readonly customization?: { readonly gates?: readonly unknown[]; readonly preset?: string };
48
+ } | undefined)?.gates) ??
49
+ ((config.phaseConfig as {
50
+ readonly customization?: { readonly gates?: readonly unknown[]; readonly preset?: string };
51
+ } | undefined)?.customization?.gates) ??
52
+ [];
53
+ const isCustomPreset = phaseConfig.customization?.preset === 'custom';
38
54
 
39
55
  // Infrastructure
40
56
  const artifactExistenceChecker = new FileSystemArtifactExistenceChecker({
@@ -47,9 +63,17 @@ export function createPhaseDependencyModelModule(
47
63
  config: phaseConfig,
48
64
  defaultOutputDir: reportOutputDir,
49
65
  });
66
+ const designDocumentGateway = new MarkdownDesignDocumentGateway({
67
+ rootDir: config.rootDir,
68
+ });
50
69
  const auditLogger = new PhaseOverrideAuditLogger({
51
70
  outputDir: reportOutputDir,
52
71
  });
72
+ const globMatcher = new PicomatchGlobMatcher();
73
+ const storyAnnotationVerifier = new StoryAnnotationVerifierAdapter({
74
+ designDocumentGateway,
75
+ });
76
+ const customGatesConfigParser = new CustomGatesConfigParser();
53
77
 
54
78
  // Application services
55
79
  const evidenceBundleAssembler = new EvidenceBundleAssembler({
@@ -57,6 +81,7 @@ export function createPhaseDependencyModelModule(
57
81
  planDocumentReader,
58
82
  phaseConfigProvider,
59
83
  });
84
+ const phaseGateResultMapper = new PhaseGateResultMapper();
60
85
 
61
86
  // Usecases
62
87
  const checkPhaseGateUseCase = new CheckPhaseGateUseCase({
@@ -64,10 +89,41 @@ export function createPhaseDependencyModelModule(
64
89
  evidenceBundleAssembler,
65
90
  auditLogger,
66
91
  });
92
+ const resolveGateUseCase = new ResolveGateUseCase({
93
+ globMatcher,
94
+ artifactExistenceChecker,
95
+ storyAnnotationVerifier,
96
+ });
97
+ const checkPhaseGateFacade = {
98
+ execute: async (input: {
99
+ readonly targetLevel: 1 | 2 | 3;
100
+ readonly unitId?: string;
101
+ readonly storyId?: string;
102
+ readonly targetFilePath?: string;
103
+ }) => {
104
+ if (isCustomPreset && input.targetFilePath) {
105
+ const { gates } = customGatesConfigParser.parse(rawCustomGates);
106
+ const resolved = await resolveGateUseCase.execute({
107
+ targetFilePath: input.targetFilePath,
108
+ gates,
109
+ scope: { unitId: input.unitId, storyId: input.storyId },
110
+ });
111
+ return phaseGateResultMapper.mapFromResolve(resolved, {
112
+ targetLevel: input.targetLevel,
113
+ });
114
+ }
115
+
116
+ return checkPhaseGateUseCase.execute({
117
+ targetLevel: input.targetLevel,
118
+ unitId: input.unitId,
119
+ storyId: input.storyId,
120
+ });
121
+ },
122
+ };
67
123
 
68
124
  // Presentation handlers
69
125
  const checkPhaseGateCommandHandler = new CheckPhaseGateCommandHandler({
70
- checkPhaseGateUseCase,
126
+ checkPhaseGateUseCase: checkPhaseGateFacade,
71
127
  });
72
128
 
73
129
  return {
@@ -3,12 +3,12 @@
3
3
  * @unit phase-dependency-model
4
4
  */
5
5
 
6
- import { DEFAULT_PHASE_NODES } from './default-phase-nodes.js';
6
+ import { FULL_PHASE_NODES } from './full-phase-nodes.js';
7
7
  import { PhaseDependency } from '../values/phase-dependency.js';
8
8
  import { PhaseNode } from '../values/phase-node.js';
9
9
 
10
10
  const nodeIndex = new Map<string, PhaseNode>(
11
- DEFAULT_PHASE_NODES.map((node) => [node.nodeKey(), node]),
11
+ FULL_PHASE_NODES.map((node) => [node.nodeKey(), node]),
12
12
  );
13
13
 
14
14
  const getNode = (nodeKey: string): PhaseNode => {
@@ -27,7 +27,7 @@ const createDependency = (
27
27
  type: 'requires' | 'recommends' = 'requires',
28
28
  ): PhaseDependency => PhaseDependency.create({ from: getNode(from), to: getNode(to), type });
29
29
 
30
- export const DEFAULT_PHASE_DEPENDENCIES: readonly PhaseDependency[] = Object.freeze([
30
+ export const FULL_PHASE_DEPENDENCIES: readonly PhaseDependency[] = Object.freeze([
31
31
  createDependency('1:product-architect', '1:story-writer'),
32
32
  createDependency('1:story-writer', '1:story-mapper'),
33
33
  createDependency('1:story-mapper', '1:unit-designer'),
@@ -22,7 +22,7 @@ const createNode = (
22
22
  artifacts: artifacts.map((artifact) => Artifact.create(artifact)),
23
23
  });
24
24
 
25
- export const DEFAULT_PHASE_NODES: readonly PhaseNode[] = Object.freeze([
25
+ export const FULL_PHASE_NODES: readonly PhaseNode[] = Object.freeze([
26
26
  createNode(1, 'product-architect', [
27
27
  {
28
28
  name: 'product-overview-plan',
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @layer domain
3
+ * @unit phase-dependency-model
4
+ */
5
+
6
+ import { StoryReflectionConfig } from '../values/story-reflection-config.js';
7
+ import { StoryReflectionMapping } from '../values/story-reflection-mapping.js';
8
+
9
+ export const FULL_STORY_REFLECTION_DEFAULTS: StoryReflectionConfig = StoryReflectionConfig.create({
10
+ enabled: true,
11
+ mappings: [
12
+ StoryReflectionMapping.create({
13
+ inception: 'docs/inception/{unit}/{storyId}/logical_design.md',
14
+ product: 'docs/product/construction/{unit}/logical_design.md',
15
+ required: true,
16
+ }),
17
+ StoryReflectionMapping.create({
18
+ inception: 'docs/inception/{unit}/{storyId}/domain_model.md',
19
+ product: 'docs/product/construction/{unit}/domain_model.md',
20
+ required: true,
21
+ }),
22
+ StoryReflectionMapping.create({
23
+ inception: 'docs/inception/{unit}/{storyId}/uiux_design.md',
24
+ product: 'docs/product/construction/{unit}/uiux_design.md',
25
+ required: false,
26
+ }),
27
+ ],
28
+ });
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @layer domain
3
+ * @unit phase-dependency-model
4
+ */
5
+
6
+ import { MINIMAL_PHASE_NODES } from './minimal-phase-nodes.js';
7
+ import { PhaseDependency } from '../values/phase-dependency.js';
8
+ import { PhaseNode } from '../values/phase-node.js';
9
+
10
+ const nodeIndex = new Map<string, PhaseNode>(
11
+ MINIMAL_PHASE_NODES.map((node) => [node.nodeKey(), node]),
12
+ );
13
+
14
+ const getNode = (nodeKey: string): PhaseNode => {
15
+ const actual = nodeIndex.get(nodeKey);
16
+
17
+ if (!actual) {
18
+ throw new Error(`ノードが見つかりません: ${nodeKey}`);
19
+ }
20
+
21
+ return actual;
22
+ };
23
+
24
+ const createDependency = (
25
+ from: string,
26
+ to: string,
27
+ type: 'requires' | 'recommends' = 'requires',
28
+ ): PhaseDependency => PhaseDependency.create({ from: getNode(from), to: getNode(to), type });
29
+
30
+ export const MINIMAL_PHASE_DEPENDENCIES: readonly PhaseDependency[] = Object.freeze([
31
+ createDependency('1:product-architect', '2:logical-designer'),
32
+ ]);
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @layer domain
3
+ * @unit phase-dependency-model
4
+ */
5
+
6
+ import { Artifact } from '../values/artifact.js';
7
+ import { PhaseLevel } from '../values/phase-level.js';
8
+ import { PhaseNode } from '../values/phase-node.js';
9
+
10
+ const createNode = (
11
+ level: 1 | 2 | 3,
12
+ skillName: string,
13
+ artifacts: readonly {
14
+ readonly name: string;
15
+ readonly path: string;
16
+ readonly required: boolean;
17
+ }[],
18
+ ): PhaseNode =>
19
+ PhaseNode.create({
20
+ skillName,
21
+ level: PhaseLevel.create(level),
22
+ artifacts: artifacts.map((artifact) => Artifact.create(artifact)),
23
+ });
24
+
25
+ export const MINIMAL_PHASE_NODES: readonly PhaseNode[] = Object.freeze([
26
+ createNode(1, 'product-architect', [
27
+ {
28
+ name: 'product-overview-plan',
29
+ path: 'docs/inception/_shared/product_overview_plan.md',
30
+ required: true,
31
+ },
32
+ {
33
+ name: 'product-overview',
34
+ path: 'docs/product/product_overview.md',
35
+ required: true,
36
+ },
37
+ ]),
38
+ createNode(2, 'logical-designer', [
39
+ {
40
+ name: 'logical-design-plan',
41
+ path: 'docs/inception/{unit}/logical_design_plan.md',
42
+ required: true,
43
+ },
44
+ {
45
+ name: 'logical-design',
46
+ path: 'docs/product/construction/{unit}/logical_design.md',
47
+ required: true,
48
+ },
49
+ ]),
50
+ ]);
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @layer domain
3
+ * @unit phase-dependency-model
4
+ */
5
+
6
+ import { StoryReflectionConfig } from '../values/story-reflection-config.js';
7
+
8
+ export const MINIMAL_STORY_REFLECTION_DEFAULTS: StoryReflectionConfig = StoryReflectionConfig.disabled();
@@ -0,0 +1,39 @@
1
+ /**
2
+ * @layer domain
3
+ * @unit phase-dependency-model
4
+ */
5
+
6
+ import { STANDARD_PHASE_NODES } from './standard-phase-nodes.js';
7
+ import { PhaseDependency } from '../values/phase-dependency.js';
8
+ import { PhaseNode } from '../values/phase-node.js';
9
+
10
+ const nodeIndex = new Map<string, PhaseNode>(
11
+ STANDARD_PHASE_NODES.map((node) => [node.nodeKey(), node]),
12
+ );
13
+
14
+ const getNode = (nodeKey: string): PhaseNode => {
15
+ const actual = nodeIndex.get(nodeKey);
16
+
17
+ if (!actual) {
18
+ throw new Error(`ノードが見つかりません: ${nodeKey}`);
19
+ }
20
+
21
+ return actual;
22
+ };
23
+
24
+ const createDependency = (
25
+ from: string,
26
+ to: string,
27
+ type: 'requires' | 'recommends' = 'requires',
28
+ ): PhaseDependency => PhaseDependency.create({ from: getNode(from), to: getNode(to), type });
29
+
30
+ export const STANDARD_PHASE_DEPENDENCIES: readonly PhaseDependency[] = Object.freeze([
31
+ createDependency('1:product-architect', '1:story-writer'),
32
+ createDependency('1:story-writer', '2:domain-designer'),
33
+ createDependency('2:domain-designer', '2:logical-designer'),
34
+ createDependency('2:logical-designer', '3:logical-designer'),
35
+ createDependency('3:logical-designer', '3:scenario-test-designer'),
36
+ createDependency('3:scenario-test-designer', '3:scenario-test-logic-designer'),
37
+ createDependency('3:scenario-test-logic-designer', '3:implementation-readiness-checker'),
38
+ createDependency('3:implementation-readiness-checker', '3:story-implementor'),
39
+ ]);
@@ -0,0 +1,118 @@
1
+ /**
2
+ * @layer domain
3
+ * @unit phase-dependency-model
4
+ */
5
+
6
+ import { Artifact } from '../values/artifact.js';
7
+ import { PhaseLevel } from '../values/phase-level.js';
8
+ import { PhaseNode } from '../values/phase-node.js';
9
+
10
+ const createNode = (
11
+ level: 1 | 2 | 3,
12
+ skillName: string,
13
+ artifacts: readonly {
14
+ readonly name: string;
15
+ readonly path: string;
16
+ readonly required: boolean;
17
+ }[],
18
+ ): PhaseNode =>
19
+ PhaseNode.create({
20
+ skillName,
21
+ level: PhaseLevel.create(level),
22
+ artifacts: artifacts.map((artifact) => Artifact.create(artifact)),
23
+ });
24
+
25
+ export const STANDARD_PHASE_NODES: readonly PhaseNode[] = Object.freeze([
26
+ createNode(1, 'product-architect', [
27
+ {
28
+ name: 'product-overview-plan',
29
+ path: 'docs/inception/_shared/product_overview_plan.md',
30
+ required: true,
31
+ },
32
+ {
33
+ name: 'product-overview',
34
+ path: 'docs/product/product_overview.md',
35
+ required: true,
36
+ },
37
+ ]),
38
+ createNode(1, 'story-writer', [
39
+ {
40
+ name: 'story-writer-plan',
41
+ path: 'docs/inception/_shared/story_writer_plan.md',
42
+ required: true,
43
+ },
44
+ {
45
+ name: 'user-stories',
46
+ path: 'docs/product/user_stories.md',
47
+ required: true,
48
+ },
49
+ ]),
50
+ createNode(2, 'domain-designer', [
51
+ {
52
+ name: 'domain-model-plan',
53
+ path: 'docs/inception/{unit}/domain_model_plan.md',
54
+ required: true,
55
+ },
56
+ {
57
+ name: 'domain-model',
58
+ path: 'docs/product/construction/{unit}/domain_model.md',
59
+ required: true,
60
+ },
61
+ ]),
62
+ createNode(2, 'logical-designer', [
63
+ {
64
+ name: 'logical-design-plan',
65
+ path: 'docs/inception/{unit}/logical_design_plan.md',
66
+ required: true,
67
+ },
68
+ {
69
+ name: 'logical-design',
70
+ path: 'docs/product/construction/{unit}/logical_design.md',
71
+ required: true,
72
+ },
73
+ ]),
74
+ createNode(3, 'logical-designer', [
75
+ {
76
+ name: 'story-logical-design-plan',
77
+ path: 'docs/inception/{unit}/{storyId}/logical_design_plan.md',
78
+ required: false,
79
+ },
80
+ {
81
+ name: 'story-logical-design',
82
+ path: 'docs/inception/{unit}/{storyId}/logical_design.md',
83
+ required: false,
84
+ },
85
+ ]),
86
+ createNode(3, 'scenario-test-designer', [
87
+ {
88
+ name: 'scenario-test-plan',
89
+ path: 'docs/inception/{unit}/{storyId}/scenario_test_plan.md',
90
+ required: false,
91
+ },
92
+ {
93
+ name: 'scenario-test-design',
94
+ path: 'docs/inception/{unit}/{storyId}/scenario_test_design.md',
95
+ required: false,
96
+ },
97
+ ]),
98
+ createNode(3, 'scenario-test-logic-designer', [
99
+ {
100
+ name: 'scenario-test-logic-plan',
101
+ path: 'docs/inception/{unit}/{storyId}/scenario_test_logic_plan.md',
102
+ required: false,
103
+ },
104
+ {
105
+ name: 'scenario-test-logic',
106
+ path: 'docs/inception/{unit}/{storyId}/scenario_test_logic.md',
107
+ required: false,
108
+ },
109
+ ]),
110
+ createNode(3, 'implementation-readiness-checker', []),
111
+ createNode(3, 'story-implementor', [
112
+ {
113
+ name: 'tdd-implementation-plan',
114
+ path: 'docs/inception/{unit}/{storyId}/tdd_implementation_plan.md',
115
+ required: false,
116
+ },
117
+ ]),
118
+ ]);
@@ -0,0 +1,23 @@
1
+ /**
2
+ * @layer domain
3
+ * @unit phase-dependency-model
4
+ */
5
+
6
+ import { StoryReflectionConfig } from '../values/story-reflection-config.js';
7
+ import { StoryReflectionMapping } from '../values/story-reflection-mapping.js';
8
+
9
+ export const STANDARD_STORY_REFLECTION_DEFAULTS: StoryReflectionConfig = StoryReflectionConfig.create({
10
+ enabled: true,
11
+ mappings: [
12
+ StoryReflectionMapping.create({
13
+ inception: 'docs/inception/{unit}/{storyId}/logical_design.md',
14
+ product: 'docs/product/construction/{unit}/logical_design.md',
15
+ required: true,
16
+ }),
17
+ StoryReflectionMapping.create({
18
+ inception: 'docs/inception/{unit}/{storyId}/domain_model.md',
19
+ product: 'docs/product/construction/{unit}/domain_model.md',
20
+ required: false,
21
+ }),
22
+ ],
23
+ });