phasegate 0.283.0 → 0.335.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 (115) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/docs/ADR/017-warning-severity-aggregation.md +17 -0
  3. package/docs/ADR/038-config-state-operation-permission-policy.md +78 -0
  4. package/docs/ADR/039-hook-observable-state-as-authorization-unit.md +74 -0
  5. package/docs/ADR/040-quick-mode-config-via-preset-resolution.md +66 -0
  6. package/docs/guide/cli-reference.md +89 -7
  7. package/docs/guide/configuration.md +43 -2
  8. package/docs/guide/layer-model.md +2 -0
  9. package/docs/guide/quick-vs-full-mode.md +63 -3
  10. package/docs/guide/troubleshooting.md +37 -0
  11. package/docs/templates/agent-context/CLAUDE.md.template.md +6 -6
  12. package/package.json +2 -2
  13. package/scripts/harness/agent-integration/application/dto/handle-pre-tool-use-dto.ts +5 -1
  14. package/scripts/harness/agent-integration/application/usecases/handle-pre-tool-use-usecase.ts +108 -20
  15. package/scripts/harness/agent-integration/domain/services/bash-write-target-extractor.ts +215 -5
  16. package/scripts/harness/agent-integration/domain/value-objects/protected-file-list.ts +5 -0
  17. package/scripts/harness/agent-integration/infrastructure/adapters/file-system-full-mode-session-query-adapter.ts +75 -23
  18. package/scripts/harness/agent-integration/infrastructure/adapters/harness-config-config-query-adapter.ts +18 -3
  19. package/scripts/harness/agent-integration/infrastructure/adapters/quick-mode-full-mode-requirement-adapter.ts +15 -1
  20. package/scripts/harness/agent-integration/presentation/pre-tool-use-hook.ts +57 -9
  21. package/scripts/harness/ci-governance/application/dto/scaffold-inception-input.ts +9 -0
  22. package/scripts/harness/ci-governance/application/dto/scaffold-inception-output.ts +13 -0
  23. package/scripts/harness/ci-governance/application/usecases/list-templates-usecase.ts +30 -0
  24. package/scripts/harness/ci-governance/application/usecases/scaffold-inception-usecase.ts +63 -0
  25. package/scripts/harness/ci-governance/application/usecases/show-template-usecase.ts +39 -0
  26. package/scripts/harness/ci-governance/composition-root.ts +57 -5
  27. package/scripts/harness/ci-governance/domain/ports/inception-doc-writer-port.ts +19 -0
  28. package/scripts/harness/ci-governance/domain/ports/inception-template-repository-port.ts +16 -0
  29. package/scripts/harness/ci-governance/domain/ports/template-catalog-port.ts +23 -0
  30. package/scripts/harness/ci-governance/domain/services/claude-md-composer.ts +20 -11
  31. package/scripts/harness/ci-governance/domain/value-objects/inception-doc-kind.ts +109 -0
  32. package/scripts/harness/ci-governance/domain/value-objects/template-catalog-entry.ts +53 -0
  33. package/scripts/harness/ci-governance/domain/value-objects/template-name.ts +50 -0
  34. package/scripts/harness/ci-governance/infrastructure/adapters/file-system-inception-doc-writer-adapter.ts +42 -0
  35. package/scripts/harness/ci-governance/infrastructure/adapters/file-system-inception-template-repository-adapter.ts +32 -0
  36. package/scripts/harness/ci-governance/infrastructure/adapters/file-system-template-catalog-adapter.ts +60 -0
  37. package/scripts/harness/ci-governance/presentation/handlers/check-repetition-handler.ts +10 -2
  38. package/scripts/harness/ci-governance/presentation/handlers/scaffold-inception-handler.ts +101 -0
  39. package/scripts/harness/ci-governance/presentation/handlers/templates-handler.ts +103 -0
  40. package/scripts/harness/config-foundation/domain/harness-config.ts +12 -0
  41. package/scripts/harness/config-foundation/infrastructure/presets/minimal.json +3 -3
  42. package/scripts/harness/config-foundation/infrastructure/presets/standard.json +3 -3
  43. package/scripts/harness/config-foundation/infrastructure/presets/strict.json +3 -3
  44. package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v2.schema.json +44 -1
  45. package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json +42 -1
  46. package/scripts/harness/harness-api/domain/services/command-dispatch-service.ts +12 -3
  47. package/scripts/harness/harness-api/domain/value-objects/ci-check-result.ts +2 -22
  48. package/scripts/harness/harness-api/domain/value-objects/known-harness-commands.ts +3 -1
  49. package/scripts/harness/harness-error/application/dto/create-harness-error-input.ts +3 -1
  50. package/scripts/harness/harness-error/application/dto/harness-error-contract.ts +3 -1
  51. package/scripts/harness/harness-error/application/mappers/harness-error-contract-mapper.ts +9 -17
  52. package/scripts/harness/harness-error/application/usecases/create-harness-error-use-case.ts +7 -7
  53. package/scripts/harness/harness-error/domain/services/harness-error-factory.ts +30 -33
  54. package/scripts/harness/harness-error/domain/value-objects/error-definition.ts +28 -17
  55. package/scripts/harness/harness-error/domain/value-objects/harness-error.ts +30 -9
  56. package/scripts/harness/harness-error/domain/value-objects/remediation-type.ts +30 -0
  57. package/scripts/harness/harness-error/infrastructure/registry/l2-error-definitions.ts +44 -29
  58. package/scripts/harness/harness-error/infrastructure/registry/l3-error-definitions.ts +44 -27
  59. package/scripts/harness/harness-error/infrastructure/registry/l4-error-definitions.ts +47 -32
  60. package/scripts/harness/installation/application/checks/claude-context-missing-check.ts +13 -7
  61. package/scripts/harness/installation/application/checks/config-status-check.ts +52 -0
  62. package/scripts/harness/installation/application/checks/husky-pre-commit-missing-check.ts +6 -0
  63. package/scripts/harness/installation/application/ports/config-status-probe-port.ts +9 -0
  64. package/scripts/harness/installation/application/usecases/run-doctor-diagnostics.ts +30 -8
  65. package/scripts/harness/installation/application/usecases/run-install.ts +44 -11
  66. package/scripts/harness/installation/application/usecases/run-reconcile.ts +44 -11
  67. package/scripts/harness/installation/composition-root.ts +13 -3
  68. package/scripts/harness/installation/domain/check-id.ts +2 -0
  69. package/scripts/harness/installation/domain/config-status.ts +17 -0
  70. package/scripts/harness/installation/domain/ports/heuristic-check.ts +10 -1
  71. package/scripts/harness/installation/infrastructure/adapters/config-status-probe-adapter.ts +79 -0
  72. package/scripts/harness/installation/presentation/cli/doctor-handler.ts +6 -1
  73. package/scripts/harness/installation/presentation/formatters/diagnostic-report-formatter.ts +19 -5
  74. package/scripts/harness/integrations/pre-commit.ts +17 -3
  75. package/scripts/harness/main.ts +159 -21
  76. package/scripts/harness/phase-dependency-model/application/services/evidence-bundle-assembler.ts +2 -1
  77. package/scripts/harness/phase-dependency-model/domain/ports/plan-document-reader-port.ts +12 -0
  78. package/scripts/harness/phase-dependency-model/infrastructure/filesystem/markdown-plan-document-reader.ts +64 -33
  79. package/scripts/harness/phase2-extensions/presentation/handlers/check-freshness-handler.ts +17 -9
  80. package/scripts/harness/quick-mode/application/ports/file-existence-port.ts +15 -0
  81. package/scripts/harness/quick-mode/application/usecases/classify-change-category-usecase.ts +60 -22
  82. package/scripts/harness/quick-mode/composition-root.ts +25 -15
  83. package/scripts/harness/quick-mode/domain/errors/quick-mode-config-error.ts +19 -0
  84. package/scripts/harness/quick-mode/domain/services/quick-mode-judgment-engine.ts +116 -18
  85. package/scripts/harness/quick-mode/domain/value-objects/category-override-rules.ts +147 -0
  86. package/scripts/harness/quick-mode/domain/value-objects/change-category.ts +33 -0
  87. package/scripts/harness/quick-mode/domain/value-objects/quick-mode-config.ts +31 -10
  88. package/scripts/harness/quick-mode/index.ts +7 -1
  89. package/scripts/harness/quick-mode/infrastructure/adapters/fs-file-existence-adapter.ts +38 -0
  90. package/scripts/harness/quick-mode/infrastructure/adapters/harness-config-quick-mode-config-adapter.ts +83 -32
  91. package/scripts/harness/skill-quality/infrastructure/adapters/file-system-requirement-test-matrix-adapter.ts +51 -8
  92. package/scripts/harness/skill-quality/presentation/handlers/check-coverage-handler.ts +13 -6
  93. package/scripts/harness/traceability-model/domain/value-objects/work-item-frontmatter.ts +5 -1
  94. package/scripts/harness/traceability-model/infrastructure/gateways/file-system-work-item-identity-gateway.ts +6 -1
  95. package/scripts/harness/traceability-model/infrastructure/gateways/file-system-work-item-status-gateway.ts +15 -2
  96. package/scripts/harness/validator-system/application/use-cases/aggregate-validation-results-usecase.ts +11 -14
  97. package/scripts/harness/validator-system/application/use-cases/run-l3-validators-usecase.ts +8 -0
  98. package/scripts/harness/validator-system/domain/services/effective-severity-policy.ts +39 -0
  99. package/scripts/harness/validator-system/domain/value-objects/consistency-report.ts +6 -4
  100. package/scripts/harness/validator-system/domain/value-objects/drift-report.ts +12 -7
  101. package/scripts/harness/validator-system/domain/value-objects/validation-result.ts +11 -3
  102. package/scripts/harness/validator-system/infrastructure/adapters/file-system-security-pattern-scanner-adapter.ts +20 -17
  103. package/scripts/harness/validator-system/infrastructure/adapters/phase-dependency-phase-gate-policy-adapter.ts +35 -14
  104. package/scripts/harness/validator-system/infrastructure/adapters/traceability-metadata-policy-adapter.ts +13 -8
  105. package/scripts/harness/validator-system/presentation/formatters/agent-validation-result-formatter.ts +19 -10
  106. package/skills/product-architect/SKILL.md +19 -0
  107. package/skills/quick-implementor/SKILL.md +19 -0
  108. package/skills/story-mapper/SKILL.md +11 -0
  109. package/skills/story-writer/SKILL.md +11 -0
  110. package/skills/unit-designer/SKILL.md +11 -0
  111. package/templates/product_overview.template.md +85 -0
  112. package/templates/product_overview_plan.template.md +55 -0
  113. package/templates/story_mapping_plan.template.md +61 -0
  114. package/templates/story_writer_plan.template.md +61 -0
  115. package/templates/unit_design_plan.template.md +63 -0
