phasegate 0.83.0 → 0.107.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 (78) hide show
  1. package/CHANGELOG.md +313 -0
  2. package/README.ja.md +15 -7
  3. package/README.md +24 -4
  4. package/docs/ADR/ADR-014-presentation-domain-dependency.md +82 -0
  5. package/docs/ADR/ADR-015-architecture-preset.md +183 -0
  6. package/docs/guide/codex-integration.md +7 -2
  7. package/docs/guide/installation.md +10 -2
  8. package/docs/guide/preset-selection.md +170 -0
  9. package/docs/guide/quick-vs-full-mode.md +3 -3
  10. package/docs/guide/retrofit-adoption.md +19 -2
  11. package/docs/guide/skills-overview.md +1 -1
  12. package/package.json +7 -1
  13. package/scripts/harness/adr-foundation/application/dto/application-errors.ts +0 -13
  14. package/scripts/harness/agent-integration/application/usecases/handle-pre-tool-use-usecase.ts +108 -100
  15. package/scripts/harness/agent-integration/domain/ports/error-guidance-query-port.ts +0 -8
  16. package/scripts/harness/agent-integration/domain/ports/phase-gate-query-port.ts +3 -3
  17. package/scripts/harness/agent-integration/domain/value-objects/write-target-scope.ts +26 -30
  18. package/scripts/harness/agent-integration/infrastructure/adapters/file-system-story-reflection-query-adapter.ts +6 -2
  19. package/scripts/harness/biome-ast-engine/application/dto/analyze-import-graph-input.ts +3 -0
  20. package/scripts/harness/biome-ast-engine/application/dto/resolve-enabled-rules-output.ts +2 -0
  21. package/scripts/harness/biome-ast-engine/application/mappers/resolve-enabled-rules-output-mapper.ts +4 -1
  22. package/scripts/harness/biome-ast-engine/application/usecases/analyze-import-graph-usecase.ts +4 -1
  23. package/scripts/harness/biome-ast-engine/application/usecases/execute-lint-usecase.ts +2 -0
  24. package/scripts/harness/biome-ast-engine/application/usecases/resolve-enabled-rules-usecase.ts +31 -3
  25. package/scripts/harness/biome-ast-engine/composition-root.ts +10 -2
  26. package/scripts/harness/biome-ast-engine/domain/ports/rule-config-provider-port.ts +16 -0
  27. package/scripts/harness/biome-ast-engine/domain/ports/source-module-analyzer-port.ts +5 -1
  28. package/scripts/harness/biome-ast-engine/domain/services/lint-runner.ts +5 -1
  29. package/scripts/harness/biome-ast-engine/domain/services/rule-definition-registry.ts +1 -0
  30. package/scripts/harness/biome-ast-engine/domain/value-objects/architecture-spec.ts +38 -0
  31. package/scripts/harness/biome-ast-engine/domain/value-objects/layer-boundary.ts +7 -8
  32. package/scripts/harness/biome-ast-engine/domain/value-objects/layer-name.ts +15 -23
  33. package/scripts/harness/biome-ast-engine/domain/value-objects/source-module-snapshot.ts +11 -4
  34. package/scripts/harness/biome-ast-engine/infrastructure/adapters/harness-config-provider-adapter.ts +29 -3
  35. package/scripts/harness/biome-ast-engine/infrastructure/adapters/typescript-source-module-analyzer-adapter.ts +22 -15
  36. package/scripts/harness/biome-ast-engine/infrastructure/mappers/source-module-snapshot-mapper.ts +26 -17
  37. package/scripts/harness/config-foundation/application/dto/resolved-config-output.ts +1 -0
  38. package/scripts/harness/config-foundation/application/usecases/load-resolved-config-use-case.ts +34 -2
  39. package/scripts/harness/config-foundation/application/usecases/migrate-schema-use-case.ts +89 -0
  40. package/scripts/harness/config-foundation/composition-root.ts +8 -0
  41. package/scripts/harness/config-foundation/domain/harness-config.ts +6 -0
  42. package/scripts/harness/config-foundation/domain/services/architecture-resolution-service.ts +257 -0
  43. package/scripts/harness/config-foundation/domain/value-objects/architecture-config.ts +66 -0
  44. package/scripts/harness/config-foundation/domain/value-objects/architecture-preset-catalog.ts +75 -0
  45. package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json +546 -0
  46. package/scripts/harness/config-foundation/infrastructure/validators/ajv-config-schema-validator.ts +18 -6
  47. package/scripts/harness/config-foundation/presentation/cli/migrate-schema-command-handler.ts +83 -0
  48. package/scripts/harness/integrations/pre-commit.ts +211 -52
  49. package/scripts/harness/main.ts +460 -340
  50. package/scripts/harness/phase-dependency-model/domain/ports/story-reflection-file-system-port.ts +2 -4
  51. package/scripts/harness/phase-dependency-model/domain/services/story-reflection-checker.ts +54 -17
  52. package/scripts/harness/phase-dependency-model/infrastructure/filesystem/file-system-story-reflection-adapter.ts +154 -36
  53. package/scripts/harness/setup/skill-deployer.ts +140 -102
  54. package/scripts/harness/skill-quality/domain/errors/skill-quality-error.ts +24 -23
  55. package/scripts/harness/skill-quality/domain/value-objects/commit-message.ts +23 -7
  56. package/scripts/harness/traceability-model/application/usecases/apply-work-item-migration-usecase.ts +52 -0
  57. package/scripts/harness/traceability-model/application/usecases/plan-work-item-migration-usecase.ts +29 -0
  58. package/scripts/harness/traceability-model/application/usecases/validate-design-story-annotations-usecase.ts +83 -18
  59. package/scripts/harness/traceability-model/composition-root.ts +48 -30
  60. package/scripts/harness/traceability-model/domain/ports/design-document-port.ts +9 -15
  61. package/scripts/harness/traceability-model/domain/ports/work-item-migration-apply-port.ts +11 -0
  62. package/scripts/harness/traceability-model/domain/ports/work-item-migration-source-port.ts +9 -0
  63. package/scripts/harness/traceability-model/domain/services/metadata-validator.ts +1 -1
  64. package/scripts/harness/traceability-model/domain/services/work-item-migration-planner.ts +162 -0
  65. package/scripts/harness/traceability-model/domain/value-objects/story-id.ts +3 -3
  66. package/scripts/harness/traceability-model/domain/value-objects/work-item-frontmatter.ts +57 -0
  67. package/scripts/harness/traceability-model/domain/value-objects/work-item-migration-candidate.ts +47 -0
  68. package/scripts/harness/traceability-model/infrastructure/gateways/file-system-work-item-migration-apply-gateway.ts +110 -0
  69. package/scripts/harness/traceability-model/infrastructure/gateways/file-system-work-item-migration-source-gateway.ts +182 -0
  70. package/scripts/harness/traceability-model/infrastructure/gateways/markdown-design-document-gateway.ts +29 -43
  71. package/scripts/harness/traceability-model/infrastructure/parsers/story-catalog-parser.ts +2 -2
  72. package/scripts/harness/traceability-model/infrastructure/parsers/work-item-frontmatter-parser.ts +136 -0
  73. package/scripts/harness/traceability-model/presentation/cli/migrate-work-items-command-handler.ts +186 -0
  74. package/skills/quick-implementor/SKILL.md +17 -1
  75. package/templates/.husky/commit-msg +1 -0
  76. package/scripts/harness/adr-foundation/application/dto/seed-adr-definition.ts +0 -21
  77. package/scripts/harness/adr-foundation/application/usecases/seed-initial-adrs-use-case.ts +0 -84
  78. package/scripts/harness/adr-foundation/infrastructure/seeds/initial-adr-definitions.ts +0 -161
