gsdd-cli 0.26.0 → 0.27.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/README.md CHANGED
@@ -15,7 +15,7 @@ The public product name is Workspine. The retained technical contracts remain `g
15
15
  npx -y gsdd-cli init
16
16
  ```
17
17
 
18
- Use `npx -y gsdd-cli init` for repo-local setup. Use `npx -y gsdd-cli install --global` to install reusable Workspine skills and native runtime surfaces into your agent homes so they are available across repos.
18
+ Use `npx -y gsdd-cli init` for repo-local setup. Use `npx -y gsdd-cli install --global --auto` to install reusable Workspine skills and native runtime surfaces into detected agent homes so they are available across repos.
19
19
 
20
20
  </div>
21
21
 
@@ -81,10 +81,11 @@ If `gsdd-cli` is installed globally, install reusable Workspine surfaces into yo
81
81
 
82
82
  ```bash
83
83
  npx -y gsdd-cli install --global
84
+ npx -y gsdd-cli install --global --auto
84
85
  npx -y gsdd-cli install --global --tools claude,opencode,codex,copilot
85
86
  ```
86
87
 
87
- When run in a TTY without `--tools`, `install --global` lets you select which agents to install. It does not create `.planning/` in the current repo. It writes Workspine-managed skills, native agent surfaces, and per-runtime manifests under the selected agent homes:
88
+ Use `--auto` for non-interactive install into detected local agent homes. Use `--tools <targets>` when you want to override detection explicitly. When run in a TTY without `--tools` or `--auto`, `install --global` lets you select which agents to install. It does not create `.planning/` in the current repo. It writes Workspine-managed skills, native agent surfaces, and per-runtime manifests under the selected agent homes:
88
89
 
89
90
  | Target | Global surfaces |
90
91
  |--------|-----------------|
@@ -127,7 +128,7 @@ npx -y gsdd-cli models profile budget # minimize cost
127
128
 
128
129
  ## Troubleshooting
129
130
 
130
- Inside a repo-local `.planning/` workspace, start with `npx -y gsdd-cli health`. It checks local generated runtime surfaces against current render output and reports whether `npx -y gsdd-cli update` can repair drift. To repair or refresh a personal global install, rerun `npx -y gsdd-cli install --global --tools <targets>`. For details, see the [User Guide](docs/USER-GUIDE.md).
131
+ Inside a repo-local `.planning/` workspace, start with `npx -y gsdd-cli health`. It checks local generated runtime surfaces against current render output and reports whether `npx -y gsdd-cli update` can repair drift. To repair or refresh a personal global install, rerun `npx -y gsdd-cli install --global --auto` or explicitly scope it with `npx -y gsdd-cli install --global --tools <targets>`. For details, see the [User Guide](docs/USER-GUIDE.md).
131
132
 
132
133
  ---
133
134
 
@@ -102,14 +102,22 @@ function validateGlobalTools(tools) {
102
102
  return `ERROR: unsupported global install target(s): ${invalid.join(', ')}. Use --tools claude,opencode,codex,copilot or --tools all.`;
103
103
  }
104
104
 
105
+ function detectGlobalInstallTargets(roots) {
106
+ return GLOBAL_AGENT_IDS.filter((target) => existsSync(roots[target]));
107
+ }
108
+
105
109
  function displayPath(filePath) {
106
110
  return filePath.replace(/\\/g, '/');
107
111
  }
108
112
 