@@ -0,0 +1,103 @@
1
+ // @unit ci-governance
2
+ // @layer presentation
3
+ // @work-item-id WI-367
4
+
5
+ import type { ListTemplatesUseCase } from "../../application/usecases/list-templates-usecase.js";
6
+ import type { ShowTemplateUseCase } from "../../application/usecases/show-template-usecase.js";
7
+
8
+ export interface TemplatesHandlerResult {
9
+ readonly exitCode: number;
10
+ /** stdout に出す内容(空文字なら出力しない) */
11
+ readonly output: string;
12
+ /** stderr に出す内容(空文字なら出力しない) */
13
+ readonly errorOutput: string;
14
+ }
15
+
16
+ export interface TemplatesListArgs {
17
+ readonly format?: "human" | "json";
18
+ }
19
+
20
+ export interface TemplatesShowArgs {
21
+ readonly name?: string;
22
+ }
23
+
24
+ const USAGE = "Usage: phasegate templates <list|show <name>>";
25
+
26
+ export class TemplatesHandler {
27
+ constructor(
28
+ private readonly listUseCase: ListTemplatesUseCase,
29
+ private readonly showUseCase: ShowTemplateUseCase,
30
+ ) {}
31
+
32
+ async list(args: TemplatesListArgs = {}): Promise<TemplatesHandlerResult> {
33
+ const result = await this.listUseCase.execute();
34
+
35
+ if (args.format === "json") {
36
+ return {
37
+ exitCode: 0,
38
+ output: JSON.stringify(result, null, 2),
39
+ errorOutput: "",
40
+ };
41
+ }
42
+
43
+ if (result.templates.length === 0) {
44
+ return {
45
+ exitCode: 0,
46
+ output: [
47
+ "Available templates (0):",
48
+ "",
49
+ ` テンプレートディレクトリが見つかりません: ${result.directoryPath}`,
50
+ ].join("\n"),
51
+ errorOutput: "",
52
+ };
53
+ }
54
+
55
+ const lines = [`Available templates (${result.templates.length}):`, ""];
56
+ for (const entry of result.templates) {
57
+ lines.push(` ${entry.name} (${entry.fileName})`);
58
+ }
59
+ lines.push("", "本文を表示: phasegate templates show <name>");
60
+
61
+ return { exitCode: 0, output: lines.join("\n"), errorOutput: "" };
62
+ }
63
+
64
+ async show(args: TemplatesShowArgs): Promise<TemplatesHandlerResult> {
65
+ const rawName = args.name ?? "";
66
+ if (rawName.length === 0) {
67
+ return {
68
+ exitCode: 2,
69
+ output: "",
70
+ errorOutput: "Usage: phasegate templates show <name>",
71
+ };
72
+ }
73
+
74
+ const result = await this.showUseCase.execute(rawName);
75
+
76
+ if (result.found) {
77
+ // テンプレート本文だけを stdout に出す。リダイレクトでそのまま文書として保存できる。
78
+ return { exitCode: 0, output: result.content, errorOutput: "" };
79
+ }
80
+
81
+ if (result.reason === "invalid-name") {
82
+ return {
83
+ exitCode: 2,
84
+ output: "",
85
+ errorOutput: [
86
+ `Invalid template name: ${rawName}`,
87
+ "テンプレート名は英小文字・数字・_ ・- のみで指定してください(パスは指定できません)。",
88
+ USAGE,
89
+ ].join("\n"),
90
+ };
91
+ }
92
+
93
+ return {
94
+ exitCode: 2,
95
+ output: "",
96
+ errorOutput: [`Template not found: ${rawName}`, `Available: ${result.availableNames.join(", ")}`].join("\n"),
97
+ };
98
+ }
99
+
100
+ usage(): TemplatesHandlerResult {
101
+ return { exitCode: 2, output: "", errorOutput: USAGE };
102
+ }
103
+ }
@@ -99,6 +99,18 @@ export interface HarnessConfigResolvedDocument {
99
99
  allowedCategories: string[];
100
100
  maintainedLayers: string[];
101
101
  relaxedGates: string[];
102
+ // WI-377: JSON Schema (v2/v3) は当該キーを許容し preset 解決の deepMerge も
103
+ // 実行時には保持していたが、型宣言だけが欠けていた。preset 定義側は宣言しないため optional。
104
+ fullModeRequiredWhen?: {
105
+ mixedCategories?: boolean;
106
+ newDomainFile?: boolean;
107
+ apiContractChange?: boolean;
108
+ };
109
+ // WI-372: プロジェクト固有パスのカテゴリ割当(quick-mode unit が消費する)。
110
+ // preset には既定を持たせず、source config 側でのみ指定する任意項目。
111
+ // preset 解決の deepMerge は preset 側に無いキーを source からそのまま引き継ぐため、
112
+ // 明示宣言は WI-377 の preset 解決経路を通しても保持される。
113
+ categoryOverrides?: Record<string, string[]>;
102
114
  };