@@ -0,0 +1,186 @@
1
+ // @unit traceability-model
2
+ // @layer presentation
3
+
4
+ import type { ApplyWorkItemMigrationUseCase } from "../../application/usecases/apply-work-item-migration-usecase.js";
5
+ import type { PlanWorkItemMigrationUseCase } from "../../application/usecases/plan-work-item-migration-usecase.js";
6
+ import type {
7
+ WorkItemMigrationApplyResult,
8
+ WorkItemMigrationCandidate,
9
+ WorkItemMigrationPlan,
10
+ } from "../../domain/value-objects/work-item-migration-candidate.js";
11
+
12
+ export interface MigrateWorkItemsCommandInput {
13
+ readonly dryRun?: boolean;
14
+ readonly apply?: boolean;
15
+ readonly json?: boolean;
16
+ }
17
+
18
+ export interface MigrateWorkItemsCommandOutput {
19
+ readonly exitCode: 0 | 1 | 2;
20
+ readonly text: string;
21
+ }
22
+
23
+ type PlanUseCase = Pick<PlanWorkItemMigrationUseCase, "execute">;
24
+ type ApplyUseCase = Pick<ApplyWorkItemMigrationUseCase, "execute">;
25
+
26
+ export interface MigrateWorkItemsCommandHandlerDeps {
27
+ readonly planWorkItemMigrationUseCase: PlanUseCase;
28
+ readonly applyWorkItemMigrationUseCase?: ApplyUseCase;
29
+ }
30
+
31
+ export class MigrateWorkItemsCommandHandler {
32
+ private readonly planUseCase: PlanUseCase;
33
+ private readonly applyUseCase?: ApplyUseCase;
34
+
35
+ constructor(deps: MigrateWorkItemsCommandHandlerDeps) {
36
+ this.planUseCase = deps.planWorkItemMigrationUseCase;
37
+ this.applyUseCase = deps.applyWorkItemMigrationUseCase;
38
+ }
39
+
40
+ async execute(input: MigrateWorkItemsCommandInput): Promise<Readonly<MigrateWorkItemsCommandOutput>> {
41
+ if (input.apply && input.dryRun) {
42
+ return Object.freeze({
43
+ exitCode: 2,
44
+ text: "Error: --apply and --dry-run cannot be used together.",
45
+ });
46
+ }
47
+
48
+ if (input.apply) {
49
+ return this.executeApply(input);
50
+ }
51
+
52
+ if (!input.dryRun) {
53
+ return Object.freeze({
54
+ exitCode: 2,
55
+ text: "Error: either --dry-run or --apply is required for migrate work-items.",
56
+ });
57
+ }
58
+
59
+ try {
60
+ const plan = await this.planUseCase.execute();
61
+ const hasConflict = plan.candidates.some((candidate) => candidate.conflict);
62
+ return Object.freeze({
63
+ exitCode: hasConflict ? 1 : 0,
64
+ text: input.json ? this.formatJson(plan) : this.formatHuman(plan),
65
+ });
66
+ } catch {
67
+ return Object.freeze({
68
+ exitCode: 2,
69
+ text: "Error: failed to plan work item migration unexpectedly.",
70
+ });
71
+ }
72
+ }
73
+
74
+ private formatJson(plan: WorkItemMigrationPlan): string {
75
+ return JSON.stringify(
76
+ {
77
+ candidates: plan.candidates,
78
+ warnings: plan.warnings,
79
+ },
80
+ null,
81
+ 2,
82
+ );
83
+ }
84
+
85
+ private async executeApply(input: MigrateWorkItemsCommandInput): Promise<Readonly<MigrateWorkItemsCommandOutput>> {
86
+ if (!this.applyUseCase) {
87
+ return Object.freeze({
88
+ exitCode: 2,
89
+ text: "Error: --apply is not configured for migrate work-items.",
90
+ });
91
+ }
92
+
93
+ try {
94
+ const result = await this.applyUseCase.execute();
95
+ return Object.freeze({
96
+ exitCode: result.blocked ? 1 : 0,
97
+ text: input.json ? this.formatApplyJson(result) : this.formatApplyHuman(result),
98
+ });
99
+ } catch {
100
+ return Object.freeze({
101
+ exitCode: 2,
102
+ text: "Error: failed to apply work item migration unexpectedly.",
103
+ });
104
+ }
105
+ }
106
+
107
+ private formatApplyJson(result: WorkItemMigrationApplyResult): string {
108
+ return JSON.stringify(
109
+ {
110
+ applied: result.applied,
111
+ skipped: result.skipped,
112
+ warnings: result.warnings,
113
+ blocked: result.blocked,
114
+ },
115
+ null,
116
+ 2,
117
+ );
118
+ }
119
+
120
+ private formatApplyHuman(result: WorkItemMigrationApplyResult): string {
121
+ const lines = [
122
+ "WorkItem migration apply",
123
+ `applied: ${result.applied.length}`,
124
+ `skipped: ${result.skipped.length}`,
125
+ `warnings: ${result.warnings.length}`,
126
+ `blocked: ${result.blocked ? "yes" : "no"}`,
127
+ "",
128
+ ];
129
+
130
+ for (const applied of result.applied) {
131
+ lines.push(`- applied ${applied.legacyId} -> ${applied.nextId}`);
132
+ lines.push(` target: ${applied.targetPath}`);
133
+ lines.push(` description: ${applied.descriptionPath}`);
134
+ lines.push("");
135
+ }
136
+
137
+ for (const skipped of result.skipped) {
138
+ lines.push(`- skipped ${skipped.legacyId} -> ${skipped.nextId}`);
139
+ lines.push(` reason: conflict`);
140
+ lines.push(` target: ${skipped.targetPath}`);
141
+ lines.push("");
142
+ }
143
+
144
+ if (result.warnings.length > 0) {
145
+ lines.push("Warnings:");
146
+ for (const warning of result.warnings) {
147
+ lines.push(` - ${warning}`);
148
+ }
149
+ }
150
+
151
+ return lines.join("\n").trimEnd();
152
+ }
153
+
154
+ private formatHuman(plan: WorkItemMigrationPlan): string {
155
+ const lines = [
156
+ "WorkItem migration dry-run",
157
+ `candidates: ${plan.candidates.length}`,
158
+ `warnings: ${plan.warnings.length}`,
159
+ "",
160
+ ];
161
+
162
+ for (const candidate of plan.candidates) {
163
+ lines.push(...this.formatCandidate(candidate), "");
164
+ }
165
+
166
+ if (plan.warnings.length > 0) {
167
+ lines.push("Warnings:");
168
+ for (const warning of plan.warnings) {
169
+ lines.push(` - ${warning}`);
170
+ }
171
+ }
172
+
173
+ return lines.join("\n").trimEnd();
174
+ }
175
+
176
+ private formatCandidate(candidate: WorkItemMigrationCandidate): string[] {
177
+ return [
178
+ `- ${candidate.legacyId} -> ${candidate.nextId}`,
179
+ ` source: ${candidate.sourcePath}`,
180
+ ` target: ${candidate.targetPath}`,
181
+ ` scope: ${candidate.scope}`,
182
+ ` description: ${candidate.descriptionFileName ?? "missing"}`,
183
+ ` conflict: ${candidate.conflict ? "yes" : "no"}`,
184
+ ];
185
+ }
186
+ }
@@ -18,6 +18,20 @@ Quick Mode下での軽微変更実装スキル。story-implementorの緩和版
18
18
  | `test` | テスト追加・修正(新機能のテストではない) |
