@skillcap/gdh 0.6.0 → 0.8.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/INSTALL-BUNDLE.json +1 -1
- package/README.md +23 -5
- package/node_modules/@gdh/adapters/dist/index.d.ts +6 -3
- package/node_modules/@gdh/adapters/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/adapters/dist/index.js +222 -258
- package/node_modules/@gdh/adapters/dist/index.js.map +1 -1
- package/node_modules/@gdh/adapters/dist/self-update-mechanics.d.ts.map +1 -1
- package/node_modules/@gdh/adapters/dist/self-update-mechanics.js +9 -1
- package/node_modules/@gdh/adapters/dist/self-update-mechanics.js.map +1 -1
- package/node_modules/@gdh/adapters/package.json +8 -8
- package/node_modules/@gdh/authoring/dist/prepare.d.ts.map +1 -1
- package/node_modules/@gdh/authoring/dist/prepare.js +5 -1
- package/node_modules/@gdh/authoring/dist/prepare.js.map +1 -1
- package/node_modules/@gdh/authoring/package.json +2 -2
- package/node_modules/@gdh/cli/dist/index.d.ts +35 -0
- package/node_modules/@gdh/cli/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/cli/dist/index.js +279 -150
- package/node_modules/@gdh/cli/dist/index.js.map +1 -1
- package/node_modules/@gdh/cli/dist/migrate.d.ts +5 -1
- package/node_modules/@gdh/cli/dist/migrate.d.ts.map +1 -1
- package/node_modules/@gdh/cli/dist/migrate.js +57 -3
- package/node_modules/@gdh/cli/dist/migrate.js.map +1 -1
- package/node_modules/@gdh/cli/dist/self-update.d.ts.map +1 -1
- package/node_modules/@gdh/cli/dist/self-update.js +52 -3
- package/node_modules/@gdh/cli/dist/self-update.js.map +1 -1
- package/node_modules/@gdh/cli/dist/setup.d.ts +41 -0
- package/node_modules/@gdh/cli/dist/setup.d.ts.map +1 -1
- package/node_modules/@gdh/cli/dist/setup.js +181 -26
- package/node_modules/@gdh/cli/dist/setup.js.map +1 -1
- package/node_modules/@gdh/cli/package.json +10 -10
- package/node_modules/@gdh/core/dist/index.d.ts +77 -4
- package/node_modules/@gdh/core/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/core/dist/index.js +45 -6
- package/node_modules/@gdh/core/dist/index.js.map +1 -1
- package/node_modules/@gdh/core/dist/update-cache.d.ts +12 -0
- package/node_modules/@gdh/core/dist/update-cache.d.ts.map +1 -1
- package/node_modules/@gdh/core/dist/update-cache.js +20 -0
- package/node_modules/@gdh/core/dist/update-cache.js.map +1 -1
- package/node_modules/@gdh/core/dist/update-probe.d.ts.map +1 -1
- package/node_modules/@gdh/core/dist/update-probe.js +7 -1
- package/node_modules/@gdh/core/dist/update-probe.js.map +1 -1
- package/node_modules/@gdh/core/package.json +1 -1
- package/node_modules/@gdh/docs/dist/index.d.ts +2 -0
- package/node_modules/@gdh/docs/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/docs/dist/index.js +1 -0
- package/node_modules/@gdh/docs/dist/index.js.map +1 -1
- package/node_modules/@gdh/docs/dist/recovery-hints.d.ts +43 -0
- package/node_modules/@gdh/docs/dist/recovery-hints.d.ts.map +1 -0
- package/node_modules/@gdh/docs/dist/recovery-hints.js +203 -0
- package/node_modules/@gdh/docs/dist/recovery-hints.js.map +1 -0
- package/node_modules/@gdh/docs/package.json +2 -2
- package/node_modules/@gdh/mcp/package.json +8 -8
- package/node_modules/@gdh/observability/package.json +2 -2
- package/node_modules/@gdh/runtime/package.json +2 -2
- package/node_modules/@gdh/scan/dist/detect-existing-onboarding.d.ts +19 -0
- package/node_modules/@gdh/scan/dist/detect-existing-onboarding.d.ts.map +1 -0
- package/node_modules/@gdh/scan/dist/detect-existing-onboarding.js +58 -0
- package/node_modules/@gdh/scan/dist/detect-existing-onboarding.js.map +1 -0
- package/node_modules/@gdh/scan/dist/index.d.ts +1 -0
- package/node_modules/@gdh/scan/dist/index.d.ts.map +1 -1
- package/node_modules/@gdh/scan/dist/index.js +1 -0
- package/node_modules/@gdh/scan/dist/index.js.map +1 -1
- package/node_modules/@gdh/scan/dist/onboard.d.ts +2 -0
- package/node_modules/@gdh/scan/dist/onboard.d.ts.map +1 -1
- package/node_modules/@gdh/scan/dist/onboard.js +12 -4
- package/node_modules/@gdh/scan/dist/onboard.js.map +1 -1
- package/node_modules/@gdh/scan/package.json +3 -3
- package/node_modules/@gdh/verify/package.json +7 -7
- package/package.json +11 -11
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
1
2
|
import fs from "node:fs/promises";
|
|
3
|
+
import fsSync from "node:fs";
|
|
2
4
|
import os from "node:os";
|
|
3
5
|
import path from "node:path";
|
|
4
|
-
import {
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { buildGdhStatusResult, CLAUDE_CHECK_COMMAND_RELATIVE_PATH, CLAUDE_CHECK_UPDATE_HOOK_RELATIVE_PATH, CLAUDE_MIGRATE_COMMAND_RELATIVE_PATH, CLAUDE_ONBOARD_COMMAND_RELATIVE_PATH, CLAUDE_PREPARE_COMMAND_RELATIVE_PATH, CLAUDE_STATUS_COMMAND_RELATIVE_PATH, CLAUDE_VERIFY_COMMAND_RELATIVE_PATH, CODEX_CHECK_SKILL_RELATIVE_PATH, CODEX_MIGRATE_SKILL_RELATIVE_PATH, CODEX_ONBOARD_SKILL_RELATIVE_PATH, CODEX_PREPARE_SKILL_RELATIVE_PATH, CODEX_STATUS_SKILL_RELATIVE_PATH, CODEX_VERIFY_SKILL_RELATIVE_PATH, createGsdSnapshot, CURSOR_CHECK_SKILL_RELATIVE_PATH, CURSOR_MIGRATE_SKILL_RELATIVE_PATH, CURSOR_ONBOARD_SKILL_RELATIVE_PATH, CURSOR_PREPARE_SKILL_RELATIVE_PATH, CURSOR_STATUS_SKILL_RELATIVE_PATH, CURSOR_VERIFY_SKILL_RELATIVE_PATH, getSupportedAgentAdaptersStatus, installSupportedAgentAdapters, } from "@gdh/adapters";
|
|
5
8
|
import { getManagedLspStatus, hasCompleteOnboardingSurface, inspectCacheState, pruneCacheState, readProjectConfig, resolvePinnedVersion, resolveProjectRoot, readWorktreeState, resolveAuthoringStatus, resolveTargetGodotDocsVersion, runAuthoringCheck, runImportRefresh, runTargetPrepare, runWarmup, } from "@gdh/authoring";
|
|
6
9
|
import { definePackageBoundary, GDH_AUTHORING_DOGFOOD_VERSION, GDH_AUTHORING_SLICE_REPORT_VERSION, GDH_PRODUCT_NAME, resolveCurrentGdhInstall, resolveGdhProductMetadata, } from "@gdh/core";
|
|
7
10
|
import { fetchOfficialGodotDoc, getGuidanceStatus, resolveGuidanceQuery, searchOfficialGodotDocs, } from "@gdh/docs";
|
|
@@ -13,7 +16,7 @@ import { evaluateDonePolicy, exerciseRuntimeCorpusEntry, inspectRuntimeCorpusSta
|
|
|
13
16
|
import { migrateProjectLifecycleSurface } from "./migrate.js";
|
|
14
17
|
import { presentPublicRuntimeTerms } from "./public-terms.js";
|
|
15
18
|
import { runSelfUpdateCommand } from "./self-update.js";
|
|
16
|
-
import { executeSetupCommand, isSetupCanceledError, renderSetupIntro, renderSetupOutro, renderSetupSummary, } from "./setup.js";
|
|
19
|
+
import { executeSetupCommand, isSetupCanceledError, renderDurableTruthCollisionHint, renderSetupIntro, renderSetupOutro, renderSetupSummary, } from "./setup.js";
|
|
17
20
|
import { emitUpdateBannerIfStale } from "./update-banner.js";
|
|
18
21
|
export const cliPackage = definePackageBoundary({
|
|
19
22
|
name: "@gdh/cli",
|
|
@@ -41,6 +44,18 @@ export async function runCli(args, io = { stdout: process.stdout, stderr: proces
|
|
|
41
44
|
io.stdout.write(`${resolveGdhProductMetadata().version}\n`);
|
|
42
45
|
return 0;
|
|
43
46
|
}
|
|
47
|
+
// Internal diagnostic for Plan 15-05 symlink-shape test; not a user-facing feature.
|
|
48
|
+
if (command === "--print-target-path") {
|
|
49
|
+
const { targetPath, error } = parseOptionalPositionalTargetPath(rest, {
|
|
50
|
+
usage: "Usage: gdh --print-target-path [<target-path>]\n",
|
|
51
|
+
});
|
|
52
|
+
if (error !== null) {
|
|
53
|
+
io.stderr.write(error);
|
|
54
|
+
return 1;
|
|
55
|
+
}
|
|
56
|
+
io.stdout.write(`${JSON.stringify({ targetPath })}\n`);
|
|
57
|
+
return 0;
|
|
58
|
+
}
|
|
44
59
|
if (command === "version") {
|
|
45
60
|
return runVersionCommand(rest, io);
|
|
46
61
|
}
|
|
@@ -213,8 +228,12 @@ async function runSetupCommand(args, io) {
|
|
|
213
228
|
const yes = args.includes("--yes");
|
|
214
229
|
const allAgents = args.includes("--all-agents");
|
|
215
230
|
const positionalArgs = extractPositionalArgs(args, new Set(["--agent", "--project", "--integration-root"]));
|
|
216
|
-
|
|
217
|
-
|
|
231
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
232
|
+
usage: "Usage: gdh setup [<target-path>] [--agent <name>] [--all-agents] [--project <path>] [--integration-root <path>] [--yes]\n",
|
|
233
|
+
additionalOptionsWithValues: new Set(["--agent", "--project", "--integration-root"]),
|
|
234
|
+
});
|
|
235
|
+
if (targetPathError !== null) {
|
|
236
|
+
io.stderr.write(targetPathError);
|
|
218
237
|
return 1;
|
|
219
238
|
}
|
|
220
239
|
const requestedAgents = collectAdapterNames(args);
|
|
@@ -226,7 +245,6 @@ async function runSetupCommand(args, io) {
|
|
|
226
245
|
io.stderr.write("Usage error: choose either --all-agents or one or more --agent values.\n");
|
|
227
246
|
return 1;
|
|
228
247
|
}
|
|
229
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
230
248
|
const explicitTargetPath = positionalArgs.length === 1;
|
|
231
249
|
const selectedProjectRelativePath = readSingleOptionValue(args, "--project");
|
|
232
250
|
const integrationRootPath = readSingleOptionValue(args, "--integration-root");
|
|
@@ -288,6 +306,22 @@ async function runSetupCommand(args, io) {
|
|
|
288
306
|
});
|
|
289
307
|
return 1;
|
|
290
308
|
}
|
|
309
|
+
// Phase 18 plan 03 (UX-02): typed recoveryHint render before the generic
|
|
310
|
+
// failure branch. Detects DurableTruthCollisionError via the dual-package-
|
|
311
|
+
// hazard-safe predicate exported by setup.ts, renders the structured
|
|
312
|
+
// recoveryHint (Suggested fix / Run / Skill) to the CLI stderr sink, and
|
|
313
|
+
// records a blocked session (mirrors the SetupCanceledError arm shape).
|
|
314
|
+
if (renderDurableTruthCollisionHint(error, io.stderr)) {
|
|
315
|
+
await recordSessionEvent(targetPath, {
|
|
316
|
+
commandStartedAtMs,
|
|
317
|
+
kind: "onboard",
|
|
318
|
+
command: "gdh setup",
|
|
319
|
+
state: "blocked",
|
|
320
|
+
summary: "GDH setup blocked on durable-truth collision; see recoveryHint.",
|
|
321
|
+
errorMessage: formatCliError(error),
|
|
322
|
+
});
|
|
323
|
+
return 1;
|
|
324
|
+
}
|
|
291
325
|
await recordSessionEvent(targetPath, {
|
|
292
326
|
commandStartedAtMs,
|
|
293
327
|
kind: "onboard",
|
|
@@ -318,12 +352,14 @@ async function runOnboardCommand(args, io) {
|
|
|
318
352
|
return 1;
|
|
319
353
|
}
|
|
320
354
|
const dryRun = args.includes("--dry-run");
|
|
321
|
-
const
|
|
322
|
-
|
|
323
|
-
|
|
355
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
356
|
+
usage: "Usage: gdh onboard [target] [--dry-run]\n",
|
|
357
|
+
additionalOptionsWithValues: new Set(["--task-type", "--capability", "--repo-state", "--keyword"]),
|
|
358
|
+
});
|
|
359
|
+
if (targetPathError !== null) {
|
|
360
|
+
io.stderr.write(targetPathError);
|
|
324
361
|
return 1;
|
|
325
362
|
}
|
|
326
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
327
363
|
const commandStartedAtMs = Date.now();
|
|
328
364
|
try {
|
|
329
365
|
const result = await onboardGodotProject(targetPath, { dryRun });
|
|
@@ -519,16 +555,18 @@ async function runDocsVersionCommand(args, io) {
|
|
|
519
555
|
io.stderr.write(unsupportedOptionsError);
|
|
520
556
|
return 1;
|
|
521
557
|
}
|
|
522
|
-
const
|
|
523
|
-
|
|
524
|
-
|
|
558
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
559
|
+
usage: "Usage: gdh docs version [target] [--project <relative-path>]\n",
|
|
560
|
+
additionalOptionsWithValues: new Set(["--project"]),
|
|
561
|
+
});
|
|
562
|
+
if (targetPathError !== null) {
|
|
563
|
+
io.stderr.write(targetPathError);
|
|
525
564
|
return 1;
|
|
526
565
|
}
|
|
527
566
|
if (args.includes("--project") && readSingleOptionValue(args, "--project") === null) {
|
|
528
567
|
io.stderr.write("Usage error: --project requires a relative project path.\n");
|
|
529
568
|
return 1;
|
|
530
569
|
}
|
|
531
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
532
570
|
const requestedProjectPath = readSingleOptionValue(args, "--project");
|
|
533
571
|
try {
|
|
534
572
|
const context = await buildAuthoringContext(targetPath);
|
|
@@ -767,12 +805,14 @@ async function runWarmupCommand(args, io) {
|
|
|
767
805
|
return 1;
|
|
768
806
|
}
|
|
769
807
|
const dryRun = args.includes("--dry-run");
|
|
770
|
-
const
|
|
771
|
-
|
|
772
|
-
|
|
808
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
809
|
+
usage: "Usage: gdh warmup [target] [--dry-run]\n",
|
|
810
|
+
additionalOptionsWithValues: new Set(["--task-type", "--capability", "--repo-state", "--keyword"]),
|
|
811
|
+
});
|
|
812
|
+
if (targetPathError !== null) {
|
|
813
|
+
io.stderr.write(targetPathError);
|
|
773
814
|
return 1;
|
|
774
815
|
}
|
|
775
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
776
816
|
try {
|
|
777
817
|
const context = await buildAuthoringContext(targetPath);
|
|
778
818
|
const result = await runWarmup({
|
|
@@ -831,12 +871,14 @@ async function runTargetPrepareCommand(args, io) {
|
|
|
831
871
|
}
|
|
832
872
|
const dryRun = args.includes("--dry-run");
|
|
833
873
|
const refreshImports = !args.includes("--no-refresh-imports");
|
|
834
|
-
const
|
|
835
|
-
|
|
836
|
-
|
|
874
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
875
|
+
usage: "Usage: gdh target prepare [target] [--source-target <path>] [--dry-run] [--no-refresh-imports]\n",
|
|
876
|
+
additionalOptionsWithValues: new Set(["--source-target"]),
|
|
877
|
+
});
|
|
878
|
+
if (targetPathError !== null) {
|
|
879
|
+
io.stderr.write(targetPathError);
|
|
837
880
|
return 1;
|
|
838
881
|
}
|
|
839
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
840
882
|
const sourceTargetPath = collectOptionValues(args, "--source-target")[0] ?? null;
|
|
841
883
|
const commandStartedAtMs = Date.now();
|
|
842
884
|
try {
|
|
@@ -918,12 +960,13 @@ async function runImportsRefreshCommand(args, io) {
|
|
|
918
960
|
return 1;
|
|
919
961
|
}
|
|
920
962
|
const dryRun = args.includes("--dry-run");
|
|
921
|
-
const
|
|
922
|
-
|
|
923
|
-
|
|
963
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
964
|
+
usage: "Usage: gdh imports refresh [target] [--dry-run]\n",
|
|
965
|
+
});
|
|
966
|
+
if (targetPathError !== null) {
|
|
967
|
+
io.stderr.write(targetPathError);
|
|
924
968
|
return 1;
|
|
925
969
|
}
|
|
926
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
927
970
|
const commandStartedAtMs = Date.now();
|
|
928
971
|
try {
|
|
929
972
|
const context = await buildAuthoringContext(targetPath);
|
|
@@ -1259,7 +1302,7 @@ async function runVerifyCommand(args, io) {
|
|
|
1259
1302
|
" corpus <status|record>",
|
|
1260
1303
|
" Inspect or record runtime corpus release-readiness evidence as JSON.",
|
|
1261
1304
|
" drift [target]",
|
|
1262
|
-
" Check whether baked `@skillcap/gdh@<version>` literals (
|
|
1305
|
+
" Check whether baked `@skillcap/gdh@<version>` literals (skills + commands) match .gdh/project.yaml gdh_version.",
|
|
1263
1306
|
" recommend [target] --files <path> [--files <path>...]",
|
|
1264
1307
|
" Recommend authoring-first validation requirements for the supplied change set.",
|
|
1265
1308
|
" done [target] --files <path> [--files <path>...] [--performed <kind>]",
|
|
@@ -1476,12 +1519,14 @@ async function runMigrateCommand(args, io) {
|
|
|
1476
1519
|
io.stderr.write(unsupportedOptionsError);
|
|
1477
1520
|
return 1;
|
|
1478
1521
|
}
|
|
1479
|
-
const
|
|
1480
|
-
|
|
1481
|
-
|
|
1522
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
1523
|
+
usage: "Usage: gdh migrate [target] [--apply]\n",
|
|
1524
|
+
additionalOptionsWithValues: new Set(["--apply"]),
|
|
1525
|
+
});
|
|
1526
|
+
if (targetPathError !== null) {
|
|
1527
|
+
io.stderr.write(targetPathError);
|
|
1482
1528
|
return 1;
|
|
1483
1529
|
}
|
|
1484
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
1485
1530
|
const dryRun = !args.includes("--apply");
|
|
1486
1531
|
try {
|
|
1487
1532
|
const result = await migrateProjectLifecycleSurface({ targetPath, dryRun });
|
|
@@ -1510,12 +1555,13 @@ async function runBridgeStatusCommand(args, io) {
|
|
|
1510
1555
|
io.stderr.write(unsupportedOptionsError);
|
|
1511
1556
|
return 1;
|
|
1512
1557
|
}
|
|
1513
|
-
const
|
|
1514
|
-
|
|
1515
|
-
|
|
1558
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
1559
|
+
usage: "Usage: gdh bridge status [target]\nUsage: gdh bridge doctor [target]\n",
|
|
1560
|
+
});
|
|
1561
|
+
if (targetPathError !== null) {
|
|
1562
|
+
io.stderr.write(targetPathError);
|
|
1516
1563
|
return 1;
|
|
1517
1564
|
}
|
|
1518
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
1519
1565
|
const commandStartedAtMs = Date.now();
|
|
1520
1566
|
try {
|
|
1521
1567
|
const projectConfig = await readProjectConfig(targetPath);
|
|
@@ -1563,12 +1609,14 @@ async function runBridgeApplyCommand(args, io, operation) {
|
|
|
1563
1609
|
io.stderr.write(unsupportedOptionsError);
|
|
1564
1610
|
return 1;
|
|
1565
1611
|
}
|
|
1566
|
-
const
|
|
1567
|
-
|
|
1568
|
-
|
|
1612
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
1613
|
+
usage: `Usage: gdh bridge ${operation} [target] [--dry-run]\n`,
|
|
1614
|
+
additionalOptionsWithValues: new Set(["--dry-run"]),
|
|
1615
|
+
});
|
|
1616
|
+
if (targetPathError !== null) {
|
|
1617
|
+
io.stderr.write(targetPathError);
|
|
1569
1618
|
return 1;
|
|
1570
1619
|
}
|
|
1571
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
1572
1620
|
const dryRun = args.includes("--dry-run");
|
|
1573
1621
|
const commandStartedAtMs = Date.now();
|
|
1574
1622
|
try {
|
|
@@ -1642,12 +1690,14 @@ async function runRecipeListCommand(args, io) {
|
|
|
1642
1690
|
io.stderr.write(unsupportedOptionsError);
|
|
1643
1691
|
return 1;
|
|
1644
1692
|
}
|
|
1645
|
-
const
|
|
1646
|
-
|
|
1647
|
-
|
|
1693
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
1694
|
+
usage: "Usage: gdh run-config list [target]\n",
|
|
1695
|
+
additionalOptionsWithValues: new Set(["--provider", "--param", "--feature", "--no-feature", "--env"]),
|
|
1696
|
+
});
|
|
1697
|
+
if (targetPathError !== null) {
|
|
1698
|
+
io.stderr.write(targetPathError);
|
|
1648
1699
|
return 1;
|
|
1649
1700
|
}
|
|
1650
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
1651
1701
|
const effectiveTargetPath = await resolveEffectiveTargetPath(targetPath);
|
|
1652
1702
|
const commandStartedAtMs = Date.now();
|
|
1653
1703
|
try {
|
|
@@ -1876,12 +1926,14 @@ async function runScenarioListCommand(args, io) {
|
|
|
1876
1926
|
io.stderr.write(unsupportedOptionsError);
|
|
1877
1927
|
return 1;
|
|
1878
1928
|
}
|
|
1879
|
-
const
|
|
1880
|
-
|
|
1881
|
-
|
|
1929
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
1930
|
+
usage: "Usage: gdh verification-scenario list [target]\n",
|
|
1931
|
+
additionalOptionsWithValues: new Set(["--provider", "--param", "--feature", "--no-feature", "--env"]),
|
|
1932
|
+
});
|
|
1933
|
+
if (targetPathError !== null) {
|
|
1934
|
+
io.stderr.write(targetPathError);
|
|
1882
1935
|
return 1;
|
|
1883
1936
|
}
|
|
1884
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
1885
1937
|
const effectiveTargetPath = await resolveEffectiveTargetPath(targetPath);
|
|
1886
1938
|
const commandStartedAtMs = Date.now();
|
|
1887
1939
|
try {
|
|
@@ -1980,12 +2032,14 @@ async function runAdaptersStatusCommand(args, io) {
|
|
|
1980
2032
|
io.stderr.write(unsupportedOptionsError);
|
|
1981
2033
|
return 1;
|
|
1982
2034
|
}
|
|
1983
|
-
const
|
|
1984
|
-
|
|
1985
|
-
|
|
2035
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
2036
|
+
usage: "Usage: gdh adapters status [target] [--integration-root <path>]\n",
|
|
2037
|
+
additionalOptionsWithValues: new Set(["--integration-root"]),
|
|
2038
|
+
});
|
|
2039
|
+
if (targetPathError !== null) {
|
|
2040
|
+
io.stderr.write(targetPathError);
|
|
1986
2041
|
return 1;
|
|
1987
2042
|
}
|
|
1988
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
1989
2043
|
const integrationRootPath = readSingleOptionValue(args, "--integration-root");
|
|
1990
2044
|
try {
|
|
1991
2045
|
const result = await getSupportedAgentAdaptersStatus(targetPath, {
|
|
@@ -2022,9 +2076,12 @@ async function runAdaptersInstallCommand(args, io) {
|
|
|
2022
2076
|
}
|
|
2023
2077
|
const dryRun = args.includes("--dry-run");
|
|
2024
2078
|
const user = args.includes("--user");
|
|
2025
|
-
const
|
|
2026
|
-
|
|
2027
|
-
|
|
2079
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
2080
|
+
usage: "Usage: gdh adapters install [target] [--dry-run] [--agent <name>] [--user] [--dev-repo <path>] [--integration-root <path>]\n",
|
|
2081
|
+
additionalOptionsWithValues: new Set(["--agent", "--dev-repo", "--integration-root"]),
|
|
2082
|
+
});
|
|
2083
|
+
if (targetPathError !== null) {
|
|
2084
|
+
io.stderr.write(targetPathError);
|
|
2028
2085
|
return 1;
|
|
2029
2086
|
}
|
|
2030
2087
|
const agents = collectAdapterNames(args);
|
|
@@ -2032,7 +2089,6 @@ async function runAdaptersInstallCommand(args, io) {
|
|
|
2032
2089
|
io.stderr.write("Usage error: --agent must be one of codex, claude, or cursor.\n");
|
|
2033
2090
|
return 1;
|
|
2034
2091
|
}
|
|
2035
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
2036
2092
|
const devRepoPath = readSingleOptionValue(args, "--dev-repo");
|
|
2037
2093
|
const integrationRootPath = readSingleOptionValue(args, "--integration-root");
|
|
2038
2094
|
try {
|
|
@@ -2068,12 +2124,14 @@ async function runGsdSnapshotCommand(args, io) {
|
|
|
2068
2124
|
io.stderr.write(unsupportedOptionsError);
|
|
2069
2125
|
return 1;
|
|
2070
2126
|
}
|
|
2071
|
-
const
|
|
2072
|
-
|
|
2073
|
-
|
|
2127
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
2128
|
+
usage: "Usage: gdh adapters gsd snapshot [target] [--files <path>] [--performed <kind>]\n",
|
|
2129
|
+
additionalOptionsWithValues: new Set(["--files", "--performed"]),
|
|
2130
|
+
});
|
|
2131
|
+
if (targetPathError !== null) {
|
|
2132
|
+
io.stderr.write(targetPathError);
|
|
2074
2133
|
return 1;
|
|
2075
2134
|
}
|
|
2076
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
2077
2135
|
try {
|
|
2078
2136
|
const result = await createGsdSnapshot(targetPath, {
|
|
2079
2137
|
files: collectOptionValues(args, "--files"),
|
|
@@ -2098,29 +2156,30 @@ async function runMcpManifestCommand(args, io) {
|
|
|
2098
2156
|
async function runMcpServeCommand(args, io) {
|
|
2099
2157
|
if (args.includes("--help")) {
|
|
2100
2158
|
io.stdout.write([
|
|
2101
|
-
"Usage: gdh mcp serve --target <path>",
|
|
2159
|
+
"Usage: gdh mcp serve [--target <path>]",
|
|
2102
2160
|
"",
|
|
2103
|
-
"Run the real GDH stdio MCP server
|
|
2161
|
+
"Run the real GDH stdio MCP server. When --target is omitted, defaults to",
|
|
2162
|
+
"the current working directory and walks up to find the nearest .gdh/project.yaml.",
|
|
2104
2163
|
].join("\n") + "\n");
|
|
2105
2164
|
return 0;
|
|
2106
2165
|
}
|
|
2107
2166
|
const unsupportedOptionsError = findUnsupportedOptionsError(args, {
|
|
2108
|
-
usage: "Usage: gdh mcp serve --target <path
|
|
2167
|
+
usage: "Usage: gdh mcp serve [--target <path>]\n",
|
|
2109
2168
|
optionsWithValues: ["--target"],
|
|
2110
2169
|
});
|
|
2111
2170
|
if (unsupportedOptionsError !== null) {
|
|
2112
2171
|
io.stderr.write(unsupportedOptionsError);
|
|
2113
2172
|
return 1;
|
|
2114
2173
|
}
|
|
2115
|
-
const targetPath = readSingleOptionValue(args, "--target");
|
|
2116
|
-
if (targetPath === null) {
|
|
2117
|
-
io.stderr.write("Usage error: gdh mcp serve requires --target <path>.\n");
|
|
2118
|
-
return 1;
|
|
2119
|
-
}
|
|
2120
2174
|
if (extractPositionalArgs(args, new Set(["--target"])).length > 0) {
|
|
2121
2175
|
io.stderr.write("Usage error: gdh mcp serve accepts only --target <path>.\n");
|
|
2122
2176
|
return 1;
|
|
2123
2177
|
}
|
|
2178
|
+
const targetPath = readSingleOptionValue(args, "--target") ?? process.cwd();
|
|
2179
|
+
const devRepoExitCode = maybeReexecIntoDevRepo(targetPath);
|
|
2180
|
+
if (devRepoExitCode !== null) {
|
|
2181
|
+
return devRepoExitCode;
|
|
2182
|
+
}
|
|
2124
2183
|
try {
|
|
2125
2184
|
await serveMcpOverStdio(targetPath);
|
|
2126
2185
|
return 0;
|
|
@@ -2130,6 +2189,42 @@ async function runMcpServeCommand(args, io) {
|
|
|
2130
2189
|
return 1;
|
|
2131
2190
|
}
|
|
2132
2191
|
}
|
|
2192
|
+
function maybeReexecIntoDevRepo(targetPath) {
|
|
2193
|
+
if (process.env["GDH_MCP_DEV_REEXEC"] === "1") {
|
|
2194
|
+
// Already running under a dev-repo re-exec; skip to avoid a loop.
|
|
2195
|
+
return null;
|
|
2196
|
+
}
|
|
2197
|
+
const envDevRepoPath = process.env["GDH_DEV_REPO"]?.trim() || null;
|
|
2198
|
+
const hintsPath = path.join(path.resolve(targetPath), ".gdh-state", "local-paths.json");
|
|
2199
|
+
let hintDevRepoPath = null;
|
|
2200
|
+
try {
|
|
2201
|
+
const raw = fsSync.readFileSync(hintsPath, "utf8");
|
|
2202
|
+
const parsed = JSON.parse(raw);
|
|
2203
|
+
if (typeof parsed.gdhDevRepoPath === "string" && parsed.gdhDevRepoPath.length > 0) {
|
|
2204
|
+
hintDevRepoPath = parsed.gdhDevRepoPath;
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
catch {
|
|
2208
|
+
// No hints file or unparseable — fall through.
|
|
2209
|
+
}
|
|
2210
|
+
const devRepoPath = envDevRepoPath || hintDevRepoPath;
|
|
2211
|
+
if (devRepoPath === null) {
|
|
2212
|
+
return null;
|
|
2213
|
+
}
|
|
2214
|
+
const devCliEntry = path.join(devRepoPath, "packages/cli/dist/cli.js");
|
|
2215
|
+
if (!fsSync.existsSync(devCliEntry)) {
|
|
2216
|
+
return null;
|
|
2217
|
+
}
|
|
2218
|
+
const currentCliPath = path.resolve(fileURLToPath(import.meta.url));
|
|
2219
|
+
const resolvedDevRepoPath = path.resolve(devRepoPath);
|
|
2220
|
+
// Avoid loop if the currently-running CLI source already lives inside the
|
|
2221
|
+
// dev repo (e.g. contributor running the dev CLI directly via tsx).
|
|
2222
|
+
if (currentCliPath.startsWith(`${resolvedDevRepoPath}${path.sep}`)) {
|
|
2223
|
+
return null;
|
|
2224
|
+
}
|
|
2225
|
+
const result = spawnSync(process.execPath, [devCliEntry, "mcp", "serve", "--target", path.resolve(targetPath)], { stdio: "inherit", env: { ...process.env, GDH_MCP_DEV_REEXEC: "1" } });
|
|
2226
|
+
return result.status ?? 1;
|
|
2227
|
+
}
|
|
2133
2228
|
async function runMcpInvokeCommand(args, io) {
|
|
2134
2229
|
if (args.includes("--help")) {
|
|
2135
2230
|
io.stdout.write([
|
|
@@ -2157,12 +2252,14 @@ async function runMcpInvokeCommand(args, io) {
|
|
|
2157
2252
|
io.stderr.write(unsupportedOptionsError);
|
|
2158
2253
|
return 1;
|
|
2159
2254
|
}
|
|
2160
|
-
const
|
|
2161
|
-
|
|
2162
|
-
|
|
2255
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(rest, {
|
|
2256
|
+
usage: "Usage: gdh mcp invoke <tool> [target] [--input-json <json>]\n",
|
|
2257
|
+
additionalOptionsWithValues: new Set(["--input-json"]),
|
|
2258
|
+
});
|
|
2259
|
+
if (targetPathError !== null) {
|
|
2260
|
+
io.stderr.write(targetPathError);
|
|
2163
2261
|
return 1;
|
|
2164
2262
|
}
|
|
2165
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
2166
2263
|
try {
|
|
2167
2264
|
const result = await invokeMcpTool({
|
|
2168
2265
|
toolName: toolName,
|
|
@@ -2220,9 +2317,12 @@ async function runVerifyRecommendCommand(args, io) {
|
|
|
2220
2317
|
io.stderr.write(unsupportedOptionsError);
|
|
2221
2318
|
return 1;
|
|
2222
2319
|
}
|
|
2223
|
-
const
|
|
2224
|
-
|
|
2225
|
-
|
|
2320
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
2321
|
+
usage: "Usage: gdh verify recommend [target] --files <path> [--files <path>...]\n",
|
|
2322
|
+
additionalOptionsWithValues: new Set(["--files"]),
|
|
2323
|
+
});
|
|
2324
|
+
if (targetPathError !== null) {
|
|
2325
|
+
io.stderr.write(targetPathError);
|
|
2226
2326
|
return 1;
|
|
2227
2327
|
}
|
|
2228
2328
|
const files = collectOptionValues(args, "--files");
|
|
@@ -2230,7 +2330,6 @@ async function runVerifyRecommendCommand(args, io) {
|
|
|
2230
2330
|
io.stderr.write("Usage error: gdh verify recommend requires at least one --files <path> argument.\n");
|
|
2231
2331
|
return 1;
|
|
2232
2332
|
}
|
|
2233
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
2234
2333
|
const commandStartedAtMs = Date.now();
|
|
2235
2334
|
try {
|
|
2236
2335
|
const context = await buildAuthoringContext(targetPath);
|
|
@@ -2289,9 +2388,12 @@ async function runVerifyDoneCommand(args, io) {
|
|
|
2289
2388
|
io.stderr.write(unsupportedOptionsError);
|
|
2290
2389
|
return 1;
|
|
2291
2390
|
}
|
|
2292
|
-
const
|
|
2293
|
-
|
|
2294
|
-
|
|
2391
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
2392
|
+
usage: "Usage: gdh verify done [target] --files <path> [--files <path>...] [--performed <kind>]\n",
|
|
2393
|
+
additionalOptionsWithValues: new Set(["--files", "--performed"]),
|
|
2394
|
+
});
|
|
2395
|
+
if (targetPathError !== null) {
|
|
2396
|
+
io.stderr.write(targetPathError);
|
|
2295
2397
|
return 1;
|
|
2296
2398
|
}
|
|
2297
2399
|
const files = collectOptionValues(args, "--files");
|
|
@@ -2299,7 +2401,6 @@ async function runVerifyDoneCommand(args, io) {
|
|
|
2299
2401
|
io.stderr.write("Usage error: gdh verify done requires at least one --files <path> argument.\n");
|
|
2300
2402
|
return 1;
|
|
2301
2403
|
}
|
|
2302
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
2303
2404
|
const commandStartedAtMs = Date.now();
|
|
2304
2405
|
try {
|
|
2305
2406
|
const context = await buildAuthoringContext(targetPath);
|
|
@@ -2450,12 +2551,14 @@ async function runVerifyInspectCommand(args, io) {
|
|
|
2450
2551
|
io.stderr.write(unsupportedOptionsError);
|
|
2451
2552
|
return 1;
|
|
2452
2553
|
}
|
|
2453
|
-
const
|
|
2454
|
-
|
|
2455
|
-
|
|
2554
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
2555
|
+
usage: "Usage: gdh verify inspect [target] [--run-record <run-record-id>]\n",
|
|
2556
|
+
additionalOptionsWithValues: new Set(["--run-record", "--bundle"]),
|
|
2557
|
+
});
|
|
2558
|
+
if (targetPathError !== null) {
|
|
2559
|
+
io.stderr.write(targetPathError);
|
|
2456
2560
|
return 1;
|
|
2457
2561
|
}
|
|
2458
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
2459
2562
|
const commandStartedAtMs = Date.now();
|
|
2460
2563
|
try {
|
|
2461
2564
|
const result = await inspectRuntimeVerificationBundleState({
|
|
@@ -2502,12 +2605,13 @@ async function runVerifyReadinessCommand(args, io) {
|
|
|
2502
2605
|
io.stderr.write(unsupportedOptionsError);
|
|
2503
2606
|
return 1;
|
|
2504
2607
|
}
|
|
2505
|
-
const
|
|
2506
|
-
|
|
2507
|
-
|
|
2608
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
2609
|
+
usage: "Usage: gdh verify readiness [target]\n",
|
|
2610
|
+
});
|
|
2611
|
+
if (targetPathError !== null) {
|
|
2612
|
+
io.stderr.write(targetPathError);
|
|
2508
2613
|
return 1;
|
|
2509
2614
|
}
|
|
2510
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
2511
2615
|
const commandStartedAtMs = Date.now();
|
|
2512
2616
|
try {
|
|
2513
2617
|
const projectConfig = await readProjectConfig(targetPath);
|
|
@@ -2542,7 +2646,6 @@ async function runVerifyReadinessCommand(args, io) {
|
|
|
2542
2646
|
}
|
|
2543
2647
|
}
|
|
2544
2648
|
const VERIFY_DRIFT_SCANNED_FILES = [
|
|
2545
|
-
{ relativePath: MCP_LAUNCHER_RELATIVE_PATH, description: "managed MCP launcher" },
|
|
2546
2649
|
{ relativePath: CODEX_ONBOARD_SKILL_RELATIVE_PATH, description: "Codex gdh-onboard skill" },
|
|
2547
2650
|
{ relativePath: CODEX_STATUS_SKILL_RELATIVE_PATH, description: "Codex gdh-status skill" },
|
|
2548
2651
|
{ relativePath: CODEX_MIGRATE_SKILL_RELATIVE_PATH, description: "Codex gdh-migrate skill" },
|
|
@@ -2611,8 +2714,8 @@ async function runVerifyDriftCommand(args, io) {
|
|
|
2611
2714
|
"Usage: gdh verify drift [target]",
|
|
2612
2715
|
"",
|
|
2613
2716
|
"Compares every baked `@skillcap/gdh@<version>` literal across the managed",
|
|
2614
|
-
"surfaces (
|
|
2615
|
-
"
|
|
2717
|
+
"surfaces (regenerated Codex/Cursor/Claude skill + command files) against",
|
|
2718
|
+
".gdh/project.yaml gdh_version. Exits 1 and",
|
|
2616
2719
|
"emits a structured JSON result when ANY file's baked version diverges from",
|
|
2617
2720
|
"the pinned value. Covers ROADMAP Success Criterion #3 (one source of truth).",
|
|
2618
2721
|
"",
|
|
@@ -2626,12 +2729,13 @@ async function runVerifyDriftCommand(args, io) {
|
|
|
2626
2729
|
io.stderr.write(unsupportedOptionsError);
|
|
2627
2730
|
return 1;
|
|
2628
2731
|
}
|
|
2629
|
-
const
|
|
2630
|
-
|
|
2631
|
-
|
|
2732
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
2733
|
+
usage: "Usage: gdh verify drift [target]\n",
|
|
2734
|
+
});
|
|
2735
|
+
if (targetPathError !== null) {
|
|
2736
|
+
io.stderr.write(targetPathError);
|
|
2632
2737
|
return 1;
|
|
2633
2738
|
}
|
|
2634
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
2635
2739
|
const commandStartedAtMs = Date.now();
|
|
2636
2740
|
let pinnedVersion;
|
|
2637
2741
|
try {
|
|
@@ -2902,12 +3006,14 @@ async function runCacheInspectCommand(args, io) {
|
|
|
2902
3006
|
io.stderr.write(unsupportedOptionsError);
|
|
2903
3007
|
return 1;
|
|
2904
3008
|
}
|
|
2905
|
-
const
|
|
2906
|
-
|
|
2907
|
-
|
|
3009
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
3010
|
+
usage: "Usage: gdh cache inspect [target]\n",
|
|
3011
|
+
additionalOptionsWithValues: new Set(["--task-type", "--capability", "--repo-state", "--keyword"]),
|
|
3012
|
+
});
|
|
3013
|
+
if (targetPathError !== null) {
|
|
3014
|
+
io.stderr.write(targetPathError);
|
|
2908
3015
|
return 1;
|
|
2909
3016
|
}
|
|
2910
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
2911
3017
|
try {
|
|
2912
3018
|
const context = await buildAuthoringContext(targetPath);
|
|
2913
3019
|
const result = await inspectCacheState({
|
|
@@ -2939,12 +3045,13 @@ async function runGuidanceStatusCommand(args, io) {
|
|
|
2939
3045
|
io.stderr.write(unsupportedOptionsError);
|
|
2940
3046
|
return 1;
|
|
2941
3047
|
}
|
|
2942
|
-
const
|
|
2943
|
-
|
|
2944
|
-
|
|
3048
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
3049
|
+
usage: "Usage: gdh guidance status [target]\n",
|
|
3050
|
+
});
|
|
3051
|
+
if (targetPathError !== null) {
|
|
3052
|
+
io.stderr.write(targetPathError);
|
|
2945
3053
|
return 1;
|
|
2946
3054
|
}
|
|
2947
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
2948
3055
|
const commandStartedAtMs = Date.now();
|
|
2949
3056
|
try {
|
|
2950
3057
|
const context = await buildAuthoringContext(targetPath);
|
|
@@ -3006,12 +3113,14 @@ async function runGuidanceResolveCommand(args, io) {
|
|
|
3006
3113
|
io.stderr.write(unsupportedOptionsError);
|
|
3007
3114
|
return 1;
|
|
3008
3115
|
}
|
|
3009
|
-
const
|
|
3010
|
-
|
|
3011
|
-
|
|
3116
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
3117
|
+
usage: "Usage: gdh guidance resolve [target] [--task-type <type>] [--capability <id>] [--repo-state <state>] [--keyword <term>]\n",
|
|
3118
|
+
additionalOptionsWithValues: new Set(["--task-type", "--capability", "--repo-state", "--keyword"]),
|
|
3119
|
+
});
|
|
3120
|
+
if (targetPathError !== null) {
|
|
3121
|
+
io.stderr.write(targetPathError);
|
|
3012
3122
|
return 1;
|
|
3013
3123
|
}
|
|
3014
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
3015
3124
|
const commandStartedAtMs = Date.now();
|
|
3016
3125
|
try {
|
|
3017
3126
|
const context = await buildAuthoringContext(targetPath);
|
|
@@ -3065,12 +3174,13 @@ async function runGuidanceAuditCommand(args, io) {
|
|
|
3065
3174
|
io.stderr.write(unsupportedOptionsError);
|
|
3066
3175
|
return 1;
|
|
3067
3176
|
}
|
|
3068
|
-
const
|
|
3069
|
-
|
|
3070
|
-
|
|
3177
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
3178
|
+
usage: "Usage: gdh guidance audit [target]\n",
|
|
3179
|
+
});
|
|
3180
|
+
if (targetPathError !== null) {
|
|
3181
|
+
io.stderr.write(targetPathError);
|
|
3071
3182
|
return 1;
|
|
3072
3183
|
}
|
|
3073
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
3074
3184
|
try {
|
|
3075
3185
|
const result = await inspectGuidanceAudit(targetPath);
|
|
3076
3186
|
await recordSessionEvent(targetPath, {
|
|
@@ -3112,12 +3222,14 @@ async function runObservabilitySessionCommand(args, io) {
|
|
|
3112
3222
|
io.stderr.write(unsupportedOptionsError);
|
|
3113
3223
|
return 1;
|
|
3114
3224
|
}
|
|
3115
|
-
const
|
|
3116
|
-
|
|
3117
|
-
|
|
3225
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
3226
|
+
usage: "Usage: gdh observability session [target] [--latest] [--session-id <id>]\n",
|
|
3227
|
+
additionalOptionsWithValues: new Set(["--session-id"]),
|
|
3228
|
+
});
|
|
3229
|
+
if (targetPathError !== null) {
|
|
3230
|
+
io.stderr.write(targetPathError);
|
|
3118
3231
|
return 1;
|
|
3119
3232
|
}
|
|
3120
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
3121
3233
|
const sessionId = readSingleOptionValue(args, "--session-id");
|
|
3122
3234
|
try {
|
|
3123
3235
|
const result = await inspectAuthoringSessions(targetPath, {
|
|
@@ -3150,12 +3262,14 @@ async function runObservabilityEffectivenessCommand(args, io) {
|
|
|
3150
3262
|
io.stderr.write(unsupportedOptionsError);
|
|
3151
3263
|
return 1;
|
|
3152
3264
|
}
|
|
3153
|
-
const
|
|
3154
|
-
|
|
3155
|
-
|
|
3265
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
3266
|
+
usage: "Usage: gdh observability effectiveness [target] [--latest] [--session-id <id>]\n",
|
|
3267
|
+
additionalOptionsWithValues: new Set(["--session-id"]),
|
|
3268
|
+
});
|
|
3269
|
+
if (targetPathError !== null) {
|
|
3270
|
+
io.stderr.write(targetPathError);
|
|
3156
3271
|
return 1;
|
|
3157
3272
|
}
|
|
3158
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
3159
3273
|
const sessionId = readSingleOptionValue(args, "--session-id");
|
|
3160
3274
|
try {
|
|
3161
3275
|
const result = await inspectAuthoringEffectiveness(targetPath, {
|
|
@@ -3190,17 +3304,19 @@ async function runCachePruneCommand(args, io) {
|
|
|
3190
3304
|
return 1;
|
|
3191
3305
|
}
|
|
3192
3306
|
const dryRun = args.includes("--dry-run");
|
|
3193
|
-
const
|
|
3307
|
+
const { targetPath, error: targetPathError } = parseOptionalPositionalTargetPath(args, {
|
|
3308
|
+
usage: "Usage: gdh cache prune [target] [--scope <scope>] [--dry-run]\n",
|
|
3309
|
+
additionalOptionsWithValues: new Set(["--scope"]),
|
|
3310
|
+
});
|
|
3311
|
+
if (targetPathError !== null) {
|
|
3312
|
+
io.stderr.write(targetPathError);
|
|
3313
|
+
return 1;
|
|
3314
|
+
}
|
|
3194
3315
|
const scope = resolveCachePruneScope(args);
|
|
3195
3316
|
if (scope === null) {
|
|
3196
3317
|
io.stderr.write("Usage error: --scope must be one of worktree, project, or all.\n");
|
|
3197
3318
|
return 1;
|
|
3198
3319
|
}
|
|
3199
|
-
if (positionalArgs.length > 1) {
|
|
3200
|
-
io.stderr.write("Usage error: gdh cache prune accepts at most one positional target path.\n");
|
|
3201
|
-
return 1;
|
|
3202
|
-
}
|
|
3203
|
-
const targetPath = positionalArgs[0] ?? ".";
|
|
3204
3320
|
try {
|
|
3205
3321
|
const context = await buildAuthoringContext(targetPath);
|
|
3206
3322
|
const result = await pruneCacheState({
|
|
@@ -3807,24 +3923,6 @@ function resolveCachePruneScope(args) {
|
|
|
3807
3923
|
}
|
|
3808
3924
|
return null;
|
|
3809
3925
|
}
|
|
3810
|
-
function extractCachePrunePositionalArgs(args) {
|
|
3811
|
-
const positionalArgs = [];
|
|
3812
|
-
for (let index = 0; index < args.length; index += 1) {
|
|
3813
|
-
const arg = args[index];
|
|
3814
|
-
if (!arg) {
|
|
3815
|
-
continue;
|
|
3816
|
-
}
|
|
3817
|
-
if (arg === "--scope") {
|
|
3818
|
-
index += 1;
|
|
3819
|
-
continue;
|
|
3820
|
-
}
|
|
3821
|
-
if (arg.startsWith("--")) {
|
|
3822
|
-
continue;
|
|
3823
|
-
}
|
|
3824
|
-
positionalArgs.push(arg);
|
|
3825
|
-
}
|
|
3826
|
-
return positionalArgs;
|
|
3827
|
-
}
|
|
3828
3926
|
function collectOptionValues(args, optionName) {
|
|
3829
3927
|
const values = [];
|
|
3830
3928
|
for (let index = 0; index < args.length; index += 1) {
|
|
@@ -3873,7 +3971,14 @@ export function findUnsupportedOptionsError(args, options) {
|
|
|
3873
3971
|
}
|
|
3874
3972
|
return `Usage error: unsupported option(s): ${unknownOptions.join(", ")}.\n${options.usage}`;
|
|
3875
3973
|
}
|
|
3876
|
-
|
|
3974
|
+
/**
|
|
3975
|
+
* CLI ingress helper. Returns an ABSOLUTE `targetPath` on both success and error paths.
|
|
3976
|
+
*
|
|
3977
|
+
* Part of the "targetPath is absolute post-ingress" invariant committed in
|
|
3978
|
+
* `docs/architecture/package-boundaries.md#path-contracts`. Uses `path.resolve` — NEVER
|
|
3979
|
+
* `fs.realpath` — to preserve caller-supplied symlink path shapes (worktree invocations).
|
|
3980
|
+
*/
|
|
3981
|
+
export function parseSingleTargetPathArg(args, options) {
|
|
3877
3982
|
const allowTargetOption = options.allowTargetOption ?? false;
|
|
3878
3983
|
const unsupportedOptionsError = findUnsupportedOptionsError(args, {
|
|
3879
3984
|
usage: options.usage,
|
|
@@ -3881,7 +3986,7 @@ function parseSingleTargetPathArg(args, options) {
|
|
|
3881
3986
|
});
|
|
3882
3987
|
if (unsupportedOptionsError !== null) {
|
|
3883
3988
|
return {
|
|
3884
|
-
targetPath: ".",
|
|
3989
|
+
targetPath: path.resolve("."),
|
|
3885
3990
|
error: unsupportedOptionsError,
|
|
3886
3991
|
};
|
|
3887
3992
|
}
|
|
@@ -3889,24 +3994,51 @@ function parseSingleTargetPathArg(args, options) {
|
|
|
3889
3994
|
const positionalArgs = extractPositionalArgs(args, new Set(allowTargetOption ? ["--target"] : []));
|
|
3890
3995
|
if (allowTargetOption && args.includes("--target") && targetOptionValue === null) {
|
|
3891
3996
|
return {
|
|
3892
|
-
targetPath: ".",
|
|
3997
|
+
targetPath: path.resolve("."),
|
|
3893
3998
|
error: `Usage error: --target requires a path value.\n${options.usage}`,
|
|
3894
3999
|
};
|
|
3895
4000
|
}
|
|
3896
4001
|
if (positionalArgs.length > 1) {
|
|
3897
4002
|
return {
|
|
3898
|
-
targetPath: ".",
|
|
4003
|
+
targetPath: path.resolve("."),
|
|
3899
4004
|
error: `Usage error: command accepts at most one target path.\n${options.usage}`,
|
|
3900
4005
|
};
|
|
3901
4006
|
}
|
|
3902
4007
|
if (allowTargetOption && targetOptionValue !== null && positionalArgs.length > 0) {
|
|
3903
4008
|
return {
|
|
3904
|
-
targetPath: ".",
|
|
4009
|
+
targetPath: path.resolve("."),
|
|
3905
4010
|
error: `Usage error: choose either a positional target path or --target <path>.\n${options.usage}`,
|
|
3906
4011
|
};
|
|
3907
4012
|
}
|
|
3908
4013
|
return {
|
|
3909
|
-
targetPath: targetOptionValue ?? positionalArgs[0] ?? ".",
|
|
4014
|
+
targetPath: path.resolve(targetOptionValue ?? positionalArgs[0] ?? "."),
|
|
4015
|
+
error: null,
|
|
4016
|
+
};
|
|
4017
|
+
}
|
|
4018
|
+
/**
|
|
4019
|
+
* CLI ingress helper for subcommands that accept at most one optional positional
|
|
4020
|
+
* target-path argument (no `--target` option). Returns an ABSOLUTE `targetPath` on both
|
|
4021
|
+
* success and error paths.
|
|
4022
|
+
*
|
|
4023
|
+
* Part of the "targetPath is absolute post-ingress" invariant committed in
|
|
4024
|
+
* `docs/architecture/package-boundaries.md#path-contracts`. Uses `path.resolve` — NEVER
|
|
4025
|
+
* `fs.realpath` — to preserve caller-supplied symlink path shapes (worktree invocations).
|
|
4026
|
+
*
|
|
4027
|
+
* @param args - argv slice starting after the subcommand name.
|
|
4028
|
+
* @param options.usage - usage string embedded in error messages.
|
|
4029
|
+
* @param options.additionalOptionsWithValues - options the subcommand consumes with values
|
|
4030
|
+
* so they are not misinterpreted as positionals (forwarded to `extractPositionalArgs`).
|
|
4031
|
+
*/
|
|
4032
|
+
export function parseOptionalPositionalTargetPath(args, options) {
|
|
4033
|
+
const positionalArgs = extractPositionalArgs(args, options.additionalOptionsWithValues ?? new Set());
|
|
4034
|
+
if (positionalArgs.length > 1) {
|
|
4035
|
+
return {
|
|
4036
|
+
targetPath: path.resolve("."),
|
|
4037
|
+
error: `Usage error: command accepts at most one positional target path.\n${options.usage}`,
|
|
4038
|
+
};
|
|
4039
|
+
}
|
|
4040
|
+
return {
|
|
4041
|
+
targetPath: path.resolve(positionalArgs[0] ?? "."),
|
|
3910
4042
|
error: null,
|
|
3911
4043
|
};
|
|
3912
4044
|
}
|
|
@@ -3993,9 +4125,6 @@ function collectPerformedValidationKinds(args) {
|
|
|
3993
4125
|
}
|
|
3994
4126
|
});
|
|
3995
4127
|
}
|
|
3996
|
-
function extractGuidanceResolvePositionalArgs(args) {
|
|
3997
|
-
return extractPositionalArgs(args, new Set(["--task-type", "--capability", "--repo-state", "--keyword"]));
|
|
3998
|
-
}
|
|
3999
4128
|
function extractRecipePositionalArgs(args) {
|
|
4000
4129
|
return extractPositionalArgs(args, new Set(["--provider", "--param", "--feature", "--no-feature", "--env"]));
|
|
4001
4130
|
}
|