phasegate 0.16.0 → 0.31.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.
- package/README.ja.md +71 -39
- package/README.md +69 -9
- package/docs/ADR/ADR-013-story-reflection-gate.md +100 -0
- package/docs/guide/configuration.md +244 -7
- package/package.json +4 -2
- package/scripts/harness/adr-foundation/domain/ports/adr-document-parser-port.ts +1 -0
- package/scripts/harness/adr-foundation/domain/ports/adr-frontmatter-parser-port.ts +1 -0
- package/scripts/harness/adr-foundation/domain/ports/adr-repository-port.ts +1 -0
- package/scripts/harness/adr-foundation/domain/value-objects/adr-status.ts +6 -6
- package/scripts/harness/agent-integration/application/dto/handle-pre-tool-use-dto.ts +3 -1
- package/scripts/harness/agent-integration/application/usecases/handle-pre-tool-use-usecase.ts +108 -2
- package/scripts/harness/agent-integration/domain/ports/config-query-port.ts +2 -0
- package/scripts/harness/agent-integration/domain/ports/phase-gate-query-port.ts +1 -1
- package/scripts/harness/agent-integration/domain/ports/story-reflection-query-port.ts +8 -0
- package/scripts/harness/agent-integration/domain/services/bash-write-target-extractor.ts +258 -0
- package/scripts/harness/agent-integration/domain/services/hook-to-cli-translator.ts +21 -4
- package/scripts/harness/agent-integration/domain/value-objects/protected-file-list.ts +20 -0
- package/scripts/harness/agent-integration/domain/value-objects/story-reflection-query-result.ts +63 -0
- package/scripts/harness/agent-integration/infrastructure/adapters/file-system-story-reflection-query-adapter.ts +122 -0
- package/scripts/harness/agent-integration/infrastructure/adapters/harness-config-config-query-adapter.ts +20 -0
- package/scripts/harness/agent-integration/infrastructure/adapters/phase-gate-query-adapter.ts +17 -3
- package/scripts/harness/agent-integration/presentation/pre-tool-use-hook.ts +29 -2
- package/scripts/harness/biome-ast-engine/domain/services/lint-runner.ts +24 -0
- package/scripts/harness/biome-ast-engine/domain/services/rule-definition-registry.ts +1 -1
- package/scripts/harness/biome-ast-engine/domain/value-objects/source-module-snapshot.ts +5 -2
- package/scripts/harness/biome-ast-engine/infrastructure/adapters/node-workspace-file-adapter.ts +1 -1
- package/scripts/harness/biome-ast-engine/infrastructure/adapters/typescript-source-module-analyzer-adapter.ts +1 -1
- package/scripts/harness/biome-ast-engine/infrastructure/parsers/unit-comment-parser.ts +12 -7
- package/scripts/harness/ci-governance/composition-root.ts +1 -0
- package/scripts/harness/config-foundation/application/mappers/phase-config-section-mapper.ts +44 -0
- package/scripts/harness/config-foundation/application/usecases/load-resolved-config-use-case.ts +20 -1
- package/scripts/harness/config-foundation/domain/harness-config.ts +2 -1
- package/scripts/harness/config-foundation/domain/value-objects/phase-dependencies-config.ts +18 -4
- package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v2.schema.json +185 -10
- package/scripts/harness/config-foundation/infrastructure/validators/ajv-config-schema-validator.ts +2 -1
- package/scripts/harness/harness-api/application/dto/command-dispatch-input.ts +1 -0
- package/scripts/harness/harness-api/application/dto/command-dispatch-output.ts +1 -0
- package/scripts/harness/harness-api/application/dto/exit-code-decision-input.ts +1 -0
- package/scripts/harness/harness-api/application/dto/exit-code-decision-output.ts +1 -0
- package/scripts/harness/harness-api/application/dto/harness-api-response-contract.ts +1 -0
- package/scripts/harness/harness-api/application/dto/initialize-registry-input.ts +1 -0
- package/scripts/harness/harness-api/application/dto/registry-summary-output.ts +1 -0
- package/scripts/harness/harness-api/application/dto/status-derivation-input.ts +1 -0
- package/scripts/harness/harness-api/application/mappers/harness-api-response-mapper.ts +1 -0
- package/scripts/harness/harness-api/application/usecases/decide-exit-code-usecase.ts +1 -0
- package/scripts/harness/harness-api/application/usecases/derive-harness-status-usecase.ts +1 -0
- package/scripts/harness/harness-api/application/usecases/dispatch-command-usecase.ts +1 -0
- package/scripts/harness/harness-api/application/usecases/initialize-command-registry-usecase.ts +1 -0
- package/scripts/harness/harness-api/composition-root.ts +1 -0
- package/scripts/harness/harness-api/domain/ports/artifact-scanner-port.ts +1 -0
- package/scripts/harness/harness-api/domain/ports/biome-lint-port.ts +1 -0
- package/scripts/harness/harness-api/domain/ports/config-query-port.ts +1 -0
- package/scripts/harness/harness-api/domain/ports/impact-analysis-port.ts +1 -0
- package/scripts/harness/harness-api/domain/ports/phase-gate-query-port.ts +1 -0
- package/scripts/harness/harness-api/domain/ports/validator-execution-port.ts +1 -0
- package/scripts/harness/harness-api/domain/services/command-dispatch-service.ts +1 -0
- package/scripts/harness/harness-api/domain/services/command-registry.ts +1 -0
- package/scripts/harness/harness-api/domain/services/status-derivation-service.ts +1 -0
- package/scripts/harness/harness-api/domain/value-objects/artifact-scan-result.ts +1 -0
- package/scripts/harness/harness-api/domain/value-objects/check-ready-result.ts +1 -0
- package/scripts/harness/harness-api/domain/value-objects/ci-check-result.ts +1 -0
- package/scripts/harness/harness-api/domain/value-objects/cli-command-definition.ts +1 -0
- package/scripts/harness/harness-api/domain/value-objects/command-input-spec.ts +1 -0
- package/scripts/harness/harness-api/domain/value-objects/drift-report-summary.ts +1 -0
- package/scripts/harness/harness-api/domain/value-objects/exit-code-spec.ts +1 -0
- package/scripts/harness/harness-api/domain/value-objects/harness-api-response.ts +1 -0
- package/scripts/harness/harness-api/domain/value-objects/harness-status-summary.ts +1 -0
- package/scripts/harness/harness-api/domain/value-objects/layer-health.ts +1 -0
- package/scripts/harness/harness-api/domain/value-objects/phase-info.ts +1 -0
- package/scripts/harness/harness-api/index.ts +1 -0
- package/scripts/harness/harness-api/infrastructure/adapters/biome-ast-engine-lint-adapter.ts +1 -0
- package/scripts/harness/harness-api/infrastructure/adapters/file-system-artifact-scanner-adapter.ts +1 -0
- package/scripts/harness/harness-api/infrastructure/adapters/harness-config-query-adapter.ts +1 -0
- package/scripts/harness/harness-api/infrastructure/adapters/nyquist-validation-impact-analysis-adapter.ts +1 -0
- package/scripts/harness/harness-api/infrastructure/adapters/phase-dependency-model-query-adapter.ts +1 -0
- package/scripts/harness/harness-api/infrastructure/adapters/validator-system-execution-adapter.ts +1 -0
- package/scripts/harness/harness-api/presentation/dto/cli-output-options.ts +1 -0
- package/scripts/harness/harness-api/presentation/formatters/harness-api-json-formatter.ts +1 -0
- package/scripts/harness/harness-api/presentation/handlers/check-phase-handler.ts +1 -0
- package/scripts/harness/harness-api/presentation/handlers/check-ready-handler.ts +1 -0
- package/scripts/harness/harness-api/presentation/handlers/ci-check-handler.ts +1 -0
- package/scripts/harness/harness-api/presentation/handlers/complete-check-handler.ts +1 -0
- package/scripts/harness/harness-api/presentation/handlers/detect-drift-handler.ts +1 -0
- package/scripts/harness/harness-api/presentation/handlers/impact-analysis-handler.ts +1 -0
- package/scripts/harness/harness-api/presentation/handlers/lint-handler.ts +1 -0
- package/scripts/harness/harness-api/presentation/handlers/status-handler.ts +1 -0
- package/scripts/harness/harness-error/infrastructure/adapters/legacy-error-reporter-adapter.ts +7 -1
- package/scripts/harness/integrations/pre-commit.ts +1 -0
- package/scripts/harness/main.ts +154 -34
- package/scripts/harness/phase-dependency-model/application/dto/resolve-gate-result-dto.ts +14 -0
- package/scripts/harness/phase-dependency-model/application/services/phase-gate-result-mapper.ts +20 -0
- package/scripts/harness/phase-dependency-model/application/usecases/check-story-reflection-usecase.ts +42 -0
- package/scripts/harness/phase-dependency-model/application/usecases/resolve-gate-usecase.ts +161 -0
- package/scripts/harness/phase-dependency-model/composition-root.ts +57 -1
- package/scripts/harness/phase-dependency-model/domain/definitions/{default-phase-dependencies.ts → full-phase-dependencies.ts} +3 -3
- package/scripts/harness/phase-dependency-model/domain/definitions/{default-phase-nodes.ts → full-phase-nodes.ts} +1 -1
- package/scripts/harness/phase-dependency-model/domain/definitions/full-story-reflection-defaults.ts +28 -0
- package/scripts/harness/phase-dependency-model/domain/definitions/minimal-phase-dependencies.ts +32 -0
- package/scripts/harness/phase-dependency-model/domain/definitions/minimal-phase-nodes.ts +50 -0
- package/scripts/harness/phase-dependency-model/domain/definitions/minimal-story-reflection-defaults.ts +8 -0
- package/scripts/harness/phase-dependency-model/domain/definitions/standard-phase-dependencies.ts +39 -0
- package/scripts/harness/phase-dependency-model/domain/definitions/standard-phase-nodes.ts +118 -0
- package/scripts/harness/phase-dependency-model/domain/definitions/standard-story-reflection-defaults.ts +23 -0
- package/scripts/harness/phase-dependency-model/domain/models/phase-structure.ts +95 -23
- package/scripts/harness/phase-dependency-model/domain/ports/glob-matcher-port.ts +8 -0
- package/scripts/harness/phase-dependency-model/domain/ports/phase-config-provider-port.ts +2 -0
- package/scripts/harness/phase-dependency-model/domain/ports/story-annotation-verifier-port.ts +14 -0
- package/scripts/harness/phase-dependency-model/domain/ports/story-reflection-file-system-port.ts +16 -0
- package/scripts/harness/phase-dependency-model/domain/services/gate-graph.ts +223 -0
- package/scripts/harness/phase-dependency-model/domain/services/story-reflection-checker.ts +66 -0
- package/scripts/harness/phase-dependency-model/domain/values/gate-definition.ts +127 -0
- package/scripts/harness/phase-dependency-model/domain/values/gate-name.ts +40 -0
- package/scripts/harness/phase-dependency-model/domain/values/gate-story-annotation.ts +39 -0
- package/scripts/harness/phase-dependency-model/domain/values/phase-customization-policy.ts +16 -4
- package/scripts/harness/phase-dependency-model/domain/values/story-reflection-config.ts +44 -0
- package/scripts/harness/phase-dependency-model/domain/values/story-reflection-mapping.ts +91 -0
- package/scripts/harness/phase-dependency-model/domain/values/story-reflection-result.ts +55 -0
- package/scripts/harness/phase-dependency-model/infrastructure/adapters/picomatch-glob-matcher.ts +17 -0
- package/scripts/harness/phase-dependency-model/infrastructure/adapters/story-annotation-verifier-adapter.ts +46 -0
- package/scripts/harness/phase-dependency-model/infrastructure/config/custom-gates-config-parser.ts +22 -0
- package/scripts/harness/phase-dependency-model/infrastructure/config/harness-config-phase-config-provider.ts +78 -2
- package/scripts/harness/phase-dependency-model/infrastructure/filesystem/file-system-story-reflection-adapter.ts +94 -0
- package/scripts/harness/phase-dependency-model/presentation/cli/check-phase-gate-command-handler.ts +12 -4
- package/scripts/harness/phase-dependency-model/presentation/cli/story-reflection-status-presenter.ts +87 -0
- package/scripts/harness/regression-suite/application/dto/analyze-migration-input.ts +1 -0
- package/scripts/harness/regression-suite/application/dto/analyze-migration-output.ts +1 -0
- package/scripts/harness/regression-suite/application/dto/configure-ci-gate-input.ts +1 -0
- package/scripts/harness/regression-suite/application/dto/configure-ci-gate-output.ts +1 -0
- package/scripts/harness/regression-suite/application/dto/migrate-v0-tests-input.ts +1 -0
- package/scripts/harness/regression-suite/application/dto/migrate-v0-tests-output.ts +1 -0
- package/scripts/harness/regression-suite/application/dto/run-regression-suite-input.ts +1 -0
- package/scripts/harness/regression-suite/application/dto/run-regression-suite-output.ts +1 -0
- package/scripts/harness/regression-suite/application/mappers/migration-mapping-mapper.ts +1 -0
- package/scripts/harness/regression-suite/application/mappers/test-execution-summary-mapper.ts +1 -0
- package/scripts/harness/regression-suite/application/usecases/analyze-v0-migration-usecase.ts +1 -0
- package/scripts/harness/regression-suite/application/usecases/configure-ci-gate-usecase.ts +1 -0
- package/scripts/harness/regression-suite/application/usecases/migrate-v0-tests-usecase.ts +1 -0
- package/scripts/harness/regression-suite/application/usecases/run-agent-independence-guard-usecase.ts +1 -0
- package/scripts/harness/regression-suite/application/usecases/run-gng-gate-regression-usecase.ts +1 -0
- package/scripts/harness/regression-suite/application/usecases/run-k-requirements-regression-usecase.ts +1 -0
- package/scripts/harness/regression-suite/application/usecases/run-k14-k15-regression-usecase.ts +1 -0
- package/scripts/harness/regression-suite/composition-root.ts +1 -0
- package/scripts/harness/regression-suite/domain/aggregates/v0-test-migration.ts +1 -0
- package/scripts/harness/regression-suite/domain/ports/ci-gate-result-writer-port.ts +1 -0
- package/scripts/harness/regression-suite/domain/ports/config-query-port.ts +1 -0
- package/scripts/harness/regression-suite/domain/ports/import-analyzer-port.ts +1 -0
- package/scripts/harness/regression-suite/domain/ports/migration-mapping-repository-port.ts +1 -0
- package/scripts/harness/regression-suite/domain/ports/suite-registry-port.ts +1 -0
- package/scripts/harness/regression-suite/domain/ports/test-runner-port.ts +1 -0
- package/scripts/harness/regression-suite/domain/ports/v0-spec-reader-port.ts +1 -0
- package/scripts/harness/regression-suite/domain/services/import-guard-service.ts +1 -0
- package/scripts/harness/regression-suite/domain/services/migration-analyzer.ts +1 -0
- package/scripts/harness/regression-suite/domain/services/regression-runner.ts +1 -0
- package/scripts/harness/regression-suite/domain/value-objects/agent-independence-test.ts +1 -0
- package/scripts/harness/regression-suite/domain/value-objects/biome-modification-spec.ts +1 -0
- package/scripts/harness/regression-suite/domain/value-objects/ci-gate-config.ts +1 -0
- package/scripts/harness/regression-suite/domain/value-objects/coverage-rate.ts +1 -0
- package/scripts/harness/regression-suite/domain/value-objects/gng-condition-test.ts +1 -0
- package/scripts/harness/regression-suite/domain/value-objects/import-violation.ts +1 -0
- package/scripts/harness/regression-suite/domain/value-objects/k-requirement-test.ts +1 -0
- package/scripts/harness/regression-suite/domain/value-objects/migration-mapping.ts +1 -0
- package/scripts/harness/regression-suite/domain/value-objects/regression-suite-definition.ts +1 -0
- package/scripts/harness/regression-suite/domain/value-objects/suite-id.ts +1 -0
- package/scripts/harness/regression-suite/domain/value-objects/test-execution-summary.ts +1 -0
- package/scripts/harness/regression-suite/domain/value-objects/test-failure-detail.ts +1 -0
- package/scripts/harness/regression-suite/domain/value-objects/v0-test-id.ts +1 -0
- package/scripts/harness/regression-suite/domain/value-objects/v1-test-path.ts +1 -0
- package/scripts/harness/regression-suite/infrastructure/adapters/biome-ast-import-analyzer-adapter.ts +1 -0
- package/scripts/harness/regression-suite/infrastructure/adapters/file-system-v0-spec-reader-adapter.ts +1 -0
- package/scripts/harness/regression-suite/infrastructure/adapters/harness-config-query-adapter.ts +1 -0
- package/scripts/harness/regression-suite/infrastructure/adapters/json-ci-gate-result-writer-adapter.ts +1 -0
- package/scripts/harness/regression-suite/infrastructure/adapters/markdown-migration-mapping-repository-adapter.ts +1 -0
- package/scripts/harness/regression-suite/infrastructure/adapters/static-suite-registry-adapter.ts +1 -0
- package/scripts/harness/regression-suite/infrastructure/adapters/vitest-test-runner-adapter.ts +1 -0
- package/scripts/harness/regression-suite/infrastructure/registry/agent-independence-suite-definition.ts +1 -0
- package/scripts/harness/regression-suite/infrastructure/registry/gng-gate-suite-definition.ts +1 -0
- package/scripts/harness/regression-suite/infrastructure/registry/k-requirements-suite-definition.ts +1 -0
- package/scripts/harness/regression-suite/infrastructure/registry/v0-migration-suite-definition.ts +1 -0
- package/scripts/harness/setup/skill-deployer.ts +82 -5
- package/scripts/harness/shared-kernel/harness-api.ts +1 -0
- package/scripts/harness/skill-quality/composition-root.ts +1 -0
- package/scripts/harness/skill-quality/infrastructure/adapters/ajv-lesson-artifact-schema-adapter.ts +5 -4
- package/scripts/harness/traceability-model/domain/services/metadata-validator.ts +12 -10
- package/scripts/harness/traceability-model/infrastructure/parsers/source-metadata-parser.ts +16 -2
- package/skills/cascade-updater/SKILL.md +16 -3
- package/skills/codebase-mapper/SKILL.md +9 -9
- package/skills/codex-delegator/SKILL.md +5 -56
- package/skills/consistency-checker/SKILL.md +5 -9
- 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
- package/skills/doc-freshness-checker/SKILL.md +6 -6
- package/skills/engineering-perspective/SKILL.md +2 -58
- package/skills/engineering-perspective/references/domain-model.md +4 -135
- package/skills/implementation-readiness-checker/SKILL.md +18 -72
- package/skills/it-test-designer/SKILL.md +25 -161
- package/skills/it-test-designer/references/it-test-design-template.md +131 -0
- package/skills/it-test-logic-designer/SKILL.md +13 -388
- package/skills/it-test-logic-designer/references/controller-test-patterns.md +100 -0
- package/skills/it-test-logic-designer/references/repository-test-patterns.md +206 -0
- package/skills/it-test-logic-designer/references/usecase-test-patterns.md +87 -0
- package/skills/pointer-validator/SKILL.md +4 -4
- package/skills/scenario-test-designer/SKILL.md +4 -68
- package/skills/scenario-test-designer/references/scenario-test-design-template.md +41 -0
- package/skills/scenario-test-designer/references/scenario-test-plan-template.md +35 -0
- package/skills/scenario-test-logic-designer/SKILL.md +21 -304
- package/skills/scenario-test-logic-designer/references/msw-patterns.md +36 -0
- package/skills/scenario-test-logic-designer/references/playwright-patterns.md +237 -0
- package/skills/test-coverage-checker/SKILL.md +39 -121
- package/skills/test-coverage-checker/references/coverage-report-template.md +99 -0
- package/skills/uiux-designer/SKILL.md +27 -92
- package/skills/uiux-designer/references/data-testid-convention.md +38 -0
- package/skills/uiux-designer/references/uiux-design-template.md +105 -0
- package/skills/unit-test-designer/SKILL.md +5 -106
- package/skills/unit-test-designer/references/unit-test-design-template.md +127 -0
- package/skills/unit-test-logic-designer/SKILL.md +28 -250
- package/skills/unit-test-logic-designer/references/test-patterns.md +207 -0
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @layer domain
|
|
3
|
+
* @unit phase-dependency-model
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import type { StoryReflectionMapping } from './story-reflection-mapping.js';
|
|
7
|
+
|
|
8
|
+
export interface StoryReflectionViolation {
|
|
9
|
+
readonly storyId: string;
|
|
10
|
+
readonly mapping: StoryReflectionMapping;
|
|
11
|
+
readonly inceptionPath: string;
|
|
12
|
+
readonly productPath: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface StoryReflectionResultCreateArgs {
|
|
16
|
+
readonly passed: boolean;
|
|
17
|
+
readonly violations: readonly StoryReflectionViolation[];
|
|
18
|
+
readonly warnings: readonly StoryReflectionViolation[];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class StoryReflectionResult {
|
|
22
|
+
readonly passed: boolean;
|
|
23
|
+
readonly violations: readonly StoryReflectionViolation[];
|
|
24
|
+
readonly warnings: readonly StoryReflectionViolation[];
|
|
25
|
+
|
|
26
|
+
private constructor(args: StoryReflectionResultCreateArgs) {
|
|
27
|
+
this.passed = args.passed;
|
|
28
|
+
this.violations = Object.freeze([...args.violations]);
|
|
29
|
+
this.warnings = Object.freeze([...args.warnings]);
|
|
30
|
+
Object.freeze(this);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static pass(): StoryReflectionResult {
|
|
34
|
+
return new StoryReflectionResult({
|
|
35
|
+
passed: true,
|
|
36
|
+
violations: [],
|
|
37
|
+
warnings: [],
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static create(args: {
|
|
42
|
+
violations: readonly StoryReflectionViolation[];
|
|
43
|
+
warnings: readonly StoryReflectionViolation[];
|
|
44
|
+
}): StoryReflectionResult {
|
|
45
|
+
return new StoryReflectionResult({
|
|
46
|
+
passed: args.violations.length === 0,
|
|
47
|
+
violations: args.violations,
|
|
48
|
+
warnings: args.warnings,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
isBlocked(): boolean {
|
|
53
|
+
return this.violations.length > 0;
|
|
54
|
+
}
|
|
55
|
+
}
|
package/scripts/harness/phase-dependency-model/infrastructure/adapters/picomatch-glob-matcher.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// @unit phase-dependency-model
|
|
2
|
+
// @layer infrastructure
|
|
3
|
+
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
5
|
+
import type { GlobMatcherPort } from '../../domain/ports/glob-matcher-port.js';
|
|
6
|
+
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
const picomatch = require('picomatch') as (
|
|
9
|
+
pattern: string,
|
|
10
|
+
options?: { readonly dot?: boolean },
|
|
11
|
+
) => (path: string) => boolean;
|
|
12
|
+
|
|
13
|
+
export class PicomatchGlobMatcher implements GlobMatcherPort {
|
|
14
|
+
match(pattern: string, path: string): boolean {
|
|
15
|
+
return picomatch(pattern, { dot: true })(path);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// @unit phase-dependency-model
|
|
2
|
+
// @layer infrastructure
|
|
3
|
+
|
|
4
|
+
import type { StoryAnnotationVerifierPort } from '../../domain/ports/story-annotation-verifier-port.js';
|
|
5
|
+
import { ProjectRelativePath } from '../../../traceability-model/domain/value-objects/project-relative-path.js';
|
|
6
|
+
import type { MarkdownDesignDocumentGateway } from '../../../traceability-model/infrastructure/gateways/markdown-design-document-gateway.js';
|
|
7
|
+
|
|
8
|
+
export interface StoryAnnotationVerifierAdapterDeps {
|
|
9
|
+
readonly designDocumentGateway: Pick<
|
|
10
|
+
MarkdownDesignDocumentGateway,
|
|
11
|
+
'readStoryAnnotations'
|
|
12
|
+
>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class StoryAnnotationVerifierAdapter
|
|
16
|
+
implements StoryAnnotationVerifierPort
|
|
17
|
+
{
|
|
18
|
+
private readonly designDocumentGateway: StoryAnnotationVerifierAdapterDeps['designDocumentGateway'];
|
|
19
|
+
|
|
20
|
+
constructor(deps: StoryAnnotationVerifierAdapterDeps) {
|
|
21
|
+
this.designDocumentGateway = deps.designDocumentGateway;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async verify(targetFilePath: string, tag: string) {
|
|
25
|
+
if (tag.trim() !== '@story-id') {
|
|
26
|
+
return Object.freeze({
|
|
27
|
+
hasAnnotation: false,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const filePath = ProjectRelativePath.create(targetFilePath);
|
|
32
|
+
const annotations =
|
|
33
|
+
await this.designDocumentGateway.readStoryAnnotations(filePath);
|
|
34
|
+
|
|
35
|
+
if (annotations.length === 0) {
|
|
36
|
+
return Object.freeze({
|
|
37
|
+
hasAnnotation: false,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return Object.freeze({
|
|
42
|
+
hasAnnotation: true,
|
|
43
|
+
storyId: annotations[0]?.storyId.value,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
}
|
package/scripts/harness/phase-dependency-model/infrastructure/config/custom-gates-config-parser.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
// @unit phase-dependency-model
|
|
2
|
+
// @layer infrastructure
|
|
3
|
+
|
|
4
|
+
import { GateGraph } from '../../domain/services/gate-graph.js';
|
|
5
|
+
import { GateDefinition } from '../../domain/values/gate-definition.js';
|
|
6
|
+
|
|
7
|
+
export interface CustomGatesConfigParseResult {
|
|
8
|
+
readonly gates: readonly GateDefinition[];
|
|
9
|
+
readonly graph: GateGraph;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export class CustomGatesConfigParser {
|
|
13
|
+
parse(raw: readonly unknown[]): CustomGatesConfigParseResult {
|
|
14
|
+
const gates = Object.freeze(raw.map((entry) => GateDefinition.fromRaw(entry)));
|
|
15
|
+
const graph = GateGraph.build([...gates]);
|
|
16
|
+
|
|
17
|
+
return Object.freeze({
|
|
18
|
+
gates,
|
|
19
|
+
graph,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -5,8 +5,34 @@
|
|
|
5
5
|
|
|
6
6
|
import type { PhaseConfigProviderPort } from '../../domain/ports/phase-config-provider-port.js';
|
|
7
7
|
import { PlanningMode } from '../../domain/values/planning-mode.js';
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
PhaseCustomizationPolicy,
|
|
10
|
+
type PresetName,
|
|
11
|
+
} from '../../domain/values/phase-customization-policy.js';
|
|
9
12
|
import { CustomRule } from '../../domain/values/custom-rule.js';
|
|
13
|
+
import { StoryReflectionConfig } from '../../domain/values/story-reflection-config.js';
|
|
14
|
+
import { StoryReflectionMapping } from '../../domain/values/story-reflection-mapping.js';
|
|
15
|
+
import { FULL_STORY_REFLECTION_DEFAULTS } from '../../domain/definitions/full-story-reflection-defaults.js';
|
|
16
|
+
import { STANDARD_STORY_REFLECTION_DEFAULTS } from '../../domain/definitions/standard-story-reflection-defaults.js';
|
|
17
|
+
import { MINIMAL_STORY_REFLECTION_DEFAULTS } from '../../domain/definitions/minimal-story-reflection-defaults.js';
|
|
18
|
+
|
|
19
|
+
export interface StoryReflectionMappingInput {
|
|
20
|
+
readonly inception: string;
|
|
21
|
+
readonly product: string;
|
|
22
|
+
readonly required: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface StoryReflectionSectionInput {
|
|
26
|
+
readonly enabled?: boolean;
|
|
27
|
+
readonly mappings?: readonly StoryReflectionMappingInput[];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type PhasePresetInput =
|
|
31
|
+
| 'default'
|
|
32
|
+
| 'full'
|
|
33
|
+
| 'standard'
|
|
34
|
+
| 'minimal'
|
|
35
|
+
| 'custom';
|
|
10
36
|
|
|
11
37
|
export interface PhaseConfigSection {
|
|
12
38
|
readonly planningMode?:
|
|
@@ -18,7 +44,7 @@ export interface PhaseConfigSection {
|
|
|
18
44
|
readonly overrides?: Record<string, string>;
|
|
19
45
|
};
|
|
20
46
|
readonly customization?: {
|
|
21
|
-
readonly preset?:
|
|
47
|
+
readonly preset?: PhasePresetInput;
|
|
22
48
|
readonly overrideEnabled?: boolean;
|
|
23
49
|
readonly rules?: ReadonlyArray<{
|
|
24
50
|
readonly targetPhase: string;
|
|
@@ -26,9 +52,22 @@ export interface PhaseConfigSection {
|
|
|
26
52
|
readonly action: readonly string[];
|
|
27
53
|
}>;
|
|
28
54
|
};
|
|
55
|
+
readonly storyReflection?: StoryReflectionSectionInput;
|
|
29
56
|
readonly reportingOutputDir?: string;
|
|
30
57
|
}
|
|
31
58
|
|
|
59
|
+
/**
|
|
60
|
+
* プリセットごとの storyReflection デフォルト定義。
|
|
61
|
+
* `default` は v1.0 で `full` に統合されたため同一値にエイリアスする。
|
|
62
|
+
*/
|
|
63
|
+
const PRESET_STORY_REFLECTION_DEFAULTS: Record<PresetName, StoryReflectionConfig> = {
|
|
64
|
+
full: FULL_STORY_REFLECTION_DEFAULTS,
|
|
65
|
+
standard: STANDARD_STORY_REFLECTION_DEFAULTS,
|
|
66
|
+
minimal: MINIMAL_STORY_REFLECTION_DEFAULTS,
|
|
67
|
+
// custom プリセットは明示設定を強制するためデフォルトは無効扱い
|
|
68
|
+
custom: StoryReflectionConfig.disabled(),
|
|
69
|
+
};
|
|
70
|
+
|
|
32
71
|
export interface HarnessConfigPhaseConfigProviderDeps {
|
|
33
72
|
readonly config: PhaseConfigSection;
|
|
34
73
|
readonly defaultOutputDir: string;
|
|
@@ -95,4 +134,41 @@ export class HarnessConfigPhaseConfigProvider
|
|
|
95
134
|
async getReportingOutputDir(): Promise<string> {
|
|
96
135
|
return this.config.reportingOutputDir ?? this.defaultOutputDir;
|
|
97
136
|
}
|
|
137
|
+
|
|
138
|
+
async getStoryReflectionConfig(): Promise<StoryReflectionConfig> {
|
|
139
|
+
const policy = await this.getCustomizationPolicy();
|
|
140
|
+
const presetDefault = PRESET_STORY_REFLECTION_DEFAULTS[policy.preset];
|
|
141
|
+
const section = this.config.storyReflection;
|
|
142
|
+
|
|
143
|
+
if (section === undefined) {
|
|
144
|
+
return presetDefault;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// enabled 明示 false → disabled で即返す(mappings 無視)
|
|
148
|
+
if (section.enabled === false) {
|
|
149
|
+
return StoryReflectionConfig.disabled();
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// enabled 省略時はプリセットの enabled を継承
|
|
153
|
+
const enabled = section.enabled ?? presetDefault.enabled;
|
|
154
|
+
|
|
155
|
+
// mappings 省略 → プリセットデフォルトの mappings を流用
|
|
156
|
+
const rawMappings = section.mappings;
|
|
157
|
+
if (rawMappings === undefined) {
|
|
158
|
+
return StoryReflectionConfig.create({
|
|
159
|
+
enabled,
|
|
160
|
+
mappings: presetDefault.mappings,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const mappings = rawMappings.map((m) =>
|
|
165
|
+
StoryReflectionMapping.create({
|
|
166
|
+
inception: m.inception,
|
|
167
|
+
product: m.product,
|
|
168
|
+
required: m.required,
|
|
169
|
+
}),
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
return StoryReflectionConfig.create({ enabled, mappings });
|
|
173
|
+
}
|
|
98
174
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @layer infrastructure
|
|
3
|
+
* @unit phase-dependency-model
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { readdir, readFile, access } from 'node:fs/promises';
|
|
7
|
+
import path from 'node:path';
|
|
8
|
+
import type { StoryReflectionFileSystemPort } from '../../domain/ports/story-reflection-file-system-port.js';
|
|
9
|
+
|
|
10
|
+
export interface FileSystemStoryReflectionAdapterDeps {
|
|
11
|
+
readonly rootDir: string;
|
|
12
|
+
/** inception ディレクトリのルート(デフォルト: docs/inception) */
|
|
13
|
+
readonly inceptionRoot?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* ファイルシステム上の docs/inception ディレクトリ列挙と
|
|
18
|
+
* product 文書内 `@story-id` アノテーション検索を実装するアダプタ。
|
|
19
|
+
*
|
|
20
|
+
* 存在しないパス・読めないファイルは true/false に正規化し例外を投げない
|
|
21
|
+
* ことで、上位 (StoryReflectionChecker) の純粋性を保つ。
|
|
22
|
+
*/
|
|
23
|
+
export class FileSystemStoryReflectionAdapter
|
|
24
|
+
implements StoryReflectionFileSystemPort
|
|
25
|
+
{
|
|
26
|
+
private readonly rootDir: string;
|
|
27
|
+
private readonly inceptionRoot: string;
|
|
28
|
+
|
|
29
|
+
constructor(deps: FileSystemStoryReflectionAdapterDeps) {
|
|
30
|
+
this.rootDir = deps.rootDir;
|
|
31
|
+
this.inceptionRoot = deps.inceptionRoot ?? 'docs/inception';
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async listStoryDirectories(unitId: string): Promise<readonly string[]> {
|
|
35
|
+
const unitDir = path.join(this.rootDir, this.inceptionRoot, unitId);
|
|
36
|
+
|
|
37
|
+
let entries;
|
|
38
|
+
try {
|
|
39
|
+
entries = await readdir(unitDir, { withFileTypes: true });
|
|
40
|
+
} catch {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return entries
|
|
45
|
+
.filter((entry) => entry.isDirectory())
|
|
46
|
+
.map((entry) => entry.name)
|
|
47
|
+
.filter((name) => !name.startsWith('_') && !name.startsWith('.'))
|
|
48
|
+
.sort();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async fileExists(relativePath: string): Promise<boolean> {
|
|
52
|
+
const absolutePath = path.join(this.rootDir, relativePath);
|
|
53
|
+
try {
|
|
54
|
+
await access(absolutePath);
|
|
55
|
+
return true;
|
|
56
|
+
} catch {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async fileContainsStoryAnnotation(
|
|
62
|
+
productPath: string,
|
|
63
|
+
storyId: string,
|
|
64
|
+
): Promise<boolean> {
|
|
65
|
+
const absolutePath = path.join(this.rootDir, productPath);
|
|
66
|
+
|
|
67
|
+
let content: string;
|
|
68
|
+
try {
|
|
69
|
+
content = await readFile(absolutePath, 'utf8');
|
|
70
|
+
} catch {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// `@story-id` の直後にカンマ/空白区切りで列挙される story ID を抽出。
|
|
75
|
+
// 例: `@story-id US-001`, `@story-id US-001, US-002`,
|
|
76
|
+
// `<!-- @story-id US-001 -->`
|
|
77
|
+
// 行末または `-->` まで(story ID 自体の `-` は許容するため `-->` を明示終端に使う)。
|
|
78
|
+
const pattern = /@story-id[ \t]+([^\n\r]+)/g;
|
|
79
|
+
let match: RegExpExecArray | null;
|
|
80
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
81
|
+
// `-->` 以降の HTML コメント閉じ記号を取り除く
|
|
82
|
+
const raw = match[1].replace(/-->.*$/, '');
|
|
83
|
+
const ids = raw
|
|
84
|
+
.split(/[\s,]+/)
|
|
85
|
+
.map((s) => s.trim())
|
|
86
|
+
.filter((s) => s.length > 0);
|
|
87
|
+
if (ids.includes(storyId)) {
|
|
88
|
+
return true;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
package/scripts/harness/phase-dependency-model/presentation/cli/check-phase-gate-command-handler.ts
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
* @unit phase-dependency-model
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type { CheckPhaseGateUseCase, CheckPhaseGateInput } from '../../application/usecases/check-phase-gate-usecase.js';
|
|
7
6
|
import type { PhaseGateResultDto } from '../../application/dto/phase-gate-result-dto.js';
|
|
8
7
|
|
|
9
8
|
export interface CheckPhaseGateCommandInput {
|
|
10
9
|
readonly targetLevel: number;
|
|
11
10
|
readonly unitId?: string;
|
|
12
11
|
readonly storyId?: string;
|
|
12
|
+
readonly targetFilePath?: string;
|
|
13
13
|
readonly json?: boolean;
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -20,11 +20,18 @@ export interface CheckPhaseGateCommandOutput {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export interface CheckPhaseGateCommandHandlerDeps {
|
|
23
|
-
readonly checkPhaseGateUseCase:
|
|
23
|
+
readonly checkPhaseGateUseCase: {
|
|
24
|
+
execute(input: {
|
|
25
|
+
readonly targetLevel: 1 | 2 | 3;
|
|
26
|
+
readonly unitId?: string;
|
|
27
|
+
readonly storyId?: string;
|
|
28
|
+
readonly targetFilePath?: string;
|
|
29
|
+
}): Promise<PhaseGateResultDto>;
|
|
30
|
+
};
|
|
24
31
|
}
|
|
25
32
|
|
|
26
33
|
export class CheckPhaseGateCommandHandler {
|
|
27
|
-
private readonly useCase:
|
|
34
|
+
private readonly useCase: CheckPhaseGateCommandHandlerDeps['checkPhaseGateUseCase'];
|
|
28
35
|
|
|
29
36
|
constructor(deps: CheckPhaseGateCommandHandlerDeps) {
|
|
30
37
|
this.useCase = deps.checkPhaseGateUseCase;
|
|
@@ -42,10 +49,11 @@ export class CheckPhaseGateCommandHandler {
|
|
|
42
49
|
}
|
|
43
50
|
|
|
44
51
|
try {
|
|
45
|
-
const useCaseInput
|
|
52
|
+
const useCaseInput = {
|
|
46
53
|
targetLevel: input.targetLevel as 1 | 2 | 3,
|
|
47
54
|
unitId: input.unitId,
|
|
48
55
|
storyId: input.storyId,
|
|
56
|
+
targetFilePath: input.targetFilePath,
|
|
49
57
|
};
|
|
50
58
|
|
|
51
59
|
const result = await this.useCase.execute(useCaseInput);
|
package/scripts/harness/phase-dependency-model/presentation/cli/story-reflection-status-presenter.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
// @unit phase-dependency-model
|
|
2
|
+
// @layer presentation
|
|
3
|
+
/**
|
|
4
|
+
* StoryReflectionStatusPresenter
|
|
5
|
+
*
|
|
6
|
+
* CLI (`phasegate:status`, `phasegate validate --layer L2`) 用の
|
|
7
|
+
* storyReflection 状態整形を担うプレゼンター。
|
|
8
|
+
*
|
|
9
|
+
* 責務:
|
|
10
|
+
* - status コマンド向けの 1 行サマリー生成(有効/無効・preset・mapping 数)
|
|
11
|
+
* - validate --layer L2 向けの検証結果サマリー生成
|
|
12
|
+
* (violations / warnings 件数と代表情報)
|
|
13
|
+
*
|
|
14
|
+
* 呼び出し元 (main.ts / presentation) で設定と CheckStoryReflectionUseCase の
|
|
15
|
+
* 実行結果を受け取り、人間可読な行を組み立てる。
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import type { StoryReflectionConfig } from '../../domain/values/story-reflection-config.js';
|
|
19
|
+
import type { StoryReflectionResult } from '../../domain/values/story-reflection-result.js';
|
|
20
|
+
import type { PresetName } from '../../domain/values/phase-customization-policy.js';
|
|
21
|
+
|
|
22
|
+
export interface StoryReflectionStatusLineInput {
|
|
23
|
+
readonly config: StoryReflectionConfig;
|
|
24
|
+
readonly preset: PresetName;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface StoryReflectionValidationSummaryInput {
|
|
28
|
+
readonly config: StoryReflectionConfig;
|
|
29
|
+
readonly preset: PresetName;
|
|
30
|
+
readonly result: StoryReflectionResult;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class StoryReflectionStatusPresenter {
|
|
34
|
+
formatStatusLine(input: StoryReflectionStatusLineInput): string {
|
|
35
|
+
const { config, preset } = input;
|
|
36
|
+
const state = config.enabled ? 'enabled' : 'disabled';
|
|
37
|
+
const required = config.mappings.filter((m) => m.required).length;
|
|
38
|
+
const optional = config.mappings.filter((m) => !m.required).length;
|
|
39
|
+
|
|
40
|
+
return [
|
|
41
|
+
'storyReflection:',
|
|
42
|
+
state,
|
|
43
|
+
`preset=${preset}`,
|
|
44
|
+
`mappings=${config.mappings.length}`,
|
|
45
|
+
`required=${required}`,
|
|
46
|
+
`optional=${optional}`,
|
|
47
|
+
].join(' ');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
formatValidationSummary(input: StoryReflectionValidationSummaryInput): string {
|
|
51
|
+
const { config, preset, result } = input;
|
|
52
|
+
const lines: string[] = [];
|
|
53
|
+
|
|
54
|
+
if (!config.enabled) {
|
|
55
|
+
lines.push(
|
|
56
|
+
`[L2-STORY-REFLECTION] disabled (preset=${preset}, violations=0, warnings=0)`,
|
|
57
|
+
);
|
|
58
|
+
return lines.join('\n');
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const status = result.isBlocked() ? 'failed' : 'passed';
|
|
62
|
+
const violations = result.violations.length;
|
|
63
|
+
const warnings = result.warnings.length;
|
|
64
|
+
|
|
65
|
+
lines.push(
|
|
66
|
+
`[L2-STORY-REFLECTION] ${status} (preset=${preset}, mappings=${config.mappings.length}, violations=${violations}, warnings=${warnings})`,
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
if (result.isBlocked()) {
|
|
70
|
+
for (const violation of result.violations) {
|
|
71
|
+
lines.push(
|
|
72
|
+
` - ${violation.storyId}: ${violation.productPath} に @story-id ${violation.storyId} が未反映 (inception: ${violation.inceptionPath})`,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (warnings > 0) {
|
|
78
|
+
for (const warning of result.warnings) {
|
|
79
|
+
lines.push(
|
|
80
|
+
` ! ${warning.storyId}: ${warning.productPath} に @story-id ${warning.storyId} が未反映 (optional)`,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return lines.join('\n');
|
|
86
|
+
}
|
|
87
|
+
}
|
package/scripts/harness/regression-suite/application/usecases/analyze-v0-migration-usecase.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @layer application
|
|
1
2
|
import { MigrationAnalyzer } from '../../domain/services/migration-analyzer.js';
|
|
2
3
|
import type { V0SpecReaderPort } from '../../domain/ports/v0-spec-reader-port.js';
|
|
3
4
|
import type { MigrationMappingRepositoryPort } from '../../domain/ports/migration-mapping-repository-port.js';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @layer application
|
|
1
2
|
import { MigrationAnalyzer } from '../../domain/services/migration-analyzer.js';
|
|
2
3
|
import type { V0SpecReaderPort } from '../../domain/ports/v0-spec-reader-port.js';
|
|
3
4
|
import type { MigrationMappingRepositoryPort } from '../../domain/ports/migration-mapping-repository-port.js';
|