103
115
  phaseDependencies: {
104
116
  preset: PhaseDependenciesPresetId;
@@ -21,9 +21,9 @@
21
21
  }
22
22
  },
23
23
  "quickMode": {
24
- "allowedCategories": ["bugfix"],
25
- "maintainedLayers": ["L1", "L2"],
26
- "relaxedGates": []
24
+ "allowedCategories": ["bugfix", "docs", "test", "config"],
25
+ "maintainedLayers": ["L1", "L2-002", "L2-003", "L2-014", "L3-001"],
26
+ "relaxedGates": ["L2-001", "L3-002", "L3-003", "L3-004", "L4"]
27
27
  },
28
28
  "phaseDependencies": {
29
29
  "preset": "default",
@@ -21,9 +21,9 @@
21
21
  }
22
22
  },
23
23
  "quickMode": {
24
- "allowedCategories": ["bugfix"],
25
- "maintainedLayers": ["L1", "L2"],
26
- "relaxedGates": []
24
+ "allowedCategories": ["bugfix", "docs", "test", "config"],
25
+ "maintainedLayers": ["L1", "L2-002", "L2-003", "L2-014", "L3-001"],
26
+ "relaxedGates": ["L2-001", "L3-002", "L3-003", "L3-004", "L4"]
27
27
  },
