@opengsd/gsd-core 1.7.0-rc.1 → 1.7.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/.claude-plugin/marketplace.json +20 -0
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.opencode/plugins/gsd-core.js +711 -0
  4. package/agents/gsd-advisor-researcher.md +2 -0
  5. package/agents/gsd-ai-researcher.md +1 -1
  6. package/agents/gsd-assumptions-analyzer.md +2 -0
  7. package/agents/gsd-code-fixer.md +2 -0
  8. package/agents/gsd-code-reviewer.md +2 -0
  9. package/agents/gsd-codebase-mapper.md +2 -0
  10. package/agents/gsd-debugger.md +2 -0
  11. package/agents/gsd-doc-writer.md +2 -0
  12. package/agents/gsd-eval-auditor.md +2 -0
  13. package/agents/gsd-executor.md +9 -6
  14. package/agents/gsd-integration-checker.md +2 -0
  15. package/agents/gsd-nyquist-auditor.md +2 -0
  16. package/agents/gsd-phase-researcher.md +2 -0
  17. package/agents/gsd-plan-checker.md +2 -0
  18. package/agents/gsd-planner.md +2 -0
  19. package/agents/gsd-project-researcher.md +2 -0
  20. package/agents/gsd-research-synthesizer.md +2 -0
  21. package/agents/gsd-roadmapper.md +2 -0
  22. package/agents/gsd-security-auditor.md +2 -0
  23. package/agents/gsd-ui-auditor.md +2 -0
  24. package/agents/gsd-ui-checker.md +2 -0
  25. package/agents/gsd-ui-researcher.md +2 -0
  26. package/agents/gsd-verifier.md +4 -2
  27. package/bin/install.js +118 -1
  28. package/gemini-extension.json +1 -1
  29. package/gsd-core/bin/gsd-tools.cjs +18 -7
  30. package/gsd-core/bin/lib/capability-loader.cjs +27 -9
  31. package/gsd-core/bin/lib/capability-registry.cjs +51 -49
  32. package/gsd-core/bin/lib/capability-source.cjs +22 -7
  33. package/gsd-core/bin/lib/capability-validator.cjs +24 -2
  34. package/gsd-core/bin/lib/commands.cjs +2 -1
  35. package/gsd-core/bin/lib/frontmatter.cjs +53 -6
  36. package/gsd-core/bin/lib/handshake-serialized.cjs +70 -0
  37. package/gsd-core/bin/lib/host-integration-sdk.cjs +53 -0
  38. package/gsd-core/bin/lib/host-integration.cjs +61 -0
  39. package/gsd-core/bin/lib/init.cjs +34 -6
  40. package/gsd-core/bin/lib/milestone.cjs +49 -10
  41. package/gsd-core/bin/lib/phase-id.cjs +18 -0
  42. package/gsd-core/bin/lib/phase.cjs +37 -27
  43. package/gsd-core/bin/lib/phases-command-router.cjs +4 -3
  44. package/gsd-core/bin/lib/probe-core.cjs +44 -4
  45. package/gsd-core/bin/lib/roadmap-command-router.cjs +3 -2
  46. package/gsd-core/bin/lib/roadmap-parser.cjs +21 -11
  47. package/gsd-core/bin/lib/roadmap.cjs +28 -20
  48. package/gsd-core/bin/lib/state-transition.cjs +15 -0
  49. package/gsd-core/bin/lib/state.cjs +27 -8
  50. package/gsd-core/bin/lib/validate.cjs +2 -1
  51. package/gsd-core/bin/lib/verify.cjs +6 -4
  52. package/gsd-core/bin/lib/workstream-inventory-builder.cjs +12 -2
  53. package/gsd-core/bin/lib/workstream-inventory.cjs +28 -0
  54. package/gsd-core/bin/shared/model-catalog.json +8 -8
  55. package/gsd-core/references/agent-skills-bootstrap.md +60 -0
  56. package/gsd-core/references/model-profiles.md +27 -0
  57. package/gsd-core/workflows/autonomous.md +22 -24
  58. package/gsd-core/workflows/complete-milestone.md +6 -10
  59. package/gsd-core/workflows/execute-phase.md +1 -1
  60. package/gsd-core/workflows/forensics.md +3 -3
  61. package/gsd-core/workflows/help/modes/full.md +1 -1
  62. package/gsd-core/workflows/milestone-summary.md +3 -3
  63. package/gsd-core/workflows/new-milestone.md +6 -0
  64. package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +42 -0
  65. package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +102 -0
  66. package/gsd-core/workflows/plan-phase/steps/windows-troubleshooting.md +23 -0
  67. package/gsd-core/workflows/plan-phase.md +3 -158
  68. package/gsd-core/workflows/review.md +7 -2
  69. package/gsd-core/workflows/settings-advanced.md +10 -10
  70. package/gsd-core/workflows/verify-work.md +1 -2
  71. package/package.json +3 -1
  72. package/scripts/run-tests.cjs +51 -1
  73. package/scripts/sync-manifest-versions.cjs +66 -14
  74. package/skills/gsd-review/SKILL.md +6 -0
