phasegate 0.254.0 → 0.264.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 +22 -0
- package/README.ja.md +6 -3
- package/README.md +6 -3
- package/docs/contracts/attestation-v2.schema.json +110 -0
- package/docs/guide/cli-reference.md +12 -1
- package/docs/guide/configuration.md +56 -0
- package/docs/templates/ci/aidlc-gate.yml +42 -2
- package/package.json +1 -1
- package/scripts/harness/agent-integration/application/dto/open-world-obligations-context-dto.ts +30 -0
- package/scripts/harness/agent-integration/application/ports/world-obligations-query-port.ts +30 -0
- package/scripts/harness/agent-integration/application/usecases/get-open-world-obligations-context-usecase.ts +66 -0
- package/scripts/harness/agent-integration/infrastructure/adapters/world-model-open-obligations-query-adapter.ts +58 -0
- package/scripts/harness/agent-integration/presentation/session-start-hook.ts +37 -1
- package/scripts/harness/agent-integration/presentation/world-obligations-session-context.ts +60 -0
- package/scripts/harness/attestation/application/dto/attestation-document.ts +17 -4
- package/scripts/harness/attestation/application/mappers/attestation-record-mapper.ts +55 -4
- package/scripts/harness/attestation/application/ports/world-snapshot-root-provider.ts +10 -0
- package/scripts/harness/attestation/application/usecases/produce-attestation-usecase.ts +33 -7
- package/scripts/harness/attestation/composition-root.ts +5 -0
- package/scripts/harness/attestation/domain/entities/attestation-record.ts +37 -2
- package/scripts/harness/attestation/index.ts +7 -1
- package/scripts/harness/attestation/presentation/handlers/attest-handler.ts +5 -2
- package/scripts/harness/config-foundation/application/mappers/validator-system-config-mapper.ts +35 -8
- package/scripts/harness/config-foundation/application/mappers/world-model-config-mapper.ts +15 -0
- package/scripts/harness/config-foundation/domain/harness-config.ts +67 -87
- package/scripts/harness/config-foundation/domain/services/preset-resolution-service.ts +77 -88
- package/scripts/harness/config-foundation/domain/value-objects/world-config.ts +198 -0
- package/scripts/harness/config-foundation/index.ts +14 -15
- package/scripts/harness/config-foundation/infrastructure/presets/minimal.json +24 -0
- package/scripts/harness/config-foundation/infrastructure/presets/standard.json +24 -0
- package/scripts/harness/config-foundation/infrastructure/presets/strict.json +24 -0
- package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v2.schema.json +83 -0
- package/scripts/harness/config-foundation/infrastructure/schemas/harness-config-v3.schema.json +83 -0
- package/scripts/harness/harness-api/domain/value-objects/ci-check-result.ts +18 -4
- package/scripts/harness/integrations/pre-commit.ts +169 -27
- package/scripts/harness/main.ts +174 -130
- package/scripts/harness/traceability-model/application/dto/changed-design-fragment-dto.ts +31 -0
- package/scripts/harness/traceability-model/application/facades/design-change-read-facade.ts +14 -0
- package/scripts/harness/traceability-model/application/ports/staged-design-change-source-port.ts +9 -0
- package/scripts/harness/traceability-model/composition-root.ts +5 -0
- package/scripts/harness/traceability-model/index.ts +9 -0
- package/scripts/harness/traceability-model/infrastructure/adapters/git-staged-design-change-adapter.ts +155 -0
- package/scripts/harness/validator-system/application/use-cases/run-l2-validators-usecase.ts +31 -0
- package/scripts/harness/validator-system/application/use-cases/run-l3-validators-usecase.ts +34 -0
- package/scripts/harness/validator-system/composition-root.ts +21 -6
- package/scripts/harness/validator-system/domain/ports/world-constraint-admission-policy-port.ts +28 -0
- package/scripts/harness/validator-system/domain/ports/world-constraint-rederivation-policy-port.ts +11 -0
- package/scripts/harness/validator-system/domain/services/design-change-declaration-policy.ts +75 -0
- package/scripts/harness/validator-system/domain/services/world-constraint-admission-service.ts +78 -0
- package/scripts/harness/validator-system/domain/services/world-constraint-rederivation-service.ts +76 -0
- package/scripts/harness/validator-system/domain/value-objects/validator-id.ts +4 -0
- package/scripts/harness/validator-system/infrastructure/adapters/harness-config-validator-config-adapter.ts +38 -16
- package/scripts/harness/validator-system/infrastructure/adapters/world-model-constraint-admission-adapter.ts +56 -0
- package/scripts/harness/validator-system/infrastructure/adapters/world-model-constraint-rederivation-adapter.ts +56 -0
- package/scripts/harness/world-model/application/dto/pinned-design-endpoint-dto.ts +19 -0
- package/scripts/harness/world-model/application/dto/world-resolved-config-input.ts +92 -27
- package/scripts/harness/world-model/application/dto/world-snapshot-root-dto.ts +8 -0
- package/scripts/harness/world-model/application/facades/pinned-design-endpoint-facade.ts +63 -0
- package/scripts/harness/world-model/application/facades/world-snapshot-root-facade.ts +19 -0
- package/scripts/harness/world-model/application/usecases/derive-world-obligations-use-case.ts +3 -1
- package/scripts/harness/world-model/composition-root.ts +62 -33
- package/scripts/harness/world-model/index.ts +11 -0
- package/scripts/harness/world-model/infrastructure/adapters/attestation-fact-extractor.ts +48 -13
- package/scripts/harness/world-model/infrastructure/adapters/file-system-world-control-repository-adapters.ts +6 -4
- package/scripts/harness/world-model/presentation/cli/world-derive-command-handler.ts +6 -2
package/scripts/harness/main.ts
CHANGED
|
@@ -22,6 +22,9 @@
|
|
|
22
22
|
* @work-item-id WI-217
|
|
23
23
|
* @work-item-id WI-219
|
|
24
24
|
* @work-item-id WI-291
|
|
25
|
+
* @work-item-id WI-300
|
|
26
|
+
* @work-item-id WI-306
|
|
27
|
+
* @work-item-id WI-308
|
|
25
28
|
*
|
|
26
29
|
* Phasegate CLI エントリポイント。
|
|
27
30
|
* 各Unitの Composition Root からハンドラーを取得し、コマンドに応じてディスパッチする。
|
|
@@ -45,6 +48,7 @@ import { createBiomeAstEngineModule } from "./biome-ast-engine/composition-root.
|
|
|
45
48
|
import { buildCiGovernance } from "./ci-governance/composition-root.js";
|
|
46
49
|
import { toPhaseConfigSection } from "./config-foundation/application/mappers/phase-config-section-mapper.js";
|
|
47
50
|
import { toValidatorSystemConfig } from "./config-foundation/application/mappers/validator-system-config-mapper.js";
|
|
51
|
+
import { toWorldModelConfig } from "./config-foundation/application/mappers/world-model-config-mapper.js";
|
|
48
52
|
import { createConfigFoundationModule } from "./config-foundation/composition-root.js";
|
|
49
53
|
import { ConfigValidationError } from "./config-foundation/domain/errors/config-validation-error.js";
|
|
50
54
|
import type { HarnessConfigV2 } from "./config-foundation/domain/harness-config.js";
|
|
@@ -1881,24 +1885,41 @@ async function loadWorldResolvedConfig() {
|
|
|
1881
1885
|
try {
|
|
1882
1886
|
const configModule = createConfigFoundationModule();
|
|
1883
1887
|
const result = await configModule.usecases.loadResolvedConfigUseCase.execute();
|
|
1884
|
-
return
|
|
1885
|
-
designDocsRoot: result.config.paths.designDocs,
|
|
1886
|
-
inceptionRoot: result.config.paths.inceptionDocs,
|
|
1887
|
-
requirementMatrixPath: result.config.layers.L3.requirementMatrixPath,
|
|
1888
|
-
};
|
|
1888
|
+
return toWorldModelConfig(result.config);
|
|
1889
1889
|
} catch (error) {
|
|
1890
1890
|
if (error instanceof ConfigNotFoundError) return undefined;
|
|
1891
1891
|
throw error;
|
|
1892
1892
|
}
|
|
1893
1893
|
}
|
|
1894
1894
|
|
|
1895
|
+
/**
|
|
1896
|
+
* WI-308: pipe接続されたstdout / stderrのpending writeを完了してから終了状態へ移る。
|
|
1897
|
+
* `process.exit()`はNodeのstream queueを待たないため、64 KiB超のJSONを切断し得る。
|
|
1898
|
+
*/
|
|
1899
|
+
async function finishCliExit(exitCode: number): Promise<void> {
|
|
1900
|
+
const drain = (stream: NodeJS.WriteStream): Promise<void> =>
|
|
1901
|
+
new Promise((resolvePromise, reject) => {
|
|
1902
|
+
stream.write("", (error) => {
|
|
1903
|
+
if (error) {
|
|
1904
|
+
reject(error);
|
|
1905
|
+
return;
|
|
1906
|
+
}
|
|
1907
|
+
resolvePromise();
|
|
1908
|
+
});
|
|
1909
|
+
});
|
|
1910
|
+
|
|
1911
|
+
await Promise.all([drain(process.stdout), drain(process.stderr)]);
|
|
1912
|
+
process.exitCode = exitCode;
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1895
1915
|
async function main(): Promise<void> {
|
|
1896
1916
|
const args = process.argv.slice(2);
|
|
1897
1917
|
const command = args[0];
|
|
1898
1918
|
|
|
1899
1919
|
if (!command || command === "--help" || command === "help") {
|
|
1900
1920
|
printUsage();
|
|
1901
|
-
|
|
1921
|
+
await finishCliExit(0);
|
|
1922
|
+
return;
|
|
1902
1923
|
}
|
|
1903
1924
|
|
|
1904
1925
|
const rootDir = getProjectRoot();
|
|
@@ -1907,13 +1928,15 @@ async function main(): Promise<void> {
|
|
|
1907
1928
|
if (command === "--version" || command === "version") {
|
|
1908
1929
|
const version = await getHarnessVersion(harnessRoot);
|
|
1909
1930
|
console.log(`phasegate v${version}`);
|
|
1910
|
-
|
|
1931
|
+
await finishCliExit(0);
|
|
1932
|
+
return;
|
|
1911
1933
|
}
|
|
1912
1934
|
|
|
1913
1935
|
// Pre-dispatch: 全 subcommand で --help / -h を最優先で解釈し usage 出力 (副作用走行を防ぐ — WI-091 finding #3)
|
|
1914
1936
|
if (hasFlag(args, "--help") || hasFlag(args, "-h")) {
|
|
1915
1937
|
printSubcommandHelp(command);
|
|
1916
|
-
|
|
1938
|
+
await finishCliExit(0);
|
|
1939
|
+
return;
|
|
1917
1940
|
}
|
|
1918
1941
|
|
|
1919
1942
|
const json = hasFlag(args, "--json");
|
|
@@ -2188,8 +2211,8 @@ async function main(): Promise<void> {
|
|
|
2188
2211
|
console.log(" • Q&A about phasegate concepts: invoke /phasegate-toolkit-guide");
|
|
2189
2212
|
console.log(" • Diagnose & tune phasegate.config.json: invoke /phasegate-config-doctor");
|
|
2190
2213
|
}
|
|
2191
|
-
|
|
2192
|
-
|
|
2214
|
+
await finishCliExit(hasStructuredInstallError(installResult) ? 1 : 0);
|
|
2215
|
+
return;
|
|
2193
2216
|
}
|
|
2194
2217
|
|
|
2195
2218
|
case "update-skills": {
|
|
@@ -2214,8 +2237,8 @@ async function main(): Promise<void> {
|
|
|
2214
2237
|
});
|
|
2215
2238
|
if (!json) console.log("phasegate update-skills is deprecated; running phasegate reconcile.");
|
|
2216
2239
|
console.log(result.stdout);
|
|
2217
|
-
|
|
2218
|
-
|
|
2240
|
+
await finishCliExit(result.exitCode);
|
|
2241
|
+
return;
|
|
2219
2242
|
}
|
|
2220
2243
|
|
|
2221
2244
|
case "doctor": {
|
|
@@ -2241,14 +2264,14 @@ async function main(): Promise<void> {
|
|
|
2241
2264
|
agent,
|
|
2242
2265
|
});
|
|
2243
2266
|
console.log(result.stdout);
|
|
2244
|
-
|
|
2245
|
-
|
|
2267
|
+
await finishCliExit(result.exitCode);
|
|
2268
|
+
return;
|
|
2246
2269
|
}
|
|
2247
2270
|
|
|
2248
2271
|
case "emit-agent-rules": {
|
|
2249
2272
|
console.log(emitAgentRulesBlock());
|
|
2250
|
-
|
|
2251
|
-
|
|
2273
|
+
await finishCliExit(0);
|
|
2274
|
+
return;
|
|
2252
2275
|
}
|
|
2253
2276
|
|
|
2254
2277
|
case "scaffold-wi": {
|
|
@@ -2274,8 +2297,8 @@ async function main(): Promise<void> {
|
|
|
2274
2297
|
inceptionRoot: parseFlag(args, "--root") ?? configuredPersonalRoot,
|
|
2275
2298
|
});
|
|
2276
2299
|
console.log(`Created ${descriptionPath}`);
|
|
2277
|
-
|
|
2278
|
-
|
|
2300
|
+
await finishCliExit(0);
|
|
2301
|
+
return;
|
|
2279
2302
|
}
|
|
2280
2303
|
|
|
2281
2304
|
case "install": {
|
|
@@ -2332,8 +2355,8 @@ async function main(): Promise<void> {
|
|
|
2332
2355
|
json,
|
|
2333
2356
|
});
|
|
2334
2357
|
console.log(result.stdout);
|
|
2335
|
-
|
|
2336
|
-
|
|
2358
|
+
await finishCliExit(result.exitCode);
|
|
2359
|
+
return;
|
|
2337
2360
|
}
|
|
2338
2361
|
|
|
2339
2362
|
case "setup:agent": {
|
|
@@ -2415,8 +2438,8 @@ async function main(): Promise<void> {
|
|
|
2415
2438
|
console.log("Validation:");
|
|
2416
2439
|
for (const command of plan.validation) console.log(`- ${command}`);
|
|
2417
2440
|
}
|
|
2418
|
-
|
|
2419
|
-
|
|
2441
|
+
await finishCliExit(hasStructuredInstallError(installResult) ? 1 : 0);
|
|
2442
|
+
return;
|
|
2420
2443
|
}
|
|
2421
2444
|
|
|
2422
2445
|
case "config:plan": {
|
|
@@ -2446,7 +2469,8 @@ async function main(): Promise<void> {
|
|
|
2446
2469
|
for (const operation of applyResult.appliedOperations)
|
|
2447
2470
|
console.log(`- ${operation.op} ${operation.pointer}`);
|
|
2448
2471
|
}
|
|
2449
|
-
|
|
2472
|
+
await finishCliExit(0);
|
|
2473
|
+
return;
|
|
2450
2474
|
} catch (error) {
|
|
2451
2475
|
const message = error instanceof Error ? error.message : String(error);
|
|
2452
2476
|
if (json) {
|
|
@@ -2460,7 +2484,8 @@ async function main(): Promise<void> {
|
|
|
2460
2484
|
} else {
|
|
2461
2485
|
console.error(`Error: ${message}`);
|
|
2462
2486
|
}
|
|
2463
|
-
|
|
2487
|
+
await finishCliExit(1);
|
|
2488
|
+
return;
|
|
2464
2489
|
}
|
|
2465
2490
|
}
|
|
2466
2491
|
if (json) {
|
|
@@ -2474,8 +2499,8 @@ async function main(): Promise<void> {
|
|
|
2474
2499
|
console.log("Validation:");
|
|
2475
2500
|
for (const validation of plan.validations) console.log(`- ${validation}`);
|
|
2476
2501
|
}
|
|
2477
|
-
|
|
2478
|
-
|
|
2502
|
+
await finishCliExit(0);
|
|
2503
|
+
return;
|
|
2479
2504
|
}
|
|
2480
2505
|
|
|
2481
2506
|
case "session": {
|
|
@@ -2496,7 +2521,8 @@ async function main(): Promise<void> {
|
|
|
2496
2521
|
`Full Mode session started: ${session.workItemId} unit=${session.unit} expiresAt=${session.expiresAt}`,
|
|
2497
2522
|
);
|
|
2498
2523
|
}
|
|
2499
|
-
|
|
2524
|
+
await finishCliExit(0);
|
|
2525
|
+
return;
|
|
2500
2526
|
} catch (error) {
|
|
2501
2527
|
const message = error instanceof Error ? error.message : String(error);
|
|
2502
2528
|
if (json) {
|
|
@@ -2504,7 +2530,8 @@ async function main(): Promise<void> {
|
|
|
2504
2530
|
} else {
|
|
2505
2531
|
console.error(`Error: ${message}`);
|
|
2506
2532
|
}
|
|
2507
|
-
|
|
2533
|
+
await finishCliExit(2);
|
|
2534
|
+
return;
|
|
2508
2535
|
}
|
|
2509
2536
|
}
|
|
2510
2537
|
if (subcommand === "end") {
|
|
@@ -2517,7 +2544,8 @@ async function main(): Promise<void> {
|
|
|
2517
2544
|
} else {
|
|
2518
2545
|
console.log("No Full Mode session was active.");
|
|
2519
2546
|
}
|
|
2520
|
-
|
|
2547
|
+
await finishCliExit(0);
|
|
2548
|
+
return;
|
|
2521
2549
|
} catch (error) {
|
|
2522
2550
|
const message = error instanceof Error ? error.message : String(error);
|
|
2523
2551
|
if (json) {
|
|
@@ -2525,7 +2553,8 @@ async function main(): Promise<void> {
|
|
|
2525
2553
|
} else {
|
|
2526
2554
|
console.error(`Error: ${message}`);
|
|
2527
2555
|
}
|
|
2528
|
-
|
|
2556
|
+
await finishCliExit(2);
|
|
2557
|
+
return;
|
|
2529
2558
|
}
|
|
2530
2559
|
}
|
|
2531
2560
|
console.error("Error: session subcommand must be begin or end.");
|
|
@@ -2552,8 +2581,8 @@ async function main(): Promise<void> {
|
|
|
2552
2581
|
json,
|
|
2553
2582
|
});
|
|
2554
2583
|
console.log(result.stdout);
|
|
2555
|
-
|
|
2556
|
-
|
|
2584
|
+
await finishCliExit(result.exitCode);
|
|
2585
|
+
return;
|
|
2557
2586
|
}
|
|
2558
2587
|
|
|
2559
2588
|
case "reconcile": {
|
|
@@ -2577,8 +2606,8 @@ async function main(): Promise<void> {
|
|
|
2577
2606
|
json,
|
|
2578
2607
|
});
|
|
2579
2608
|
console.log(result.stdout);
|
|
2580
|
-
|
|
2581
|
-
|
|
2609
|
+
await finishCliExit(result.exitCode);
|
|
2610
|
+
return;
|
|
2582
2611
|
}
|
|
2583
2612
|
|
|
2584
2613
|
// ── config-foundation ──
|
|
@@ -2593,8 +2622,8 @@ async function main(): Promise<void> {
|
|
|
2593
2622
|
configPath,
|
|
2594
2623
|
});
|
|
2595
2624
|
console.log(result.output);
|
|
2596
|
-
|
|
2597
|
-
|
|
2625
|
+
await finishCliExit(result.exitCode);
|
|
2626
|
+
return;
|
|
2598
2627
|
}
|
|
2599
2628
|
|
|
2600
2629
|
case "disable-feature": {
|
|
@@ -2608,8 +2637,8 @@ async function main(): Promise<void> {
|
|
|
2608
2637
|
configPath,
|
|
2609
2638
|
});
|
|
2610
2639
|
console.log(result.output);
|
|
2611
|
-
|
|
2612
|
-
|
|
2640
|
+
await finishCliExit(result.exitCode);
|
|
2641
|
+
return;
|
|
2613
2642
|
}
|
|
2614
2643
|
|
|
2615
2644
|
case "list-features": {
|
|
@@ -2618,8 +2647,8 @@ async function main(): Promise<void> {
|
|
|
2618
2647
|
list: true,
|
|
2619
2648
|
});
|
|
2620
2649
|
console.log(result.output);
|
|
2621
|
-
|
|
2622
|
-
|
|
2650
|
+
await finishCliExit(result.exitCode);
|
|
2651
|
+
return;
|
|
2623
2652
|
}
|
|
2624
2653
|
|
|
2625
2654
|
case "migrate": {
|
|
@@ -2631,8 +2660,8 @@ async function main(): Promise<void> {
|
|
|
2631
2660
|
json,
|
|
2632
2661
|
});
|
|
2633
2662
|
console.log(result.text);
|
|
2634
|
-
|
|
2635
|
-
|
|
2663
|
+
await finishCliExit(result.exitCode);
|
|
2664
|
+
return;
|
|
2636
2665
|
}
|
|
2637
2666
|
const mod = createConfigFoundationModule();
|
|
2638
2667
|
const targetVersion = parseFlag(args, "--schema") ?? "v3";
|
|
@@ -2642,8 +2671,8 @@ async function main(): Promise<void> {
|
|
|
2642
2671
|
configPath,
|
|
2643
2672
|
});
|
|
2644
2673
|
console.log(result.output);
|
|
2645
|
-
|
|
2646
|
-
|
|
2674
|
+
await finishCliExit(result.exitCode);
|
|
2675
|
+
return;
|
|
2647
2676
|
}
|
|
2648
2677
|
|
|
2649
2678
|
// ── harness-error ──
|
|
@@ -2657,8 +2686,8 @@ async function main(): Promise<void> {
|
|
|
2657
2686
|
failOnError,
|
|
2658
2687
|
});
|
|
2659
2688
|
console.log(result.output);
|
|
2660
|
-
|
|
2661
|
-
|
|
2689
|
+
await finishCliExit(result.exitCode);
|
|
2690
|
+
return;
|
|
2662
2691
|
}
|
|
2663
2692
|
|
|
2664
2693
|
case "validate-fix": {
|
|
@@ -2672,8 +2701,8 @@ async function main(): Promise<void> {
|
|
|
2672
2701
|
format,
|
|
2673
2702
|
});
|
|
2674
2703
|
console.log(result.output);
|
|
2675
|
-
|
|
2676
|
-
|
|
2704
|
+
await finishCliExit(result.exitCode);
|
|
2705
|
+
return;
|
|
2677
2706
|
}
|
|
2678
2707
|
|
|
2679
2708
|
case "list-errors": {
|
|
@@ -2685,8 +2714,8 @@ async function main(): Promise<void> {
|
|
|
2685
2714
|
layer,
|
|
2686
2715
|
});
|
|
2687
2716
|
console.log(result.output);
|
|
2688
|
-
|
|
2689
|
-
|
|
2717
|
+
await finishCliExit(result.exitCode);
|
|
2718
|
+
return;
|
|
2690
2719
|
}
|
|
2691
2720
|
|
|
2692
2721
|
// ── traceability-model ──
|
|
@@ -2698,8 +2727,8 @@ async function main(): Promise<void> {
|
|
|
2698
2727
|
json,
|
|
2699
2728
|
});
|
|
2700
2729
|
console.log(result.text);
|
|
2701
|
-
|
|
2702
|
-
|
|
2730
|
+
await finishCliExit(result.exitCode);
|
|
2731
|
+
return;
|
|
2703
2732
|
}
|
|
2704
2733
|
|
|
2705
2734
|
case "work-items:status": {
|
|
@@ -2714,8 +2743,8 @@ async function main(): Promise<void> {
|
|
|
2714
2743
|
json,
|
|
2715
2744
|
});
|
|
2716
2745
|
console.log(result.text);
|
|
2717
|
-
|
|
2718
|
-
|
|
2746
|
+
await finishCliExit(result.exitCode);
|
|
2747
|
+
return;
|
|
2719
2748
|
}
|
|
2720
2749
|
|
|
2721
2750
|
// ── world-model ──
|
|
@@ -2791,8 +2820,8 @@ async function main(): Promise<void> {
|
|
|
2791
2820
|
json,
|
|
2792
2821
|
});
|
|
2793
2822
|
console.log(result.text);
|
|
2794
|
-
|
|
2795
|
-
|
|
2823
|
+
await finishCliExit(result.exitCode);
|
|
2824
|
+
return;
|
|
2796
2825
|
}
|
|
2797
2826
|
|
|
2798
2827
|
// ── adr-foundation ──
|
|
@@ -2807,8 +2836,8 @@ async function main(): Promise<void> {
|
|
|
2807
2836
|
json,
|
|
2808
2837
|
});
|
|
2809
2838
|
console.log(result.text);
|
|
2810
|
-
|
|
2811
|
-
|
|
2839
|
+
await finishCliExit(result.exitCode);
|
|
2840
|
+
return;
|
|
2812
2841
|
}
|
|
2813
2842
|
|
|
2814
2843
|
case "validate-adr": {
|
|
@@ -2821,8 +2850,8 @@ async function main(): Promise<void> {
|
|
|
2821
2850
|
json,
|
|
2822
2851
|
});
|
|
2823
2852
|
console.log(result.text);
|
|
2824
|
-
|
|
2825
|
-
|
|
2853
|
+
await finishCliExit(result.exitCode);
|
|
2854
|
+
return;
|
|
2826
2855
|
}
|
|
2827
2856
|
|
|
2828
2857
|
// ── biome-ast-engine ──
|
|
@@ -2832,8 +2861,8 @@ async function main(): Promise<void> {
|
|
|
2832
2861
|
const mod = createBiomeAstEngineModule(rootDir, { l1Config, architecture });
|
|
2833
2862
|
const result = await mod.harnessLintCommandHandler.execute(args.slice(1));
|
|
2834
2863
|
console.log(result.text);
|
|
2835
|
-
|
|
2836
|
-
|
|
2864
|
+
await finishCliExit(result.exitCode);
|
|
2865
|
+
return;
|
|
2837
2866
|
}
|
|
2838
2867
|
|
|
2839
2868
|
// ── validator-system ──
|
|
@@ -2860,8 +2889,8 @@ async function main(): Promise<void> {
|
|
|
2860
2889
|
if ((layer === "L2" || layer === "all") && format !== "ci") {
|
|
2861
2890
|
await printStoryReflectionValidationSummary(rootDir, unit);
|
|
2862
2891
|
}
|
|
2863
|
-
|
|
2864
|
-
|
|
2892
|
+
await finishCliExit(result.exitCode);
|
|
2893
|
+
return;
|
|
2865
2894
|
}
|
|
2866
2895
|
|
|
2867
2896
|
// ── quick-mode / ci-check ──
|
|
@@ -2916,8 +2945,8 @@ async function main(): Promise<void> {
|
|
|
2916
2945
|
format,
|
|
2917
2946
|
failOnFullRequired,
|
|
2918
2947
|
});
|
|
2919
|
-
|
|
2920
|
-
|
|
2948
|
+
await finishCliExit(result.exitCode);
|
|
2949
|
+
return;
|
|
2921
2950
|
}
|
|
2922
2951
|
|
|
2923
2952
|
// ── harness-api ──
|
|
@@ -3077,7 +3106,16 @@ async function main(): Promise<void> {
|
|
|
3077
3106
|
}
|
|
3078
3107
|
const { createAttestationModule } = await import("./attestation/index.js");
|
|
3079
3108
|
const pkgVersion = await getHarnessVersion(harnessRoot);
|
|
3080
|
-
const
|
|
3109
|
+
const worldModule = createWorldModelModule({
|
|
3110
|
+
rootDir,
|
|
3111
|
+
resolvedConfig: await loadWorldResolvedConfig(),
|
|
3112
|
+
});
|
|
3113
|
+
const mod = createAttestationModule(rootDir, {
|
|
3114
|
+
pkgVersion,
|
|
3115
|
+
worldSnapshotRootProvider: {
|
|
3116
|
+
getWorldSnapshotRoot: async () => (await worldModule.worldSnapshotRootFacade.read()).worldSnapshotRoot,
|
|
3117
|
+
},
|
|
3118
|
+
});
|
|
3081
3119
|
const result = await mod.attestHandler.handle({
|
|
3082
3120
|
out: parseFlag(args, "--out") ?? ".harness/attestation.json",
|
|
3083
3121
|
requirePass: hasFlag(args, "--require-pass"),
|
|
@@ -3085,8 +3123,8 @@ async function main(): Promise<void> {
|
|
|
3085
3123
|
mode: parseFlag(args, "--mode"),
|
|
3086
3124
|
});
|
|
3087
3125
|
console.log(result.output);
|
|
3088
|
-
|
|
3089
|
-
|
|
3126
|
+
await finishCliExit(result.exitCode);
|
|
3127
|
+
return;
|
|
3090
3128
|
}
|
|
3091
3129
|
|
|
3092
3130
|
case "phasegate:verify-attestation": {
|
|
@@ -3103,8 +3141,8 @@ async function main(): Promise<void> {
|
|
|
3103
3141
|
emitJson: json,
|
|
3104
3142
|
});
|
|
3105
3143
|
console.log(result.output);
|
|
3106
|
-
|
|
3107
|
-
|
|
3144
|
+
await finishCliExit(result.exitCode);
|
|
3145
|
+
return;
|
|
3108
3146
|
}
|
|
3109
3147
|
|
|
3110
3148
|
// ── ci-governance ──
|
|
@@ -3127,7 +3165,8 @@ Options:
|
|
|
3127
3165
|
Examples:
|
|
3128
3166
|
phasegate ci:generate-template --type aidlc-gate
|
|
3129
3167
|
phasegate ci:generate-template --preset strict --type pre-commit --render`);
|
|
3130
|
-
|
|
3168
|
+
await finishCliExit(0);
|
|
3169
|
+
return;
|
|
3131
3170
|
}
|
|
3132
3171
|
const flagError = validateKnownFlags(args.slice(1), ["--preset", "--type", "--render", "--json", "--help"]);
|
|
3133
3172
|
if (flagError !== null) {
|
|
@@ -3141,8 +3180,8 @@ Examples:
|
|
|
3141
3180
|
const format = json ? "json" : "human";
|
|
3142
3181
|
const result = await mod.generateCiTemplateHandler.handle({ presetId, templateType, render, format });
|
|
3143
3182
|
console.log(result.output);
|
|
3144
|
-
|
|
3145
|
-
|
|
3183
|
+
await finishCliExit(result.exitCode);
|
|
3184
|
+
return;
|
|
3146
3185
|
}
|
|
3147
3186
|
|
|
3148
3187
|
case "ci:migrate-agents-md": {
|
|
@@ -3152,8 +3191,8 @@ Examples:
|
|
|
3152
3191
|
const format = json ? "json" : "human";
|
|
3153
3192
|
const result = await mod.migrateAgentsMdHandler.handle({ dryRun, validateOnly, format });
|
|
3154
3193
|
console.log(result.output);
|
|
3155
|
-
|
|
3156
|
-
|
|
3194
|
+
await finishCliExit(result.exitCode);
|
|
3195
|
+
return;
|
|
3157
3196
|
}
|
|
3158
3197
|
|
|
3159
3198
|
case "ci:auto-refresh-agent-context": {
|
|
@@ -3163,8 +3202,8 @@ Examples:
|
|
|
3163
3202
|
const format = json ? "json" : "human";
|
|
3164
3203
|
const result = await mod.refreshAgentContextHandler.handle({ dryRun, apply, format });
|
|
3165
3204
|
console.log(result.output);
|
|
3166
|
-
|
|
3167
|
-
|
|
3205
|
+
await finishCliExit(result.exitCode);
|
|
3206
|
+
return;
|
|
3168
3207
|
}
|
|
3169
3208
|
|
|
3170
3209
|
case "refresh-claude-md": {
|
|
@@ -3174,8 +3213,8 @@ Examples:
|
|
|
3174
3213
|
const format = json ? "json" : "human";
|
|
3175
3214
|
const result = await mod.refreshClaudeMdHandler.handle({ dryRun, apply, format });
|
|
3176
3215
|
console.log(result.output);
|
|
3177
|
-
|
|
3178
|
-
|
|
3216
|
+
await finishCliExit(result.exitCode);
|
|
3217
|
+
return;
|
|
3179
3218
|
}
|
|
3180
3219
|
|
|
3181
3220
|
case "p2:check-agent-context": {
|
|
@@ -3185,8 +3224,8 @@ Examples:
|
|
|
3185
3224
|
const format = json ? "json" : "human";
|
|
3186
3225
|
const result = await mod.checkAgentContextHandler.handle({ thresholdDays, format });
|
|
3187
3226
|
console.log(result.output);
|
|
3188
|
-
|
|
3189
|
-
|
|
3227
|
+
await finishCliExit(result.exitCode);
|
|
3228
|
+
return;
|
|
3190
3229
|
}
|
|
3191
3230
|
|
|
3192
3231
|
case "ci:check-repetition": {
|
|
@@ -3196,8 +3235,8 @@ Examples:
|
|
|
3196
3235
|
const format = json ? "json" : "human";
|
|
3197
3236
|
const result = await mod.checkRepetitionHandler.handle({ errorCode, reset, format });
|
|
3198
3237
|
console.log(result.output);
|
|
3199
|
-
|
|
3200
|
-
|
|
3238
|
+
await finishCliExit(result.exitCode);
|
|
3239
|
+
return;
|
|
3201
3240
|
}
|
|
3202
3241
|
|
|
3203
3242
|
case "baseline": {
|
|
@@ -3219,8 +3258,8 @@ Examples:
|
|
|
3219
3258
|
format,
|
|
3220
3259
|
});
|
|
3221
3260
|
console.log(result.output);
|
|
3222
|
-
|
|
3223
|
-
|
|
3261
|
+
await finishCliExit(result.exitCode);
|
|
3262
|
+
return;
|
|
3224
3263
|
}
|
|
3225
3264
|
|
|
3226
3265
|
case "scaffold-design": {
|
|
@@ -3240,8 +3279,8 @@ Examples:
|
|
|
3240
3279
|
format,
|
|
3241
3280
|
});
|
|
3242
3281
|
console.log(result.output);
|
|
3243
|
-
|
|
3244
|
-
|
|
3282
|
+
await finishCliExit(result.exitCode);
|
|
3283
|
+
return;
|
|
3245
3284
|
}
|
|
3246
3285
|
|
|
3247
3286
|
case "integrity:pin": {
|
|
@@ -3250,8 +3289,8 @@ Examples:
|
|
|
3250
3289
|
const format = json ? "json" : "human";
|
|
3251
3290
|
const result = await mod.integrityHandler.pin({ dryRun, format });
|
|
3252
3291
|
console.log(result.output);
|
|
3253
|
-
|
|
3254
|
-
|
|
3292
|
+
await finishCliExit(result.exitCode);
|
|
3293
|
+
return;
|
|
3255
3294
|
}
|
|
3256
3295
|
|
|
3257
3296
|
case "integrity:verify": {
|
|
@@ -3259,8 +3298,8 @@ Examples:
|
|
|
3259
3298
|
const format = json ? "json" : "human";
|
|
3260
3299
|
const result = await mod.integrityHandler.verify({ format });
|
|
3261
3300
|
console.log(result.output);
|
|
3262
|
-
|
|
3263
|
-
|
|
3301
|
+
await finishCliExit(result.exitCode);
|
|
3302
|
+
return;
|
|
3264
3303
|
}
|
|
3265
3304
|
|
|
3266
3305
|
// ── skill-quality ──
|
|
@@ -3275,8 +3314,8 @@ Examples:
|
|
|
3275
3314
|
const passed = hasFlag(args, "--passed");
|
|
3276
3315
|
const result = await mod.executeTddCycleHandler.handle({ unit, storyId, description, phase, passed });
|
|
3277
3316
|
console.log(result.message);
|
|
3278
|
-
|
|
3279
|
-
|
|
3317
|
+
await finishCliExit(result.exitCode);
|
|
3318
|
+
return;
|
|
3280
3319
|
}
|
|
3281
3320
|
|
|
3282
3321
|
case "skill:check-coverage": {
|
|
@@ -3285,8 +3324,8 @@ Examples:
|
|
|
3285
3324
|
const format = json ? "json" : "human";
|
|
3286
3325
|
const result = await mod.checkCoverageHandler.handle({ storyId, format });
|
|
3287
3326
|
console.log(result.message);
|
|
3288
|
-
|
|
3289
|
-
|
|
3327
|
+
await finishCliExit(result.exitCode);
|
|
3328
|
+
return;
|
|
3290
3329
|
}
|
|
3291
3330
|
|
|
3292
3331
|
case "skill:collect-lessons": {
|
|
@@ -3297,8 +3336,8 @@ Examples:
|
|
|
3297
3336
|
const writeArtifact = hasFlag(args, "--write-artifact");
|
|
3298
3337
|
const result = await mod.collectLessonsHandler.handle({ storyId, sources, writeArtifact });
|
|
3299
3338
|
console.log(result.message);
|
|
3300
|
-
|
|
3301
|
-
|
|
3339
|
+
await finishCliExit(result.exitCode);
|
|
3340
|
+
return;
|
|
3302
3341
|
}
|
|
3303
3342
|
|
|
3304
3343
|
case "skill:apply-cascade-update": {
|
|
@@ -3307,8 +3346,8 @@ Examples:
|
|
|
3307
3346
|
const dryRun = hasFlag(args, "--dry-run");
|
|
3308
3347
|
const result = await mod.applyCascadeUpdateHandler.handle({ storyId, dryRun, format: json ? "json" : "human" });
|
|
3309
3348
|
console.log(result.message);
|
|
3310
|
-
|
|
3311
|
-
|
|
3349
|
+
await finishCliExit(result.exitCode);
|
|
3350
|
+
return;
|
|
3312
3351
|
}
|
|
3313
3352
|
|
|
3314
3353
|
case "skill:validate-structure": {
|
|
@@ -3317,8 +3356,8 @@ Examples:
|
|
|
3317
3356
|
const format = json ? "json" : "human";
|
|
3318
3357
|
const result = await mod.validateSkillStructureHandler.handle({ skillFile, format });
|
|
3319
3358
|
console.log(result.message);
|
|
3320
|
-
|
|
3321
|
-
|
|
3359
|
+
await finishCliExit(result.exitCode);
|
|
3360
|
+
return;
|
|
3322
3361
|
}
|
|
3323
3362
|
|
|
3324
3363
|
// ── regression-suite ──
|
|
@@ -3329,8 +3368,8 @@ Examples:
|
|
|
3329
3368
|
? JSON.stringify(result, null, 2)
|
|
3330
3369
|
: `K-Requirements: ${result.passedCount}/${result.totalCount} passed`;
|
|
3331
3370
|
console.log(output);
|
|
3332
|
-
|
|
3333
|
-
|
|
3371
|
+
await finishCliExit(result.failedCount > 0 ? 1 : 0);
|
|
3372
|
+
return;
|
|
3334
3373
|
}
|
|
3335
3374
|
|
|
3336
3375
|
case "regression:run-gng-gate": {
|
|
@@ -3340,8 +3379,8 @@ Examples:
|
|
|
3340
3379
|
? JSON.stringify(result, null, 2)
|
|
3341
3380
|
: `GnG Gate: ${result.passedCount}/${result.totalCount} passed`;
|
|
3342
3381
|
console.log(output);
|
|
3343
|
-
|
|
3344
|
-
|
|
3382
|
+
await finishCliExit(result.failedCount > 0 ? 1 : 0);
|
|
3383
|
+
return;
|
|
3345
3384
|
}
|
|
3346
3385
|
|
|
3347
3386
|
case "regression:run-agent-guard": {
|
|
@@ -3351,8 +3390,8 @@ Examples:
|
|
|
3351
3390
|
? JSON.stringify(result, null, 2)
|
|
3352
3391
|
: `Agent Independence: ${result.passedCount}/${result.totalCount} passed`;
|
|
3353
3392
|
console.log(output);
|
|
3354
|
-
|
|
3355
|
-
|
|
3393
|
+
await finishCliExit(result.failedCount > 0 ? 1 : 0);
|
|
3394
|
+
return;
|
|
3356
3395
|
}
|
|
3357
3396
|
|
|
3358
3397
|
case "regression:run-k14-k15": {
|
|
@@ -3362,8 +3401,8 @@ Examples:
|
|
|
3362
3401
|
? JSON.stringify(result, null, 2)
|
|
3363
3402
|
: `K14/K15: ${result.passedCount}/${result.totalCount} passed`;
|
|
3364
3403
|
console.log(output);
|
|
3365
|
-
|
|
3366
|
-
|
|
3404
|
+
await finishCliExit(result.failedCount > 0 ? 1 : 0);
|
|
3405
|
+
return;
|
|
3367
3406
|
}
|
|
3368
3407
|
|
|
3369
3408
|
case "regression:configure-ci-gate": {
|
|
@@ -3379,8 +3418,8 @@ Examples:
|
|
|
3379
3418
|
? JSON.stringify(result, null, 2)
|
|
3380
3419
|
: `CI gate configured: suites=${result.requiredSuiteIds.join(",")}, threshold=${result.coverageThreshold}%`;
|
|
3381
3420
|
console.log(output);
|
|
3382
|
-
|
|
3383
|
-
|
|
3421
|
+
await finishCliExit(0);
|
|
3422
|
+
return;
|
|
3384
3423
|
}
|
|
3385
3424
|
|
|
3386
3425
|
case "regression:analyze-migration": {
|
|
@@ -3391,8 +3430,8 @@ Examples:
|
|
|
3391
3430
|
? JSON.stringify(result, null, 2)
|
|
3392
3431
|
: `Migration analysis: total=${result.totalCount}, migrated=${result.migratedCount}, modified=${result.modifiedCount}, skipped=${result.skippedCount}`;
|
|
3393
3432
|
console.log(output);
|
|
3394
|
-
|
|
3395
|
-
|
|
3433
|
+
await finishCliExit(0);
|
|
3434
|
+
return;
|
|
3396
3435
|
}
|
|
3397
3436
|
|
|
3398
3437
|
case "regression:migrate-v0-tests": {
|
|
@@ -3403,8 +3442,8 @@ Examples:
|
|
|
3403
3442
|
? JSON.stringify(result, null, 2)
|
|
3404
3443
|
: `Migration: total=${result.totalCount}, migrated=${result.migratedCount}, modified=${result.modifiedCount}, skipped=${result.skippedCount}`;
|
|
3405
3444
|
console.log(output);
|
|
3406
|
-
|
|
3407
|
-
|
|
3445
|
+
await finishCliExit(0);
|
|
3446
|
+
return;
|
|
3408
3447
|
}
|
|
3409
3448
|
|
|
3410
3449
|
// ── phase2-extensions ──
|
|
@@ -3413,8 +3452,8 @@ Examples:
|
|
|
3413
3452
|
const p2args = args.slice(1);
|
|
3414
3453
|
const result = await mod.checkFreshnessHandler.handle(p2args);
|
|
3415
3454
|
console.log(result.stdout);
|
|
3416
|
-
|
|
3417
|
-
|
|
3455
|
+
await finishCliExit(result.exitCode);
|
|
3456
|
+
return;
|
|
3418
3457
|
}
|
|
3419
3458
|
|
|
3420
3459
|
case "p2:validate-pointers": {
|
|
@@ -3422,8 +3461,8 @@ Examples:
|
|
|
3422
3461
|
const p2args = args.slice(1);
|
|
3423
3462
|
const result = await mod.validatePointersHandler.handle(p2args);
|
|
3424
3463
|
console.log(result.stdout);
|
|
3425
|
-
|
|
3426
|
-
|
|
3464
|
+
await finishCliExit(result.exitCode);
|
|
3465
|
+
return;
|
|
3427
3466
|
}
|
|
3428
3467
|
|
|
3429
3468
|
case "p2:generate-e2e-template": {
|
|
@@ -3431,8 +3470,8 @@ Examples:
|
|
|
3431
3470
|
const p2args = args.slice(1);
|
|
3432
3471
|
const result = await mod.generateE2ETemplateHandler.handle(p2args);
|
|
3433
3472
|
console.log(result.stdout);
|
|
3434
|
-
|
|
3435
|
-
|
|
3473
|
+
await finishCliExit(result.exitCode);
|
|
3474
|
+
return;
|
|
3436
3475
|
}
|
|
3437
3476
|
|
|
3438
3477
|
case "p2:check-initial-creation": {
|
|
@@ -3440,8 +3479,8 @@ Examples:
|
|
|
3440
3479
|
const p2args = args.slice(1);
|
|
3441
3480
|
const result = await mod.checkInitialCreationExpirationHandler.handle(p2args);
|
|
3442
3481
|
console.log(result.stdout);
|
|
3443
|
-
|
|
3444
|
-
|
|
3482
|
+
await finishCliExit(result.exitCode);
|
|
3483
|
+
return;
|
|
3445
3484
|
}
|
|
3446
3485
|
|
|
3447
3486
|
// ── agent integration / hooks ──
|
|
@@ -3500,7 +3539,8 @@ Examples:
|
|
|
3500
3539
|
case "delegate-sonnet": {
|
|
3501
3540
|
if (hasFlag(args, "--help") || hasFlag(args, "-h")) {
|
|
3502
3541
|
printSubcommandHelp("delegate-sonnet");
|
|
3503
|
-
|
|
3542
|
+
await finishCliExit(0);
|
|
3543
|
+
return;
|
|
3504
3544
|
}
|
|
3505
3545
|
if (!hasFlag(args, "--dry-run") && (await isModelDelegationDisabled(rootDir))) {
|
|
3506
3546
|
console.error(
|
|
@@ -3509,7 +3549,8 @@ Examples:
|
|
|
3509
3549
|
message: "phasegate delegate-sonnet is disabled by modelRouting.delegation=none",
|
|
3510
3550
|
}),
|
|
3511
3551
|
);
|
|
3512
|
-
|
|
3552
|
+
await finishCliExit(1);
|
|
3553
|
+
return;
|
|
3513
3554
|
}
|
|
3514
3555
|
const { spawn } = await import("node:child_process");
|
|
3515
3556
|
const scriptPath = join(harnessRoot, "scripts/delegate-sonnet.sh");
|
|
@@ -3559,7 +3600,8 @@ Examples:
|
|
|
3559
3600
|
}
|
|
3560
3601
|
console.log("");
|
|
3561
3602
|
}
|
|
3562
|
-
|
|
3603
|
+
await finishCliExit(0);
|
|
3604
|
+
return;
|
|
3563
3605
|
}
|
|
3564
3606
|
|
|
3565
3607
|
if (subCommand === "info") {
|
|
@@ -3573,7 +3615,8 @@ Examples:
|
|
|
3573
3615
|
try {
|
|
3574
3616
|
const content = await fs.readFile(skillMdPath, "utf-8");
|
|
3575
3617
|
console.log(content);
|
|
3576
|
-
|
|
3618
|
+
await finishCliExit(0);
|
|
3619
|
+
return;
|
|
3577
3620
|
} catch {
|
|
3578
3621
|
console.error(`Skill not found: ${skillName}`);
|
|
3579
3622
|
console.error(`Expected: ${skillMdPath}`);
|
|
@@ -3589,12 +3632,13 @@ Examples:
|
|
|
3589
3632
|
default:
|
|
3590
3633
|
console.error(`Unknown command: ${command}`);
|
|
3591
3634
|
printUsage();
|
|
3592
|
-
|
|
3635
|
+
await finishCliExit(2);
|
|
3636
|
+
return;
|
|
3593
3637
|
}
|
|
3594
3638
|
} catch (error: unknown) {
|
|
3595
3639
|
const message = error instanceof Error ? error.message : "Unknown error occurred";
|
|
3596
3640
|
console.error(`Fatal: ${message}`);
|
|
3597
|
-
|
|
3641
|
+
await finishCliExit(2);
|
|
3598
3642
|
}
|
|
3599
3643
|
}
|
|
3600
3644
|
|