28
28
  "phaseDependencies": {
29
29
  "preset": "default",
@@ -21,9 +21,9 @@
21
21
  }
22
22
  },
23
23
  "quickMode": {
24
- "allowedCategories": ["bugfix"],
25
- "maintainedLayers": ["L1", "L2"],
26
- "relaxedGates": []
24
+ "allowedCategories": ["bugfix", "docs", "test", "config"],
25
+ "maintainedLayers": ["L1", "L2-002", "L2-003", "L2-014", "L3-001"],
26
+ "relaxedGates": ["L2-001", "L3-002", "L3-003", "L3-004", "L4"]
27
27
  },
28
28
  "phaseDependencies": {
29
29
  "preset": "default",
@@ -5,6 +5,20 @@
5
5
  "required": [
6
6
  "project"
7
7
  ],
8
+ "$defs": {
9
+ "changeCategory": {
10
+ "type": "string",
11
+ "enum": ["bugfix", "docs", "test", "config", "feature", "domain", "api"]
12
+ },
13
+ "categoryOverrideGlobs": {
14
+ "type": "array",
15
+ "items": {
16
+ "type": "string",
17
+ "minLength": 1
18
+ },
19
+ "uniqueItems": true
20
+ }
21
+ },
8
22
  "properties": {
9
23
  "project": {
10
24
  "type": "object",
@@ -160,9 +174,10 @@
160
174
  "additionalProperties": false,
161
175
  "properties": {
162
176
  "allowedCategories": {
177
+ "description": "Quick Mode を通過させる ChangeCategory。7 値の enum で、未知値は設定エラーとして拒否される。",
163
178
  "type": "array",
164
179
  "items": {
165
- "type": "string"
180
+ "$ref": "#/$defs/changeCategory"
166
181
  },
167
182
  "uniqueItems": true
168
183
  },
@@ -194,6 +209,34 @@
194
209
  "type": "boolean"
195
210
  }
196
211
  }
212
+ },
213
+ "categoryOverrides": {
214
+ "description": "プロジェクト固有パスを任意の ChangeCategory へ割り当てる glob ルール。",
215
+ "type": "object",
216
+ "additionalProperties": false,
217
+ "properties": {
218
+ "bugfix": {
219
+ "$ref": "#/$defs/categoryOverrideGlobs"
220
+ },
221
+ "docs": {
222
+ "$ref": "#/$defs/categoryOverrideGlobs"
223
+ },
224
+ "test": {
225
+ "$ref": "#/$defs/categoryOverrideGlobs"
226
+ },
227
+ "config": {
228
+ "$ref": "#/$defs/categoryOverrideGlobs"
229
+ },
230
+ "feature": {
231
+ "$ref": "#/$defs/categoryOverrideGlobs"
232
+ },
233
+ "domain": {
234
+ "$ref": "#/$defs/categoryOverrideGlobs"
235
+ },
236
+ "api": {
237
+ "$ref": "#/$defs/categoryOverrideGlobs"
238
+ }
239
+ }
197
240
  }
198
241
  }
199
242
  },
@@ -13,6 +13,18 @@
13
13
  "decisionSignal": {
14
14
  "type": "string",
15
15
  "enum": ["business-rule-branch", "validation-rule", "error-construction", "state-transition", "policy-selection"]
16
+ },
17
+ "changeCategory": {
18
+ "type": "string",
19
+ "enum": ["bugfix", "docs", "test", "config", "feature", "domain", "api"]
20
+ },
21
+ "categoryOverrideGlobs": {
22
+ "type": "array",
23
+ "items": {
24
+ "type": "string",
25
+ "minLength": 1
26
+ },
27
+ "uniqueItems": true
16
28
  }
17
29
  },