@@ -277,10 +277,15 @@ fi
277
277
  # $CODEX_BYPASS_FLAG is capability-gated above (#1115). Capture stderr to a .err
278
278
  # file (not /dev/null) so a non-zero exit — e.g. a flag the installed codex-cli
279
279
  # does not support — is diagnosable instead of a silent empty review.
280
+ # Capture the review via codex's own `-o/--output-last-message <FILE>` (only the
281
+ # final agent message) and discard stdout (#1698): on some platforms (Windows)
282
+ # codex writes process-teardown output to stdout *after* the final message, and a
283
+ # stdout redirect would append that noise to a non-empty file — slipping past the
284
+ # `[ ! -s … ]` empty-output guard as a silently polluted review.
280
285
  if [ -n "$CODEX_MODEL" ] && [ "$CODEX_MODEL" != "null" ]; then
281
- cat /tmp/gsd-review-prompt-{phase}.md | codex exec --ephemeral $CODEX_BYPASS_FLAG --model "$CODEX_MODEL" --skip-git-repo-check - 2>/tmp/gsd-review-codex-{phase}.err > /tmp/gsd-review-codex-{phase}.md
286
+ cat /tmp/gsd-review-prompt-{phase}.md | codex exec --ephemeral $CODEX_BYPASS_FLAG --model "$CODEX_MODEL" --skip-git-repo-check -o /tmp/gsd-review-codex-{phase}.md - 2>/tmp/gsd-review-codex-{phase}.err >/dev/null
282
287
  else
283
- cat /tmp/gsd-review-prompt-{phase}.md | codex exec --ephemeral $CODEX_BYPASS_FLAG --skip-git-repo-check - 2>/tmp/gsd-review-codex-{phase}.err > /tmp/gsd-review-codex-{phase}.md
288
+ cat /tmp/gsd-review-prompt-{phase}.md | codex exec --ephemeral $CODEX_BYPASS_FLAG --skip-git-repo-check -o /tmp/gsd-review-codex-{phase}.md - 2>/tmp/gsd-review-codex-{phase}.err >/dev/null
284
289
  fi
285
290
  if [ ! -s /tmp/gsd-review-codex-{phase}.md ]; then
286
291
  echo "Codex review failed or returned empty output. stderr:" > /tmp/gsd-review-codex-{phase}.md
@@ -353,13 +353,13 @@ Built-in tier defaults by runtime:
353
353
 
354
354
  | Runtime | `opus` | `sonnet` | `haiku` |
355
355
  |------------|-------------------------------|---------------------------------|-------------------------------|
356
- | `claude` | `claude-opus-4-8` | `claude-sonnet-4-6` | `claude-haiku-4-5` |
356
+ | `claude` | `claude-opus-4-8` | `claude-sonnet-5` | `claude-haiku-4-5` |
357
357
  | `codex` | `gpt-5.5` | `gpt-5.4` | `gpt-5.4-mini` |
358
358
  | `gemini` | `gemini-3.1-pro-preview` | `gemini-3-flash` | `gemini-2.5-flash-lite` |
359
359
  | `qwen` | `qwen3-max-2026-01-23` | `qwen3-coder-plus` | `qwen3-coder-next` |