19
19
  | `config` | 設定変更、依存バージョン更新 |
20
20
 
21
+ ### WI-aware trivial path(ISSUE-026 Phase D)
22
+
23
+ 作業対象に `WI-XXX` が明示されている場合、最初に `docs/inception/{unit}/WI-XXX/description.md` または `docs/inception/_cross/WI-XXX/description.md` のfrontmatterを確認する。
24
+
25
+ | WI type | Quick Modeでの扱い |
26
+ |---------|-------------------|
27
+ | `fix` | 適用候補。既存仕様の局所修正として扱う |
28
+ | `chore` | 適用候補。依存更新・運用・ドキュメント整備として扱う |
29
+ | `story` | 適用不可。`story-implementor` にエスカレーション |
30
+ | `issue` | 適用不可。product反映が必要な可能性が高いため `story-implementor` にエスカレーション |
31
+ | `refactor` | 適用不可。設計影響を伴う可能性が高いため `story-implementor` にエスカレーション |
32
+
33
+ `type: fix | chore` でも、API契約変更・新ドメインモデル追加・レイヤー構造変更・複数Unitにまたがる実装変更が見えた場合は、通常の除外ルールを優先して `story-implementor` に切り替える。
34
+
21
35
  ### 適用除外(フルハーネス必須 → story-implementor を使用)