18
30
  "properties": {
@@ -170,9 +182,10 @@
170
182
  "additionalProperties": false,
171
183
  "properties": {
172
184
  "allowedCategories": {
185
+ "description": "Quick Mode を通過させる ChangeCategory。7 値の enum で、未知値は設定エラーとして拒否される。",
173
186
  "type": "array",
174
187
  "items": {
175
- "type": "string"
188
+ "$ref": "#/$defs/changeCategory"
176
189
  },
177
190
  "uniqueItems": true
178
191
  },
@@ -204,6 +217,34 @@
204
217
  "type": "boolean"
205
218
  }
206
219
  }
220
+ },
221
+ "categoryOverrides": {
222
+ "description": "プロジェクト固有パスを任意の ChangeCategory へ割り当てる glob ルール。組み込み分類より先に評価されるが、組み込みが domain / api のファイルは降格できない。",
223
+ "type": "object",
224
+ "additionalProperties": false,
225
+ "properties": {
226
+ "bugfix": {
227
+ "$ref": "#/$defs/categoryOverrideGlobs"
228
+ },
229
+ "docs": {
230
+ "$ref": "#/$defs/categoryOverrideGlobs"
231
+ },
232
+ "test": {
233
+ "$ref": "#/$defs/categoryOverrideGlobs"
234
+ },
235
+ "config": {
236
+ "$ref": "#/$defs/categoryOverrideGlobs"
237
+ },
238
+ "feature": {
239
+ "$ref": "#/$defs/categoryOverrideGlobs"
240
+ },
241
+ "domain": {
242
+ "$ref": "#/$defs/categoryOverrideGlobs"
243
+ },
244
+ "api": {
245
+ "$ref": "#/$defs/categoryOverrideGlobs"
246
+ }
247
+ }
207
248
  }
208
249
  }
209
250
  },
@@ -1,6 +1,6 @@
1
1
  // @layer domain
2
2
  // @unit harness-api
3
- // @work-item-id WI-108 / WI-114, WI-186, WI-318, WI-321, WI-328
3
+ // @work-item-id WI-108 / WI-114, WI-186, WI-318, WI-321, WI-328, WI-339
4
4
  // command-dispatch-service.ts — CommandDispatchService Domain Service
5
5
 
6
6
  import type { ArtifactScannerPort } from "../ports/artifact-scanner-port.js";
@@ -10,7 +10,7 @@ import type { ImpactAnalysisPort } from "../ports/impact-analysis-port.js";
10
10
  import type { PhaseGateQueryPort } from "../ports/phase-gate-query-port.js";
11
11
  import type { ValidatorExecutionPort } from "../ports/validator-execution-port.js";
12
12
  import { CheckReadyResult } from "../value-objects/check-ready-result.js";
13
- import { CiCheckResult } from "../value-objects/ci-check-result.js";
13
+ import { CiCheckResult, type ValidatorCheckItem } from "../value-objects/ci-check-result.js";
14
14
  import { DriftReportSummary } from "../value-objects/drift-report-summary.js";
15
15
  import { type ExitCode, HarnessApiResponse, type HarnessError } from "../value-objects/harness-api-response.js";
16
16
  import type {
@@ -76,6 +76,15 @@ function summarizeLayerResults(
76
76
  return result;
77
77
  }
78
78
 
79
+ /**
80
+ * WI-339: status の layer 集計へ渡す前に、ci-check / complete-check と同じ
81
+ * CiCheckResult 投影で raw passed を実効 passed に正規化する。
82
+ * failOnWarning は既存 harness-api 経路と同じ既定値 false を使用する。
83
+ */
84
+ function toEffectiveValidatorResults(items: readonly ValidatorCheckItem[]): readonly ValidatorCheckItem[] {
85
+ return items.length === 0 ? items : CiCheckResult.fromResults(items).validatorResults;
86
+ }
87
+
79
88
  function hasEnabledLiveFailure(
80
89
  enabledLayers: readonly LayerId[],
81
90
  liveValidationByLayer: Partial<Record<LayerId, LiveValidationState>>,
@@ -248,7 +257,7 @@ export class CommandDispatchService {
248
257
  this.ports.validatorExecutionPort.runAllValidators(),
249
258
  ]);
250
259
  liveValidationByLayer.L1 = lintResult.passed ? "pass" : "fail";
251
- Object.assign(liveValidationByLayer, summarizeLayerResults(validatorResults));
260
+ Object.assign(liveValidationByLayer, summarizeLayerResults(toEffectiveValidatorResults(validatorResults)));
252
261
  } catch {
253
262
  liveValidationByLayer.L1 = liveValidationByLayer.L1 ?? "error";
254
263
  }
@@ -1,8 +1,10 @@
1
1
  // @layer domain
2
2
  // @unit harness-api
3
3
  // @work-item-id WI-307
4
+ // @work-item-id WI-332
4
5
  // ci-check-result.ts — CiCheckResult Value Object
5
6
 
7
+ import { isEffectivelyPassed } from "../../../validator-system/domain/services/effective-severity-policy.js";
6
8
  import type { HarnessError } from "./harness-api-response.js";
7
9
 
