phasegate 0.335.0 → 0.341.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 (111) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.ja.md +22 -9
  3. package/README.md +28 -17
  4. package/docs/ADR/038-config-state-operation-permission-policy.md +5 -2
  5. package/docs/ADR/041-non-excludable-agent-trust-roots.md +68 -0
  6. package/docs/folder_management_rules.md +10 -1
  7. package/docs/guide/antigravity-integration.md +26 -0
  8. package/docs/guide/cli-reference.md +27 -7
  9. package/docs/guide/codex-integration.md +44 -107
  10. package/docs/guide/configuration.md +28 -2
  11. package/docs/guide/grok-integration.md +26 -0
  12. package/docs/guide/hooks-integration.md +34 -5
  13. package/docs/guide/installation.md +4 -2
  14. package/docs/guide/setup-artifacts.md +4 -4
  15. package/docs/guide/skills-overview.md +4 -1
  16. package/package.json +2 -1
  17. package/scripts/harness/agent-integration/application/dto/handle-pre-tool-use-dto.ts +1 -1
  18. package/scripts/harness/agent-integration/application/dto/normalized-pre-tool-use-request.ts +32 -0
  19. package/scripts/harness/agent-integration/application/usecases/handle-post-tool-use-usecase.ts +4 -0
  20. package/scripts/harness/agent-integration/application/usecases/handle-pre-tool-use-usecase.ts +38 -3
  21. package/scripts/harness/agent-integration/application/usecases/handle-stop-usecase.ts +3 -9
  22. package/scripts/harness/agent-integration/domain/ports/full-mode-requirement-query-port.ts +3 -1
  23. package/scripts/harness/agent-integration/domain/ports/story-reflection-query-port.ts +2 -0
  24. package/scripts/harness/agent-integration/domain/services/apply-patch-write-target-extractor.ts +98 -0
  25. package/scripts/harness/agent-integration/domain/services/bash-write-target-extractor.ts +6 -52
  26. package/scripts/harness/agent-integration/domain/services/hook-to-cli-translator.ts +8 -5
  27. package/scripts/harness/agent-integration/domain/value-objects/hook-translation-result.ts +2 -2
  28. package/scripts/harness/agent-integration/domain/value-objects/protected-file-list.ts +35 -18
  29. package/scripts/harness/agent-integration/domain/value-objects/story-reflection-query-result.ts +10 -2
  30. package/scripts/harness/agent-integration/domain/value-objects/write-target-scope.ts +12 -0
  31. package/scripts/harness/agent-integration/infrastructure/adapters/child-process-cli-executor-adapter.ts +64 -13
  32. package/scripts/harness/agent-integration/infrastructure/adapters/file-system-story-reflection-query-adapter.ts +108 -2
  33. package/scripts/harness/agent-integration/infrastructure/adapters/harness-config-config-query-adapter.ts +8 -6
  34. package/scripts/harness/agent-integration/presentation/hook-skip-event-recorder.ts +3 -0
  35. package/scripts/harness/agent-integration/presentation/phasegate-status-context.ts +1 -1
  36. package/scripts/harness/agent-integration/presentation/post-tool-use-feedback.ts +39 -0
  37. package/scripts/harness/agent-integration/presentation/post-tool-use-hook.ts +21 -27
  38. package/scripts/harness/agent-integration/presentation/pre-tool-use-hook.ts +126 -70
  39. package/scripts/harness/agent-integration/presentation/pre-tool-use-payload-normalizer.ts +228 -0
  40. package/scripts/harness/agent-integration/presentation/pre-tool-use-response-renderer.ts +38 -0
  41. package/scripts/harness/agent-integration/presentation/stop-hook.ts +1 -3
  42. package/scripts/harness/biome-ast-engine/infrastructure/adapters/biome-cli-executor-adapter.ts +21 -1
  43. package/scripts/harness/biome-ast-engine/infrastructure/adapters/typescript-source-module-analyzer-adapter.ts +5 -0
  44. package/scripts/harness/ci-governance/domain/value-objects/integrity-target.ts +2 -0
  45. package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json +15 -0
  46. package/scripts/harness/config-foundation/infrastructure/validators/ajv-config-schema-validator.ts +6 -3
  47. package/scripts/harness/harness-api/domain/ports/biome-lint-port.ts +2 -1
  48. package/scripts/harness/harness-api/domain/services/command-dispatch-service.ts +12 -1
  49. package/scripts/harness/harness-api/infrastructure/adapters/biome-ast-engine-lint-adapter.ts +10 -2
  50. package/scripts/harness/installation/application/bundled-skill-selection.ts +28 -2
  51. package/scripts/harness/installation/application/checks/antigravity-hook-missing-check.ts +79 -0
  52. package/scripts/harness/installation/application/checks/check-utils.ts +2 -2
  53. package/scripts/harness/installation/application/checks/codex-hook-missing-check.ts +70 -6
  54. package/scripts/harness/installation/application/checks/grok-hook-missing-check.ts +79 -0
  55. package/scripts/harness/installation/application/checks/husky-runtime-inactive-check.ts +33 -0
  56. package/scripts/harness/installation/application/named-hook-json.ts +17 -0
  57. package/scripts/harness/installation/application/operator-notice.ts +42 -0
  58. package/scripts/harness/installation/application/usecases/run-doctor-diagnostics.ts +18 -7
  59. package/scripts/harness/installation/application/usecases/run-install.ts +157 -57
  60. package/scripts/harness/installation/application/usecases/run-reconcile.ts +148 -31
  61. package/scripts/harness/installation/application/usecases/run-uninstall.ts +149 -25
  62. package/scripts/harness/installation/composition-root.ts +10 -0
  63. package/scripts/harness/installation/domain/agent-target.ts +39 -0
  64. package/scripts/harness/installation/domain/check-id.ts +5 -0
  65. package/scripts/harness/installation/domain/husky-runtime-state.ts +34 -0
  66. package/scripts/harness/installation/domain/ports/git-hooks-runtime-probe.ts +9 -0
  67. package/scripts/harness/installation/domain/repair-table.ts +5 -0
  68. package/scripts/harness/installation/infrastructure/adapters/git-hooks-runtime-probe-adapter.ts +62 -0
  69. package/scripts/harness/installation/presentation/cli/install-handler.ts +25 -5
  70. package/scripts/harness/installation/presentation/cli/reconcile-handler.ts +7 -1
  71. package/scripts/harness/installation/presentation/formatters/diagnostic-report-formatter.ts +27 -0
  72. package/scripts/harness/main.ts +227 -128
  73. package/scripts/harness/phase-dependency-model/domain/services/story-reflection-checker.ts +48 -5
  74. package/scripts/harness/phase-dependency-model/domain/services/work-item-reflection-scope-resolver.ts +64 -0
  75. package/scripts/harness/phase-dependency-model/domain/values/story-reflection-mapping.ts +8 -2
  76. package/scripts/harness/phase-dependency-model/infrastructure/filesystem/file-system-story-reflection-adapter.ts +6 -1
  77. package/scripts/harness/phase-dependency-model/infrastructure/filesystem/file-system-work-item-dependency-catalog.ts +73 -0
  78. package/scripts/harness/quick-mode/application/dto/change-category-classification-contract.ts +5 -1
  79. package/scripts/harness/quick-mode/application/dto/quick-mode-eligibility-contract.ts +1 -1
  80. package/scripts/harness/quick-mode/application/ports/change-risk-advisory-port.ts +16 -0
  81. package/scripts/harness/quick-mode/application/usecases/classify-change-category-usecase.ts +3 -1
  82. package/scripts/harness/quick-mode/composition-root.ts +5 -1
  83. package/scripts/harness/quick-mode/domain/services/quick-mode-judgment-engine.ts +13 -2
  84. package/scripts/harness/quick-mode/domain/types/rejection-rule.ts +1 -1
  85. package/scripts/harness/quick-mode/infrastructure/adapters/snapshot-risk-advisory-adapter.ts +118 -0
  86. package/scripts/harness/quick-mode/presentation/formatters/change-category-formatter.ts +7 -0
  87. package/scripts/harness/quick-mode/presentation/handlers/check-change-category-handler.ts +12 -1
  88. package/scripts/harness/regression-suite/infrastructure/adapters/vitest-test-runner-adapter.ts +13 -3
  89. package/scripts/harness/setup/skill-deployer.ts +3 -45
  90. package/scripts/harness/skill-quality/application/dto/run-plan-checker-loop-output.ts +1 -0
  91. package/scripts/harness/skill-quality/application/usecases/apply-cascade-update-usecase.ts +9 -4
  92. package/scripts/harness/skill-quality/application/usecases/execute-tdd-cycle-usecase.ts +2 -1
  93. package/scripts/harness/skill-quality/application/usecases/run-plan-checker-loop-usecase.ts +8 -0
  94. package/scripts/harness/skill-quality/composition-root.ts +14 -7
  95. package/scripts/harness/skill-quality/domain/ports/plan-check-executor-port.ts +2 -0
  96. package/scripts/harness/skill-quality/domain/value-objects/cascade-update-target.ts +15 -1
  97. package/scripts/harness/skill-quality/infrastructure/adapters/l1-biome-validator-adapter.ts +9 -1
  98. package/scripts/harness/skill-quality/infrastructure/adapters/l2-validator-system-adapter.ts +18 -2
  99. package/scripts/harness/skill-quality/presentation/handlers/apply-cascade-update-handler.ts +8 -2
  100. package/scripts/harness/skill-quality/presentation/handlers/execute-tdd-cycle-handler.ts +4 -3
  101. package/scripts/harness/skill-quality/presentation/handlers/run-plan-checker-loop-handler.ts +11 -4
  102. package/scripts/harness/traceability-model/infrastructure/parsers/work-item-frontmatter-parser.ts +41 -0
  103. package/skills/README.md +7 -0
  104. package/skills/cascade-updater/SKILL.md +37 -109
  105. package/skills/cascade-updater/references//345/261/244/345/210/245/345/210/244/345/256/232/343/202/254/343/202/244/343/203/211.md +5 -3
  106. package/skills/release-publisher/SKILL.md +3 -1
  107. package/skills/skill-creator/SKILL.md +8 -9
  108. package/templates/.agents/hooks.json +16 -0
  109. package/templates/.claude/scripts/analyze-errors-hook.sh +2 -2
  110. package/templates/.claude/settings.json +5 -3
  111. package/templates/.codex/hooks.json +2 -2