22
36
 
23
37
  - 新機能追加
@@ -82,10 +96,12 @@ pnpm test # 全テスト グリーンを確認
82
96
 
83
97
  ### Step 5: コミット
84
98
 
85
- Atomic commit で変更をコミットする。コミットメッセージに `[quick]` プレフィックスを付与。
99
+ Atomic commit で変更をコミットする。コミットメッセージに `[quick]` プレフィックスを付与。作業対象WIがある場合は `Work-Item: WI-XXX` trailer を必ず含める。
86
100
 
87
101
  ```
88
102
  [quick] fix: {変更内容の要約}
103
+
104
+ Work-Item: WI-XXX
89
105
  ```
90
106
 
91
107
  ---
@@ -0,0 +1 @@
1
+ npx phasegate commit-msg "$1"
@@ -1,21 +0,0 @@
1
- /**
2
- * @layer application
3
- * @unit adr-foundation
4
- */
5
- export interface SeedAdrDefinition {
6
- readonly title: string;
7
- readonly status: 'Proposed' | 'Accepted' | 'Deprecated' | 'Superseded';
8
- readonly date: string;
9
- readonly body: {
10
- readonly context: string;
11
- readonly decision: string;
12
- readonly consequences: string;
13
- readonly alternatives?: string;
14
- };
15
- readonly archgate?: {
16
- readonly enforcedBy: ReadonlyArray<{
17
- readonly validatorId: string;
18
- readonly errorCode: string;
19
- }>;
20
- };
21
- }
@@ -1,84 +0,0 @@
1
- /**
2
- * @layer application
3
- * @unit adr-foundation
4
- */
5
- import { ADR } from '../../domain/aggregates/adr.js';
6
- import type { AdrDocumentParserPort } from '../../domain/ports/adr-document-parser-port.js';
7
- import type { AdrRepositoryPort } from '../../domain/ports/adr-repository-port.js';
8
- import { AdrValidationService } from '../../domain/services/adr-validation-service.js';
9
- import { AdrId } from '../../domain/value-objects/adr-id.js';
10
- import {
11
- DuplicateAdrIdApplicationError,
12
- SeedAdrDefinitionCountError,
13
- } from '../dto/application-errors.js';
14
- import type { SeedAdrDefinition } from '../dto/seed-adr-definition.js';
15
-
16
- export interface SeedInitialAdrsInput {
17
- readonly definitions: SeedAdrDefinition[];
18
- readonly overwrite?: boolean;
19
- }
20
-
21
- export interface SeedInitialAdrsOutput {
22
- readonly created: readonly string[];
23
- readonly skipped: readonly string[];
24
- }
25
-
26
- export class SeedInitialAdrsUseCase {
27
- constructor(
28
- private readonly adrRepository: AdrRepositoryPort,
29
- private readonly documentParser: AdrDocumentParserPort,
30
- ) {}
31
-
32
- async execute(input: SeedInitialAdrsInput): Promise<Readonly<SeedInitialAdrsOutput>> {
33
- if (input.definitions.length !== 11) {
34
- throw new SeedAdrDefinitionCountError(input.definitions.length);
35
- }
36
-
37
- const created: string[] = [];
38
- const skipped: string[] = [];
39
-
40
- for (const [index, definition] of input.definitions.entries()) {
41
- const adrId = AdrId.create(String(index + 1).padStart(3, '0'));
42
- const adrRef = adrId.toAdrRef();
43
-
44
- if (created.includes(adrRef) || skipped.includes(adrRef)) {
45
- throw new DuplicateAdrIdApplicationError(adrRef);
46
- }
47
-
48
- const adr = ADR.create(
49
- {
50
- adr_id: adrId.value,
51
- title: definition.title,
52
- status: definition.status,
53
- date: definition.date,
54
- archgate: definition.archgate
55
- ? {
56
- adr_id: adrId.value,
57
- enforced_by: definition.archgate.enforcedBy.map((entry) => ({
58
- validator_id: entry.validatorId,
59
- error_code: entry.errorCode,
60
- })),
61
- }
62
- : undefined,
63
- },
64
- definition.body,
65
- new AdrValidationService(),
66
- );
67
-
68
- const exists = await this.adrRepository.exists(adrId);
69
- if (exists && input.overwrite !== true) {
70
- skipped.push(adrRef);
71
- continue;
72
- }
73
-
74
- this.documentParser.serializeDocument(adr);
75
- await this.adrRepository.save(adr);
76
- created.push(adrRef);
77
- }
78
-
79
- return Object.freeze({
80
- created: Object.freeze(created),
81
- skipped: Object.freeze(skipped),
82
- });
83
- }
84
- }
@@ -1,161 +0,0 @@
1
- /**
2
- * @layer infrastructure
3
- * @unit adr-foundation
4
- */
5
- import type { SeedAdrDefinition } from '../../application/dto/seed-adr-definition.js';
6
-
7
- export const INITIAL_ADR_DEFINITIONS: readonly SeedAdrDefinition[] = [
8
- {
9
- title: 'Package separation',
10
- status: 'Accepted',
11
- date: '2026-03-13',
12
- body: {
13
- context:
14
- 'The harness codebase has grown beyond a single-package structure. Build times increase and cross-cutting changes create unnecessary coupling.',
15
- decision:
16
- 'Separate the repository into discrete packages aligned with bounded contexts, each with its own build and test lifecycle.',
17
- consequences:
18
- 'Packages can evolve independently. CI must orchestrate multi-package builds. Shared kernel contracts must be explicitly published.',
19
- },
20
- },
21
- {
22
- title: 'Full migration from ESLint to Biome',
23
- status: 'Accepted',
24
- date: '2026-03-13',
25
- body: {
26
- context:
27
- 'The project currently uses ESLint for linting. Biome offers faster execution and unified formatting with linting in a single tool.',
28
- decision:
29
- 'Migrate all linting and formatting from ESLint and Prettier to Biome as the sole toolchain.',
30
- consequences:
31
- 'Tooling becomes simpler and faster. Custom ESLint rules must be re-implemented as Biome plugins or GritQL patterns.',
32
- alternatives:
33
- 'Keep dual toolchain with ESLint for rules not yet supported by Biome.',
34
- },
35
- },
36
- {
37
- title: 'Quality harness owns K1-K13',
38
- status: 'Accepted',
39
- date: '2026-03-13',
40
- body: {
41
- context:
42
- 'Quality indicators K1 through K13 are defined across multiple documents with no single owner enforcing them.',
43
- decision:
44
- 'The quality harness unit owns the enforcement of all K1-K13 indicators, providing validators and gates for each.',
45
- consequences:
46
- 'A single unit is accountable for quality enforcement. Other units must integrate through the harness contract rather than implementing ad-hoc checks.',
47
- },
48
- },
49
- {
50
- title: 'FUSE Hooks Engine is out of v1 scope',
51
- status: 'Proposed',
52
- date: '2026-03-13',
53
- body: {
54
- context:
55
- 'The FUSE Hooks Engine provides extensible event-driven hooks but adds significant complexity to the initial delivery.',
56
- decision:
57
- 'Defer the FUSE Hooks Engine to a post-v1 phase. The v1 harness will use direct invocation patterns.',
58
- consequences:
59
- 'Reduced initial scope and risk. Hook-based extensibility will require a migration path when introduced later.',
60
- alternatives:
61
- 'Include a minimal hooks engine in v1 with limited extensibility.',
62
- },
63
- },
64
- {
65
- title: 'HarnessError requires fix_example',
66
- status: 'Accepted',
67
- date: '2026-03-13',
68
- body: {
69
- context:
70
- 'Developers receiving harness errors often lack actionable guidance on how to resolve violations.',
71
- decision:
72
- 'Every HarnessError definition must include a fix_example field demonstrating the corrective action.',
73
- consequences:
74
- 'Error definitions are more verbose but significantly more useful. All existing error definitions must be updated to include examples.',
75
- },
76
- },
77
- {
78
- title: 'Strict quick mode eligibility',
79
- status: 'Accepted',
80
- date: '2026-03-13',
81
- body: {
82
- context:
83
- 'Quick mode bypasses expensive validators but must not compromise quality gates for critical changes.',
84
- decision:
85
- 'Define strict eligibility criteria for quick mode based on file change scope and affected layers.',
86
- consequences:
87
- 'Quick mode runs faster for eligible changes. Complex cross-layer changes always run the full validator stack.',
88
- alternatives:
89
- 'Allow developers to manually opt into quick mode regardless of change scope.',
90
- },
91
- },
92
- {
93
- title: 'Separate config files',
94
- status: 'Accepted',
95
- date: '2026-03-13',
96
- body: {
97
- context:
98
- 'A single monolithic configuration file makes it difficult to manage unit-specific settings and increases merge conflicts.',
99
- decision:
100
- 'Split configuration into separate files per concern: phasegate.config.json for core settings, with unit-specific overrides.',
101
- consequences:
102
- 'Configuration is modular and easier to maintain. The config loader must implement a merge strategy for layered configs.',
103
- },
104
- },
105
- {
106
- title: 'Nyquist integration for truths and artifacts',
107
- status: 'Proposed',
108
- date: '2026-03-13',
109
- body: {
110
- context:
111
- 'Nyquist provides a truth-source registry and artifact tracking system that could centralize harness state management.',
112
- decision:
113
- 'Integrate with Nyquist for truth registration and artifact lifecycle tracking.',
114
- consequences:
115
- 'Harness gains a centralized truth source. A dependency on Nyquist availability is introduced.',
116
- alternatives:
117
- 'Build a standalone truth registry within the harness codebase.',
118
- },
119
- },
120
- {
121
- title: 'Artifact-driven state derivation',
122
- status: 'Accepted',
123
- date: '2026-03-13',
124
- body: {
125
- context:
126
- 'Harness state is currently computed on-the-fly, leading to inconsistent results across different invocation points.',
127
- decision:
128
- 'Derive harness state exclusively from persisted artifacts, making state deterministic and reproducible.',
129
- consequences:
130
- 'State becomes auditable and cacheable. All state-changing operations must produce artifacts as their primary output.',
131
- },
132
- },
133
- {
134
- title: 'Validator stack detection',
135
- status: 'Accepted',
136
- date: '2026-03-13',
137
- body: {
138
- context:
139
- 'Validators are registered individually, but their execution order and dependencies are not explicitly managed.',
140
- decision:
141
- 'Implement automatic validator stack detection that resolves execution order based on declared dependencies and layer constraints.',
142
- consequences:
143
- 'Validator execution order is deterministic and verifiable. Circular dependencies are detected at registration time.',
144
- },
145
- },
146
- {
147
- title: 'Temporary 4-layer definition with return path to 5-layer',
148
- status: 'Proposed',
149
- date: '2026-03-13',
150
- body: {
151
- context:
152
- 'The target architecture defines 5 layers, but the current codebase structure and team familiarity support only 4 layers.',
153
- decision:
154
- 'Adopt a temporary 4-layer definition (domain, application, infrastructure, presentation) with a documented return path to the 5-layer target.',
155
- consequences:
156
- 'Initial implementation is simpler. The migration plan to 5 layers must be maintained and reviewed periodically.',
157
- alternatives:
158
- 'Adopt the full 5-layer structure from the start despite the complexity cost.',
159
- },
160
- },
161
- ] as const;