8
10
  export interface ValidatorCheckItem {
@@ -19,28 +21,6 @@ export interface CiCheckResultProps {
19
21
  failOnWarning?: boolean;
20
22
  }
21
23
 
22
- /**
23
- * WI-260 / ADR-017: validator 1件が「実質 pass」か判定する severity-aware ルール。
24
- * `validate` 経路の AggregateValidationResultsUseCase と同一の判定式を harness-api の
25
- * domain VO 側に持たせ、ci-check と validate の集約挙動を一致させる(レイヤー越境回避のため
26
- * usecase を直接 import せず判定ロジックを共有)。
27
- *
28
- * - skipped: 実質 pass
29
- * - passed=true: 実質 pass
30
- * - passed=false かつ error severity(!= warning)を含む: fail
31
- * - passed=false かつ errors=[](severity 判定不能): 安全側に倒して fail
32
- * - passed=false かつ warning のみ: failOnWarning=false(既定)で実質 pass、true で fail
33
- */
34
- function isEffectivelyPassed(item: ValidatorCheckItem, failOnWarning: boolean): boolean {
35
- if (item.skipped || item.passed) return true;
36
- const errors = item.errors ?? [];
37
- const hasNonWarningError = errors.some((e) => e.severity !== "warning");
38
- const hasWarnings = errors.some((e) => e.severity === "warning");
39
- const isEmptyFail = errors.length === 0;
40
- const hasFail = isEmptyFail || hasNonWarningError || (failOnWarning && hasWarnings);
41
- return !hasFail;
42
- }
43
-
44
24
  /**
45
25
  * WI-307: public ci-check projection の `passed` を aggregate policy と一致させる。
46
26
  * skipped は独立した green state のため raw passed を維持し、warning-only failure だけを
@@ -1,6 +1,6 @@
1
1
  // @unit harness-api
2
2
  // @layer domain
3
- // @work-item-id WI-250, WI-291, WI-296
3
+ // @work-item-id WI-250, WI-291, WI-296, WI-367, WI-368
4
4
  // known-harness-commands.ts — CLI 実サーフェスの canonical 既知コマンド一覧
5
5
  //
6
6
  // main.ts の CLI dispatch(`switch (command)`)が受理する全トップレベルコマンド名の
@@ -70,6 +70,7 @@ export const KNOWN_HARNESS_COMMANDS: readonly string[] = Object.freeze([
70
70
  "regression:run-k14-k15",
71
71
  "render-errors",
72
72
  "scaffold-design",
73
+ "scaffold-inception",
73
74
  "scaffold-wi",
74
75
  "session",
75
76
  "setup:agent",
@@ -80,6 +81,7 @@ export const KNOWN_HARNESS_COMMANDS: readonly string[] = Object.freeze([
80
81
  "skill:validate-structure",
81
82
  "skills",
82
83
  "status",
84
+ "templates",
83
85
  "uninstall",
84
86
  "update-skills",
85
87
  "validate",
@@ -8,11 +8,13 @@ export interface CreateHarnessErrorInput {
8
8
  readonly code: string;
9
9
  readonly message: string;
10
10
  readonly suggestion: string;
11
- readonly severity?: 'error' | 'warning';
11
+ readonly severity?: "error" | "warning";
12
12
  readonly adrRef?: string;
13
13
  readonly fixExample?: string;
14
14
  readonly validatorId: string;
15
15
  readonly suggestedSkill?: string;
16
16
  readonly scaffoldCommand?: string;
17
17
  readonly templatePath?: string;
18
+ /** WI-335: 修復方式分類。省略時は ErrorDefinition の既定(未定義なら manual 扱い)。 */
19
+ readonly remediationType?: "mechanical" | "ai-assisted" | "manual";
18
20
  }
@@ -3,7 +3,7 @@
3
3
 