@@ -25,6 +25,8 @@
25
25
  * @work-item-id WI-300
26
26
  * @work-item-id WI-306
27
27
  * @work-item-id WI-308
28
+ * @work-item-id WI-384
29
+ * @work-item-id WI-385
28
30
  *
29
31
  * Phasegate CLI エントリポイント。
30
32
  * 各Unitの Composition Root からハンドラーを取得し、コマンドに応じてディスパッチする。
@@ -43,9 +45,8 @@ import {
43
45
  } from "node:fs/promises";
44
46
  import { basename, dirname, join, resolve } from "node:path";
45
47
  import { fileURLToPath } from "node:url";
46
- import { createAdrFoundationModule } from "./adr-foundation/composition-root.js";
47
48
  import { createBiomeAstEngineModule } from "./biome-ast-engine/composition-root.js";
48
- import { buildCiGovernance, type CiGovernanceDocPaths } from "./ci-governance/composition-root.js";
49
+ import type { CiGovernanceDocPaths } from "./ci-governance/composition-root.js";
49
50
  import { toPhaseConfigSection } from "./config-foundation/application/mappers/phase-config-section-mapper.js";
50
51
  import { toValidatorSystemConfig } from "./config-foundation/application/mappers/validator-system-config-mapper.js";
51
52
  import { toWorldModelConfig } from "./config-foundation/application/mappers/world-model-config-mapper.js";
@@ -57,15 +58,13 @@ import {
57
58
  ConfigPersistenceError,
58
59
  } from "./config-foundation/infrastructure/repositories/file-system-config-repository.js";
59
60
  import { createHarnessApiModule } from "./harness-api/composition-root.js";
60
- import { createHarnessErrorModule } from "./harness-error/composition-root.js";
61
61
  import {
62
62
  type DeployManifestRecord,
63
63
  SkillDeployerManifestBuilder,
64
64
  } from "./installation/application/wrappers/skill-deployer-manifest-builder.js";
65
- import { createInstallationModule } from "./installation/composition-root.js";
65
+ import { type AgentTarget, isAgentTarget } from "./installation/domain/agent-target.js";
66
66
  import { NodeCryptoHashAdapter } from "./installation/infrastructure/adapters/node-crypto-hash-adapter.js";
67
67
  import { CheckStoryReflectionUseCase } from "./phase-dependency-model/application/usecases/check-story-reflection-usecase.js";
68
- import { createPhaseDependencyModelModule } from "./phase-dependency-model/composition-root.js";
69
68
  import { StoryReflectionChecker } from "./phase-dependency-model/domain/services/story-reflection-checker.js";
70
69
  import { StoryReflectionResult } from "./phase-dependency-model/domain/values/story-reflection-result.js";
