@productbrain/cli 0.1.0-beta.6755 → 0.1.0-beta.6781
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.
|
@@ -44,11 +44,19 @@
|
|
|
44
44
|
* Never imports the production frontmatter parser (WP-431 S4 precedent, see
|
|
45
45
|
* pb-setup-passthrough.test.ts) — an independent reader means this test
|
|
46
46
|
* doesn't share a blind spot with whatever a future generator produces.
|
|
47
|
+
* It does use the generic `yaml` library (already a repo dependency,
|
|
48
|
+
* root package.json, resolved via workspace hoisting) to parse the
|
|
49
|
+
* frontmatter block itself — that's a third-party parser, not production
|
|
50
|
+
* code, so it doesn't reintroduce the shared-blind-spot risk WP-431 S4
|
|
51
|
+
* guarded against; see readFrontmatter below (TEN-3784 finding 4: the old
|
|
52
|
+
* whitespace-joining reader couldn't tell a folded (`>-`) description from
|
|
53
|
+
* a literal (`|-`) one, or preserve a paragraph break).
|
|
47
54
|
*/
|
|
48
55
|
import { describe, expect, it } from 'vitest';
|
|
49
56
|
import { existsSync, readFileSync, readdirSync } from 'fs';
|
|
50
57
|
import { dirname, join } from 'path';
|
|
51
58
|
import { fileURLToPath } from 'url';
|
|
59
|
+
import { parse as parseYaml } from 'yaml';
|
|
52
60
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
53
61
|
// repo root: packages/cli/src/surfaces/__tests__ -> ../../../../..
|
|
54
62
|
const REPO_ROOT = join(__dirname, '..', '..', '..', '..', '..');
|
|
@@ -68,42 +76,29 @@ const INCLUDED_SKILLS = {
|
|
|
68
76
|
* found wrong or dangerous to invoke, and removed. Not consulted by
|
|
69
77
|
* INCLUDED_SKILLS above (which already excludes them by omission); asserted
|
|
70
78
|
* below so a future edit can't silently re-expose one.
|
|
79
|
+
*
|
|
80
|
+
* `prototype` (round 2's third finding) is NOT here: E4a-2 deleted the
|
|
81
|
+
* canonical skill outright (no scaffold/manifest/sync-script has ever
|
|
82
|
+
* existed in this repo — confirmed live), so there is no file left to
|
|
83
|
+
* exclude a pointer for. https://github.com/ProductBrain/Product-OS/pull/1039#discussion_r4070378892
|
|
71
84
|
*/
|
|
72
85
|
const EXCLUDED_SKILLS = {
|
|
73
86
|
'git-cleanup': 'Step 7 pushes `git push origin main` directly — the forbidden direct-to-main path (worktree contract, .claude/rules/git-workflow.md). https://github.com/ProductBrain/Product-OS/pull/1039#discussion_r4070378871',
|
|
74
87
|
'create-blog': 'Step 3 hardcodes an absolute Mac path ("/Users/randyhereman/Coding/Product-OS/docs/blog/readme.md") for the mandatory voice-guide gate — fails on any other checkout. https://github.com/ProductBrain/Product-OS/pull/1039#discussion_r4070378884',
|
|
75
|
-
prototype: 'The workflow requires prototype/starter-kit(-admin)/index.html, prototype/manifest.json, and `npm run sync:prototype-manifest` — none exist in this repo today (confirmed live: no prototype/ directory at all). https://github.com/ProductBrain/Product-OS/pull/1039#discussion_r4070378892',
|
|
76
88
|
};
|
|
77
89
|
/**
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
90
|
+
* Parses one canonical/pointer file's frontmatter block via the `yaml`
|
|
91
|
+
* library (TEN-3784 finding 4) and returns it as a plain object. Folded
|
|
92
|
+
* (`>-`) vs literal (`|-`) block scalars and paragraph breaks are resolved
|
|
93
|
+
* per real YAML semantics, unlike the old whitespace-joining reader this
|
|
94
|
+
* replaces.
|
|
81
95
|
*/
|
|
82
|
-
function
|
|
96
|
+
function readFrontmatter(raw) {
|
|
83
97
|
const fmMatch = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
|
|
84
98
|
if (!fmMatch)
|
|
85
|
-
return
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
if (startIdx === -1)
|
|
89
|
-
return null;
|
|
90
|
-
let endIdx = lines.length;
|
|
91
|
-
for (let i = startIdx + 1; i < lines.length; i++) {
|
|
92
|
-
if (/^[A-Za-z_][A-Za-z0-9_-]*:/.test(lines[i])) {
|
|
93
|
-
endIdx = i;
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
const block = lines.slice(startIdx, endIdx);
|
|
98
|
-
const firstLineValue = block[0].replace(new RegExp(`^${field}:\\s*`), '');
|
|
99
|
-
const continuation = block
|
|
100
|
-
.slice(1)
|
|
101
|
-
.map((l) => l.replace(/^\s+/, ''))
|
|
102
|
-
.filter((l) => l.length > 0);
|
|
103
|
-
if (firstLineValue && !firstLineValue.startsWith('>') && !firstLineValue.startsWith('|')) {
|
|
104
|
-
return firstLineValue.trim();
|
|
105
|
-
}
|
|
106
|
-
return continuation.join(' ').trim();
|
|
99
|
+
return {};
|
|
100
|
+
const parsed = parseYaml(fmMatch[1]);
|
|
101
|
+
return parsed && typeof parsed === 'object' ? parsed : {};
|
|
107
102
|
}
|
|
108
103
|
/** Strips the frontmatter block, returning only the body, trimmed. */
|
|
109
104
|
function stripFrontmatter(raw) {
|
|
@@ -130,18 +125,20 @@ describe('Claude skill pointer drift (WP-761 E4a)', () => {
|
|
|
130
125
|
}
|
|
131
126
|
const canonicalRaw = readFileSync(canonicalPath, 'utf8');
|
|
132
127
|
const pointerRaw = readFileSync(pointerPath, 'utf8');
|
|
133
|
-
const
|
|
134
|
-
const
|
|
128
|
+
const canonicalFm = readFrontmatter(canonicalRaw);
|
|
129
|
+
const pointerFm = readFrontmatter(pointerRaw);
|
|
130
|
+
const canonicalName = canonicalFm.name;
|
|
131
|
+
const pointerName = pointerFm.name;
|
|
135
132
|
if (pointerName !== name) {
|
|
136
|
-
mismatches.push(`${name}: pointer name field is "${pointerName}", expected "${name}"`);
|
|
133
|
+
mismatches.push(`${name}: pointer name field is "${String(pointerName)}", expected "${name}"`);
|
|
137
134
|
failedNames.add(name);
|
|
138
135
|
}
|
|
139
136
|
if (canonicalName !== name) {
|
|
140
|
-
mismatches.push(`${name}: canonical name field is "${canonicalName}", expected "${name}"`);
|
|
137
|
+
mismatches.push(`${name}: canonical name field is "${String(canonicalName)}", expected "${name}"`);
|
|
141
138
|
failedNames.add(name);
|
|
142
139
|
}
|
|
143
|
-
const canonicalDesc =
|
|
144
|
-
const pointerDesc =
|
|
140
|
+
const canonicalDesc = canonicalFm.description;
|
|
141
|
+
const pointerDesc = pointerFm.description;
|
|
145
142
|
if (canonicalDesc !== pointerDesc) {
|
|
146
143
|
mismatches.push(`${name}: description drift — canonical="${canonicalDesc}" pointer="${pointerDesc}"`);
|
|
147
144
|
failedNames.add(name);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-skill-pointer-drift.test.js","sourceRoot":"","sources":["../../../src/surfaces/__tests__/claude-skill-pointer-drift.test.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"claude-skill-pointer-drift.test.js","sourceRoot":"","sources":["../../../src/surfaces/__tests__/claude-skill-pointer-drift.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqDG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAE1C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,mEAAmE;AACnE,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAChE,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,eAAe,EAAE,QAAQ,CAAC,CAAC;AACjE,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC;AAE1D;;;;GAIG;AACH,MAAM,eAAe,GAA2B;IAC9C,OAAO,EACL,oHAAoH;IACtH,sBAAsB,EACpB,iGAAiG;CACpG,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,eAAe,GAA2B;IAC9C,aAAa,EACX,mNAAmN;IACrN,aAAa,EACX,mPAAmP;CACtP,CAAC;AAEF;;;;;;GAMG;AACH,SAAS,eAAe,CAAC,GAAW;IAClC,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,mCAAmC,CAAC,CAAC;IAC/D,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACxB,MAAM,MAAM,GAAY,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9C,OAAO,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAE,MAAkC,CAAC,CAAC,CAAC,EAAE,CAAC;AACzF,CAAC;AAED,sEAAsE;AACtE,SAAS,gBAAgB,CAAC,GAAW;IACnC,MAAM,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;IAC7D,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;AAC/D,CAAC;AAED,QAAQ,CAAC,yCAAyC,EAAE,GAAG,EAAE;IACvD,EAAE,CAAC,+GAA+G,EAAE,GAAG,EAAE;QACvH,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,EAAE,CAAC;QAClD,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,MAAM,WAAW,GAAG,IAAI,GAAG,EAAU,CAAC;QACtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,aAAa,GAAG,IAAI,CAAC,aAAa,EAAE,GAAG,IAAI,KAAK,CAAC,CAAC;YACxD,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;YACzD,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC/B,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,4DAA4D,IAAI,KAAK,CAAC,CAAC;gBAC9F,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACtB,SAAS;YACX,CAAC;YACD,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;gBAC7B,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,+CAA+C,IAAI,WAAW,CAAC,CAAC;gBACvF,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACtB,SAAS;YACX,CAAC;YACD,MAAM,YAAY,GAAG,YAAY,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;YACzD,MAAM,UAAU,GAAG,YAAY,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;YAErD,MAAM,WAAW,GAAG,eAAe,CAAC,YAAY,CAAC,CAAC;YAClD,MAAM,SAAS,GAAG,eAAe,CAAC,UAAU,CAAC,CAAC;YAE9C,MAAM,aAAa,GAAG,WAAW,CAAC,IAAI,CAAC;YACvC,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,CAAC;YACnC,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;gBACzB,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,4BAA4B,MAAM,CAAC,WAAW,CAAC,gBAAgB,IAAI,GAAG,CAAC,CAAC;gBAC/F,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;YACD,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;gBAC3B,UAAU,CAAC,IAAI,CAAC,GAAG,IAAI,8BAA8B,MAAM,CAAC,aAAa,CAAC,gBAAgB,IAAI,GAAG,CAAC,CAAC;gBACnG,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;YAED,MAAM,aAAa,GAAG,WAAW,CAAC,WAAW,CAAC;YAC9C,MAAM,WAAW,GAAG,SAAS,CAAC,WAAW,CAAC;YAC1C,IAAI,aAAa,KAAK,WAAW,EAAE,CAAC;gBAClC,UAAU,CAAC,IAAI,CACb,GAAG,IAAI,oCAAoC,aAAa,cAAc,WAAW,GAAG,CACrF,CAAC;gBACF,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;YAED,iEAAiE;YACjE,iEAAiE;YACjE,8DAA8D;YAC9D,MAAM,YAAY,GAAG,wCAAwC,IAAI,KAAK,CAAC;YACvE,MAAM,UAAU,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAAC;YAChD,IAAI,UAAU,KAAK,YAAY,EAAE,CAAC;gBAChC,UAAU,CAAC,IAAI,CACb,GAAG,IAAI,sBAAsB,UAAU,wBAAwB,YAAY,GAAG,CAC/E,CAAC;gBACF,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACxB,CAAC;QACH,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC;QAChD,MAAM,CAAC,UAAU,EAAE,GAAG,OAAO,IAAI,KAAK,CAAC,MAAM,gDAAgD,CAAC,CAAC,OAAO,CACpG,EAAE,CACH,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2GAA2G,EAAE,GAAG,EAAE;QACnH,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;QAC5D,MAAM,YAAY,GAAG,UAAU,CAAC,YAAY,CAAC;YAC3C,CAAC,CAAC,WAAW,CAAC,YAAY,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC;iBAC/C,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;iBAC9B,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;iBAClB,IAAI,EAAE;YACX,CAAC,CAAC,EAAE,CAAC;QACP,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3E,MAAM,CACJ,UAAU,EACV,GAAG,YAAY,CAAC,MAAM,GAAG,UAAU,CAAC,MAAM,IAAI,YAAY,CAAC,MAAM,2CAA2C,CAC7G,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACd,MAAM,CAAC,YAAY,CAAC,MAAM,EAAE,kBAAkB,YAAY,CAAC,MAAM,wBAAwB,aAAa,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAClH,aAAa,CAAC,IAAI,CACnB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4FAA4F,EAAE,GAAG,EAAE;QACpG,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAChE,UAAU,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CACjD,CAAC;QACF,MAAM,CACJ,YAAY,EACZ,GAAG,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,GAAG,YAAY,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,4CAA4C,CAChJ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|