109
- async function resolveGlobalInstallTargets({ args, promptApi, output }) {
113
+ async function resolveGlobalInstallTargets({ args, promptApi, output, roots }) {
110
114
  const parsedTools = normalizeGlobalTools(parseGlobalToolsFlag(args));
111
115
  if (parsedTools.length > 0) return parsedTools;
112
116
 
117
+ if (args.includes('--auto')) {
118
+ return detectGlobalInstallTargets(roots);
119
+ }
120
+
113
121
  if (!process.stdin.isTTY) {
114
122
  return [];
115
123
  }
@@ -530,6 +538,7 @@ export function createCmdInstall(ctx) {
530
538
  return async function cmdInstall(...installArgs) {
531
539
  const globalFlag = installArgs.includes('--global') || installArgs.includes('-g');
532
540
  const localFlag = installArgs.includes('--local');
541
+ const autoFlag = installArgs.includes('--auto');
533
542
  const dryRun = installArgs.includes('--dry');
534
543
  const verifyRuntime = installArgs.includes('--verify-runtime');
535
544
  const liveRuntime = installArgs.includes('--live-runtime');
@@ -559,14 +568,19 @@ export function createCmdInstall(ctx) {
559
568
  return;
560
569
  }
561
570
 
571
+ const roots = resolveGlobalInstallRoots();
562
572
  const targets = await resolveGlobalInstallTargets({
563
573
  args: installArgs,
564
574
  promptApi: ctx.globalInstallPromptApi,
565
575
  output: process.stdout,
576
+ roots,
566
577
  });
567
578
 
568
579
  if (targets.length === 0) {
569
- console.error('ERROR: no global install targets selected. Use --tools claude,opencode,codex,copilot or run interactively.');
580
+ const autoHint = autoFlag
581
+ ? 'No supported agent homes were detected for --auto. Create an agent config home first or use --tools claude,opencode,codex,copilot explicitly.'
582
+ : 'Use --tools claude,opencode,codex,copilot or run interactively.';
583
+ console.error(`ERROR: no global install targets selected. ${autoHint}`);
570
584
  process.exitCode = 1;
571
585
  return;
572
586
  }
@@ -578,7 +592,6 @@ export function createCmdInstall(ctx) {
578
592
  return;
579
593
  }
580
594
 
581
- const roots = resolveGlobalInstallRoots();
582
595
  console.log(`Workspine global install - installing runtime surfaces${dryRun ? ' (dry run)' : ''}\n`);
583
596
 
584
597
  const reports = targets.map((target) => installTarget({
@@ -172,8 +172,9 @@ Commands:
172
172
  Launch guided install wizard in TTYs, or use --tools for manual/headless setup
173
173
  --auto: non-interactive mode with smart defaults (requires --tools)
174
174
  --brief <file>: copy project brief to .planning/PROJECT_BRIEF.md
175
- install --global [--tools <platform>] [--dry]
175
+ install --global [--auto] [--tools <platform>] [--dry]
176
176
  Install reusable Workspine skills and native runtime surfaces into agent home directories
177
+ --auto: non-interactive mode that installs detected local agent targets
177
178
  In TTYs, omitting --tools opens an agent picker
178
179
  update [--tools <platform>] [--templates] [--dry]
179
180
  Regenerate adapters from latest framework sources
@@ -223,11 +224,12 @@ Global install targets:
223
224
  all Install all global targets above
224
225
 
225
226
  Notes:
226
- - use \`npx -y gsdd-cli init\` for repo-local setup; use \`npx -y gsdd-cli install --global\` when you want reusable skills in agent homes
227
+ - use \`npx -y gsdd-cli init\` for repo-local setup; use \`npx -y gsdd-cli install --global --auto\` when you want reusable skills in detected agent homes
227
228
  - init always generates open-standard skills at .agents/skills/gsdd-*; this is the shared workflow entry surface
228
229
  - init also generates a local .planning/bin/gsdd* helper surface for workflow-embedded lifecycle helpers; it is internal/advanced, not the normal first-run user entrypoint
229
230
  - install --global never creates .planning/ in the current repo; it writes only selected agent-home surfaces and per-runtime Workspine manifests
230
- - repair or refresh a global install by rerunning \`npx -y gsdd-cli install --global --tools <targets>\`; runtime probes stay in test harnesses
231
+ - use \`npx -y gsdd-cli install --global --auto\` for non-interactive global install into detected agent homes; use \`--tools <targets>\` to override detection explicitly
232
+ - repair or refresh a global install by rerunning \`npx -y gsdd-cli install --global --auto\` or \`npx -y gsdd-cli install --global --tools <targets>\`; runtime probes stay in test harnesses
231
233
  - Workspine is the public product name; the retained package, command, workflow, and workspace contracts stay gsdd-cli, gsdd, gsdd-*, and .planning/
232
234
  - running \`npx -y gsdd-cli init\` in a terminal opens the guided runtime-selection wizard; bare \`gsdd init\` is equivalent only when globally installed
233
235
  - the wizard lets you pick runtimes first, then separately decide whether repo-wide AGENTS.md governance is worth installing
@@ -256,6 +258,7 @@ Examples:
256
258
  npx -y gsdd-cli init --tools agents
257
259
  npx -y gsdd-cli init --tools all
258
260
  npx -y gsdd-cli install --global
261
+ npx -y gsdd-cli install --global --auto
259
262
  npx -y gsdd-cli install --global --tools claude,opencode,codex,copilot
260
263
  npx -y gsdd-cli update
261
264
  npx -y gsdd-cli next --json
@@ -1,4 +1,4 @@
1
- import { existsSync, readFileSync } from 'fs';
1
+ import { existsSync, readFileSync, readdirSync } from 'fs';
2
2
  import { join, resolve } from 'path';
3
3
  import { output } from './cli-utils.mjs';
4
4
  import { buildControlMap } from './control-map.mjs';
@@ -76,6 +76,7 @@ const RELEASE_CONTRADICTION_CHECKS = Object.freeze([
76
76
 
77
77
  const RELEASE_CONTRADICTION_STATUSES = Object.freeze(['passed', 'failed', 'not_applicable']);
78
78
  const PREFLIGHT_CONTROL_MAP_SKIP_CODES = Object.freeze(['planning_state_drift']);
79
+ const WORK_PHASE_LINE_RE = /^\s*[-*]\s*\[([ x-])\]\s*\*\*Phase\s+(\d+(?:\.\d+)*[A-Za-z]?):\s*(.+?)\*\*/i;
79
80
 
80
81
  export function evaluateLifecyclePreflight({
81
82
  planningDir,
@@ -95,7 +96,12 @@ export function evaluateLifecyclePreflight({
95
96
 
96
97
  const lifecycle = evaluateLifecycleState({ planningDir });
97
98
  const normalizedPhase = phaseNumber ? normalizePhaseToken(phaseNumber) : null;
99
+ const workMilestone = normalizedPhase ? evaluateWorkMilestoneState({ planningDir, phaseToken: normalizedPhase }) : null;
98
100
  const checkpointPath = join(planningDir, '.continue-here.md');
101
+ const resumeWorkCheckpoint = surface === 'resume'
102
+ ? evaluateResumeWorkCheckpoint({ planningDir, checkpointPath })
103
+ : null;
104
+ const usesWorkAuthority = Boolean(workMilestone?.phaseEntry || resumeWorkCheckpoint);
99
105
  const specPath = join(planningDir, 'SPEC.md');
100
106
  const milestonesPath = join(planningDir, 'MILESTONES.md');
101
107
  const blockers = [];
@@ -119,7 +125,11 @@ export function evaluateLifecyclePreflight({
119
125
  }
120
126
 
121
127
  if (normalizedPhase) {
122
- blockers.push(...buildPhaseBlockers({ lifecycle, phaseToken: normalizedPhase, surface }));
128
+ blockers.push(
129
+ ...(usesWorkAuthority
130
+ ? buildWorkPhaseBlockers({ workMilestone, phaseToken: normalizedPhase, surface })
131
+ : buildPhaseBlockers({ lifecycle, phaseToken: normalizedPhase, surface }))
132
+ );
123
133
  }
124
134
 
125
135
  if (surface === 'audit-milestone') {
@@ -176,12 +186,17 @@ export function evaluateLifecyclePreflight({
176
186
  details: drift.details,
177
187
  files: drift.files,
178
188
  };
179
- if (policy.classification === 'owned_write') {
189
+ if (policy.classification === 'owned_write' && !usesWorkAuthority) {
180
190
  blockers.push(driftNotice);
181
191
  } else {
192
+ const workWarningContext = resumeWorkCheckpoint
193
+ ? 'because the checkpoint points at .work/milestone continuity'
194
+ : `by .work/milestone for Phase ${normalizedPhase}`;
182
195
  warnings.push({
183
196
  ...driftNotice,
184
- message: `Planning state has drifted since the last recorded session: ${drift.details.join('; ')}`,
197
+ message: usesWorkAuthority
198
+ ? `Planning state has drifted since the last recorded session, but ${surface} is using work_milestone authority ${workWarningContext}: ${drift.details.join('; ')}`
199
+ : `Planning state has drifted since the last recorded session: ${drift.details.join('; ')}`,
185
200
  });
186
201
  }
187
202
  }
@@ -198,7 +213,7 @@ export function evaluateLifecyclePreflight({
198
213
  else warnings.push(notice);
199
214
  }
200
215
 
201
- if (lifecycle.phaseStatusAlignment.mismatches.length > 0) {
216
+ if (!usesWorkAuthority && lifecycle.phaseStatusAlignment.mismatches.length > 0) {
202
217
  warnings.push({
203
218
  code: 'roadmap_phase_status_mismatch',
204
219
  message: `ROADMAP.md overview/detail phase statuses disagree: ${lifecycle.phaseStatusAlignment.mismatches.join('; ')}`,
@@ -214,6 +229,7 @@ export function evaluateLifecyclePreflight({
214
229
  explicitLifecycleMutation: policy.explicitLifecycleMutation,
215
230
  closureEvidence: describeEvidenceSurface(surface),
216
231
  mutationRequest: expectsMutation,
232
+ authority: usesWorkAuthority ? 'work_milestone' : 'planning',
217
233
  allowed: blockers.length === 0,
218
234
  status: blockers.length === 0 ? 'allowed' : 'blocked',
219
235
  reason: blockers[0]?.code ?? null,
@@ -222,10 +238,20 @@ export function evaluateLifecyclePreflight({
222
238
  planningState,
223
239
  controlMap: controlMap.summary,
224
240
  lifecycle: {
241
+ authority: usesWorkAuthority ? 'work_milestone' : 'planning',
225
242
  currentMilestone: lifecycle.currentMilestone,
226
243
  currentPhase: lifecycle.currentPhase ? lifecycle.currentPhase.number : null,
227
244
  nextPhase: lifecycle.nextPhase ? lifecycle.nextPhase.number : null,
228
245
  counts: lifecycle.counts,
246
+ workMilestone: usesWorkAuthority
247
+ ? {
248
+ phase: workMilestone?.phaseEntry?.number ?? null,
249
+ status: workMilestone?.phaseEntry?.status ?? null,
250
+ roadmapPath: '.work/milestone/ROADMAP.md',
251
+ milestoneDir: '.work/milestone',
252
+ source: resumeWorkCheckpoint ? 'checkpoint' : 'phase',
253
+ }
254
+ : null,
229
255
  },
230
256
  };
231
257
  }
@@ -346,6 +372,186 @@ function buildPhaseBlockers({ lifecycle, phaseToken, surface }) {
346
372
  return blockers;
347
373
  }
348
374
 
375
+ function evaluateWorkMilestoneState({ planningDir, phaseToken }) {
376
+ const workspaceRoot = resolve(planningDir, '..');
377
+ const milestoneDir = join(workspaceRoot, '.work', 'milestone');
378
+ const roadmapPath = join(milestoneDir, 'ROADMAP.md');
379
+ const phasesDir = join(milestoneDir, 'phases');
380
+
381
+ if (!existsSync(roadmapPath)) {
382
+ return null;
383
+ }
384
+
385
+ const phases = parseWorkRoadmapPhases(readFileSync(roadmapPath, 'utf-8'));
386
+ const phaseEntry = phases.find((phase) => phase.number === phaseToken);
387
+ if (!phaseEntry) {
388
+ return null;
389
+ }
390
+
391
+ return {
392
+ milestoneDir,
393
+ roadmapPath,
394
+ phasesDir,
395
+ phases,
396
+ phaseEntry,
397
+ phaseArtifacts: collectWorkPhaseArtifacts({ workspaceRoot, phasesDir, phaseToken }),
398
+ };
399
+ }
400
+
401
+ function parseWorkRoadmapPhases(content) {
402
+ return String(content || '')
403
+ .replace(/\r\n/g, '\n')
404
+ .split('\n')
405
+ .map((line) => {
406
+ const match = line.match(WORK_PHASE_LINE_RE);
407
+ if (!match) return null;
408
+ return {
409
+ status: parseWorkPhaseStatus(match[1]),
410
+ number: normalizePhaseToken(match[2]),
411
+ title: match[3].trim(),
412
+ };
413
+ })
414
+ .filter(Boolean);
415
+ }
416
+
417
+ function parseWorkPhaseStatus(rawStatus) {
418
+ const status = String(rawStatus || '').trim().toLowerCase();
419
+ if (status === 'x') return 'done';
420
+ if (status === '-') return 'in_progress';
421
+ return 'pending';
422
+ }
423
+
424
+ function evaluateResumeWorkCheckpoint({ planningDir, checkpointPath }) {
425
+ if (!existsSync(checkpointPath)) return null;
426
+
427
+ const workspaceRoot = resolve(planningDir, '..');
428
+ const milestoneDir = join(workspaceRoot, '.work', 'milestone');
429
+ const roadmapPath = join(milestoneDir, 'ROADMAP.md');
430
+ if (!existsSync(roadmapPath)) return null;
431
+
432
+ let content = '';
433
+ try {
434
+ content = readFileSync(checkpointPath, 'utf-8');
435
+ } catch {
436
+ return null;
437
+ }
438
+
439
+ if (!/(^|[`"'(\s])\.work[\\/]+milestone([`"')\s/]|$)/i.test(content)) {
440
+ return null;
441
+ }
442
+
443
+ return {
444
+ milestoneDir,
445
+ roadmapPath,
446
+ };
447
+ }
448
+
449
+ function collectWorkPhaseArtifacts({ workspaceRoot, phasesDir, phaseToken }) {
450
+ if (!existsSync(phasesDir)) return [];
451
+
452
+ return collectMarkdownFiles(phasesDir)
453
+ .map((filePath) => {
454
+ const filename = filePath.split(/[\\/]/).pop();
455
+ const match = filename.match(/^(\d+(?:\.\d+)*[A-Za-z]?)-(.+?)\.md$/i);
456
+ if (!match || normalizePhaseToken(match[1]) !== phaseToken) return null;
457
+
458
+ const kind = parseWorkArtifactKind(match[2]);
459
+ if (!kind) return null;
460
+
461
+ return {
462
+ phaseToken,
463
+ kind,
464
+ path: filePath,
465
+ displayPath: relativeDisplayPath(workspaceRoot, filePath),
466
+ };
467
+ })
468
+ .filter(Boolean);
469
+ }
470
+
471
+ function collectMarkdownFiles(dir) {
472
+ const files = [];
473
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
474
+ const fullPath = join(dir, entry.name);
475
+ if (entry.isDirectory()) {
476
+ files.push(...collectMarkdownFiles(fullPath));
477
+ } else if (entry.isFile() && entry.name.toLowerCase().endsWith('.md')) {
478
+ files.push(fullPath);
479
+ }
480
+ }
481
+ return files;
482
+ }
483
+
484
+ function parseWorkArtifactKind(rawKind) {
485
+ const kind = String(rawKind || '').toLowerCase();
486
+ if (kind === 'plan') return 'plan';
487
+ if (kind === 'execute') return 'execute';
488
+ if (kind === 'verify' || kind === 'verification') return 'verification';
489
+ return null;
490
+ }
491
+
492
+ function relativeDisplayPath(root, filePath) {
493
+ return filePath.slice(root.length + 1).replace(/\\/g, '/');
494
+ }
495
+
496
+ function buildWorkPhaseBlockers({ workMilestone, phaseToken, surface }) {
497
+ const blockers = [];
498
+ const planArtifacts = workMilestone.phaseArtifacts.filter((artifact) => artifact.kind === 'plan');
499
+ const executeArtifacts = workMilestone.phaseArtifacts.filter((artifact) => artifact.kind === 'execute');
500
+
501
+ if (surface === 'execute') {
502
+ if (planArtifacts.length === 0) {
503
+ blockers.push(
504
+ blocker(
505
+ 'missing_plan',
506
+ `Phase ${phaseToken} cannot execute because no .work PLAN artifact exists.`,
507
+ ['.work/milestone/phases/']
508
+ )
509
+ );
510
+ } else if (executeArtifacts.length > 0) {
511
+ blockers.push(
512
+ blocker(
513
+ 'no_pending_plan',
514
+ `Phase ${phaseToken} has already been executed in .work/milestone.`,
515
+ executeArtifacts.map((artifact) => artifact.displayPath)
516
+ )
517
+ );
518
+ }
519
+ }
520
+
521
+ if (surface === 'plan' && workMilestone.phaseEntry.status === 'done') {
522
+ blockers.push(
523
+ blocker(
524
+ 'phase_already_complete',
525
+ `Phase ${phaseToken} is already complete in .work/milestone and should not be planned again.`,
526
+ ['.work/milestone/ROADMAP.md']
527
+ )
528
+ );
529
+ }
530
+
531
+ if (surface === 'verify') {
532
+ if (planArtifacts.length === 0) {
533
+ blockers.push(
534
+ blocker(
535
+ 'missing_plan',
536
+ `Phase ${phaseToken} cannot be verified because no .work PLAN artifact exists.`,
537
+ ['.work/milestone/phases/']
538
+ )
539
+ );
540
+ }
541
+ if (executeArtifacts.length === 0) {
542
+ blockers.push(
543
+ blocker(
544
+ 'missing_execute',
545
+ `Phase ${phaseToken} cannot be verified because no .work EXECUTE artifact exists yet.`,
546
+ ['.work/milestone/phases/']
547
+ )
548
+ );
549
+ }
550
+ }
551
+
552
+ return blockers;
553
+ }
554
+
349
555
  function buildRoadmapAlignmentBlockers(lifecycle) {
350
556
  if (lifecycle.phaseStatusAlignment.mismatches.length === 0) return [];
351
557
  return [
@@ -4,7 +4,7 @@ Workspine is a repo-native delivery spine with portable multi-runtime workflow s
4
4
 
5
5
  This matrix is the release-floor truth surface.
6
6
 
7
- Human repo setup and repair commands in this document use `npx -y gsdd-cli ...` because that works without a global install. If you installed `gsdd-cli` globally, the equivalent bare `gsdd ...` command is fine. For cross-repo personal use, `npx -y gsdd-cli install --global` installs reusable Workspine skills and native runtime surfaces into selected agent homes.
7
+ Human repo setup and repair commands in this document use `npx -y gsdd-cli ...` because that works without a global install. If you installed `gsdd-cli` globally, the equivalent bare `gsdd ...` command is fine. For cross-repo personal use, `npx -y gsdd-cli install --global --auto` installs reusable Workspine skills and native runtime surfaces into detected agent homes.
8
8
 
9
9
  The install contract is deliberately skills-first: `npx -y gsdd-cli init` always creates `.agents/skills/gsdd-*` and `.planning/bin/gsdd*`; runtime-specific adapters are optional discovery or orchestration helpers layered on top.
10
10
 
@@ -55,7 +55,7 @@ Two surfaces matter for users:
55
55
 
56
56
  ## Global install surfaces
57
57
 
58
- `npx -y gsdd-cli install --global` can install personal cross-repo surfaces for these targets:
58
+ `npx -y gsdd-cli install --global --auto` can install personal cross-repo surfaces for detected agent homes. Use `npx -y gsdd-cli install --global --tools <targets>` to override detection explicitly. Supported targets:
59
59
 
60
60
  | Target | Global surfaces |
61
61
  | --- | --- |
@@ -77,7 +77,7 @@ The authored source contract stays in `distilled/workflows/*`. Generated runtime
77
77
  - `npx -y gsdd-cli update` regenerates drifted generated surfaces from the authored workflow and delegate sources.
78
78
  - Bare `gsdd health` and `gsdd update` are equivalent only when `gsdd-cli` is globally installed.
79
79
  - Missing generated surfaces are not treated as drift unless the corresponding runtime surface is actually installed locally.
80
- - Global user-home installs are refreshed by rerunning `npx -y gsdd-cli install --global --tools <targets>`; global runtime probes remain an internal pressure-harness concern, not a public install flag.
80
+ - Global user-home installs are refreshed by rerunning `npx -y gsdd-cli install --global --auto` or explicitly scoped with `npx -y gsdd-cli install --global --tools <targets>`; global runtime probes remain an internal pressure-harness concern, not a public install flag.
81
81
 
82
82
  ## Entry and helper surfaces
83
83
 
@@ -13,7 +13,7 @@ For a new project or a broad brownfield effort:
13
13
  3. Review the plan from `gsdd-plan` before starting `gsdd-execute`.
14
14
  4. Run `gsdd-verify` before calling the phase done.
15
15
 
16
- Use `npx -y gsdd-cli init` for repo-local setup. Use `npx -y gsdd-cli install --global` to install reusable Workspine skills and native runtime surfaces into selected agent homes without creating `.planning/` in the current repo.
16
+ Use `npx -y gsdd-cli init` for repo-local setup. Use `npx -y gsdd-cli install --global --auto` to install reusable Workspine skills and native runtime surfaces into detected agent homes without creating `.planning/` in the current repo.
17
17
 
18
18
  For a bounded existing-code change, use `gsdd-quick`. For an unfamiliar or risky repo, use `gsdd-map-codebase` before choosing between `gsdd-quick` and `gsdd-new-project`.
19
19
 
@@ -188,9 +188,12 @@ Use global agent install when you want Workspine workflows available across repo
188
188
 
189
189
  ```bash
190
190
  npx -y gsdd-cli install --global
191
+ npx -y gsdd-cli install --global --auto
191
192
  npx -y gsdd-cli install --global --tools claude,opencode,codex,copilot
192
193
  ```
193
194
 
195
+ Use `--auto` for non-interactive global install into detected local agent homes. Use `--tools <targets>` when you want to install a specific target set regardless of detection.
196
+
194
197
  Global install writes Workspine-managed files under selected agent homes and records per-runtime manifests. It does not bootstrap project planning state.
195
198
 
196
199
  ### Workflows (run via generated skills or adapters)
@@ -239,7 +242,7 @@ Normal user flow:
239
242
  2. Enter workflows through your runtime surface: `/gsdd-*` or `$gsdd-*`.
240
243
  3. Use `npx -y gsdd-cli health` to check repo-local generated surfaces.
241
244
  4. Use `npx -y gsdd-cli update` when repo-local generated surfaces drift or you want the latest shipped output.
242
- 5. For personal global installs, rerun `npx -y gsdd-cli install --global --tools <targets>` to repair or refresh selected agent homes.
245
+ 5. For personal global installs, rerun `npx -y gsdd-cli install --global --auto` to repair or refresh detected agent homes, or use `npx -y gsdd-cli install --global --tools <targets>` to scope the target set explicitly.
243
246
 
244
247
  Surface split:
245
248
 
@@ -446,7 +449,7 @@ If you've modified any templates, the generation manifest detects this and warns
446
449
 
447
450
  ### Generated Surfaces Drift Or A Runtime Command Goes Missing
448
451
 
449
- In a repo-local `.planning/` workspace, start with `npx -y gsdd-cli health`. If it reports drift or missing installed generated surfaces, run `npx -y gsdd-cli update` for the whole workspace or `npx -y gsdd-cli update --tools <runtime>` for a specific runtime. For global personal installs, rerun `npx -y gsdd-cli install --global --tools <targets>`.
452
+ In a repo-local `.planning/` workspace, start with `npx -y gsdd-cli health`. If it reports drift or missing installed generated surfaces, run `npx -y gsdd-cli update` for the whole workspace or `npx -y gsdd-cli update --tools <runtime>` for a specific runtime. For global personal installs, rerun `npx -y gsdd-cli install --global --auto` or scope it explicitly with `npx -y gsdd-cli install --global --tools <targets>`.
450
453
 
451
454
  That repair path is deterministic for generated files. It does not imply that every runtime has equal native ergonomics or equal validation depth.
452
455
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gsdd-cli",
3
- "version": "0.26.0",
3
+ "version": "0.27.0",
4
4
  "description": "Workspine — a repo-native delivery spine for long-horizon AI-assisted work, with directly validated support for Claude Code, Codex CLI, and OpenCode, published as gsdd-cli.",
5
5
  "type": "module",
6
6
  "bin": {