71
70
  import {
@@ -74,10 +73,9 @@ import {
74
73
  } from "./phase-dependency-model/infrastructure/config/harness-config-phase-config-provider.js";
75
74
  import { FileSystemStoryReflectionAdapter } from "./phase-dependency-model/infrastructure/filesystem/file-system-story-reflection-adapter.js";
76
75
  import { StoryReflectionStatusPresenter } from "./phase-dependency-model/presentation/cli/story-reflection-status-presenter.js";
77
- import { buildPhase2Extensions } from "./phase2-extensions/composition-root.js";
78
- import { createQuickModeCompositionRoot, type QuickModeCompositionRootOptions } from "./quick-mode/composition-root.js";
79
- import { buildRegressionSuite } from "./regression-suite/composition-root.js";
76
+ import type { QuickModeCompositionRootOptions } from "./quick-mode/composition-root.js";
80
77
  import type { SkillSet } from "./setup/skill-deployer.js";
78
+ import { isSkillSet } from "./installation/application/bundled-skill-selection.js";
81
79
  import {
82
80
  deployAgentSkillLinks,
83
81
  deployCiWorkflows,
@@ -94,11 +92,7 @@ import {
94
92
  initHarnessConfig,
95
93
  listAvailableSkillNames,
96
94
  } from "./setup/skill-deployer.js";
97
- import { createSkillQualityHandlers } from "./skill-quality/composition-root.js";
98
- import { createTraceabilityModelModule } from "./traceability-model/composition-root.js";
99
- import { createValidatorSystemModule } from "./validator-system/composition-root.js";
100
- import {
101
- createWorldModelModule,
95
+ import type {
102
96
  WorldDeriveCommandHandler,
103
97
  WorldInspectCommandHandler,
104
98
  WorldPinCommandHandler,
@@ -207,14 +201,14 @@ Usage: phasegate <command> [options]
207
201
  Setup:
208
202
  init Initialize project: deploy skills + design docs + phasegate.config.json
209
203
  (--name <project-name>, --preset <full|standard|minimal|custom>,
210
- --skills <core|all>, --agent <claude|codex|both>, --workflow <standard|strict>,
204
+ --skills <core|consumer|all>, --agent <claude|codex|both|grok|antigravity|all>, --workflow <standard|strict>,
211
205
  --language <language>, --with-husky, --with-ci, --yes)
212
206
  update-skills Alias for reconcile (kept for compatibility)
213
- doctor Diagnose silent installation failures (--json, --strict, --personal, --agent <claude|codex|both>, --report-out <path>)
207
+ doctor Diagnose silent installation failures (--json, --strict, --personal, --agent <claude|codex|both|grok|antigravity|all>, --report-out <path>)
214
208
  scaffold-wi <unit|_cross> <story|issue|fix|refactor|chore>
215
209
  Create docs/inception/{unit}/WI-XXX/description.md
216
210
  emit-agent-rules Print AGENTS.md / CLAUDE.md WI workflow rules block
217
- install Install phasegate managed files (--dry-run|--apply, --force, --personal, --agent <claude|codex|both>)
211
+ install Install phasegate managed files (--dry-run|--apply, --force, --personal, --agent <claude|codex|both|grok|antigravity|all>)
218
212
  uninstall Uninstall phasegate managed files (--dry-run|--apply, --force)
219
213
  reconcile Reconcile phasegate managed files (--dry-run|--apply, --force)
220
214
  setup:agent Diagnose repo setup and produce/apply an agent-readable setup plan
@@ -271,7 +265,7 @@ Gate semantics:
271
265
  ci:auto-refresh-agent-context Refresh AGENTS.md / CLAUDE.md (--dry-run, --apply, --json)
272
266
  refresh-claude-md Refresh CLAUDE.md standard sections (--dry-run, --apply, --json)
273
267
  p2:check-agent-context Check AGENTS.md / CLAUDE.md freshness (--threshold-days <n>, --json)
274
- setup:agent Plan agent-driven setup (--intent <minimal|recommended|strict|ci-only|agent-hooks|retrofit>, --agent <claude|codex|both>, --dry-run|--apply, --json)
268
+ setup:agent Plan agent-driven setup (--intent <minimal|recommended|strict|ci-only|agent-hooks|retrofit>, --agent <claude|codex|both|grok|antigravity|all>, --dry-run|--apply, --json)
275
269
  config:plan Plan safe config changes (--intent <l4-strict|codex-hooks|ci-fail-on-warning|baseline-reset|quick-mode-strict|quick-mode-relax|retrofit-bootstrap|planning-mode-relax>, --dry-run|--apply, --json)
276
270
  ci:check-repetition Check error repetition (--code <errorCode>, --reset, --json)
277
271
  baseline Create retrofit baseline snapshot (--dry-run, --force, --paths <glob,glob,...>, --json)
@@ -280,7 +274,7 @@ Gate semantics:
280
274
  session begin Start a Full Mode session (--mode full, --unit, --work-item, --reason, --duration)
281
275
  session end End a Full Mode session (--work-item)
282
276
 
283
- skill:execute-tdd-cycle Execute TDD cycle (--unit, --story, --desc, --phase RED|GREEN|REFACTOR, --passed)
277
+ skill:execute-tdd-cycle Execute TDD cycle (--unit, --story, --desc, --phase RED|GREEN|REFACTOR, --passed, optional --configured-validation)
284
278
  skill:check-coverage Check coverage (--story <storyId>, --json)
285
279
  skill:collect-lessons Collect lessons (--story <storyId>, --sources <paths>, --write-artifact)
286
280
  skill:apply-cascade-update Apply cascade update (--story <storyId>, --dry-run)
@@ -492,7 +486,7 @@ async function saveInstallationManifest(
492
486
  ): Promise<void> {
493
487
  const filteredRecords = (await Promise.all(records)).filter((record) => record !== null);
494
488
  if (filteredRecords.length === 0) return;
495
- const mod = createInstallationModule();
489
+ const mod = (await import("./installation/composition-root.js")).createInstallationModule();
496
490
  const builder = new SkillDeployerManifestBuilder(new NodeCryptoHashAdapter());
497
491
  await mod.manifestRepository.save(rootDir, builder.build(version, filteredRecords));
498
492
  }
@@ -704,8 +698,8 @@ Initialize phasegate in the current project: deploy skills + design docs + phase
704
698
  Options:
705
699
  --name <project-name> Project name (default: "my-project")
706
700
  --preset <full|standard|minimal|custom> Phase dependency preset (default: "standard")
707
- --skills <core|all> Skill set to deploy (default: "all")
708
- --agent <claude|codex|both> Agent integration target (default: "claude")
701
+ --skills <core|consumer|all> Skill set to deploy (default: "all"; consumer excludes maintainer skills)
702
+ --agent <claude|codex|both|grok|antigravity|all> Agent integration target (default: "claude")
709
703
  --workflow <standard|strict> Workflow enforcement defaults (default: "standard")
710
704
  --language <language> Project language declaration (default: "typescript")
711
705
  --with-husky Install Husky pre-commit hooks
@@ -731,8 +725,8 @@ Options:
731
725
  --dry-run Preview target actions without writing (default)
732
726
  --apply Write merge results and manifest
733
727
  --force Force ai-assisted/manual targets after backing up existing files
734
- --agent <claude|codex|both> Agent context and hook targets (default: both)
735
- --skills <core|all> Rendered agent context skill mode (default: all)
728
+ --agent <claude|codex|both|grok|antigravity|all> Agent context and hook targets (default: both)
729
+ --skills <core|consumer|all> Skill set to deploy (default: all; consumer excludes maintainer skills)
736
730
  --workflow <standard|strict> Rendered agent context workflow mode (default: standard)
737
731
  --with-husky Include Husky hook targets (opt-in; omitted by default)
738
732
  --with-ci Include GitHub Actions target (opt-in; omitted by default)
@@ -740,13 +734,24 @@ Options:
740
734
  With --agent claude, initializes .phasegate-local config/settings/skills and ignored .claude shims.
741
735
  --json Output machine-readable JSON
742
736
  --help, -h Show this help`,
737
+ doctor: `Usage: phasegate doctor [options]
738
+
739
+ Diagnose silent installation failures for the selected runtime scope.
740
+
741
+ Options:
742
+ --json Output machine-readable JSON
743
+ --strict Treat warnings as failures
744
+ --personal Diagnose a personal installation
745
+ --agent <claude|codex|both|grok|antigravity|all> Diagnostic scope (default: both)
746
+ --report-out <path> Write the JSON report to a file
747
+ --help, -h Show this help`,
743
748
  "setup:agent": `Usage: phasegate setup:agent [options]
744
749
 
745
750
  Diagnose repository setup and produce an agent-readable setup plan.
746
751
 
747
752
  Options:
748
753
  --intent <minimal|recommended|strict|ci-only|agent-hooks|retrofit>
749
- --agent <claude|codex|both>
754
+ --agent <claude|codex|both|grok|antigravity|all>
750
755
  --workflow <standard|strict>
751
756
  --with-husky
752
757
  --with-ci
@@ -888,6 +893,7 @@ Options:
888
893
  --paths <csv> Comma-separated file paths to classify.
889
894
  --format <human|json> Output format. Default: human.
890
895
  --fail-on-full-required Exit with code 1 when Full Mode is required.
896
+ --risk-snapshots <json> Optional before/after snapshots for advisory review; does not change gates.
891
897
  --help, -h Show this help.
892
898
 
893
899
  Examples:
@@ -1075,7 +1081,7 @@ function parseCoverageThreshold(raw: string | undefined): number {
1075
1081
  }
1076
1082
 
1077
1083
  type InitPhasePreset = "full" | "standard" | "minimal" | "custom";
1078
- type AgentTarget = "claude" | "codex" | "both";
1084
+ const AGENT_TARGET_USAGE = "claude|codex|both|grok|antigravity|all";
1079
1085
  type SetupIntent = "minimal" | "recommended" | "strict" | "ci-only" | "agent-hooks" | "retrofit";
1080
1086
  type ConfigChangeIntent =
1081
1087
  | "l4-strict"
@@ -1097,7 +1103,7 @@ interface SetupCompletenessEntry {
1097
1103
  }
1098
1104
 
1099
1105
  interface AgentReadinessEntry {
1100
- readonly agent: "claude" | "codex" | "shared";
1106
+ readonly agent: "claude" | "codex" | "grok" | "antigravity" | "shared";
1101
1107
  readonly status: SetupCompletenessStatus;
1102
1108
  readonly evidence: readonly string[];
1103
1109
  readonly nextAction: string | null;
@@ -1134,14 +1140,9 @@ function parseInitPhasePreset(value: string | undefined): InitPhasePreset | unde
1134
1140
  return undefined;
1135
1141
  }
1136
1142
 
1137
- function parseAgentTarget(value: string | undefined, fallback: AgentTarget = "both"): AgentTarget {
1138
- if (value === "claude" || value === "codex" || value === "both") return value;
1139
- return fallback;
1140
- }
1141
-
1142
1143
  function parseRequiredAgentTarget(value: string | undefined, fallback: AgentTarget = "both"): AgentTarget | null {
1143
1144
  if (value === undefined) return fallback;
1144
- if (value === "claude" || value === "codex" || value === "both") return value;
1145
+ if (isAgentTarget(value)) return value;
1145
1146
  return null;
1146
1147
  }
1147
1148
 
@@ -1234,6 +1235,7 @@ function buildSetupCompleteness(input: {
1234
1235
  readonly phasegateConfig: boolean;
1235
1236
  readonly claudeSettings: boolean;
1236
1237
  readonly codexHooks: boolean;
1238
+ readonly antigravityHooks: boolean;
1237
1239
  readonly agentsMd: boolean;
1238
1240
  readonly claudeMd: boolean;
1239
1241
  readonly huskyPreCommit: boolean;
@@ -1241,12 +1243,19 @@ function buildSetupCompleteness(input: {
1241
1243
  readonly skillsVersion: boolean;
1242
1244
  };
1243
1245
  }): readonly SetupCompletenessEntry[] {
1244
- const includeClaude = input.agent === "claude" || input.agent === "both";
1245
- const includeCodex = input.agent === "codex" || input.agent === "both";
1246
+ const includeClaude = input.agent === "claude" || input.agent === "both" || input.agent === "all";
1247
+ const includeCodex = input.agent === "codex" || input.agent === "both" || input.agent === "all";
1248
+ const includeGrok = input.agent === "grok" || input.agent === "all";
1249
+ const includeAntigravity = input.agent === "antigravity" || input.agent === "all";
1250
+ const includeClaudeHook = includeClaude || includeGrok;
1251
+ const includeAgentsContext = includeCodex || includeGrok || includeAntigravity;
1246
1252
  const doctorCommand = doctorValidationCommand(input.agent);
1247
1253
  const agentHooksConfigured =
1248
- (!includeClaude || input.checks.claudeSettings) && (!includeCodex || input.checks.codexHooks);
1249
- const agentContextConfigured = (!includeClaude || input.checks.claudeMd) && (!includeCodex || input.checks.agentsMd);
1254
+ (!includeClaudeHook || input.checks.claudeSettings) &&
1255
+ (!includeCodex || input.checks.codexHooks) &&
1256
+ (!includeAntigravity || input.checks.antigravityHooks);
1257
+ const agentContextConfigured =
1258
+ (!includeClaude || input.checks.claudeMd) && (!includeAgentsContext || input.checks.agentsMd);
1250
1259
  const entries: SetupCompletenessEntry[] = [
1251
1260
  setupCompletenessEntry({
1252
1261
  area: "local-config",
@@ -1258,16 +1267,22 @@ function buildSetupCompleteness(input: {
1258
1267
  }),
1259
1268
  setupCompletenessEntry({
1260
1269
  area: "agent-hooks",
1261
- included: includeClaude || includeCodex,
1270
+ included: includeClaudeHook || includeCodex || includeAntigravity,
1262
1271
  configured: agentHooksConfigured,
1263
1272
  configuredEvidence: "Selected agent hook settings are present.",
1264
1273
  plannedEvidence: "setup:agent will create or refresh selected agent hook settings.",
1265
1274
  nextAction: "Run setup:agent --apply for selected agents.",
1266
- risk: includeCodex ? "Codex user-level hook feature enablement remains a manual external check." : undefined,
1275
+ risk: includeCodex
1276
+ ? "Codex user-level hook feature enablement remains a manual external check."
1277
+ : includeGrok
1278
+ ? "Grok project-hook trust remains a manual external check."
1279
+ : includeAntigravity
1280
+ ? "Antigravity hard blocking is CLI-only; IDE/desktop relies on L2 pre-commit."
1281
+ : undefined,
1267
1282
  }),
1268
1283
  setupCompletenessEntry({
1269
1284
  area: "agent-context",
1270
- included: includeClaude || includeCodex,
1285
+ included: includeClaude || includeAgentsContext,
1271
1286
  configured: agentContextConfigured,
1272
1287
  configuredEvidence: "Selected AGENTS.md / CLAUDE.md managed context files are present.",
1273
1288
  plannedEvidence: "setup:agent will create or refresh selected managed agent context sections.",
@@ -1371,6 +1386,7 @@ function buildAgentReadiness(input: {
1371
1386
  readonly phasegateConfig: boolean;
1372
1387
  readonly claudeSettings: boolean;
1373
1388
  readonly codexHooks: boolean;
1389
+ readonly antigravityHooks: boolean;
1374
1390
  readonly agentsMd: boolean;
1375
1391
  readonly claudeMd: boolean;
1376
1392
  readonly huskyPreCommit: boolean;
@@ -1378,8 +1394,10 @@ function buildAgentReadiness(input: {
1378
1394
  readonly skillsVersion: boolean;
1379
1395
  };
1380
1396
  }): readonly AgentReadinessEntry[] {
1381
- const includeClaude = input.agent === "claude" || input.agent === "both";
1382
- const includeCodex = input.agent === "codex" || input.agent === "both";
1397
+ const includeClaude = input.agent === "claude" || input.agent === "both" || input.agent === "all";
1398
+ const includeCodex = input.agent === "codex" || input.agent === "both" || input.agent === "all";
1399
+ const includeGrok = input.agent === "grok" || input.agent === "all";
1400
+ const includeAntigravity = input.agent === "antigravity" || input.agent === "all";
1383
1401
  const doctorCommand = doctorValidationCommand(input.agent);
1384
1402
  const sharedConfigured =
1385
1403
  input.checks.packageJson &&
@@ -1423,6 +1441,24 @@ function buildAgentReadiness(input: {
1423
1441
  nextAction: "Run setup:agent --agent codex --apply, then enable hooks at user level if needed.",
1424
1442
  risk: "Codex user-level hook feature enablement remains a manual external check.",
1425
1443
  }),
1444
+ setupReadinessEntry({
1445
+ agent: "grok",
1446
+ included: includeGrok,
1447
+ configured: input.checks.claudeSettings && input.checks.agentsMd,
1448
+ configuredEvidence: [".claude/settings.json and AGENTS.md are present for Grok compatibility."],
1449
+ plannedEvidence: ["setup:agent will deploy the Claude-compatible hook and AGENTS.md without .grok duplication."],
1450
+ nextAction: "Run setup:agent --agent grok --apply, then verify grok inspect and /hooks trust.",
1451
+ risk: "Grok project-hook trust cannot be verified by Phasegate.",
1452
+ }),
1453
+ setupReadinessEntry({
1454
+ agent: "antigravity",
1455
+ included: includeAntigravity,
1456
+ configured: input.checks.antigravityHooks && input.checks.agentsMd,
1457
+ configuredEvidence: [".agents/hooks.json and AGENTS.md are present for Antigravity CLI."],
1458
+ plannedEvidence: ["setup:agent will deploy the Antigravity named hook map and AGENTS.md."],
1459
+ nextAction: "Run setup:agent --agent antigravity --apply, then inspect /hooks in agy.",
1460
+ risk: "IDE/desktop hook execution is not guaranteed; keep the L2 pre-commit backstop.",
1461
+ }),
1426
1462
  setupReadinessEntry({
1427
1463
  agent: "shared",
1428
1464
  included: true,
@@ -1452,14 +1488,17 @@ async function buildAgentSetupPlan(
1452
1488
  phasegateConfig: await projectFileExists(rootDir, "phasegate.config.json"),
1453
1489
  claudeSettings: await projectFileExists(rootDir, ".claude/settings.json"),
1454
1490
  codexHooks: await projectFileExists(rootDir, ".codex/hooks.json"),
1491
+ antigravityHooks: await projectFileExists(rootDir, ".agents/hooks.json"),
1455
1492
  agentsMd: await projectFileExists(rootDir, "AGENTS.md"),
1456
1493
  claudeMd: await projectFileExists(rootDir, "CLAUDE.md"),
1457
1494
  huskyPreCommit: await projectFileExists(rootDir, ".husky/pre-commit"),
1458
1495
  ciWorkflow: await projectFileExists(rootDir, ".github/workflows/phasegate-aidlc-gate.yml"),
1459
1496
  skillsVersion: await projectFileExists(rootDir, "skills/.harness-version"),
1460
1497
  };
1461
- const includeClaude = input.agent === "claude" || input.agent === "both";
1462
- const includeCodex = input.agent === "codex" || input.agent === "both";
1498
+ const includeClaude = input.agent === "claude" || input.agent === "both" || input.agent === "all";
1499
+ const includeCodex = input.agent === "codex" || input.agent === "both" || input.agent === "all";
1500
+ const includeGrok = input.agent === "grok" || input.agent === "all";
1501
+ const includeAntigravity = input.agent === "antigravity" || input.agent === "all";
1463
1502
  const changes = [
1464
1503
  !checks.packageJson
1465
1504
  ? "Add phasegate devDependency and phasegate scripts to package.json."
@@ -1469,6 +1508,8 @@ async function buildAgentSetupPlan(
1469
1508
  : "Keep existing phasegate.config.json; review config:plan before changing policy.",
1470
1509
  includeClaude ? "Create or refresh .claude/settings.json and CLAUDE.md managed section." : null,
1471
1510
  includeCodex ? "Create or refresh .codex/hooks.json and AGENTS.md managed section." : null,
1511
+ includeGrok ? "Create or refresh the Claude-compatible hook and AGENTS.md without a .grok hook duplicate." : null,
1512
+ includeAntigravity ? "Create or refresh .agents/hooks.json named hook and AGENTS.md managed section." : null,
1472
1513
  input.withHusky
1473
1514
  ? "Create or refresh Husky pre-commit, commit-msg, and pre-push backstops."
1474
1515
  : "Leave Husky hooks unmanaged in this setup run.",
@@ -1518,11 +1559,7 @@ function isPlainRecord(value: unknown): value is Record<string, unknown> {
1518
1559
  }
1519
1560
 
1520
1561
  async function readProjectJson(rootDir: string, relativePath: string): Promise<unknown | null> {
1521
- try {
1522
- return JSON.parse(await fsReadFile(join(rootDir, relativePath), "utf8")) as unknown;
1523
- } catch {
1524
- return null;
1525
- }
1562
+ return JSON.parse(await fsReadFile(join(rootDir, relativePath), "utf8")) as unknown;
1526
1563
  }
1527
1564
 
1528
1565
  function withNestedValue(source: unknown, path: readonly string[], value: unknown): Record<string, unknown> {
@@ -1546,7 +1583,7 @@ function getNestedValue(source: unknown, path: readonly string[]): unknown {
1546
1583
  return cursor;
1547
1584
  }
1548
1585
 
1549
- function buildConfigPatchPreview(intent: ConfigChangeIntent, before: unknown | null): ConfigPatchPreview {
1586
+ function buildConfigPatchPreview(intent: ConfigChangeIntent, before: unknown | null, missing = false): ConfigPatchPreview {
1550
1587
  const configIntents: Record<
1551
1588
  ConfigChangeIntent,
1552
1589
  readonly { readonly pointer: string; readonly path: readonly string[]; readonly value: unknown }[]
@@ -1590,6 +1627,16 @@ function buildConfigPatchPreview(intent: ConfigChangeIntent, before: unknown | n
1590
1627
  operations: [],
1591
1628
  };
1592
1629
  }
1630
+ if (!isPlainRecord(before) && !missing) {
1631
+ return {
1632
+ path: "phasegate.config.json",
1633
+ applicability: "blocked",
1634
+ blockedReason: "An existing JSON object configuration is required. Review phasegate install --dry-run before initialization, or restore a valid configuration before retrying.",
1635
+ before,
1636
+ after: before,
1637
+ operations: [],
1638
+ };
1639
+ }
1593
1640
  let after: unknown = before;
1594
1641
  const operations: ConfigPatchOperation[] = [];
1595
1642
  for (const change of changes) {
@@ -1625,6 +1672,9 @@ async function applyConfigPlan(
1625
1672
  if (patch.applicability !== "applicable") {
1626
1673
  throw new Error(`config plan is not applicable: ${patch.blockedReason ?? patch.applicability}`);
1627
1674
  }
1675
+ if (!isPlainRecord(patch.before)) {
1676
+ throw new Error("phasegate.config.json is missing. Review phasegate install --dry-run before initialization; config:plan does not create a partial configuration.");
1677
+ }
1628
1678
  if (patch.operations.length === 0) {
1629
1679
  throw new Error("config plan has no operations to apply.");
1630
1680
  }
@@ -1633,13 +1683,16 @@ async function applyConfigPlan(
1633
1683
  }
1634
1684
 
1635
1685
  const configPath = join(rootDir, patch.path);
1686
+ const beforeText = await fsReadFile(configPath, "utf8");
1687
+ if (JSON.stringify(JSON.parse(beforeText)) !== JSON.stringify(patch.before)) {
1688
+ throw new Error("phasegate.config.json changed after planning. Review config:plan --dry-run again before applying; no configuration was changed.");
1689
+ }
1636
1690
  const backupPath = configPlanBackupPath(rootDir, new Date());
1637
1691
  await fsMkdir(dirname(backupPath), { recursive: true });
1638
- const beforeText = patch.before === null ? "" : `${JSON.stringify(patch.before, null, 2)}\n`;
1639
- await fsWriteFile(backupPath, beforeText, "utf8");
1692
+ await fsWriteFile(backupPath, beforeText, { encoding: "utf8", flag: "wx" });
1640
1693
 
1641
1694
  const tempPath = `${configPath}.tmp-${process.pid}-${Date.now()}`;
1642
- await fsWriteFile(tempPath, `${JSON.stringify(patch.after, null, 2)}\n`, "utf8");
1695
+ await fsWriteFile(tempPath, `${JSON.stringify(patch.after, null, 2)}\n`, { encoding: "utf8", flag: "wx" });
1643
1696
  await fsRename(tempPath, configPath);
1644
1697
 
1645
1698
  return {
@@ -1780,11 +1833,31 @@ async function buildConfigChangePlan(rootDir: string, intent: ConfigChangeIntent
1780
1833
  ],
1781
1834
  },
1782
1835
  };
1783
- const before = await readProjectJson(rootDir, "phasegate.config.json");
1836
+ let before: unknown = null;
1837
+ let readFailure: string | undefined;
1838
+ let missing = false;
1839
+ try {
1840
+ before = await readProjectJson(rootDir, "phasegate.config.json");
1841
+ } catch (error) {
1842
+ if ((error as NodeJS.ErrnoException).code === "ENOENT") {
1843
+ missing = true;
1844
+ } else if (error instanceof SyntaxError) {
1845
+ readFailure = "Cannot parse phasegate.config.json. Restore valid JSON from version control or a known-good backup through an authorized recovery path, then preview again. The original file has not been changed.";
1846
+ } else {
1847
+ readFailure = `Cannot read phasegate.config.json. Check file access permissions before retrying. The original file has not been changed. ${error instanceof Error ? error.message : String(error)}`;
1848
+ }
1849
+ }
1850
+ let configPatch = buildConfigPatchPreview(intent, before, missing);
1851
+ if (readFailure && configPatch.applicability !== "not-applicable") {
1852
+ configPatch = { ...configPatch, applicability: "blocked", blockedReason: readFailure, after: before, operations: [] };
1853
+ }
1784
1854
  return {
1785
1855
  intent,
1786
1856
  ...catalog[intent],
1787
- configPatch: buildConfigPatchPreview(intent, before),
1857
+ commands: missing && configPatch.applicability === "applicable"
1858
+ ? ["phasegate install --dry-run", ...catalog[intent].commands]
1859
+ : catalog[intent].commands,
1860
+ configPatch,
1788
1861
  diffExplanation:
1789
1862
  "Review the listed targets first, apply through PhaseGate managed commands where possible, then run the validations in order.",
1790
1863
  rollback: "Use git diff for config changes; use phasegate uninstall/reconcile dry-runs for managed setup targets.",
@@ -2094,14 +2167,14 @@ async function main(): Promise<void> {
2094
2167
  }
2095
2168
  const phasePreset = parseInitPhasePreset(rawPhasePreset);
2096
2169
  const skillSetRaw = parseFlag(args, "--skills") ?? "all";
2097
- if (skillSetRaw !== "core" && skillSetRaw !== "all") {
2098
- console.error(`Invalid --skills value: "${skillSetRaw}". Use "core" or "all".`);
2170
+ if (!isSkillSet(skillSetRaw)) {
2171
+ console.error(`Invalid --skills value: "${skillSetRaw}". Use "core", "consumer", or "all".`);
2099
2172
  process.exit(2);
2100
2173
  }
2101
2174
  const skillSet: SkillSet = skillSetRaw;
2102
2175
  const agentRaw = parseFlag(args, "--agent") ?? "claude";
2103
- if (agentRaw !== "claude" && agentRaw !== "codex" && agentRaw !== "both") {
2104
- console.error(`Invalid --agent value: "${agentRaw}". Use "claude", "codex", or "both".`);
2176
+ if (!isAgentTarget(agentRaw)) {
2177
+ console.error(`Invalid --agent value: "${agentRaw}". Use <${AGENT_TARGET_USAGE}>.`);
2105
2178
  process.exit(2);
2106
2179
  }
2107
2180
  const agent = agentRaw;
@@ -2116,8 +2189,8 @@ async function main(): Promise<void> {
2116
2189
  console.error("Invalid --language value: value must not be empty.");
2117
2190
  process.exit(2);
2118
2191
  }
2119
- const deployClaude = agent === "claude" || agent === "both";
2120
- const deployCodex = agent === "codex" || agent === "both";
2192
+ const deployClaude = agent === "claude" || agent === "both" || agent === "grok" || agent === "all";
2193
+ const deployCodex = agent === "codex" || agent === "both" || agent === "all";
2121
2194
  const result = await deploySkills(harnessRoot, rootDir, skillSet);
2122
2195
  const packageResult = await ensurePhasegatePackageDependency(rootDir, result.version);
2123
2196
  const skillLinkResult = await deployAgentSkillLinks(rootDir, {
@@ -2177,7 +2250,7 @@ async function main(): Promise<void> {
2177
2250
  huskyPrePushResult?.created ? await createFileManifestRecord(rootDir, join(".husky", "pre-push")) : null,
2178
2251
  ...(ciWorkflowResult?.copiedFiles.map((path) => createFileManifestRecord(rootDir, path)) ?? []),
2179
2252
  ]);
2180
- const installModule = createInstallationModule();
2253
+ const installModule = (await import("./installation/composition-root.js")).createInstallationModule();
2181
2254
  const installResult = await installModule.runInstallUseCase.execute({
2182
2255
  projectRoot: rootDir,
2183
2256
  harnessRoot,
@@ -2312,11 +2385,15 @@ async function main(): Promise<void> {
2312
2385
  console.log(" 3. Edit .claude/scripts/hook-config.json to set target directories");
2313
2386
  }
2314
2387
  if (deployCodex) {
2315
- console.log(` ${deployClaude ? "4" : "3"}. Enable Codex hooks: codex features enable hooks`);
2388
+ console.log(
2389
+ ` ${deployClaude ? "4" : "3"}. Use Codex CLI >= 0.124.0, then open /hooks and trust the current hook definition hash`,
2390
+ );
2316
2391
  console.log(
2317
2392
  ` ${deployClaude ? "5" : "4"}. (Recommended) Install pre-commit backstop: rerun with --with-husky or set up husky manually`,
2318
2393
  );
2319
- console.log(` See docs/guide/codex-integration.md for the native apply_patch limitation.`);
2394
+ console.log(
2395
+ ` See docs/guide/codex-integration.md for native apply_patch coverage and trust troubleshooting.`,
2396
+ );
2320
2397
  }
2321
2398
  if (skillSet !== "core") {
2322
2399
  console.log("");
@@ -2337,7 +2414,7 @@ async function main(): Promise<void> {
2337
2414
  }
2338
2415
  const apply = hasFlag(args, "--apply");
2339
2416
  const dryRun = hasFlag(args, "--dry-run") || !apply;
2340
- const mod = createInstallationModule();
2417
+ const mod = (await import("./installation/composition-root.js")).createInstallationModule();
2341
2418
  const phasegateVersion = await getHarnessVersion(harnessRoot);
2342
2419
  const result = await mod.reconcileHandler.execute({
2343
2420
  projectRoot: rootDir,
@@ -2363,10 +2440,10 @@ async function main(): Promise<void> {
2363
2440
  }
2364
2441
  const agent = parseRequiredAgentTarget(parseFlag(args, "--agent"), "both");
2365
2442
  if (agent === null) {
2366
- console.error(`Invalid --agent value: "${parseFlag(args, "--agent")}". Use "claude", "codex", or "both".`);
2443
+ console.error(`Invalid --agent value: "${parseFlag(args, "--agent")}". Use <${AGENT_TARGET_USAGE}>.`);
2367
2444
  process.exit(2);
2368
2445
  }
2369
- const mod = createInstallationModule();
2446
+ const mod = (await import("./installation/composition-root.js")).createInstallationModule();
2370
2447
  const phasegateVersion = await getHarnessVersion(harnessRoot);
2371
2448
  const result = await mod.doctorHandler.execute({
2372
2449
  projectRoot: rootDir,
@@ -2434,10 +2511,14 @@ async function main(): Promise<void> {
2434
2511
  }
2435
2512
  const apply = hasFlag(args, "--apply");
2436
2513
  const dryRun = hasFlag(args, "--dry-run") || !apply;
2437
- const agent = parseAgentTarget(parseFlag(args, "--agent"), "both");
2514
+ const agent = parseRequiredAgentTarget(parseFlag(args, "--agent"), "both");
2515
+ if (agent === null) {
2516
+ console.error(`Invalid --agent value: "${parseFlag(args, "--agent")}". Use <${AGENT_TARGET_USAGE}>.`);
2517
+ process.exit(2);
2518
+ }
2438
2519
  const skillSetRaw = parseFlag(args, "--skills") ?? "all";
2439
- if (skillSetRaw !== "core" && skillSetRaw !== "all") {
2440
- console.error(`Invalid --skills value: "${skillSetRaw}". Use "core" or "all".`);
2520
+ if (!isSkillSet(skillSetRaw)) {
2521
+ console.error(`Invalid --skills value: "${skillSetRaw}". Use "core", "consumer", or "all".`);
2441
2522
  process.exit(2);
2442
2523
  }
2443
2524
  const workflowRaw = parseFlag(args, "--workflow");
@@ -2445,10 +2526,10 @@ async function main(): Promise<void> {
2445
2526
  console.error(`Invalid --workflow value: "${workflowRaw}". Use "standard" or "strict".`);
2446
2527
  process.exit(2);
2447
2528
  }
2448
- const includeClaude = agent === "claude" || agent === "both";
2449
- const includeCodex = agent === "codex" || agent === "both";
2529
+ const includeClaude = agent === "claude" || agent === "both" || agent === "grok" || agent === "all";
2530
+ const includeCodex = agent === "codex" || agent === "both" || agent === "all";
2450
2531
  const personal = hasFlag(args, "--personal");
2451
- const mod = createInstallationModule();
2532
+ const mod = (await import("./installation/composition-root.js")).createInstallationModule();
2452
2533
  const phasegateVersion = await getHarnessVersion(harnessRoot);
2453
2534
  const result = await mod.installHandler.execute({
2454
2535
  projectRoot: rootDir,
@@ -2490,7 +2571,11 @@ async function main(): Promise<void> {
2490
2571
  process.exit(2);
2491
2572
  }
2492
2573
  const intent = parseSetupIntent(parseFlag(args, "--intent"));
2493
- const agent = parseAgentTarget(parseFlag(args, "--agent"), "both");
2574
+ const agent = parseRequiredAgentTarget(parseFlag(args, "--agent"), "both");
2575
+ if (agent === null) {
2576
+ console.error(`Invalid --agent value: "${parseFlag(args, "--agent")}". Use <${AGENT_TARGET_USAGE}>.`);
2577
+ process.exit(2);
2578
+ }
2494
2579
  const workflow = parseWorkflowMode(
2495
2580
  parseFlag(args, "--workflow") ?? (intent === "strict" ? "strict" : "standard"),
2496
2581
  );
@@ -2517,7 +2602,7 @@ async function main(): Promise<void> {
2517
2602
  packageDependency: packageResult,
2518
2603
  configCreated: configResult.created,
2519
2604
  };
2520
- const mod = createInstallationModule();
2605
+ const mod = (await import("./installation/composition-root.js")).createInstallationModule();
2521
2606
  const phasegateVersion = await getHarnessVersion(harnessRoot);
2522
2607
  installResult = await mod.runInstallUseCase.execute({
2523
2608
  projectRoot: rootDir,
@@ -2526,8 +2611,8 @@ async function main(): Promise<void> {
2526
2611
  dryRun: false,
2527
2612
  apply: true,
2528
2613
  force: hasFlag(args, "--force"),
2529
- includeClaude: agent === "claude" || agent === "both",
2530
- includeCodex: agent === "codex" || agent === "both",
2614
+ includeClaude: agent === "claude" || agent === "both" || agent === "grok" || agent === "all",
2615
+ includeCodex: agent === "codex" || agent === "both" || agent === "all",
2531
2616
  includeHusky: withHusky,
2532
2617
  includeCi: withCi,
2533
2618
  skillSet: "all",
@@ -2684,7 +2769,7 @@ async function main(): Promise<void> {
2684
2769
  }
2685
2770
  const apply = hasFlag(args, "--apply");
2686
2771
  const dryRun = hasFlag(args, "--dry-run") || !apply;
2687
- const mod = createInstallationModule();
2772
+ const mod = (await import("./installation/composition-root.js")).createInstallationModule();
2688
2773
  const result = await mod.uninstallHandler.execute({
2689
2774
  projectRoot: rootDir,
2690
2775
  harnessRoot,
@@ -2707,7 +2792,7 @@ async function main(): Promise<void> {
2707
2792
  }
2708
2793
  const apply = hasFlag(args, "--apply");
2709
2794
  const dryRun = hasFlag(args, "--dry-run") || !apply;
2710
- const mod = createInstallationModule();
2795
+ const mod = (await import("./installation/composition-root.js")).createInstallationModule();
2711
2796
  const phasegateVersion = await getHarnessVersion(harnessRoot);
2712
2797
  const result = await mod.reconcileHandler.execute({
2713
2798
  projectRoot: rootDir,
@@ -2766,7 +2851,7 @@ async function main(): Promise<void> {
2766
2851
 
2767
2852
  case "migrate": {
2768
2853
  if (args[1] === "work-items") {
2769
- const mod = createTraceabilityModelModule(rootDir, toTraceabilityModelOptions(resolvedConfig));
2854
+ const mod = (await import("./traceability-model/composition-root.js")).createTraceabilityModelModule(rootDir, toTraceabilityModelOptions(resolvedConfig));
2770
2855
  const result = await mod.migrateWorkItemsCommandHandler.execute({
2771
2856
  dryRun: hasFlag(args, "--dry-run"),
2772
2857
  apply: hasFlag(args, "--apply"),
@@ -2790,7 +2875,7 @@ async function main(): Promise<void> {
2790
2875
 
2791
2876
  // ── harness-error ──
2792
2877
  case "render-errors": {
2793
- const mod = createHarnessErrorModule(rootDir);
2878
+ const mod = (await import("./harness-error/composition-root.js")).createHarnessErrorModule(rootDir);
2794
2879
  const format = toRenderFormat(parseFlag(args, "--format") ?? "human");
2795
2880
  const failOnError = hasFlag(args, "--fail-on-error");
2796
2881
  const result = mod.renderHarnessErrorsHandler.execute({
@@ -2804,7 +2889,7 @@ async function main(): Promise<void> {
2804
2889
  }
2805
2890
 
2806
2891
  case "validate-fix": {
2807
- const mod = createHarnessErrorModule(rootDir);
2892
+ const mod = (await import("./harness-error/composition-root.js")).createHarnessErrorModule(rootDir);
2808
2893
  const code = parseFlag(args, "--code");
2809
2894
  const failFast = hasFlag(args, "--fail-fast");
2810
2895
  const format = toListFormat(parseFlag(args, "--format") ?? "human");
@@ -2819,7 +2904,7 @@ async function main(): Promise<void> {
2819
2904
  }
2820
2905
 
2821
2906
  case "list-errors": {
2822
- const mod = createHarnessErrorModule(rootDir);
2907
+ const mod = (await import("./harness-error/composition-root.js")).createHarnessErrorModule(rootDir);
2823
2908
  const format = toListFormat(parseFlag(args, "--format") ?? "human");
2824
2909
  const layer = toLayerFilter(parseFlag(args, "--layer"));
2825
2910
  const result = await mod.listErrorDefinitionsHandler.execute({
@@ -2833,7 +2918,7 @@ async function main(): Promise<void> {
2833
2918
 
2834
2919
  // ── traceability-model ──
2835
2920
  case "validate-metadata": {
2836
- const mod = createTraceabilityModelModule(rootDir, toTraceabilityModelOptions(resolvedConfig));
2921
+ const mod = (await import("./traceability-model/composition-root.js")).createTraceabilityModelModule(rootDir, toTraceabilityModelOptions(resolvedConfig));
2837
2922
  const filePaths = parsePositionalArgs(args.slice(1));
2838
2923
  const result = await mod.validateMetadataCommandHandler.execute({
2839
2924
  filePaths,
@@ -2845,7 +2930,7 @@ async function main(): Promise<void> {
2845
2930
  }
2846
2931
 
2847
2932
  case "work-items:status": {
2848
- const mod = createTraceabilityModelModule(rootDir, toTraceabilityModelOptions(resolvedConfig));
2933
+ const mod = (await import("./traceability-model/composition-root.js")).createTraceabilityModelModule(rootDir, toTraceabilityModelOptions(resolvedConfig));
2849
2934
  const result = await mod.workItemStatusCommandHandler.execute({
2850
2935
  dryRun: hasFlag(args, "--dry-run"),
2851
2936
  apply: hasFlag(args, "--apply"),
@@ -2864,12 +2949,12 @@ async function main(): Promise<void> {
2864
2949
  case "world:inspect": {
2865
2950
  let handler: WorldInspectCommandHandler;
2866
2951
  try {
2867
- handler = createWorldModelModule({
2952
+ handler = (await import("./world-model/index.js")).createWorldModelModule({
2868
2953
  rootDir,
2869
2954
  resolvedConfig: await loadWorldResolvedConfig(),
2870
2955
  }).worldInspectCommandHandler;
2871
2956
  } catch (error) {
2872
- handler = WorldInspectCommandHandler.fromFailure(error);
2957
+ handler = (await import("./world-model/index.js")).WorldInspectCommandHandler.fromFailure(error);
2873
2958
  }
2874
2959
  const result = await handler.execute(args.slice(1));
2875
2960
  if (result.stdout.length > 0) process.stdout.write(result.stdout);
@@ -2881,12 +2966,12 @@ async function main(): Promise<void> {
2881
2966
  case "world:pin": {
2882
2967
  let handler: WorldPinCommandHandler;
2883
2968
  try {
2884
- handler = createWorldModelModule({
2969
+ handler = (await import("./world-model/index.js")).createWorldModelModule({
2885
2970
  rootDir,
2886
2971
  resolvedConfig: await loadWorldResolvedConfig(),
2887
2972
  }).worldPinCommandHandler;
2888
2973
  } catch (error) {
2889
- handler = WorldPinCommandHandler.fromFailure(error);
2974
+ handler = (await import("./world-model/index.js")).WorldPinCommandHandler.fromFailure(error);
2890
2975
  }
2891
2976
  const result = await handler.execute(args.slice(1));
2892
2977
  if (result.stdout.length > 0) process.stdout.write(result.stdout);
@@ -2898,12 +2983,12 @@ async function main(): Promise<void> {
2898
2983
  case "world:derive": {
2899
2984
  let handler: WorldDeriveCommandHandler;
2900
2985
  try {
2901
- handler = createWorldModelModule({
2986
+ handler = (await import("./world-model/index.js")).createWorldModelModule({
2902
2987
  rootDir,
2903
2988
  resolvedConfig: await loadWorldResolvedConfig(),
2904
2989
  }).worldDeriveCommandHandler;
2905
2990
  } catch (error) {
2906
- handler = WorldDeriveCommandHandler.fromFailure(error);
2991
+ handler = (await import("./world-model/index.js")).WorldDeriveCommandHandler.fromFailure(error);
2907
2992
  }
2908
2993
  const result = await handler.execute(args.slice(1));
2909
2994
  if (result.stdout.length > 0) process.stdout.write(result.stdout);
@@ -2916,7 +3001,7 @@ async function main(): Promise<void> {
2916
3001
  case "check-phase-gate": {
2917
3002
  const phaseConfig = resolvedConfig ? toPhaseConfigSection(resolvedConfig) : undefined;
2918
3003
  const reportOutputDir = resolvedConfig?.reporting.outputDir;
2919
- const mod = createPhaseDependencyModelModule({
3004
+ const mod = (await import("./phase-dependency-model/composition-root.js")).createPhaseDependencyModelModule({
2920
3005
  rootDir,
2921
3006
  phaseConfig,
2922
3007
  reportOutputDir,
@@ -2942,7 +3027,7 @@ async function main(): Promise<void> {
2942
3027
  // ADR ディレクトリを rootDir として渡す(project root を渡すと readdir が ADR を
2943
3028
  // 一切発見できず vacuous な valid を返す phantom gate になる)。
2944
3029
  case "list-adrs": {
2945
- const mod = createAdrFoundationModule(join(rootDir, "docs", "ADR"));
3030
+ const mod = (await import("./adr-foundation/composition-root.js")).createAdrFoundationModule(join(rootDir, "docs", "ADR"));
2946
3031
  const statuses = toAdrStatuses(parseFlag(args, "--status"));
2947
3032
  const result = await mod.listAdrsCommandHandler.execute({
2948
3033
  statuses,
@@ -2954,7 +3039,7 @@ async function main(): Promise<void> {
2954
3039
  }
2955
3040
 
2956
3041
  case "validate-adr": {
2957
- const mod = createAdrFoundationModule(join(rootDir, "docs", "ADR"));
3042
+ const mod = (await import("./adr-foundation/composition-root.js")).createAdrFoundationModule(join(rootDir, "docs", "ADR"));
2958
3043
  const all = hasFlag(args, "--all");
2959
3044
  const adrRef = args.find((a) => !a.startsWith("--") && a !== command);
2960
3045
  const result = await mod.validateAdrCommandHandler.execute({
@@ -2980,7 +3065,7 @@ async function main(): Promise<void> {
2980
3065
 
2981
3066
  // ── validator-system ──
2982
3067
  case "validate": {
2983
- const mod = createValidatorSystemModule(toValidatorSystemConfig(resolvedConfig));
3068
+ const mod = (await import("./validator-system/composition-root.js")).createValidatorSystemModule(toValidatorSystemConfig(resolvedConfig));
2984
3069
  const layer = parseValidateLayer(args);
2985
3070
  const unit = parseFlag(args, "--unit");
2986
3071
  const phase = parseFlag(args, "--phase");
@@ -3013,7 +3098,7 @@ async function main(): Promise<void> {
3013
3098
  // WI-364: check-change-category (WI-351) と同様に解決済み configPath / rootDir を注入する。
3014
3099
  // 無指定だと quickMode 設定を cwd 基準でしか探せず、サブディレクトリ実行で
3015
3100
  // HarnessConfigNotFoundError → exit 2 になっていた。
3016
- const mod = createQuickModeCompositionRoot(await resolveQuickModeCompositionOptions());
3101
+ const mod = (await import("./quick-mode/composition-root.js")).createQuickModeCompositionRoot(await resolveQuickModeCompositionOptions());
3017
3102
  const failOnReject = hasFlag(args, "--fail-on-reject");
3018
3103
  const dryRun = hasFlag(args, "--dry-run");
3019
3104
  const files = parseFlag(args, "--files");
@@ -3042,6 +3127,7 @@ async function main(): Promise<void> {
3042
3127
  " --paths <csv> Comma-separated file paths to classify.",
3043
3128
  " --format <human|json> Output format. Default: human.",
3044
3129
  " --fail-on-full-required Exit with code 1 when Full Mode is required.",
3130
+ " --risk-snapshots <json> Optional before/after snapshots for advisory review; does not change gates.",
3045
3131
  " --help Show this help.",
3046
3132
  "",
3047
3133
  "Examples:",
@@ -3052,14 +3138,19 @@ async function main(): Promise<void> {
3052
3138
  );
3053
3139
  return;
3054
3140
  }
3055
- const mod = createQuickModeCompositionRoot(await resolveQuickModeCompositionOptions());
3141
+ const mod = (await import("./quick-mode/composition-root.js")).createQuickModeCompositionRoot(await resolveQuickModeCompositionOptions());
3056
3142
  const paths = parseFlag(args, "--paths");
3057
3143
  const format = parseFlag(args, "--format") as "human" | "json" | undefined;
3058
3144
  const failOnFullRequired = hasFlag(args, "--fail-on-full-required");
3145
+ const riskSnapshots = parseFlag(args, "--risk-snapshots");
3146
+ if (hasFlag(args, "--risk-snapshots") && !riskSnapshots) {
3147
+ throw new Error("--risk-snapshots requires a JSON file path.");
3148
+ }
3059
3149
  const result = await mod.checkChangeCategoryHandler.handle({
3060
3150
  paths,
3061
3151
  format,
3062
3152
  failOnFullRequired,
3153
+ riskSnapshots,
3063
3154
  });
3064
3155
  await finishCliExit(result.exitCode);
3065
3156
  return;
@@ -3145,9 +3236,8 @@ async function main(): Promise<void> {
3145
3236
  const mod = createHarnessApiModule();
3146
3237
  const flags: Record<string, boolean | string> = {};
3147
3238
  if (json) flags.json = true;
3148
- const target = parseFlag(args, "--target");
3149
- if (target) flags.target = target;
3150
- await mod.handlers.lint.handle({}, flags);
3239
+ const targets = args.flatMap((arg, index) => arg === '--target' && args[index + 1] !== undefined ? [args[index + 1]] : []);
3240
+ await mod.handlers.lint.handle(targets.length > 0 ? { reportTargets: JSON.stringify(targets) } : {}, flags);
3151
3241
  break;
3152
3242
  }
3153
3243
 
@@ -3222,7 +3312,7 @@ async function main(): Promise<void> {
3222
3312
  }
3223
3313
  const { createAttestationModule } = await import("./attestation/index.js");
3224
3314
  const pkgVersion = await getHarnessVersion(harnessRoot);
3225
- const worldModule = createWorldModelModule({
3315
+ const worldModule = (await import("./world-model/index.js")).createWorldModelModule({
3226
3316
  rootDir,
3227
3317
  resolvedConfig: await loadWorldResolvedConfig(),
3228
3318
  });
@@ -3289,7 +3379,7 @@ Examples:
3289
3379
  console.error(flagError);
3290
3380
  process.exit(2);
3291
3381
  }
3292
- const mod = buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3382
+ const mod = (await import("./ci-governance/composition-root.js")).buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3293
3383
  const presetId = parseFlag(args, "--preset") ?? "standard";
3294
3384
  const templateType = parseFlag(args, "--type") ?? "aidlc-gate";
3295
3385
  const render = hasFlag(args, "--render");
@@ -3301,7 +3391,7 @@ Examples:
3301
3391
  }
3302
3392
 
3303
3393
  case "ci:migrate-agents-md": {
3304
- const mod = buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3394
+ const mod = (await import("./ci-governance/composition-root.js")).buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3305
3395
  const dryRun = hasFlag(args, "--dry-run");
3306
3396
  const validateOnly = hasFlag(args, "--validate-only");
3307
3397
  const format = json ? "json" : "human";
@@ -3312,7 +3402,7 @@ Examples:
3312
3402
  }
3313
3403
 
3314
3404
  case "ci:auto-refresh-agent-context": {
3315
- const mod = buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3405
+ const mod = (await import("./ci-governance/composition-root.js")).buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3316
3406
  const dryRun = hasFlag(args, "--dry-run");
3317
3407
  const apply = hasFlag(args, "--apply");
3318
3408
  const format = json ? "json" : "human";
@@ -3323,7 +3413,7 @@ Examples:
3323
3413
  }
3324
3414
 
3325
3415
  case "refresh-claude-md": {
3326
- const mod = buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3416
+ const mod = (await import("./ci-governance/composition-root.js")).buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3327
3417
  const dryRun = hasFlag(args, "--dry-run");
3328
3418
  const apply = hasFlag(args, "--apply");
3329
3419
  const format = json ? "json" : "human";
@@ -3334,7 +3424,7 @@ Examples:
3334
3424
  }
3335
3425
 
3336
3426
  case "p2:check-agent-context": {
3337
- const mod = buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3427
+ const mod = (await import("./ci-governance/composition-root.js")).buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3338
3428
  const thresholdRaw = parseFlag(args, "--threshold-days");
3339
3429
  const thresholdDays = thresholdRaw === undefined ? undefined : Number(thresholdRaw);
3340
3430
  const format = json ? "json" : "human";
@@ -3345,7 +3435,7 @@ Examples:
3345
3435
  }
3346
3436
 
3347
3437
  case "ci:check-repetition": {
3348
- const mod = buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3438
+ const mod = (await import("./ci-governance/composition-root.js")).buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3349
3439
  const errorCode = parseFlag(args, "--code") ?? "";
3350
3440
  const reset = hasFlag(args, "--reset");
3351
3441
  const format = json ? "json" : "human";
@@ -3356,7 +3446,7 @@ Examples:
3356
3446
  }
3357
3447
 
3358
3448
  case "baseline": {
3359
- const mod = buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3449
+ const mod = (await import("./ci-governance/composition-root.js")).buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3360
3450
  const dryRun = hasFlag(args, "--dry-run");
3361
3451
  const force = hasFlag(args, "--force");
3362
3452
  const pathsFlag = parseFlag(args, "--paths");
@@ -3379,7 +3469,7 @@ Examples:
3379
3469
  }
3380
3470
 
3381
3471
  case "scaffold-design": {
3382
- const mod = buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3472
+ const mod = (await import("./ci-governance/composition-root.js")).buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3383
3473
  const unit = parseFlag(args, "--unit") ?? "";
3384
3474
  const phase = parseFlag(args, "--phase") ?? "";
3385
3475
  const dryRun = hasFlag(args, "--dry-run");
@@ -3400,7 +3490,7 @@ Examples:
3400
3490
  }
3401
3491
 
3402
3492
  case "scaffold-inception": {
3403
- const mod = buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3493
+ const mod = (await import("./ci-governance/composition-root.js")).buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3404
3494
  const kind = parseFlag(args, "--kind") ?? "";
3405
3495
  const dryRun = hasFlag(args, "--dry-run");
3406
3496
  const apply = hasFlag(args, "--apply");
@@ -3419,7 +3509,7 @@ Examples:
3419
3509
  }
3420
3510
 
3421
3511
  case "templates": {
3422
- const mod = buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3512
+ const mod = (await import("./ci-governance/composition-root.js")).buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3423
3513
  const subCommand = args[1];
3424
3514
  const emit = async (result: { exitCode: number; output: string; errorOutput: string }): Promise<void> => {
3425
3515
  if (result.output.length > 0) console.log(result.output);
@@ -3442,7 +3532,7 @@ Examples:
3442
3532
  }
3443
3533
 
3444
3534
  case "integrity:pin": {
3445
- const mod = buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3535
+ const mod = (await import("./ci-governance/composition-root.js")).buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3446
3536
  const dryRun = hasFlag(args, "--dry-run");
3447
3537
  const format = json ? "json" : "human";
3448
3538
  const result = await mod.integrityHandler.pin({ dryRun, format });
@@ -3452,7 +3542,7 @@ Examples:
3452
3542
  }
3453
3543
 
3454
3544
  case "integrity:verify": {
3455
- const mod = buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3545
+ const mod = (await import("./ci-governance/composition-root.js")).buildCiGovernance(rootDir, harnessRoot, toCiGovernanceDocPaths(resolvedConfig));
3456
3546
  const format = json ? "json" : "human";
3457
3547
  const result = await mod.integrityHandler.verify({ format });
3458
3548
  console.log(result.output);
@@ -3462,7 +3552,15 @@ Examples:
3462
3552
 
3463
3553
  // ── skill-quality ──
3464
3554
  case "skill:execute-tdd-cycle": {
3465
- const mod = createSkillQualityHandlers();
3555
+ const configuredValidation = hasFlag(args, "--configured-validation");
3556
+ const mod = (await import("./skill-quality/composition-root.js")).createSkillQualityHandlers(configuredValidation ? {
3557
+ rootDir,
3558
+ l1Config: resolvedConfig
3559
+ ? { l1Config: toL1Config(resolvedConfig), architecture: toArchitectureInput(resolvedConfig) }
3560
+ : undefined,
3561
+ validatorSystemConfig: toValidatorSystemConfig(resolvedConfig),
3562
+ failOnWarning: resolvedConfig?.validate.failOnWarning,
3563
+ } : {});
3466
3564
  const unit = parseFlag(args, "--unit") ?? "";
3467
3565
  const storyId = parseFlag(args, "--story") ?? "";
3468
3566
  const description = parseFlag(args, "--desc") ?? "";
@@ -3472,12 +3570,13 @@ Examples:
3472
3570
  const passed = hasFlag(args, "--passed");
3473
3571
  const result = await mod.executeTddCycleHandler.handle({ unit, storyId, description, phase, passed });
3474
3572
  console.log(result.message);
3573
+ console.log(`Validation profile: ${configuredValidation ? "configured" : "legacy (use --configured-validation to explicitly adopt resolved project validation settings)"}`);
3475
3574
  await finishCliExit(result.exitCode);
3476
3575
  return;
3477
3576
  }
3478
3577
 
3479
3578
  case "skill:check-coverage": {
3480
- const mod = createSkillQualityHandlers();
3579
+ const mod = (await import("./skill-quality/composition-root.js")).createSkillQualityHandlers();
3481
3580
  const storyId = parseFlag(args, "--story") ?? "";
3482
3581
  const format = json ? "json" : "human";
3483
3582
  const result = await mod.checkCoverageHandler.handle({ storyId, format });
@@ -3487,7 +3586,7 @@ Examples:
3487
3586
  }
3488
3587
 
3489
3588
  case "skill:collect-lessons": {
3490
- const mod = createSkillQualityHandlers();
3589
+ const mod = (await import("./skill-quality/composition-root.js")).createSkillQualityHandlers();
3491
3590
  const storyId = parseFlag(args, "--story") ?? "";
3492
3591
  const sourcesRaw = parseFlag(args, "--sources") ?? "";
3493
3592
  const sources = sourcesRaw ? sourcesRaw.split(",") : [];
@@ -3499,7 +3598,7 @@ Examples:
3499
3598
  }
3500
3599
 
3501
3600
  case "skill:apply-cascade-update": {
3502
- const mod = createSkillQualityHandlers();
3601
+ const mod = (await import("./skill-quality/composition-root.js")).createSkillQualityHandlers();
3503
3602
  const storyId = parseFlag(args, "--story") ?? "";
3504
3603
  const dryRun = hasFlag(args, "--dry-run");
3505
3604
  const result = await mod.applyCascadeUpdateHandler.handle({ storyId, dryRun, format: json ? "json" : "human" });
@@ -3509,7 +3608,7 @@ Examples:
3509
3608
  }
3510
3609
 
3511
3610
  case "skill:validate-structure": {
3512
- const mod = createSkillQualityHandlers();
3611
+ const mod = (await import("./skill-quality/composition-root.js")).createSkillQualityHandlers();
3513
3612
  const skillFile = parseFlag(args, "--file") ?? "";
3514
3613
  const format = json ? "json" : "human";
3515
3614
  const result = await mod.validateSkillStructureHandler.handle({ skillFile, format });
@@ -3520,7 +3619,7 @@ Examples:
3520
3619
 
3521
3620
  // ── regression-suite ──
3522
3621
  case "regression:run-k-requirements": {
3523
- const mod = buildRegressionSuite(rootDir);
3622
+ const mod = (await import("./regression-suite/composition-root.js")).buildRegressionSuite(rootDir);
3524
3623
  const result = await mod.runKRequirementsRegressionUseCase.execute();
3525
3624
  const output = json
3526
3625
  ? JSON.stringify(result, null, 2)
@@ -3531,7 +3630,7 @@ Examples:
3531
3630
  }
3532
3631
 
3533
3632
  case "regression:run-gng-gate": {
3534
- const mod = buildRegressionSuite(rootDir);
3633
+ const mod = (await import("./regression-suite/composition-root.js")).buildRegressionSuite(rootDir);
3535
3634
  const result = await mod.runGngGateRegressionUseCase.execute();
3536
3635
  const output = json
3537
3636
  ? JSON.stringify(result, null, 2)
@@ -3542,7 +3641,7 @@ Examples:
3542
3641
  }
3543
3642
 
3544
3643
  case "regression:run-agent-guard": {
3545
- const mod = buildRegressionSuite(rootDir);
3644
+ const mod = (await import("./regression-suite/composition-root.js")).buildRegressionSuite(rootDir);
3546
3645
  const result = await mod.runAgentIndependenceGuardUseCase.execute();
3547
3646
  const output = json
3548
3647
  ? JSON.stringify(result, null, 2)
@@ -3553,7 +3652,7 @@ Examples:
3553
3652
  }
3554
3653
 
3555
3654
  case "regression:run-k14-k15": {
3556
- const mod = buildRegressionSuite(rootDir);
3655
+ const mod = (await import("./regression-suite/composition-root.js")).buildRegressionSuite(rootDir);
3557
3656
  const result = await mod.runK14K15RegressionUseCase.execute();
3558
3657
  const output = json
3559
3658
  ? JSON.stringify(result, null, 2)
@@ -3564,7 +3663,7 @@ Examples:
3564
3663
  }
3565
3664
 
3566
3665
  case "regression:configure-ci-gate": {
3567
- const mod = buildRegressionSuite(rootDir);
3666
+ const mod = (await import("./regression-suite/composition-root.js")).buildRegressionSuite(rootDir);
3568
3667
  const requiredSuiteIds = parseSuiteIds(parseFlag(args, "--suites") ?? DEFAULT_REGRESSION_SUITES);
3569
3668
  const threshold = parseCoverageThreshold(parseFlag(args, "--threshold"));
3570
3669
  const result = await mod.configureCiGateUseCase.execute({
@@ -3581,7 +3680,7 @@ Examples:
3581
3680
  }
3582
3681
 
3583
3682
  case "regression:analyze-migration": {
3584
- const mod = buildRegressionSuite(rootDir);
3683
+ const mod = (await import("./regression-suite/composition-root.js")).buildRegressionSuite(rootDir);
3585
3684
  const dryRun = !hasFlag(args, "--no-dry-run");
3586
3685
  const result = await mod.analyzeV0MigrationUseCase.execute({ dryRun });
3587
3686
  const output = json
@@ -3593,7 +3692,7 @@ Examples:
3593
3692
  }
3594
3693
 
3595
3694
  case "regression:migrate-v0-tests": {
3596
- const mod = buildRegressionSuite(rootDir);
3695
+ const mod = (await import("./regression-suite/composition-root.js")).buildRegressionSuite(rootDir);
3597
3696
  const confirm = hasFlag(args, "--confirm");
3598
3697
  const result = await mod.migrateV0TestsUseCase.execute({ confirmExecute: confirm });
3599
3698
  const output = json
@@ -3606,7 +3705,7 @@ Examples:
3606
3705
 
3607
3706
  // ── phase2-extensions ──
3608
3707
  case "p2:check-freshness": {
3609
- const mod = buildPhase2Extensions(rootDir, resolvedConfig ?? undefined);
3708
+ const mod = (await import("./phase2-extensions/composition-root.js")).buildPhase2Extensions(rootDir, resolvedConfig ?? undefined);
3610
3709
  const p2args = args.slice(1);
3611
3710
  const result = await mod.checkFreshnessHandler.handle(p2args);
3612
3711
  console.log(result.stdout);
@@ -3615,7 +3714,7 @@ Examples:
3615
3714
  }
3616
3715
 
3617
3716
  case "p2:validate-pointers": {
3618
- const mod = buildPhase2Extensions(rootDir, resolvedConfig ?? undefined);
3717
+ const mod = (await import("./phase2-extensions/composition-root.js")).buildPhase2Extensions(rootDir, resolvedConfig ?? undefined);
3619
3718
  const p2args = args.slice(1);
3620
3719
  const result = await mod.validatePointersHandler.handle(p2args);
3621
3720
  console.log(result.stdout);
@@ -3624,7 +3723,7 @@ Examples:
3624
3723
  }
3625
3724
 
3626
3725
  case "p2:generate-e2e-template": {
3627
- const mod = buildPhase2Extensions(rootDir, resolvedConfig ?? undefined);
3726
+ const mod = (await import("./phase2-extensions/composition-root.js")).buildPhase2Extensions(rootDir, resolvedConfig ?? undefined);
3628
3727
  const p2args = args.slice(1);
3629
3728
  const result = await mod.generateE2ETemplateHandler.handle(p2args);
3630
3729
  console.log(result.stdout);
@@ -3633,7 +3732,7 @@ Examples:
3633
3732
  }
3634
3733
 
3635
3734
  case "p2:check-initial-creation": {
3636
- const mod = buildPhase2Extensions(rootDir, resolvedConfig ?? undefined);
3735
+ const mod = (await import("./phase2-extensions/composition-root.js")).buildPhase2Extensions(rootDir, resolvedConfig ?? undefined);
3637
3736
  const p2args = args.slice(1);
3638
3737
  const result = await mod.checkInitialCreationExpirationHandler.handle(p2args);
3639
3738
  console.log(result.stdout);