@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.
- package/.claude-plugin/marketplace.json +20 -0
- package/.claude-plugin/plugin.json +1 -1
- package/.opencode/plugins/gsd-core.js +711 -0
- package/agents/gsd-advisor-researcher.md +2 -0
- package/agents/gsd-ai-researcher.md +1 -1
- package/agents/gsd-assumptions-analyzer.md +2 -0
- package/agents/gsd-code-fixer.md +2 -0
- package/agents/gsd-code-reviewer.md +2 -0
- package/agents/gsd-codebase-mapper.md +2 -0
- package/agents/gsd-debugger.md +2 -0
- package/agents/gsd-doc-writer.md +2 -0
- package/agents/gsd-eval-auditor.md +2 -0
- package/agents/gsd-executor.md +9 -6
- package/agents/gsd-integration-checker.md +2 -0
- package/agents/gsd-nyquist-auditor.md +2 -0
- package/agents/gsd-phase-researcher.md +2 -0
- package/agents/gsd-plan-checker.md +2 -0
- package/agents/gsd-planner.md +2 -0
- package/agents/gsd-project-researcher.md +2 -0
- package/agents/gsd-research-synthesizer.md +2 -0
- package/agents/gsd-roadmapper.md +2 -0
- package/agents/gsd-security-auditor.md +2 -0
- package/agents/gsd-ui-auditor.md +2 -0
- package/agents/gsd-ui-checker.md +2 -0
- package/agents/gsd-ui-researcher.md +2 -0
- package/agents/gsd-verifier.md +4 -2
- package/bin/install.js +118 -1
- package/gemini-extension.json +1 -1
- package/gsd-core/bin/gsd-tools.cjs +18 -7
- package/gsd-core/bin/lib/capability-loader.cjs +27 -9
- package/gsd-core/bin/lib/capability-registry.cjs +51 -49
- package/gsd-core/bin/lib/capability-source.cjs +22 -7
- package/gsd-core/bin/lib/capability-validator.cjs +24 -2
- package/gsd-core/bin/lib/commands.cjs +2 -1
- package/gsd-core/bin/lib/frontmatter.cjs +53 -6
- package/gsd-core/bin/lib/handshake-serialized.cjs +70 -0
- package/gsd-core/bin/lib/host-integration-sdk.cjs +53 -0
- package/gsd-core/bin/lib/host-integration.cjs +61 -0
- package/gsd-core/bin/lib/init.cjs +34 -6
- package/gsd-core/bin/lib/milestone.cjs +49 -10
- package/gsd-core/bin/lib/phase-id.cjs +18 -0
- package/gsd-core/bin/lib/phase.cjs +37 -27
- package/gsd-core/bin/lib/phases-command-router.cjs +4 -3
- package/gsd-core/bin/lib/probe-core.cjs +44 -4
- package/gsd-core/bin/lib/roadmap-command-router.cjs +3 -2
- package/gsd-core/bin/lib/roadmap-parser.cjs +21 -11
- package/gsd-core/bin/lib/roadmap.cjs +28 -20
- package/gsd-core/bin/lib/state-transition.cjs +15 -0
- package/gsd-core/bin/lib/state.cjs +27 -8
- package/gsd-core/bin/lib/validate.cjs +2 -1
- package/gsd-core/bin/lib/verify.cjs +6 -4
- package/gsd-core/bin/lib/workstream-inventory-builder.cjs +12 -2
- package/gsd-core/bin/lib/workstream-inventory.cjs +28 -0
- package/gsd-core/bin/shared/model-catalog.json +8 -8
- package/gsd-core/references/agent-skills-bootstrap.md +60 -0
- package/gsd-core/references/model-profiles.md +27 -0
- package/gsd-core/workflows/autonomous.md +22 -24
- package/gsd-core/workflows/complete-milestone.md +6 -10
- package/gsd-core/workflows/execute-phase.md +1 -1
- package/gsd-core/workflows/forensics.md +3 -3
- package/gsd-core/workflows/help/modes/full.md +1 -1
- package/gsd-core/workflows/milestone-summary.md +3 -3
- package/gsd-core/workflows/new-milestone.md +6 -0
- package/gsd-core/workflows/plan-phase/steps/closed-phase-gate.md +42 -0
- package/gsd-core/workflows/plan-phase/steps/prd-express-path.md +102 -0
- package/gsd-core/workflows/plan-phase/steps/windows-troubleshooting.md +23 -0
- package/gsd-core/workflows/plan-phase.md +3 -158
- package/gsd-core/workflows/review.md +7 -2
- package/gsd-core/workflows/settings-advanced.md +10 -10
- package/gsd-core/workflows/verify-work.md +1 -2
- package/package.json +3 -1
- package/scripts/run-tests.cjs +51 -1
- package/scripts/sync-manifest-versions.cjs +66 -14
- 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 -
|
|
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 -
|
|
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-
|
|
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-
|
|
361
|
-
| `copilot` | `claude-opus-4-8` | `claude-sonnet-
|
|
362
|
-
| `hermes` | `anthropic/claude-opus-4-8` | `anthropic/claude-sonnet-
|
|
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-
|
|
627
|
-
{ label: "anthropic-fable", description: "claude-fable-5 / claude-sonnet-
|
|
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-
|
|
658
|
-
| anthropic | medium | claude-opus-4-8 | claude-sonnet-
|
|
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-
|
|
661
|
-
| anthropic-fable | medium | claude-opus-4-8 | claude-sonnet-
|
|
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.
|
|
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",
|
package/scripts/run-tests.cjs
CHANGED
|
@@ -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
|
|
25
|
-
// MUST track package.json.
|
|
26
|
-
//
|
|
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
|
|
48
|
-
const abs = path.join(root,
|
|
95
|
+
for (const entry of VERSIONED_MANIFESTS) {
|
|
96
|
+
const abs = path.join(root, entry.path);
|
|
49
97
|
const manifest = readJson(abs);
|
|
50
|
-
if (manifest.
|
|
51
|
-
manifest.
|
|
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(
|
|
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
|
|
65
|
-
const
|
|
66
|
-
|
|
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 = [...
|
|
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>
|