@opengsd/gsd-core 1.7.0-rc.4 → 1.7.0-rc.6
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 +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.opencode/plugins/gsd-core.js +20 -0
- package/agents/gsd-doc-classifier.md +105 -0
- package/agents/gsd-doc-synthesizer.md +61 -0
- package/agents/gsd-ui-checker.md +30 -0
- package/agents/gsd-ui-researcher.md +1 -0
- package/bin/install.js +1568 -622
- package/gsd-core/bin/gsd-tools.cjs +40 -1
- package/gsd-core/bin/lib/api-coverage.cjs +466 -0
- package/gsd-core/bin/lib/audit.cjs +6 -3
- package/gsd-core/bin/lib/capability-loader.cjs +11 -9
- package/gsd-core/bin/lib/capability-registry.cjs +761 -84
- package/gsd-core/bin/lib/capability-validator.cjs +56 -18
- package/gsd-core/bin/lib/capability-writer.cjs +10 -1
- package/gsd-core/bin/lib/check-command-router.cjs +242 -3
- package/gsd-core/bin/lib/commands.cjs +7 -5
- package/gsd-core/bin/lib/config-loader.cjs +1 -0
- package/gsd-core/bin/lib/config.cjs +96 -0
- package/gsd-core/bin/lib/core-utils.cjs +4 -1
- package/gsd-core/bin/lib/host-integration-adapters/cline-sdk-binding.cjs +234 -0
- package/gsd-core/bin/lib/host-integration-adapters/imperative-hook-bus.cjs +145 -0
- package/gsd-core/bin/lib/host-integration.cjs +45 -4
- package/gsd-core/bin/lib/init.cjs +76 -39
- package/gsd-core/bin/lib/install-effort-resolver.cjs +213 -0
- package/gsd-core/bin/lib/install-engine.cjs +228 -18
- package/gsd-core/bin/lib/installer-migration-report.cjs +7 -0
- package/gsd-core/bin/lib/loop-resolver.cjs +68 -17
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +50 -11
- package/gsd-core/bin/lib/mcp-server.cjs +18 -7
- package/gsd-core/bin/lib/milestone.cjs +3 -3
- package/gsd-core/bin/lib/normalize-test-command.cjs +187 -0
- package/gsd-core/bin/lib/phase-id.cjs +132 -3
- package/gsd-core/bin/lib/phase.cjs +78 -16
- package/gsd-core/bin/lib/planning-workspace.cjs +17 -0
- package/gsd-core/bin/lib/review-reviewer-selection.cjs +24 -7
- package/gsd-core/bin/lib/roadmap-command-router.cjs +5 -4
- package/gsd-core/bin/lib/roadmap-parser.cjs +21 -30
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +9 -9
- package/gsd-core/bin/lib/roadmap.cjs +42 -56
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +248 -44
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +2 -2
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +39 -23
- package/gsd-core/bin/lib/runtime-config-adapter-registry.cjs +19 -5
- package/gsd-core/bin/lib/runtime-homes.cjs +30 -0
- package/gsd-core/bin/lib/runtime-hooks-surface.cjs +534 -37
- package/gsd-core/bin/lib/runtime-name-policy.cjs +63 -5
- package/gsd-core/bin/lib/security.cjs +6 -36
- package/gsd-core/bin/lib/shell-command-projection.cjs +115 -2
- package/gsd-core/bin/lib/spec-section.cjs +111 -0
- package/gsd-core/bin/lib/stale-bake-guard.cjs +30 -10
- package/gsd-core/bin/lib/state-transition.cjs +1 -1
- package/gsd-core/bin/lib/state.cjs +24 -24
- package/gsd-core/bin/lib/surface.cjs +40 -6
- package/gsd-core/bin/lib/uat.cjs +4 -1
- package/gsd-core/bin/lib/ui-consideration-probe.cjs +249 -0
- package/gsd-core/bin/lib/validate.cjs +15 -6
- package/gsd-core/bin/lib/verify.cjs +33 -37
- package/gsd-core/bin/shared/config-schema.manifest.json +2 -0
- package/gsd-core/bin/shared/model-catalog.json +14 -9
- package/gsd-core/references/api-coverage.md +104 -0
- package/gsd-core/references/model-profiles.md +2 -2
- package/gsd-core/references/planning-config.md +2 -0
- package/gsd-core/references/specless-probe-fallback.md +172 -0
- package/gsd-core/references/ui-consideration-probe.md +73 -0
- package/gsd-core/templates/UI-SPEC.md +25 -0
- package/gsd-core/templates/VALIDATION.md +2 -0
- package/gsd-core/templates/config.json +2 -1
- package/gsd-core/workflows/audit-fix.md +9 -1
- package/gsd-core/workflows/audit-milestone.md +7 -4
- package/gsd-core/workflows/code-review-fix.md +7 -3
- package/gsd-core/workflows/code-review.md +4 -1
- package/gsd-core/workflows/discuss-phase-assumptions.md +4 -1
- package/gsd-core/workflows/execute-phase/steps/post-merge-gate.md +8 -4
- package/gsd-core/workflows/execute-phase/steps/regression-gate.md +42 -0
- package/gsd-core/workflows/execute-phase.md +1 -25
- package/gsd-core/workflows/plan-phase.md +37 -2
- package/gsd-core/workflows/quick.md +2 -2
- package/gsd-core/workflows/review.md +59 -13
- package/gsd-core/workflows/settings-advanced.md +12 -9
- package/gsd-core/workflows/settings.md +2 -2
- package/gsd-core/workflows/ui-phase.md +146 -1
- package/gsd-core/workflows/validate-phase.md +2 -2
- package/gsd-core/workflows/verify-phase.md +3 -2
- package/gsd-core/workflows/verify-work.md +38 -0
- package/hooks/dist/gsd-cursor-pre-tool.js +76 -0
- package/hooks/dist/gsd-cursor-stop.js +48 -0
- package/hooks/dist/gsd-cursor-subagent-start.js +50 -0
- package/hooks/dist/gsd-cursor-subagent-stop.js +40 -0
- package/hooks/dist/gsd-windsurf-pre-command.js +275 -0
- package/hooks/dist/gsd-windsurf-pre-write.js +132 -0
- package/hooks/dist/managed-hooks-registry.cjs +6 -0
- package/hooks/gsd-cursor-pre-tool.js +76 -0
- package/hooks/gsd-cursor-stop.js +48 -0
- package/hooks/gsd-cursor-subagent-start.js +50 -0
- package/hooks/gsd-cursor-subagent-stop.js +40 -0
- package/hooks/gsd-windsurf-pre-command.js +275 -0
- package/hooks/gsd-windsurf-pre-write.js +132 -0
- package/hooks/managed-hooks-registry.cjs +6 -0
- package/package.json +9 -4
- package/pi/gsd.cjs +354 -0
- package/scripts/build-hooks.js +8 -1
- package/scripts/gen-golden-install-parity-zcode.cjs +11 -1
- package/scripts/gen-registry.cjs +128 -0
- package/scripts/lint-phase-id-drift.cjs +150 -0
- package/scripts/lint-test-file-count.allowlist.json +2 -1
- package/scripts/registry-schema.cjs +565 -0
- package/scripts/run-tests.cjs +21 -1
- package/scripts/validate-registry.cjs +117 -0
- package/vscode/browser.js +197 -0
- package/vscode/extension.js +383 -0
- package/vscode/host-binding.js +113 -0
- package/vscode/package.json +96 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Anti-divergence drift guard for the phase-identifier parsing seam
|
|
6
|
+
* (epic #2121, Phase 4 / issue #2128, locked by ADR-2121 Decision 7).
|
|
7
|
+
*
|
|
8
|
+
* `src/phase-id.cts` is the SINGLE canonical owner of phase-ID parsing. Its
|
|
9
|
+
* `PHASE_NUMBER_TOKEN_SOURCE` (and `phaseMarkdownRegexSource` for a known number)
|
|
10
|
+
* is the one place the phase-number-token grammar `\d+[A-Z]?(?:\.\d+)*` is
|
|
11
|
+
* defined. Every other module that scans/enumerates phase headings must build
|
|
12
|
+
* its regex from that source rather than re-deriving the grammar as a literal —
|
|
13
|
+
* otherwise the trio drifts again (the #2111 / #2114 / #2104 recurrence loop this
|
|
14
|
+
* epic closes).
|
|
15
|
+
*
|
|
16
|
+
* This lint makes the invariant machine-enforced: it FAILS the moment a literal
|
|
17
|
+
* re-derivation of the canonical token grammar is introduced anywhere in
|
|
18
|
+
* `src/**` outside `phase-id.cts`, unless the site is deliberately sanctioned
|
|
19
|
+
* with a `// phase-id-owner: <reason>` comment (on the same line or the line
|
|
20
|
+
* directly above). Sites that build their regex from `PHASE_NUMBER_TOKEN_SOURCE`
|
|
21
|
+
* carry no literal grammar and pass automatically.
|
|
22
|
+
*
|
|
23
|
+
* Detection is intentionally NARROW: only the contiguous canonical token
|
|
24
|
+
* (`\d+[A-Z]?(?:\.\d+)*`, its `[A-Za-z]` and `[.-]` near-variants, in both
|
|
25
|
+
* regex-literal `\d` and `new RegExp` template `\\d` escaping) is drift. Bare
|
|
26
|
+
* `\d+` probes, `[\w][\w.-]*` ids, digits-only captures, status-message text
|
|
27
|
+
* (`Phase\s+\d`), and pipe-table structures are NOT phase-token re-derivations
|
|
28
|
+
* and are not flagged.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
const fs = require('node:fs');
|
|
32
|
+
const path = require('node:path');
|
|
33
|
+
|
|
34
|
+
// The canonical phase-number token as it appears in SOURCE TEXT:
|
|
35
|
+
// \d+[A-Z]?(?:\.\d+)* in a regex literal -> one backslash before d/.
|
|
36
|
+
// \\d+[A-Z]?(?:\\.\\d+)* in a template string -> two backslashes
|
|
37
|
+
// Tolerated near-variants so a trivial rewrite does not silently evade the guard:
|
|
38
|
+
// digit class \d \\d or [0-9]
|
|
39
|
+
// letter class [A-Z] or [A-Za-z]
|
|
40
|
+
// sub-phase sep \. \\. or [.-] (dot-or-dash)
|
|
41
|
+
// KNOWN, ACCEPTED limits of a per-line textual scan (covered instead by the
|
|
42
|
+
// identity guard + code review, not by this regex): a re-derivation split
|
|
43
|
+
// across lines via string concatenation, a capturing `(\.\d+)*` in place of the
|
|
44
|
+
// non-capturing group, or a semantically-equivalent restructuring. This guard
|
|
45
|
+
// targets the common case — an accidental copy of the exact grammar — not an
|
|
46
|
+
// adversary deliberately obfuscating a re-derivation.
|
|
47
|
+
const TOKEN_DRIFT_RE = /(?:\\{1,2}d|\[0-9\])\+\[A-Z(?:a-z)?\]\??\(\?:(?:\\{1,2}\.|\[\.-\])(?:\\{1,2}d|\[0-9\])\+\)\*/;
|
|
48
|
+
|
|
49
|
+
// A `phase-id-owner:` sanction must be a DEDICATED `//` comment line (the marker
|
|
50
|
+
// as the line's leading token). A `//` or the phrase embedded in a string
|
|
51
|
+
// literal or trailing a code line is NOT a comment and must never suppress a real
|
|
52
|
+
// flag — so sanctions live on their own line directly above the regex.
|
|
53
|
+
const OWNER_RE = /^\s*\/\/.*phase-id-owner:/;
|
|
54
|
+
const CANON_REF = 'PHASE_NUMBER_TOKEN_SOURCE';
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Pure: find every literal re-derivation of the canonical phase-number token in
|
|
58
|
+
* `text` that is NOT sanctioned. A site is sanctioned when the nearest preceding
|
|
59
|
+
* NON-BLANK line is a dedicated `// phase-id-owner:` comment (blank lines between
|
|
60
|
+
* the comment and the regex are tolerated, so an auto-formatter cannot reactivate
|
|
61
|
+
* the flag), or when the regex line references `PHASE_NUMBER_TOKEN_SOURCE` (built
|
|
62
|
+
* from the canonical source, not a literal). A `//`/phrase inside a string or
|
|
63
|
+
* trailing a code line does NOT count — put the sanction on its own line above.
|
|
64
|
+
* Returns [{ line, found }].
|
|
65
|
+
*/
|
|
66
|
+
function findPhaseIdRegexDrift(text) {
|
|
67
|
+
const out = [];
|
|
68
|
+
const lines = text.split('\n');
|
|
69
|
+
for (let i = 0; i < lines.length; i++) {
|
|
70
|
+
const line = lines[i];
|
|
71
|
+
const m = TOKEN_DRIFT_RE.exec(line);
|
|
72
|
+
if (!m) continue;
|
|
73
|
+
if (line.includes(CANON_REF)) continue;
|
|
74
|
+
let j = i - 1;
|
|
75
|
+
while (j >= 0 && lines[j].trim() === '') j--; // nearest preceding non-blank line
|
|
76
|
+
if (j >= 0 && OWNER_RE.test(lines[j])) continue;
|
|
77
|
+
out.push({ line: i + 1, found: m[0] });
|
|
78
|
+
}
|
|
79
|
+
return out;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Authored TypeScript source only (the generated bin/lib/*.cjs mirror it).
|
|
83
|
+
const SCAN_DIRS = ['src'];
|
|
84
|
+
const SCAN_EXT = new Set(['.cts', '.ts', '.mts']);
|
|
85
|
+
// The canonical owner defines the grammar; it is exempt by construction.
|
|
86
|
+
const EXEMPT = new Set([path.join('src', 'phase-id.cts')]);
|
|
87
|
+
|
|
88
|
+
function walk(dir, acc) {
|
|
89
|
+
let entries;
|
|
90
|
+
try {
|
|
91
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
92
|
+
} catch {
|
|
93
|
+
return acc;
|
|
94
|
+
}
|
|
95
|
+
for (const entry of entries) {
|
|
96
|
+
const full = path.join(dir, entry.name);
|
|
97
|
+
if (entry.isDirectory()) {
|
|
98
|
+
if (entry.name === 'node_modules' || entry.name === 'dist' || entry.name === '.git') continue;
|
|
99
|
+
walk(full, acc);
|
|
100
|
+
} else if (entry.isFile() && SCAN_EXT.has(path.extname(entry.name))) {
|
|
101
|
+
acc.push(full);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return acc;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Scan the authored source tree and return every unsanctioned phase-token
|
|
109
|
+
* re-derivation, each annotated with the repo-relative file path.
|
|
110
|
+
*/
|
|
111
|
+
function scanRepo(root) {
|
|
112
|
+
const violations = [];
|
|
113
|
+
for (const dir of SCAN_DIRS) {
|
|
114
|
+
for (const file of walk(path.join(root, dir), [])) {
|
|
115
|
+
const rel = path.relative(root, file);
|
|
116
|
+
if (EXEMPT.has(rel)) continue;
|
|
117
|
+
let text;
|
|
118
|
+
try {
|
|
119
|
+
text = fs.readFileSync(file, 'utf8');
|
|
120
|
+
} catch {
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
for (const d of findPhaseIdRegexDrift(text)) {
|
|
124
|
+
violations.push({ file: rel, ...d });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return violations;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function main() {
|
|
132
|
+
const root = path.join(__dirname, '..');
|
|
133
|
+
const violations = scanRepo(root);
|
|
134
|
+
if (violations.length === 0) {
|
|
135
|
+
process.stdout.write('ok phase-id-drift: no unsanctioned phase-token re-derivations outside phase-id.cts\n');
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
process.stderr.write('phase-id-drift: literal re-derivation(s) of the canonical phase-number token found.\n');
|
|
139
|
+
process.stderr.write('Build the regex from phase-id.cjs `PHASE_NUMBER_TOKEN_SOURCE` (or phaseMarkdownRegexSource for a\n');
|
|
140
|
+
process.stderr.write('known number), or sanction the site with a dedicated `// phase-id-owner: <reason>`\n');
|
|
141
|
+
process.stderr.write('comment on the line directly above the regex:\n');
|
|
142
|
+
for (const d of violations) {
|
|
143
|
+
process.stderr.write(` ${d.file}:${d.line} ${d.found}\n`);
|
|
144
|
+
}
|
|
145
|
+
process.exitCode = 1;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
if (require.main === module) main();
|
|
149
|
+
|
|
150
|
+
module.exports = { findPhaseIdRegexDrift, scanRepo, TOKEN_DRIFT_RE };
|
|
@@ -50,11 +50,12 @@
|
|
|
50
50
|
},
|
|
51
51
|
"security": {
|
|
52
52
|
"files": [
|
|
53
|
+
"security-dead-exports.regression.test.cjs",
|
|
53
54
|
"security-prompt-injection.security.test.cjs",
|
|
54
55
|
"security-scan.security.test.cjs",
|
|
55
56
|
"security.test.cjs"
|
|
56
57
|
],
|
|
57
|
-
"issue": "
|
|
58
|
+
"issue": "2198"
|
|
58
59
|
},
|
|
59
60
|
"state": {
|
|
60
61
|
"files": [
|