4
4
  export interface HarnessErrorContract {
5
5
  readonly code: string;
6
- readonly severity: 'error' | 'warning';
6
+ readonly severity: "error" | "warning";
7
7
  readonly message: string;
8
8
  readonly suggestion: string;
9
9
  readonly adr_ref?: string;
@@ -11,4 +11,6 @@ export interface HarnessErrorContract {
11
11
  readonly suggested_skill?: string;
12
12
  readonly scaffold_command?: string;
13
13
  readonly template_path?: string;
14
+ /** WI-335: 修復方式分類(mechanical / ai-assisted / manual)。未設定は manual 扱い。 */
15
+ readonly remediation_type?: "mechanical" | "ai-assisted" | "manual";
14
16
  }
@@ -4,8 +4,9 @@
4
4
  *
5
5
  * HarnessErrorContract への投影Mapper
6
6
  */
7
- import type { HarnessErrorContract } from '../dto/harness-error-contract.js';
8
- import type { HarnessError } from '../../domain/value-objects/harness-error.js';
7
+
8
+ import type { HarnessError } from "../../domain/value-objects/harness-error.js";
9
+ import type { HarnessErrorContract } from "../dto/harness-error-contract.js";
9
10
 
10
11
  export class HarnessErrorContractMapper {
11
12
  toReadonlyContract(harnessError: HarnessError): Readonly<HarnessErrorContract> {
@@ -14,21 +15,12 @@ export class HarnessErrorContractMapper {
14
15
  severity: harnessError.severity.toString(),
15
16
  message: harnessError.message,
16
17
  suggestion: harnessError.suggestion,
17
- ...(harnessError.adrRef !== null
18
- ? { adr_ref: harnessError.adrRef.toString() }
19
- : {}),
20
- ...(harnessError.fixExample !== null
21
- ? { fix_example: harnessError.fixExample.toString() }
22
- : {}),
23
- ...(harnessError.suggestedSkill !== null
24
- ? { suggested_skill: harnessError.suggestedSkill }
25
- : {}),
26
- ...(harnessError.scaffoldCommand !== null
27
- ? { scaffold_command: harnessError.scaffoldCommand }
28
- : {}),
29
- ...(harnessError.templatePath !== null
30
- ? { template_path: harnessError.templatePath }
31
- : {}),
18
+ ...(harnessError.adrRef !== null ? { adr_ref: harnessError.adrRef.toString() } : {}),
19
+ ...(harnessError.fixExample !== null ? { fix_example: harnessError.fixExample.toString() } : {}),
20
+ ...(harnessError.suggestedSkill !== null ? { suggested_skill: harnessError.suggestedSkill } : {}),
21
+ ...(harnessError.scaffoldCommand !== null ? { scaffold_command: harnessError.scaffoldCommand } : {}),
22
+ ...(harnessError.templatePath !== null ? { template_path: harnessError.templatePath } : {}),
23
+ ...(harnessError.remediationType !== null ? { remediation_type: harnessError.remediationType } : {}),
32
24
  };
33
25
 
34
26
  return Object.freeze(contract);
@@ -4,10 +4,11 @@
4
4
  *
5
5
  * 単一draftを HarnessErrorContract へ変換するUseCase
6
6
  */
7
- import type { CreateHarnessErrorInput } from '../dto/create-harness-error-input.js';
8
- import type { HarnessErrorContract } from '../dto/harness-error-contract.js';
9
- import type { HarnessErrorContractMapper } from '../mappers/harness-error-contract-mapper.js';
10
- import type { HarnessErrorFactory } from '../../domain/services/harness-error-factory.js';
7
+
8
+ import type { HarnessErrorFactory } from "../../domain/services/harness-error-factory.js";
9
+ import type { CreateHarnessErrorInput } from "../dto/create-harness-error-input.js";
10
+ import type { HarnessErrorContract } from "../dto/harness-error-contract.js";
11
+ import type { HarnessErrorContractMapper } from "../mappers/harness-error-contract-mapper.js";
11
12
 
12
13
  export interface CreateHarnessErrorUseCaseDeps {
13
14
  readonly harnessErrorFactory: HarnessErrorFactory;
@@ -23,9 +24,7 @@ export class CreateHarnessErrorUseCase {
23
24
  this.contractMapper = deps.contractMapper;
24
25
  }
25
26
 
26
- async execute(
27
- input: CreateHarnessErrorInput
28
- ): Promise<Readonly<HarnessErrorContract>> {
27
+ async execute(input: CreateHarnessErrorInput): Promise<Readonly<HarnessErrorContract>> {
29
28
  const harnessError = await this.harnessErrorFactory.create({
30
29
  code: input.code,
31
30
  message: input.message,
@@ -37,6 +36,7 @@ export class CreateHarnessErrorUseCase {
37
36
  suggestedSkill: input.suggestedSkill,
38
37
  scaffoldCommand: input.scaffoldCommand,
39
38
  templatePath: input.templatePath,
39
+ remediationType: input.remediationType,
40
40
  });
41
41
 
42
42
  return this.contractMapper.toReadonlyContract(harnessError);
@@ -5,33 +5,36 @@
5
5
  * HarnessErrorFactory ドメインサービス
6
6
  * ErrorDefinitionRegistry と Domain ポートを組み合わせて HarnessError を生成する唯一の入口
7
7
  */
8
- import { AdrReferenceNotFoundError } from '../errors/adr-reference-not-found-error.js';
9
- import { EmptyMessageError } from '../errors/empty-message-error.js';
10
- import { EmptySuggestionError } from '../errors/empty-suggestion-error.js';
11
- import { InvalidFixExampleError } from '../errors/invalid-fix-example-error.js';
12
- import { MissingAdrRefError } from '../errors/missing-adr-ref-error.js';
13
- import { MissingFixExampleError } from '../errors/missing-fix-example-error.js';
14
- import type { AdrExistenceCheckerPort } from '../ports/adr-existence-checker-port.js';
15
- import type { FixExampleValidatorPort } from '../ports/fix-example-validator-port.js';
16
- import { AdrRef } from '../value-objects/adr-ref.js';
17
- import { ErrorCode } from '../value-objects/error-code.js';
18
- import { FixExample } from '../value-objects/fix-example.js';
19
- import { HarnessError } from '../value-objects/harness-error.js';
20
- import { Severity } from '../value-objects/severity.js';
21
- import type { ErrorDefinitionRegistry } from './error-definition-registry.js';
22
- import type { SeverityContractEnforcer } from './severity-contract-enforcer.js';
8
+ import { AdrReferenceNotFoundError } from "../errors/adr-reference-not-found-error.js";
9
+ import { EmptyMessageError } from "../errors/empty-message-error.js";
10
+ import { EmptySuggestionError } from "../errors/empty-suggestion-error.js";
11
+ import { InvalidFixExampleError } from "../errors/invalid-fix-example-error.js";
12
+ import { MissingAdrRefError } from "../errors/missing-adr-ref-error.js";
13
+ import { MissingFixExampleError } from "../errors/missing-fix-example-error.js";
14
+ import type { AdrExistenceCheckerPort } from "../ports/adr-existence-checker-port.js";
15
+ import type { FixExampleValidatorPort } from "../ports/fix-example-validator-port.js";
16
+ import { AdrRef } from "../value-objects/adr-ref.js";
17
+ import { ErrorCode } from "../value-objects/error-code.js";
18
+ import { FixExample } from "../value-objects/fix-example.js";
19
+ import { HarnessError } from "../value-objects/harness-error.js";
20
+ import type { RemediationType } from "../value-objects/remediation-type.js";
21
+ import { Severity } from "../value-objects/severity.js";
22
+ import type { ErrorDefinitionRegistry } from "./error-definition-registry.js";
23
+ import type { SeverityContractEnforcer } from "./severity-contract-enforcer.js";
23
24
 
24
25
  export interface CreateHarnessErrorParams {
25
26
  readonly code: string;
26
27
  readonly message: string;
27
28
  readonly suggestion: string;
28
29
  readonly validatorId: string;
29
- readonly requestedSeverity?: 'error' | 'warning';
30
+ readonly requestedSeverity?: "error" | "warning";
30
31
  readonly adrRef?: string | null;
31
32
  readonly fixExample?: string | null;
32
33
  readonly suggestedSkill?: string | null;
33
34
  readonly scaffoldCommand?: string | null;
34
35
  readonly templatePath?: string | null;
36
+ /** WI-335: suggestion の修復方式分類。省略時は ErrorDefinition の既定に従う。 */
37
+ readonly remediationType?: RemediationType | null;
35
38
  }
36
39
 
37
40
  export interface HarnessErrorFactoryDeps {
@@ -68,18 +71,14 @@ export class HarnessErrorFactory {
68
71
  const definition = this.registry.getDefinition(errorCode);
69
72
 
70
73
  // 3. severity 解決
71
- const requestedSeverity = input.requestedSeverity
72
- ? Severity.create(input.requestedSeverity)
73
- : undefined;
74
- const effectiveSeverity =
75
- this.severityContractEnforcer.resolveEffectiveSeverity(
76
- requestedSeverity,
77
- definition.defaultSeverity
78
- );
74
+ const requestedSeverity = input.requestedSeverity ? Severity.create(input.requestedSeverity) : undefined;
75
+ const effectiveSeverity = this.severityContractEnforcer.resolveEffectiveSeverity(
76
+ requestedSeverity,
77
+ definition.defaultSeverity,
78
+ );
79
79
 
80
80
  // 4. ADR 解決
81
- const explicitAdrRef =
82
- input.adrRef != null ? AdrRef.create(input.adrRef) : undefined;
81
+ const explicitAdrRef = input.adrRef != null ? AdrRef.create(input.adrRef) : undefined;
83
82
  const resolvedAdrRef = definition.resolveAdrRef(explicitAdrRef);
84
83
 
85
84
  // 5. ADR 必須チェック
@@ -96,12 +95,8 @@ export class HarnessErrorFactory {
96
95
  }
97
96
 
98
97
  // 7. fix_example 解決
99
- const explicitFixExample =
100
- input.fixExample != null
101
- ? FixExample.create(input.fixExample)
102
- : undefined;
103
- const resolvedFixExample =
104
- definition.resolveFixExample(explicitFixExample);
98
+ const explicitFixExample = input.fixExample != null ? FixExample.create(input.fixExample) : undefined;
99
+ const resolvedFixExample = definition.resolveFixExample(explicitFixExample);
105
100
 
106
101
  // 8. fix_example 必須チェック
107
102
  if (definition.requiresFixExample() && resolvedFixExample === null) {
@@ -117,7 +112,7 @@ export class HarnessErrorFactory {
117
112
  });
118
113
  if (!validationResult.passed) {
119
114
  throw new InvalidFixExampleError(
120
- `fix_example の検証に失敗しました (code=${errorCode.toString()}): ${validationResult.reason}`
115
+ `fix_example の検証に失敗しました (code=${errorCode.toString()}): ${validationResult.reason}`,
121
116
  );
122
117
  }
123
118
  }
@@ -126,6 +121,7 @@ export class HarnessErrorFactory {
126
121
  const resolvedSuggestedSkill = definition.resolveSuggestedSkill(input.suggestedSkill);
127
122
  const resolvedScaffoldCommand = definition.resolveScaffoldCommand(input.scaffoldCommand);
128
123
  const resolvedTemplatePath = definition.resolveTemplatePath(input.templatePath);
124
+ const resolvedRemediationType = definition.resolveRemediationType(input.remediationType);
129
125
 
130
126
  // 11. HarnessError 生成と凍結
131
127
  const harnessError = new HarnessError({
@@ -138,6 +134,7 @@ export class HarnessErrorFactory {
138
134
  suggestedSkill: resolvedSuggestedSkill,
139
135
  scaffoldCommand: resolvedScaffoldCommand,
140
136
  templatePath: resolvedTemplatePath,
137
+ remediationType: resolvedRemediationType,
141
138
  });
142
139
 
143
140
  return Object.freeze(harnessError);