360
- | `opencode` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-4-6` | `anthropic/claude-haiku-4-5` |
361
- | `copilot` | `claude-opus-4-8` | `claude-sonnet-4-6` | `claude-haiku-4-5` |
362
- | `hermes` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-4-6` | `anthropic/claude-haiku-4-5` |
360
+ | `opencode` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-5` | `anthropic/claude-haiku-4-5` |
361
+ | `copilot` | `claude-opus-4-8` | `claude-sonnet-5` | `claude-haiku-4-5` |
362
+ | `hermes` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-5` | `anthropic/claude-haiku-4-5` |
363
363
  | Group B (`kilo`, `cline`, `cursor`, `windsurf`, `augment`, `trae`, `codebuddy`, `antigravity`) | (no built-in default — your runtime handles model selection) | | |
364
364
 
365
365
  Display a table to the user showing the effective configuration:
@@ -623,8 +623,8 @@ AskUserQuestion([
623
623
  header: "Provider",
624
624
  multiSelect: false,
625
625
  options: [
626
- { label: "anthropic", description: "claude-opus-4-8 / claude-sonnet-4-6 / claude-haiku-4-5 (Anthropic / Claude)" },
627
- { label: "anthropic-fable", description: "claude-fable-5 / claude-sonnet-4-6 / claude-haiku-4-5 (Anthropic / Claude Fable opt-in)" },
626
+ { label: "anthropic", description: "claude-opus-4-8 / claude-sonnet-5 / claude-haiku-4-5 (Anthropic / Claude)" },
627
+ { label: "anthropic-fable", description: "claude-fable-5 / claude-sonnet-5 / claude-haiku-4-5 (Anthropic / Claude Fable opt-in)" },
628
628
  { label: "openai", description: "gpt-5.5 / gpt-5.4 / gpt-5.4-mini (OpenAI / Codex)" },
629
629
  { label: "Other known provider", description: "Type google or qwen; both still use the canonical tier mapping." }
630
630
  ]
@@ -654,11 +654,11 @@ Canonical tier mappings by provider and budget:
654
654
 
655
655
  | Provider | Budget | high | medium | low |
656
656
  |-----------|--------|----------------------------|----------------------------|----------------------------|
657
- | anthropic | high | claude-opus-4-8 | claude-opus-4-8 | claude-sonnet-4-6 |
658
- | anthropic | medium | claude-opus-4-8 | claude-sonnet-4-6 | claude-haiku-4-5 |
657
+ | anthropic | high | claude-opus-4-8 | claude-opus-4-8 | claude-sonnet-5 |
658
+ | anthropic | medium | claude-opus-4-8 | claude-sonnet-5 | claude-haiku-4-5 |
659
659
  | anthropic | low | claude-haiku-4-5 | claude-haiku-4-5 | claude-haiku-4-5 |
660
- | anthropic-fable | high | claude-fable-5 | claude-fable-5 | claude-sonnet-4-6 |
661
- | anthropic-fable | medium | claude-opus-4-8 | claude-sonnet-4-6 | claude-haiku-4-5 |
660
+ | anthropic-fable | high | claude-fable-5 | claude-fable-5 | claude-sonnet-5 |
661
+ | anthropic-fable | medium | claude-opus-4-8 | claude-sonnet-5 | claude-haiku-4-5 |
662
662
  | anthropic-fable | low | claude-haiku-4-5 | claude-haiku-4-5 | claude-haiku-4-5 |
663
663
  | openai | high | gpt-5.5 | gpt-5.5 | gpt-5.5 |
664
664
  | openai | medium | gpt-5.5 | gpt-5.4 | gpt-5.4-mini |
@@ -417,6 +417,7 @@ If no more tests → Go to `complete_session`
417
417
  Read the full UAT file.
418
418
 
419
419
  Find first test with `result: [pending]`.
420
+ If no `[pending]` test found → go to `complete_session`.
420
421
 
421
422
  Announce:
422
423
  ```
@@ -514,8 +515,6 @@ Resolve the security review failure before advancing to the next phase.
514
515
  All tests passed, but phase advancement is blocked until security review produces SECURITY.md.
515
516
 
516
517
  - `/gsd:secure-phase {phase}` — security review (required before advancing)
517
- - `/gsd:plan-phase {next}` — Plan next phase
518
- - `/gsd:execute-phase {next}` — Execute next phase
519
518
  - `/gsd:ui-review {phase}` — visual quality audit (if frontend files were modified)
520
519
  ```
521
520
 
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "@opengsd/gsd-core",
3
- "version": "1.7.0-rc.1",
3
+ "version": "1.7.0-rc.2",
4
4
  "description": "GSD Core is a meta-prompting, context engineering, and spec-driven development system for AI coding agents.",
5
+ "main": ".opencode/plugins/gsd-core.js",
5
6
  "bin": {
6
7
  "gsd-core": "bin/install.js",
7
8
  "gsd-tools": "gsd-core/bin/gsd-tools.cjs",
@@ -16,6 +17,7 @@
16
17
  "assets",
17
18
  "agents",
18
19
  ".claude-plugin",
20
+ ".opencode",
19
21
  "gemini-extension.json",
20
22
  "GEMINI.md",
21
23
  "hooks",
@@ -119,6 +119,51 @@ function ensureBuiltArtifacts(overrides = {}) {
119
119
  }
120
120
  }
121
121
  }
122
+
123
+ // hooks/dist/ is gitignored (.gitignore) and NOT built by `prepare`
124
+ // (npm run build:lib only) — only the full `build`/`prepublishOnly` scripts run
125
+ // build:hooks. So on a clean checkout + `npm ci` (fresh CI, incl. the scoped
126
+ // test lane) hooks/dist starts absent. Install tests (e.g.
127
+ // bug-3683-workflow-colon-namespace-leak) spawn `install.js --<runtime> --local`
128
+ // which copies hooks from hooks/dist/ and then verifyInstalled() hard-fails if
129
+ // the target hooks dir is empty. build-hooks.js `build()` creates DIST_DIR
130
+ // empty and fills it file-by-file, so the FIRST on-demand build (triggered by
131
+ // whichever concurrent install test's before() hook runs first) exposes a
132
+ // window where hooks/dist exists but is empty/partial. A concurrently-spawned
133
+ // install reader observes zero hooks -> "Failed to install hooks: directory is
134
+ // empty" -> intermittent scoped-lane failure (full lanes dodge it only by luck
135
+ // of a hooks-builder finishing early). Building hooks/dist ONCE here — the same
136
+ // upfront chokepoint as ensureBuiltArtifacts, single-process with no concurrent
137
+ // readers — fully populates dist before any test runs, closing the first-build
138
+ // empty window everywhere (CI scoped/unit shards + local). Subsequent on-demand
139
+ // rebuilds only atomically replace individual files (per-file rename in
140
+ // build-hooks.js) and never re-empty the dir, so they stay safe.
141
+ function ensureBuiltHooks(overrides = {}) {
142
+ const { existsSync, statSync } = require('fs');
143
+ const root = overrides.root || join(__dirname, '..');
144
+ const distDir = overrides.distDir || join(root, 'hooks', 'dist');
145
+ const hookNames = overrides.hookNames || require('./build-hooks.js').HOOKS_TO_COPY;
146
+ const runBuild = overrides.runBuild || (() => {
147
+ execFileSync(process.execPath, [join(root, 'scripts', 'build-hooks.js')], {
148
+ cwd: root,
149
+ stdio: 'inherit',
150
+ });
151
+ });
152
+
153
+ // dist is "complete" only if every expected hook exists as a non-empty file.
154
+ // Absent dir, empty dir, or a missing/zero-byte hook all trigger a rebuild.
155
+ const complete = existsSync(distDir) && hookNames.every((hook) => {
156
+ const p = join(distDir, hook);
157
+ try {
158
+ return existsSync(p) && statSync(p).size > 0;
159
+ } catch {
160
+ return false;
161
+ }
162
+ });
163
+ if (!complete) {
164
+ runBuild();
165
+ }
166
+ }
122
167
  const MARKED_SUITES = ['integration', 'install', 'security', 'slow'];
123
168
 
124
169
  // Recursively collect *.test.cjs files under dir, returning paths relative to dir.
@@ -454,6 +499,11 @@ function main() {
454
499
  // Build the gitignored bin/lib artifact if absent, before any test requires it.
455
500
  ensureBuiltArtifacts();
456
501
 
502
+ // Build the gitignored hooks/dist artifact once, before any concurrent install
503
+ // test spawns install.js and reads it — closes the first-build empty-dir race
504
+ // that intermittently failed the scoped CI lane (see ensureBuiltHooks above).
505
+ ensureBuiltHooks();
506
+
457
507
  // Hermeticity: in-process tests resolve `.planning` via planningDir(cwd), which
458
508
  // honours GSD_PROJECT/GSD_WORKSTREAM. A developer shell inside a GSD workstream
459
509
  // exports GSD_WORKSTREAM, which would redirect fixture STATE.md reads away from
@@ -600,4 +650,4 @@ if (require.main === module) {
600
650
  runMain(main);
601
651
  }
602
652
 
603
- module.exports = { suiteOf, ensureBuiltArtifacts, parseShardArg, selectShard };
653
+ module.exports = { suiteOf, ensureBuiltArtifacts, ensureBuiltHooks, parseShardArg, selectShard };
@@ -21,18 +21,66 @@ const { execFileSync } = require('child_process');
21
21
 
22
22
  const ROOT = path.resolve(__dirname, '..');
23
23
 
24
- // Single source of truth: runtime-integration manifests whose top-level `version`
25
- // MUST track package.json. Add a new manifest here so `npm version` keeps it in
26
- // sync — the regression guard test (issue 844) fails if you forget.
24
+ // Single source of truth: runtime-integration manifests whose `version` field
25
+ // MUST track package.json. Each entry names the manifest path plus the dotted
26
+ // path to the version field inside that JSON document. Top-level `version` is
27
+ // the default (plugin.json, gemini-extension.json); the Claude plugin
28
+ // marketplace manifest carries its canonical version at plugins[0].version
29
+ // (the schema-canonical location runtimes read — issue #1855).
30
+ //
31
+ // Add a new manifest here so `npm version` keeps it in sync — the regression
32
+ // guard test (issue 844) fails if you forget.
27
33
  const VERSIONED_MANIFESTS = [
28
- '.claude-plugin/plugin.json',
29
- 'gemini-extension.json',
34
+ { path: '.claude-plugin/plugin.json', versionKey: 'version' },
35
+ { path: 'gemini-extension.json', versionKey: 'version' },
36
+ { path: '.claude-plugin/marketplace.json', versionKey: 'plugins.0.version' },
37
+ { path: 'vscode/package.json', versionKey: 'version' },
30
38
  ];
31
39
 
40
+ // Convenience: just the registered paths, for consumers that only need to
41
+ // iterate files (e.g. the issue-844 regression-guard ALLOWED set).
42
+ const VERSIONED_MANIFEST_PATHS = VERSIONED_MANIFESTS.map((e) => e.path);
43
+
32
44
  function readJson(p) {
33
45
  return JSON.parse(fs.readFileSync(p, 'utf8'));
34
46
  }
35
47
 
48
+ // Property names that must never be traversed/assigned through a dotted path —
49
+ // the prototype-pollution triple. Mirrors the _isSafePropKey CodeQL barrier used
50
+ // elsewhere in the repo. Versions are hand-authored descriptors, but the helpers
51
+ // are exported, so guard them before reuse across a trust boundary.
52
+ const UNSAFE_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
53
+ function assertSafePath(dotPath) {
54
+ for (const seg of String(dotPath).split('.')) {
55
+ if (UNSAFE_KEYS.has(seg)) {
56
+ throw new Error(`refusing to traverse reserved property "${seg}" in version path "${dotPath}"`);
57
+ }
58
+ }
59
+ }
60
+
61
+ // Read a dotted path ('plugins.0.version') from a parsed JSON document.
62
+ // Returns undefined if any intermediate is missing. Array indices are plain
63
+ // numeric keys, so 'plugins.0.version' resolves obj.plugins[0].version.
64
+ // Reserved properties (__proto__/constructor/prototype) are rejected.
65
+ function getByPath(obj, dotPath) {
66
+ assertSafePath(dotPath);
67
+ return String(dotPath).split('.').reduce((cur, key) => (cur == null ? cur : cur[key]), obj);
68
+ }
69
+
70
+ // Write a value at a dotted path. Intermediate nodes must already exist (every
71
+ // registered manifest is hand-authored with its version slot present, so this
72
+ // never needs to materialize a path). Reserved properties are rejected. Kept
73
+ // trivial — no eval, no creation.
74
+ function setByPath(obj, dotPath, value) {
75
+ assertSafePath(dotPath);
76
+ const parts = String(dotPath).split('.');
77
+ let cur = obj;
78
+ for (let i = 0; i < parts.length - 1; i++) {
79
+ cur = cur[parts[i]];
80
+ }
81
+ cur[parts[parts.length - 1]] = value;
82
+ }
83
+
36
84
  function getPackageVersion(root) {
37
85
  const r = root || ROOT;
38
86
  return readJson(path.join(r, 'package.json')).version;
@@ -44,13 +92,13 @@ function syncManifestVersions(opts) {
44
92
  const root = (opts && opts.root) || ROOT;
45
93
  const v = (opts && opts.version) != null ? opts.version : getPackageVersion(root);
46
94
  const changed = [];
47
- for (const rel of VERSIONED_MANIFESTS) {
48
- const abs = path.join(root, rel);
95
+ for (const entry of VERSIONED_MANIFESTS) {
96
+ const abs = path.join(root, entry.path);
49
97
  const manifest = readJson(abs);
50
- if (manifest.version !== v) {
51
- manifest.version = v;
98
+ if (getByPath(manifest, entry.versionKey) !== v) {
99
+ setByPath(manifest, entry.versionKey, v);
52
100
  fs.writeFileSync(abs, JSON.stringify(manifest, null, 2) + '\n');
53
- changed.push(rel);
101
+ changed.push(entry.path);
54
102
  }
55
103
  }
56
104
  return changed;
@@ -61,9 +109,10 @@ function findDrift(opts) {
61
109
  const root = (opts && opts.root) || ROOT;
62
110
  const v = (opts && opts.version) != null ? opts.version : getPackageVersion(root);
63
111
  const drift = [];
64
- for (const rel of VERSIONED_MANIFESTS) {
65
- const found = readJson(path.join(root, rel)).version;
66
- if (found !== v) drift.push({ manifest: rel, found, expected: v });
112
+ for (const entry of VERSIONED_MANIFESTS) {
113
+ const manifest = readJson(path.join(root, entry.path));
114
+ const found = getByPath(manifest, entry.versionKey);
115
+ if (found !== v) drift.push({ manifest: entry.path, found, expected: v });
67
116
  }
68
117
  return drift;
69
118
  }
@@ -143,7 +192,7 @@ function stageManifests(opts) {
143
192
  console.warn('sync-manifest-versions: not a git work tree; skipping staging.');
144
193
  return;
145
194
  }
146
- const toStage = [...VERSIONED_MANIFESTS, ...listCapabilityManifests({ root })];
195
+ const toStage = [...VERSIONED_MANIFEST_PATHS, ...listCapabilityManifests({ root })];
147
196
  try {
148
197
  execFileSync('git', ['add', '--', ...toStage], { cwd: root, stdio: ['ignore', 'ignore', 'pipe'] });
149
198
  } catch (err) {
@@ -154,6 +203,9 @@ function stageManifests(opts) {
154
203
 
155
204
  module.exports = {
156
205
  VERSIONED_MANIFESTS,
206
+ VERSIONED_MANIFEST_PATHS,
207
+ getByPath,
208
+ setByPath,
157
209
  syncManifestVersions,
158
210
  findDrift,
159
211
  getPackageVersion,
@@ -35,6 +35,12 @@ Phase number: extracted from $ARGUMENTS (required)
35
35
  - `--cursor` — Include Cursor agent review
36
36
  - `--agy` / `--antigravity` — Include Antigravity CLI review
37
37
  - `--all` — Include all available CLIs
38
+
39
+ **No flags** — if `review.default_reviewers` is set, review with only those configured
40
+ reviewers that are detected; otherwise review with all available CLIs. Configured
41
+ `review.reviewer_instances` names may appear in `review.default_reviewers`; each runs as an
42
+ independent reviewer identity backed by its configured adapter+model (see
43
+ `docs/CONFIGURATION.md`). Instance names are not valid as flags.
38
44
  </context>
39
45
 
40
46
  <process>