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.
- package/CHANGELOG.md +16 -0
- package/README.ja.md +22 -9
- package/README.md +28 -17
- package/docs/ADR/038-config-state-operation-permission-policy.md +5 -2
- package/docs/ADR/041-non-excludable-agent-trust-roots.md +68 -0
- package/docs/folder_management_rules.md +10 -1
- package/docs/guide/antigravity-integration.md +26 -0
- package/docs/guide/cli-reference.md +27 -7
- package/docs/guide/codex-integration.md +44 -107
- package/docs/guide/configuration.md +28 -2
- package/docs/guide/grok-integration.md +26 -0
- package/docs/guide/hooks-integration.md +34 -5
- package/docs/guide/installation.md +4 -2
- package/docs/guide/setup-artifacts.md +4 -4
- package/docs/guide/skills-overview.md +4 -1
- package/package.json +2 -1
- package/scripts/harness/agent-integration/application/dto/handle-pre-tool-use-dto.ts +1 -1
- package/scripts/harness/agent-integration/application/dto/normalized-pre-tool-use-request.ts +32 -0
- package/scripts/harness/agent-integration/application/usecases/handle-post-tool-use-usecase.ts +4 -0
- package/scripts/harness/agent-integration/application/usecases/handle-pre-tool-use-usecase.ts +38 -3
- package/scripts/harness/agent-integration/application/usecases/handle-stop-usecase.ts +3 -9
- package/scripts/harness/agent-integration/domain/ports/full-mode-requirement-query-port.ts +3 -1
- package/scripts/harness/agent-integration/domain/ports/story-reflection-query-port.ts +2 -0
- package/scripts/harness/agent-integration/domain/services/apply-patch-write-target-extractor.ts +98 -0
- package/scripts/harness/agent-integration/domain/services/bash-write-target-extractor.ts +6 -52
- package/scripts/harness/agent-integration/domain/services/hook-to-cli-translator.ts +8 -5
- package/scripts/harness/agent-integration/domain/value-objects/hook-translation-result.ts +2 -2
- package/scripts/harness/agent-integration/domain/value-objects/protected-file-list.ts +35 -18
- package/scripts/harness/agent-integration/domain/value-objects/story-reflection-query-result.ts +10 -2
- package/scripts/harness/agent-integration/domain/value-objects/write-target-scope.ts +12 -0
- package/scripts/harness/agent-integration/infrastructure/adapters/child-process-cli-executor-adapter.ts +64 -13
- package/scripts/harness/agent-integration/infrastructure/adapters/file-system-story-reflection-query-adapter.ts +108 -2
- package/scripts/harness/agent-integration/infrastructure/adapters/harness-config-config-query-adapter.ts +8 -6
- package/scripts/harness/agent-integration/presentation/hook-skip-event-recorder.ts +3 -0
- package/scripts/harness/agent-integration/presentation/phasegate-status-context.ts +1 -1
- package/scripts/harness/agent-integration/presentation/post-tool-use-feedback.ts +39 -0
- package/scripts/harness/agent-integration/presentation/post-tool-use-hook.ts +21 -27
- package/scripts/harness/agent-integration/presentation/pre-tool-use-hook.ts +126 -70
- package/scripts/harness/agent-integration/presentation/pre-tool-use-payload-normalizer.ts +228 -0
- package/scripts/harness/agent-integration/presentation/pre-tool-use-response-renderer.ts +38 -0
- package/scripts/harness/agent-integration/presentation/stop-hook.ts +1 -3
- package/scripts/harness/biome-ast-engine/infrastructure/adapters/biome-cli-executor-adapter.ts +21 -1
- package/scripts/harness/biome-ast-engine/infrastructure/adapters/typescript-source-module-analyzer-adapter.ts +5 -0
- package/scripts/harness/ci-governance/domain/value-objects/integrity-target.ts +2 -0
- package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json +15 -0
- package/scripts/harness/config-foundation/infrastructure/validators/ajv-config-schema-validator.ts +6 -3
- package/scripts/harness/harness-api/domain/ports/biome-lint-port.ts +2 -1
- package/scripts/harness/harness-api/domain/services/command-dispatch-service.ts +12 -1
- package/scripts/harness/harness-api/infrastructure/adapters/biome-ast-engine-lint-adapter.ts +10 -2
- package/scripts/harness/installation/application/bundled-skill-selection.ts +28 -2
- package/scripts/harness/installation/application/checks/antigravity-hook-missing-check.ts +79 -0
- package/scripts/harness/installation/application/checks/check-utils.ts +2 -2
- package/scripts/harness/installation/application/checks/codex-hook-missing-check.ts +70 -6
- package/scripts/harness/installation/application/checks/grok-hook-missing-check.ts +79 -0
- package/scripts/harness/installation/application/checks/husky-runtime-inactive-check.ts +33 -0
- package/scripts/harness/installation/application/named-hook-json.ts +17 -0
- package/scripts/harness/installation/application/operator-notice.ts +42 -0
- package/scripts/harness/installation/application/usecases/run-doctor-diagnostics.ts +18 -7
- package/scripts/harness/installation/application/usecases/run-install.ts +157 -57
- package/scripts/harness/installation/application/usecases/run-reconcile.ts +148 -31
- package/scripts/harness/installation/application/usecases/run-uninstall.ts +149 -25
- package/scripts/harness/installation/composition-root.ts +10 -0
- package/scripts/harness/installation/domain/agent-target.ts +39 -0
- package/scripts/harness/installation/domain/check-id.ts +5 -0
- package/scripts/harness/installation/domain/husky-runtime-state.ts +34 -0
- package/scripts/harness/installation/domain/ports/git-hooks-runtime-probe.ts +9 -0
- package/scripts/harness/installation/domain/repair-table.ts +5 -0
- package/scripts/harness/installation/infrastructure/adapters/git-hooks-runtime-probe-adapter.ts +62 -0
- package/scripts/harness/installation/presentation/cli/install-handler.ts +25 -5
- package/scripts/harness/installation/presentation/cli/reconcile-handler.ts +7 -1
- package/scripts/harness/installation/presentation/formatters/diagnostic-report-formatter.ts +27 -0
- package/scripts/harness/main.ts +227 -128
- package/scripts/harness/phase-dependency-model/domain/services/story-reflection-checker.ts +48 -5
- package/scripts/harness/phase-dependency-model/domain/services/work-item-reflection-scope-resolver.ts +64 -0
- package/scripts/harness/phase-dependency-model/domain/values/story-reflection-mapping.ts +8 -2
- package/scripts/harness/phase-dependency-model/infrastructure/filesystem/file-system-story-reflection-adapter.ts +6 -1
- package/scripts/harness/phase-dependency-model/infrastructure/filesystem/file-system-work-item-dependency-catalog.ts +73 -0
- package/scripts/harness/quick-mode/application/dto/change-category-classification-contract.ts +5 -1
- package/scripts/harness/quick-mode/application/dto/quick-mode-eligibility-contract.ts +1 -1
- package/scripts/harness/quick-mode/application/ports/change-risk-advisory-port.ts +16 -0
- package/scripts/harness/quick-mode/application/usecases/classify-change-category-usecase.ts +3 -1
- package/scripts/harness/quick-mode/composition-root.ts +5 -1
- package/scripts/harness/quick-mode/domain/services/quick-mode-judgment-engine.ts +13 -2
- package/scripts/harness/quick-mode/domain/types/rejection-rule.ts +1 -1
- package/scripts/harness/quick-mode/infrastructure/adapters/snapshot-risk-advisory-adapter.ts +118 -0
- package/scripts/harness/quick-mode/presentation/formatters/change-category-formatter.ts +7 -0
- package/scripts/harness/quick-mode/presentation/handlers/check-change-category-handler.ts +12 -1
- package/scripts/harness/regression-suite/infrastructure/adapters/vitest-test-runner-adapter.ts +13 -3
- package/scripts/harness/setup/skill-deployer.ts +3 -45
- package/scripts/harness/skill-quality/application/dto/run-plan-checker-loop-output.ts +1 -0
- package/scripts/harness/skill-quality/application/usecases/apply-cascade-update-usecase.ts +9 -4
- package/scripts/harness/skill-quality/application/usecases/execute-tdd-cycle-usecase.ts +2 -1
- package/scripts/harness/skill-quality/application/usecases/run-plan-checker-loop-usecase.ts +8 -0
- package/scripts/harness/skill-quality/composition-root.ts +14 -7
- package/scripts/harness/skill-quality/domain/ports/plan-check-executor-port.ts +2 -0
- package/scripts/harness/skill-quality/domain/value-objects/cascade-update-target.ts +15 -1
- package/scripts/harness/skill-quality/infrastructure/adapters/l1-biome-validator-adapter.ts +9 -1
- package/scripts/harness/skill-quality/infrastructure/adapters/l2-validator-system-adapter.ts +18 -2
- package/scripts/harness/skill-quality/presentation/handlers/apply-cascade-update-handler.ts +8 -2
- package/scripts/harness/skill-quality/presentation/handlers/execute-tdd-cycle-handler.ts +4 -3
- package/scripts/harness/skill-quality/presentation/handlers/run-plan-checker-loop-handler.ts +11 -4
- package/scripts/harness/traceability-model/infrastructure/parsers/work-item-frontmatter-parser.ts +41 -0
- package/skills/README.md +7 -0
- package/skills/cascade-updater/SKILL.md +37 -109
- 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
- package/skills/release-publisher/SKILL.md +3 -1
- package/skills/skill-creator/SKILL.md +8 -9
- package/templates/.agents/hooks.json +16 -0
- package/templates/.claude/scripts/analyze-errors-hook.sh +2 -2
- package/templates/.claude/settings.json +5 -3
- package/templates/.codex/hooks.json +2 -2
package/scripts/harness/main.ts
CHANGED
|
@@ -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 {
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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>
|
|
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>
|
|
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
|
-
|
|
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
|
|
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
|
-
(!
|
|
1249
|
-
|
|
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:
|
|
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
|
|
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 ||
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
2104
|
-
console.error(`Invalid --agent value: "${agentRaw}". Use
|
|
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(
|
|
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(
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
3149
|
-
|
|
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
|
|
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);
|