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
@@ -26,6 +26,9 @@ const toStringArray = (value: unknown, fallback: readonly string[]): readonly st
26
26
  ? Object.freeze([...value])
27
27
  : fallback;
28
28
 
29
+ const isTestFile = (snapshot: SourceModuleSnapshot): boolean =>
30
+ snapshot.filePath.toString().includes('__tests__/');
31
+
29
32
  export class LintRunner {
30
33
  private readonly ruleDefinitionRegistry: RuleDefinitionRegistry;
31
34
 
@@ -98,6 +101,10 @@ export class LintRunner {
98
101
  LayerBoundary.standardMatrix(),
99
102
  layerByFile
100
103
  )) {
104
+ const fromSnapshot = snapshotByPath.get(edge.from.toString());
105
+ if (fromSnapshot && isTestFile(fromSnapshot)) {
106
+ continue;
107
+ }
101
108
  ruleViolations.push(
102
109
  RuleViolation.create({
103
110
  filePath: edge.from,
@@ -112,6 +119,10 @@ export class LintRunner {
112
119
 
113
120
  for (const cycle of params.importGraph.detectCycles()) {
114
121
  const firstPath = cycle.path[0];
122
+ const firstSnapshot = snapshotByPath.get(firstPath.toString());
123
+ if (firstSnapshot && isTestFile(firstSnapshot)) {
124
+ continue;
125
+ }
115
126
  ruleViolations.push(
116
127
  RuleViolation.create({
117
128
  filePath: firstPath,
@@ -127,6 +138,9 @@ export class LintRunner {
127
138
  }
128
139
  case 'enforce-folder-structure': {
129
140
  for (const snapshot of params.snapshots) {
141
+ if (isTestFile(snapshot)) {
142
+ continue;
143
+ }
130
144
  if (snapshot.declaredLayer !== null && !snapshot.belongsToLayerDirectory()) {
131
145
  ruleViolations.push(
132
146
  RuleViolation.create({
@@ -147,6 +161,9 @@ export class LintRunner {
147
161
  const maxAnyRatio = toNumber(rule.config.maxAnyRatio, 0.05);
148
162
 
149
163
  for (const snapshot of params.snapshots) {
164
+ if (isTestFile(snapshot)) {
165
+ continue;
166
+ }
150
167
  if (
151
168
  snapshot.anyTypeCount > maxAnyCount ||
152
169
  snapshot.anyRatio() > maxAnyRatio
@@ -223,8 +240,15 @@ export class LintRunner {
223
240
  case 'no-comment-flood': {
224
241
  const maxCommentRatio = toNumber(rule.config.maxCommentRatio, 0.35);
225
242
  const maxRepeatedBlocks = toNumber(rule.config.maxRepeatedBlocks, 1);
243
+ const minLogicalLines = toNumber(rule.config.minLogicalLines, 15);
226
244
 
227
245
  for (const snapshot of params.snapshots) {
246
+ if (isTestFile(snapshot)) {
247
+ continue;
248
+ }
249
+ if (snapshot.logicalLineCount < minLogicalLines) {
250
+ continue;
251
+ }
228
252
  if (
229
253
  snapshot.commentDensity() > maxCommentRatio ||
230
254
  snapshot.repeatedCommentBlocks > maxRepeatedBlocks
@@ -92,7 +92,7 @@ export class RuleDefinitionRegistry {
92
92
  'no-comment-flood',
93
93
  'L1-008',
94
94
  Object.freeze([REQUIRED_INPUT.sourceModuleSnapshots]),
95
- Object.freeze({ maxCommentRatio: 0.35, maxRepeatedBlocks: 1 }),
95
+ Object.freeze({ maxCommentRatio: 0.35, maxRepeatedBlocks: 1, minLogicalLines: 15 }),
96
96
  'コメント過多を検出する',
97
97
  '不要なコメントを整理し自己説明的なコードへ改善する'
98
98
  ),
@@ -59,8 +59,9 @@ export class SourceModuleSnapshot {
59
59
  readonly duplicationFingerprints: readonly string[];
60
60
  readonly exportedSymbols: readonly string[];
61
61
  readonly isEntrypointCandidate: boolean;
62
+ readonly hasRawLayerAnnotation: boolean;
62
63
 
63
- private constructor(props: Omit<SourceModuleSnapshotProps, 'declaredLayer'> & { declaredLayer: LayerName | null }) {
64
+ private constructor(props: Omit<SourceModuleSnapshotProps, 'declaredLayer'> & { declaredLayer: LayerName | null; hasRawLayerAnnotation: boolean }) {
64
65
  this.filePath = props.filePath;
65
66
  this.declaredUnit = props.declaredUnit;
66
67
  this.declaredLayer = props.declaredLayer;
@@ -73,6 +74,7 @@ export class SourceModuleSnapshot {
73
74
  this.duplicationFingerprints = props.duplicationFingerprints;
74
75
  this.exportedSymbols = props.exportedSymbols;
75
76
  this.isEntrypointCandidate = props.isEntrypointCandidate;
77
+ this.hasRawLayerAnnotation = props.hasRawLayerAnnotation;
76
78
  }
77
79
 
78
80
  static create(props: SourceModuleSnapshotProps): SourceModuleSnapshot {
@@ -83,6 +85,7 @@ export class SourceModuleSnapshot {
83
85
  filePath: props.filePath,
84
86
  declaredUnit: props.declaredUnit,
85
87
  declaredLayer,
88
+ hasRawLayerAnnotation: props.declaredLayer !== null,
86
89
  imports: Object.freeze([...props.imports]),
87
90
  anyTypeCount: ensureNonNegative(props.anyTypeCount, 'anyTypeCount'),
88
91
  typedNodeCount: ensureNonNegative(props.typedNodeCount, 'typedNodeCount'),
@@ -104,7 +107,7 @@ export class SourceModuleSnapshot {
104
107
  }
105
108
 
106
109
  hasLayerComment(): boolean {
107
- return this.declaredLayer !== null;
110
+ return this.hasRawLayerAnnotation;
108
111
  }
109
112
 
110
113
  anyRatio(): number {
@@ -11,7 +11,7 @@ import { FilePath as FilePathVO } from '../../domain/value-objects/file-path.js'
11
11
  import type { WorkspaceFilePort } from '../../domain/ports/workspace-file-port.js';
12
12
 
13
13
  const SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.mts', '.cts']);
14
- const EXCLUDED_DIRS = new Set(['node_modules', 'dist', 'coverage', '__fixtures__']);
14
+ const EXCLUDED_DIRS = new Set(['node_modules', 'dist', 'coverage', '__fixtures__', 'fixtures']);
15
15
 
16
16
  export interface NodeWorkspaceFileAdapterDeps {
17
17
  readonly rootDir: string;
@@ -64,7 +64,7 @@ export class TypeScriptSourceModuleAnalyzerAdapter implements SourceModuleAnalyz
64
64
  snapshots.push(
65
65
  SourceModuleSnapshot.create({
66
66
  filePath,
67
- declaredUnit: unitResult.unitName,
67
+ declaredUnit: unitResult.unitNames[0],
68
68
  declaredLayer: layerResult.layerName,
69
69
  imports,
70
70
  anyTypeCount: anyCount,
@@ -3,24 +3,29 @@
3
3
  * @unit biome-ast-engine
4
4
  */
5
5
 
6
- const UNIT_COMMENT_PATTERN = /^\s*(?:\/\/|\/\*\*?\s*|\*)\s*@unit\s+(\S+)/m;
6
+ const UNIT_COMMENT_PATTERN = /^\s*(?:\/\/|\/\*\*?\s*|\*)\s*@unit\s+(.+)/gm;
7
7
 
8
8
  export type UnitCommentResult = {
9
- readonly unitName: string | null;
9
+ readonly unitNames: readonly string[];
10
10
  };
11
11
 
12
12
  /**
13
13
  * ソースコードから `// @unit {unit}` コメントを抽出する。
14
14
  * JSDoc (`/** @unit ... * /`) 形式にも対応する。
15
+ * カンマ区切りで複数ユニットを指定でき、複数行の @unit も収集する。
16
+ * 結果は重複除去済み。
15
17
  */
16
18
  export const parseUnitComment = (sourceCode: string): UnitCommentResult => {
17
- const match = sourceCode.match(UNIT_COMMENT_PATTERN);
19
+ const matches = sourceCode.matchAll(UNIT_COMMENT_PATTERN);
20
+ const names: string[] = [];
18
21
 
19
- if (!match) {
20
- return { unitName: null };
22
+ for (const match of matches) {
23
+ const raw = match[1].replace(/\s*\*\/$/, '').trim();
24
+ const parts = raw.split(',').map((s) => s.trim()).filter((s) => s.length > 0);
25
+ names.push(...parts);
21
26
  }
22
27
 
23
- const raw = match[1].replace(/\s*\*\/$/, '');
28
+ const deduplicated = [...new Set(names)];
24
29
 
25
- return { unitName: raw };
30
+ return { unitNames: Object.freeze(deduplicated) };
26
31
  };
@@ -1,4 +1,5 @@
1
1
  /**
2
+ * @layer infrastructure
2
3
  * @unit ci-governance
3
4
  *
4
5
  * Composition Root - 依存性の組み立て
@@ -0,0 +1,44 @@
1
+ /**
2
+ * @layer application
3
+ * @unit config-foundation
4
+ */
5
+ import type { HarnessConfigV2 } from '../../domain/harness-config.js';
6
+
7
+ function toPhasePreset(
8
+ value: string,
9
+ ): 'default' | 'full' | 'standard' | 'minimal' | 'custom' {
10
+ if (
11
+ value === 'default'
12
+ || value === 'full'
13
+ || value === 'standard'
14
+ || value === 'minimal'
15
+ || value === 'custom'
16
+ ) {
17
+ return value;
18
+ }
19
+
20
+ return 'default';
21
+ }
22
+
23
+ type PhaseDependenciesWithGates = HarnessConfigV2['phaseDependencies'] & {
24
+ readonly gates?: readonly unknown[];
25
+ };
26
+
27
+ export function toPhaseConfigSection(resolvedConfig: HarnessConfigV2) {
28
+ const phaseDependencies = resolvedConfig.phaseDependencies as PhaseDependenciesWithGates;
29
+
30
+ return {
31
+ planningMode: resolvedConfig.planningMode,
32
+ customization: {
33
+ preset: toPhasePreset(phaseDependencies.preset),
34
+ overrideEnabled: phaseDependencies.override,
35
+ rules: phaseDependencies.customRules.map((rule) => ({
36
+ targetPhase: rule.phase,
37
+ condition: 'requires' as const,
38
+ action: rule.requires,
39
+ })),
40
+ gates: phaseDependencies.gates ?? [],
41
+ },
42
+ reportingOutputDir: resolvedConfig.reporting.outputDir,
43
+ };
44
+ }
@@ -42,7 +42,26 @@ function formatHarnessErrors(errors: readonly HarnessError[]): string {
42
42
  }
43
43
 
44
44
  function toSourceDocument(document: unknown): HarnessConfigSourceDocument {
45
- return document as HarnessConfigSourceDocument;
45
+ const sourceDocument = document as HarnessConfigSourceDocument & {
46
+ readonly phaseDependencies?: HarnessConfigSourceDocument['phaseDependencies'] & {
47
+ readonly gates?: readonly unknown[];
48
+ };
49
+ };
50
+
51
+ if (
52
+ sourceDocument.phaseDependencies === undefined
53
+ || sourceDocument.phaseDependencies.gates === undefined
54
+ ) {
55
+ return sourceDocument;
56
+ }
57
+
58
+ return {
59
+ ...sourceDocument,
60
+ phaseDependencies: {
61
+ ...sourceDocument.phaseDependencies,
62
+ gates: sourceDocument.phaseDependencies.gates ?? [],
63
+ },
64
+ } as HarnessConfigSourceDocument;
46
65
  }
47
66
 
48
67
  export function validateDocumentOrThrow(
@@ -23,6 +23,7 @@ import type { L4Config } from './value-objects/l4-config.js';
23
23
  export type LayerId = 'L1' | 'L2' | 'L3' | 'L4';
24
24
  export type PresetId = 'minimal' | 'standard' | 'strict';
25
25
  export type PlanningModeValue = 'interactive' | 'embedded-qa';
26
+ export type PhaseDependenciesPresetId = 'default' | 'full' | 'standard' | 'minimal' | 'custom';
26
27
  type DeepPartial<T> = {
27
28
  [K in keyof T]?: T[K] extends Array<infer TItem>
28
29
  ? Array<DeepPartial<TItem>>
@@ -76,7 +77,7 @@ export interface HarnessConfigResolvedDocument {
76
77
  relaxedGates: string[];
77
78
  };
78
79
  phaseDependencies: {
79
- preset: 'default' | 'custom';
80
+ preset: PhaseDependenciesPresetId;
80
81
  override: boolean;
81
82
  customRules: Array<{
82
83
  phase: string;
@@ -7,17 +7,20 @@
7
7
  */
8
8
  import { CustomPhaseRule } from './custom-phase-rule.js';
9
9
  import type { CustomPhaseRuleProps } from './custom-phase-rule.js';
10
+ import type { PhaseDependenciesPresetId } from '../harness-config.js';
10
11
 
11
12
  export interface PhaseDependenciesConfigProps {
12
- readonly preset: 'default' | 'custom';
13
+ readonly preset: PhaseDependenciesPresetId;
13
14
  readonly override: boolean;
14
15
  readonly customRules: readonly CustomPhaseRuleProps[];
16
+ readonly gates?: readonly unknown[];
15
17
  }
16
18
 
17
19
  export class PhaseDependenciesConfig {
18
- readonly preset: 'default' | 'custom';
20
+ readonly preset: PhaseDependenciesPresetId;
19
21
  readonly override: boolean;
20
22
  readonly customRules: readonly CustomPhaseRule[];
23
+ readonly gates: readonly unknown[];
21
24
 
22
25
  constructor(props: PhaseDependenciesConfigProps) {
23
26
  this.preset = props.preset;
@@ -25,6 +28,7 @@ export class PhaseDependenciesConfig {
25
28
  this.customRules = props.customRules.map(
26
29
  (rule) => new CustomPhaseRule(rule)
27
30
  );
31
+ this.gates = Object.freeze([...(props.gates ?? [])]);
28
32
  }
29
33
 
30
34
  static create(raw: PhaseDependenciesConfigProps): PhaseDependenciesConfig {
@@ -35,12 +39,22 @@ export class PhaseDependenciesConfig {
35
39
  return this.customRules.length > 0;
36
40
  }
37
41
 
42
+ hasCustomGates(): boolean {
43
+ return this.gates.length > 0;
44
+ }
45
+
38
46
  equals(other: PhaseDependenciesConfig): boolean {
39
47
  if (this.preset !== other.preset) return false;
40
48
  if (this.override !== other.override) return false;
41
49
  if (this.customRules.length !== other.customRules.length) return false;
42
- return this.customRules.every((rule, idx) =>
50
+ if (
51
+ !this.customRules.every((rule, idx) =>
43
52
  rule.equals(other.customRules[idx])
44
- );
53
+ )
54
+ ) {
55
+ return false;
56
+ }
57
+
58
+ return JSON.stringify(this.gates) === JSON.stringify(other.gates);
45
59
  }
46
60
  }
@@ -16,7 +16,10 @@
16
16
  "project": {
17
17
  "type": "object",
18
18
  "additionalProperties": false,
19
- "required": ["name", "preset"],
19
+ "required": [
20
+ "name",
21
+ "preset"
22
+ ],
20
23
  "properties": {
21
24
  "name": {
22
25
  "type": "string",
@@ -24,7 +27,11 @@
24
27
  },
25
28
  "preset": {
26
29
  "type": "string",
27
- "enum": ["minimal", "standard", "strict"]
30
+ "enum": [
31
+ "minimal",
32
+ "standard",
33
+ "strict"
34
+ ]
28
35
  }
29
36
  }
30
37
  },
@@ -152,11 +159,19 @@
152
159
  "phaseDependencies": {
153
160
  "type": "object",
154
161
  "additionalProperties": false,
155
- "required": ["preset", "override", "customRules"],
162
+ "required": [
163
+ "preset"
164
+ ],
156
165
  "properties": {
157
166
  "preset": {
158
167
  "type": "string",
159
- "enum": ["default", "custom"]
168
+ "enum": [
169
+ "default",
170
+ "full",
171
+ "standard",
172
+ "minimal",
173
+ "custom"
174
+ ]
160
175
  },
161
176
  "override": {
162
177
  "type": "boolean"
@@ -166,7 +181,10 @@
166
181
  "items": {
167
182
  "type": "object",
168
183
  "additionalProperties": false,
169
- "required": ["phase", "requires"],
184
+ "required": [
185
+ "phase",
186
+ "requires"
187
+ ],
170
188
  "properties": {
171
189
  "phase": {
172
190
  "type": "string",
@@ -180,23 +198,160 @@
180
198
  }
181
199
  }
182
200
  }
201
+ },
202
+ "gates": {
203
+ "type": "array",
204
+ "items": {
205
+ "type": "object",
206
+ "additionalProperties": false,
207
+ "required": [
208
+ "name",
209
+ "level",
210
+ "requires",
211
+ "blocks",
212
+ "dependsOn"
213
+ ],
214
+ "properties": {
215
+ "name": {
216
+ "type": "string",
217
+ "pattern": "^[a-z][a-z0-9-]*$"
218
+ },
219
+ "level": {
220
+ "type": "integer",
221
+ "enum": [
222
+ 1,
223
+ 2,
224
+ 3
225
+ ]
226
+ },
227
+ "requires": {
228
+ "type": "array",
229
+ "items": {
230
+ "type": "object",
231
+ "additionalProperties": false,
232
+ "required": [
233
+ "path",
234
+ "required"
235
+ ],
236
+ "properties": {
237
+ "path": {
238
+ "type": "string",
239
+ "minLength": 1
240
+ },
241
+ "required": {
242
+ "type": "boolean"
243
+ }
244
+ }
245
+ }
246
+ },
247
+ "blocks": {
248
+ "type": "array",
249
+ "items": {
250
+ "type": "string",
251
+ "minLength": 1
252
+ }
253
+ },
254
+ "dependsOn": {
255
+ "type": "array",
256
+ "items": {
257
+ "type": "string",
258
+ "pattern": "^[a-z][a-z0-9-]*$"
259
+ }
260
+ },
261
+ "storyAnnotation": {
262
+ "type": "object",
263
+ "additionalProperties": false,
264
+ "required": [
265
+ "required",
266
+ "tag"
267
+ ],
268
+ "properties": {
269
+ "required": {
270
+ "type": "boolean"
271
+ },
272
+ "tag": {
273
+ "type": "string",
274
+ "minLength": 1
275
+ }
276
+ }
277
+ }
278
+ },
279
+ "allOf": [
280
+ {
281
+ "if": {
282
+ "required": [
283
+ "storyAnnotation"
284
+ ]
285
+ },
286
+ "then": {
287
+ "properties": {
288
+ "level": {
289
+ "const": 3
290
+ }
291
+ }
292
+ }
293
+ }
294
+ ]
295
+ }
296
+ },
297
+ "storyReflection": {
298
+ "type": "object",
299
+ "additionalProperties": false,
300
+ "properties": {
301
+ "enabled": {
302
+ "type": "boolean"
303
+ },
304
+ "mappings": {
305
+ "type": "array",
306
+ "items": {
307
+ "type": "object",
308
+ "additionalProperties": false,
309
+ "required": [
310
+ "unitId",
311
+ "artifacts"
312
+ ],
313
+ "properties": {
314
+ "unitId": {
315
+ "type": "string",
316
+ "minLength": 1
317
+ },
318
+ "artifacts": {
319
+ "type": "array",
320
+ "items": {
321
+ "type": "string",
322
+ "minLength": 1
323
+ }
324
+ }
325
+ }
326
+ }
327
+ }
328
+ }
183
329
  }
184
330
  }
185
331
  },
186
332
  "planningMode": {
187
333
  "type": "object",
188
334
  "additionalProperties": false,
189
- "required": ["default", "perPhase"],
335
+ "required": [
336
+ "default",
337
+ "perPhase"
338
+ ],
190
339
  "properties": {
191
340
  "default": {
192
341
  "type": "string",
193
- "enum": ["interactive", "embedded-qa"]
342
+ "enum": [
343
+ "interactive",
344
+ "embedded-qa"
345
+ ]
194
346
  },
195
347
  "perPhase": {
196
348
  "type": "object",
197
349
  "additionalProperties": {
198
350
  "type": "string",
199
- "enum": ["interactive", "embedded-qa"]
351
+ "enum": [
352
+ "interactive",
353
+ "embedded-qa"
354
+ ]
200
355
  }
201
356
  }
202
357
  }
@@ -223,7 +378,10 @@
223
378
  "paths": {
224
379
  "type": "object",
225
380
  "additionalProperties": false,
226
- "required": ["designDocs", "inceptionDocs"],
381
+ "required": [
382
+ "designDocs",
383
+ "inceptionDocs"
384
+ ],
227
385
  "properties": {
228
386
  "designDocs": {
229
387
  "type": "string",
@@ -238,7 +396,10 @@
238
396
  "reporting": {
239
397
  "type": "object",
240
398
  "additionalProperties": false,
241
- "required": ["format", "outputDir"],
399
+ "required": [
400
+ "format",
401
+ "outputDir"
402
+ ],
242
403
  "properties": {
243
404
  "format": {
244
405
  "type": "string",
@@ -249,6 +410,20 @@
249
410
  "minLength": 1
250
411
  }
251
412
  }
413
+ },
414
+ "protectedFiles": {
415
+ "type": "object",
416
+ "additionalProperties": false,
417
+ "properties": {
418
+ "exclude": {
419
+ "type": "array",
420
+ "items": {
421
+ "type": "string",
422
+ "minLength": 1
423
+ },
424
+ "uniqueItems": true
425
+ }
426
+ }
252
427
  }
253
428
  }
254
429
  }
@@ -5,7 +5,8 @@
5
5
  import fs from 'node:fs';
6
6
  import path from 'node:path';
7
7
  import { fileURLToPath } from 'node:url';
8
- import Ajv, { type ErrorObject, type ValidateFunction } from 'ajv';
8
+ import AjvModule, { type ErrorObject, type ValidateFunction } from 'ajv';
9
+ const Ajv = AjvModule.default ?? AjvModule;
9
10
  import { HarnessError } from '../../../harness-error/domain/value-objects/harness-error.js';
10
11
  import { ErrorCode } from '../../../harness-error/domain/value-objects/error-code.js';
11
12
  import { Severity } from '../../../harness-error/domain/value-objects/severity.js';
@@ -1,3 +1,4 @@
1
+ // @layer application
1
2
  // command-dispatch-input.ts — CommandDispatchInput DTO
2
3
 
3
4
  export interface CommandDispatchInput {
@@ -1,3 +1,4 @@
1
+ // @layer application
1
2
  // command-dispatch-output.ts — CommandDispatchOutput DTO
2
3
 
3
4
  import type { ExitCode } from '../../domain/value-objects/harness-api-response.js';
@@ -1,3 +1,4 @@
1
+ // @layer application
1
2
  // exit-code-decision-input.ts — ExitCodeDecisionInput DTO
2
3
 
3
4
  import type { ResponseStatus } from '../../domain/value-objects/harness-api-response.js';
@@ -1,3 +1,4 @@
1
+ // @layer application
1
2
  // exit-code-decision-output.ts — ExitCodeDecisionOutput DTO
2
3
 
3
4
  import type { ExitCode } from '../../domain/value-objects/harness-api-response.js';
@@ -1,3 +1,4 @@
1
+ // @layer application
1
2
  // harness-api-response-contract.ts — Cross-Unit Contract DTO
2
3
 
3
4
  import type { ResponseStatus, HarnessError, ResponseSummary } from '../../domain/value-objects/harness-api-response.js';
@@ -1,3 +1,4 @@
1
+ // @layer application
1
2
  // initialize-registry-input.ts — InitializeRegistryInput DTO
2
3
 
3
4
  export interface CliCommandDefinitionInput {
@@ -1,3 +1,4 @@
1
+ // @layer application
1
2
  // registry-summary-output.ts — RegistrySummaryOutput DTO
2
3
 
3
4
  import type { CommandName } from '../../domain/value-objects/cli-command-definition.js';
@@ -1,3 +1,4 @@
1
+ // @layer application
1
2
  // status-derivation-input.ts — StatusDerivationInput DTO
2
3
 
3
4
  // Currently no parameters — extensible for future filter conditions
@@ -1,3 +1,4 @@
1
+ // @layer application
1
2
  // harness-api-response-mapper.ts — HarnessApiResponseMapper
2
3
 
3
4
  import type { HarnessApiResponse } from '../../domain/value-objects/harness-api-response.js';
@@ -1,3 +1,4 @@
1
+ // @layer application
1
2
  // decide-exit-code-usecase.ts — DecideExitCodeUseCase
2
3
 
3
4
  import type { ExitCodeDecisionInput } from '../dto/exit-code-decision-input.js';
@@ -1,3 +1,4 @@
1
+ // @layer application
1
2
  // derive-harness-status-usecase.ts — DeriveHarnessStatusUseCase
2
3
 
3
4
  import type { ArtifactScannerPort } from '../../domain/ports/artifact-scanner-port.js';