@opengsd/gsd-core 1.5.0 → 1.6.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/plugin.json +1 -1
- package/agents/gsd-plan-checker.md +34 -0
- package/agents/gsd-planner.md +2 -0
- package/agents/gsd-roadmapper.md +6 -0
- package/bin/install.js +199 -365
- package/commands/gsd/capture.md +5 -1
- package/gemini-extension.json +1 -1
- package/gsd-core/bin/gsd-tools.cjs +695 -5
- package/gsd-core/bin/lib/adr-parser.cjs +45 -23
- package/gsd-core/bin/lib/audit.cjs +2 -2
- package/gsd-core/bin/lib/capability-consent.cjs +763 -0
- package/gsd-core/bin/lib/capability-ledger.cjs +831 -0
- package/gsd-core/bin/lib/capability-lifecycle.cjs +1551 -0
- package/gsd-core/bin/lib/capability-loader.cjs +764 -0
- package/gsd-core/bin/lib/capability-lock.cjs +553 -0
- package/gsd-core/bin/lib/capability-registry.cjs +198 -4
- package/gsd-core/bin/lib/capability-source.cjs +1242 -0
- package/gsd-core/bin/lib/capability-state.cjs +9 -6
- package/gsd-core/bin/lib/capability-trust.cjs +550 -0
- package/gsd-core/bin/lib/capability-validator.cjs +2066 -0
- package/gsd-core/bin/lib/capability-writer.cjs +14 -5
- package/gsd-core/bin/lib/check-command-router.cjs +69 -18
- package/gsd-core/bin/lib/command-aliases.cjs +8 -0
- package/gsd-core/bin/lib/commands.cjs +247 -0
- package/gsd-core/bin/lib/config-loader.cjs +98 -84
- package/gsd-core/bin/lib/config-schema.cjs +26 -7
- package/gsd-core/bin/lib/config.cjs +7 -1
- package/gsd-core/bin/lib/decisions.cjs +149 -60
- package/gsd-core/bin/lib/frontmatter.cjs +7 -3
- package/gsd-core/bin/lib/gap-checker.cjs +126 -11
- package/gsd-core/bin/lib/init.cjs +91 -22
- package/gsd-core/bin/lib/legacy-cleanup.cjs +96 -0
- package/gsd-core/bin/lib/loop-resolver.cjs +26 -2
- package/gsd-core/bin/lib/markdown-sectionizer.cjs +471 -0
- package/gsd-core/bin/lib/milestone.cjs +41 -2
- package/gsd-core/bin/lib/phase-command-router.cjs +5 -0
- package/gsd-core/bin/lib/phase-id.cjs +25 -11
- package/gsd-core/bin/lib/phase-lifecycle.cjs +14 -5
- package/gsd-core/bin/lib/phase.cjs +33 -4
- package/gsd-core/bin/lib/probe-core.cjs +7 -0
- package/gsd-core/bin/lib/prohibition-enforcement.cjs +59 -26
- package/gsd-core/bin/lib/project-root.cjs +89 -2
- package/gsd-core/bin/lib/resolution.cjs +26 -0
- package/gsd-core/bin/lib/roadmap-command-router.cjs +16 -3
- package/gsd-core/bin/lib/roadmap-parser.cjs +73 -106
- package/gsd-core/bin/lib/roadmap-upgrade.cjs +47 -17
- package/gsd-core/bin/lib/roadmap.cjs +5 -2
- package/gsd-core/bin/lib/runtime-artifact-conversion.cjs +423 -3
- package/gsd-core/bin/lib/runtime-artifact-install-plan.cjs +77 -0
- package/gsd-core/bin/lib/runtime-artifact-layout.cjs +1 -28
- package/gsd-core/bin/lib/runtime-homes.cjs +53 -1
- package/gsd-core/bin/lib/runtime-name-policy.cjs +44 -0
- package/gsd-core/bin/lib/semver-compare.cjs +127 -0
- package/gsd-core/bin/lib/shell-command-projection.cjs +55 -1
- package/gsd-core/bin/lib/state-document.cjs +4 -2
- package/gsd-core/bin/lib/state.cjs +317 -161
- package/gsd-core/bin/lib/surface.cjs +12 -19
- package/gsd-core/bin/lib/uat-predicate.cjs +7 -47
- package/gsd-core/bin/lib/uat.cjs +39 -26
- package/gsd-core/bin/lib/validate.cjs +5 -2
- package/gsd-core/bin/lib/verify.cjs +40 -15
- package/gsd-core/bin/lib/worktree-safety.cjs +202 -0
- package/gsd-core/bin/shared/config-defaults.manifest.json +6 -1
- package/gsd-core/bin/shared/config-schema.manifest.json +5 -1
- package/gsd-core/references/context-budget.md +8 -8
- package/gsd-core/references/execute-phase-between-wave-reset.md +43 -0
- package/gsd-core/references/execute-phase-context-guard.md +16 -0
- package/gsd-core/references/execute-phase-wave-guard.md +33 -0
- package/gsd-core/references/planner-antipatterns.md +48 -0
- package/gsd-core/references/planning-config.md +4 -0
- package/gsd-core/references/prohibition-probe.md +15 -9
- package/gsd-core/references/scout-codebase.md +2 -2
- package/gsd-core/workflows/autonomous.md +33 -33
- package/gsd-core/workflows/diagnose-issues.md +6 -1
- package/gsd-core/workflows/discuss-phase/templates/context.md +1 -1
- package/gsd-core/workflows/discuss-phase.md +1 -2
- package/gsd-core/workflows/execute-phase.md +12 -12
- package/gsd-core/workflows/help/modes/full.md +10 -0
- package/gsd-core/workflows/list-seeds.md +63 -0
- package/gsd-core/workflows/manager.md +37 -37
- package/gsd-core/workflows/pr-branch.md +156 -0
- package/gsd-core/workflows/quick.md +6 -1
- package/gsd-core/workflows/review.md +10 -2
- package/gsd-core/workflows/spec-phase.md +8 -3
- package/gsd-core/workflows/verify-phase.md +2 -2
- package/package.json +6 -3
- package/scripts/gen-capability-matrix.cjs +284 -0
- package/scripts/gen-capability-registry.cjs +96 -1853
- package/scripts/lint-regression-test-names.allowlist.json +1 -0
- package/scripts/lint-resolution-provenance.allowlist.json +1 -0
- package/scripts/lint-resolution-provenance.cjs +192 -0
- package/scripts/lint-test-file-count.allowlist.json +9 -0
- package/scripts/prompt-injection-scan.sh +1 -0
- package/scripts/run-tests.cjs +14 -0
- package/scripts/sync-manifest-versions.cjs +77 -5
|
@@ -13,6 +13,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
13
13
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
14
14
|
const node_path_1 = __importDefault(require("node:path"));
|
|
15
15
|
const security_cjs_1 = require("./security.cjs");
|
|
16
|
+
const markdown_sectionizer_cjs_1 = require("./markdown-sectionizer.cjs");
|
|
16
17
|
const STATUS_REJECT_SET = new Set(['superseded', 'rejected', 'deprecated']);
|
|
17
18
|
const CANONICAL_HEADERS = {
|
|
18
19
|
status: ['status', 'state', 'lifecycle', 'stage'],
|
|
@@ -57,7 +58,6 @@ const CANONICAL_HEADERS = {
|
|
|
57
58
|
'candidates',
|
|
58
59
|
'approaches considered',
|
|
59
60
|
'variants',
|
|
60
|
-
'trade-offs',
|
|
61
61
|
'pros and cons of the options',
|
|
62
62
|
'discussion',
|
|
63
63
|
],
|
|
@@ -189,15 +189,31 @@ function normalizeAdrHeader(raw) {
|
|
|
189
189
|
.replace(/[^\w\s]/g, '')
|
|
190
190
|
.trim();
|
|
191
191
|
}
|
|
192
|
-
|
|
192
|
+
// Normalized synonym index (audit M7). classifyHeader receives an ALREADY-normalized
|
|
193
|
+
// header (via normalizeAdrHeader), but historically compared it against the RAW synonym
|
|
194
|
+
// strings. Because normalizeAdrHeader collapses [\s:._-]+ to a space and strips [^\w\s],
|
|
195
|
+
// any synonym carrying a hyphen/apostrophe/etc. ('trade-offs', "won't do", 'post-grilling')
|
|
196
|
+
// could never match a normalized header — it was silently dead, and its ADR section went
|
|
197
|
+
// unmapped. Normalizing BOTH sides closes that abstraction asymmetry once, so every synonym
|
|
198
|
+
// (current and future) is reachable regardless of punctuation. Precomputed at module load to
|
|
199
|
+
// avoid re-normalizing the whole table per call; insertion order is preserved so first-match-
|
|
200
|
+
// wins and the exact-then-prefix precedence stay identical to the prior raw-compare loop.
|
|
201
|
+
const _NORMALIZED_SYNONYM_INDEX = (() => {
|
|
202
|
+
const index = [];
|
|
193
203
|
for (const [canonical, synonyms] of Object.entries(CANONICAL_HEADERS)) {
|
|
194
204
|
for (const synonym of synonyms) {
|
|
195
|
-
|
|
196
|
-
return canonical;
|
|
197
|
-
if (normalizedHeader.startsWith(`${synonym} `))
|
|
198
|
-
return canonical;
|
|
205
|
+
index.push([normalizeAdrHeader(synonym), canonical]);
|
|
199
206
|
}
|
|
200
207
|
}
|
|
208
|
+
return index;
|
|
209
|
+
})();
|
|
210
|
+
function classifyHeader(normalizedHeader) {
|
|
211
|
+
for (const [synonym, canonical] of _NORMALIZED_SYNONYM_INDEX) {
|
|
212
|
+
if (normalizedHeader === synonym)
|
|
213
|
+
return canonical;
|
|
214
|
+
if (normalizedHeader.startsWith(`${synonym} `))
|
|
215
|
+
return canonical;
|
|
216
|
+
}
|
|
201
217
|
return null;
|
|
202
218
|
}
|
|
203
219
|
function splitEntries(blockText) {
|
|
@@ -208,24 +224,30 @@ function splitEntries(blockText) {
|
|
|
208
224
|
.map((line) => line.replace(/^[-*+]\s+/, '').trim())
|
|
209
225
|
.filter(Boolean);
|
|
210
226
|
}
|
|
227
|
+
/**
|
|
228
|
+
* Thin adapter: wraps the seam's `collectSections` to produce the same
|
|
229
|
+
* `{ heading: string | null, body: string[] }` shape the rest of adr-parser
|
|
230
|
+
* consumes. ADR-1372 T2 migration.
|
|
231
|
+
*/
|
|
211
232
|
function parseSections(markdown) {
|
|
212
|
-
const
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
233
|
+
const content = typeof markdown === 'string' ? markdown : '';
|
|
234
|
+
// collectSections(content, () => true) collects every heading as a stop
|
|
235
|
+
// boundary — mirrors the old line-by-line heading walk exactly.
|
|
236
|
+
const sections = (0, markdown_sectionizer_cjs_1.collectSections)(content, () => true);
|
|
237
|
+
// Map seam Section → MarkdownSection. The seam's HeadingToken.text is the
|
|
238
|
+
// heading text after trimming (same as the old m[1].trim() capture).
|
|
239
|
+
// The body is a trimEnd()-ed joined string; split it back to lines to match
|
|
240
|
+
// the old string[] shape consumed by parseStatusFromSections / parseAdrMarkdown.
|
|
241
|
+
//
|
|
242
|
+
// Note: the old parseSections emitted a leading { heading: null, body: [...] }
|
|
243
|
+
// entry for preamble text before the first heading. Both consumers skip it
|
|
244
|
+
// immediately (parseAdrMarkdown: `if (!heading) continue`; parseStatusFromSections:
|
|
245
|
+
// `classifyHeader(normalizeAdrHeader(null))` → null ≠ 'status' → continue), so
|
|
246
|
+
// the preamble entry was dead code and is not reconstructed here.
|
|
247
|
+
return sections.map((sec) => ({
|
|
248
|
+
heading: sec.heading.text,
|
|
249
|
+
body: sec.body === '' ? [] : sec.body.split('\n'),
|
|
250
|
+
}));
|
|
229
251
|
}
|
|
230
252
|
function parseStatusFromSections(sections) {
|
|
231
253
|
for (const section of sections) {
|
|
@@ -68,7 +68,7 @@ function scanDebugSessions(planDir) {
|
|
|
68
68
|
continue;
|
|
69
69
|
// Extract hypothesis from "Current Focus" block if parseable
|
|
70
70
|
let hypothesis = '';
|
|
71
|
-
const focusMatch = content.match(/##\s*Current Focus[^\n]*\n([\s\S]*?)(?=\n##\s|$)/i);
|
|
71
|
+
const focusMatch = content.match(/##\s*Current Focus[^\n]*\n([\s\S]*?)(?=\n##\s|$)/i); // allow-adhoc-markdown: pre-seam read-only section extract in audit.cts; pending migration #1372
|
|
72
72
|
if (focusMatch) {
|
|
73
73
|
const focusText = focusMatch[1].trim().split('\n')[0].trim();
|
|
74
74
|
hypothesis = (0, security_cjs_1.sanitizeForDisplay)(focusText.slice(0, 100));
|
|
@@ -506,7 +506,7 @@ function scanContextQuestions(planDir) {
|
|
|
506
506
|
}
|
|
507
507
|
// Also check for ## Open Questions section in body
|
|
508
508
|
if (questions.length === 0) {
|
|
509
|
-
const oqMatch = content.match(/##\s*Open Questions[^\n]*\n([\s\S]*?)(?=\n##\s|$)/i);
|
|
509
|
+
const oqMatch = content.match(/##\s*Open Questions[^\n]*\n([\s\S]*?)(?=\n##\s|$)/i); // allow-adhoc-markdown: pre-seam read-only section extract in audit.cts; pending migration #1372
|
|
510
510
|
if (oqMatch) {
|
|
511
511
|
const oqBody = oqMatch[1].trim();
|
|
512
512
|
if (oqBody && oqBody.length > 0 && !/^\s*none\s*$/i.test(oqBody)) {
|