@productbrain/cli 0.1.0-beta.18 → 0.1.0-beta.22
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/dist/__tests__/adapters.test.d.ts +2 -0
- package/dist/__tests__/adapters.test.d.ts.map +1 -0
- package/dist/__tests__/adapters.test.js +382 -0
- package/dist/__tests__/adapters.test.js.map +1 -0
- package/dist/__tests__/batch-transformations.test.d.ts +2 -0
- package/dist/__tests__/batch-transformations.test.d.ts.map +1 -0
- package/dist/__tests__/batch-transformations.test.js +226 -0
- package/dist/__tests__/batch-transformations.test.js.map +1 -0
- package/dist/__tests__/repo-detect.test.js +97 -1
- package/dist/__tests__/repo-detect.test.js.map +1 -1
- package/dist/__tests__/surface-profiles.test.d.ts +2 -0
- package/dist/__tests__/surface-profiles.test.d.ts.map +1 -0
- package/dist/__tests__/surface-profiles.test.js +89 -0
- package/dist/__tests__/surface-profiles.test.js.map +1 -0
- package/dist/__tests__/update.test.js +26 -4
- package/dist/__tests__/update.test.js.map +1 -1
- package/dist/commands/capture.d.ts.map +1 -1
- package/dist/commands/capture.js +16 -2
- package/dist/commands/capture.js.map +1 -1
- package/dist/commands/codex-prep.d.ts +12 -0
- package/dist/commands/codex-prep.d.ts.map +1 -0
- package/dist/commands/codex-prep.js +118 -0
- package/dist/commands/codex-prep.js.map +1 -0
- package/dist/commands/handshake.d.ts.map +1 -1
- package/dist/commands/handshake.js +167 -17
- package/dist/commands/handshake.js.map +1 -1
- package/dist/commands/update.d.ts +1 -0
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +22 -2
- package/dist/commands/update.js.map +1 -1
- package/dist/formatters/capture.d.ts +3 -3
- package/dist/formatters/capture.d.ts.map +1 -1
- package/dist/formatters/capture.js +2 -1
- package/dist/formatters/capture.js.map +1 -1
- package/dist/formatters/entry.d.ts +0 -4
- package/dist/formatters/entry.d.ts.map +1 -1
- package/dist/formatters/entry.js +16 -13
- package/dist/formatters/entry.js.map +1 -1
- package/dist/formatters/handshake.d.ts +2 -0
- package/dist/formatters/handshake.d.ts.map +1 -1
- package/dist/formatters/handshake.js +9 -0
- package/dist/formatters/handshake.js.map +1 -1
- package/dist/formatters/search.d.ts +0 -4
- package/dist/formatters/search.d.ts.map +1 -1
- package/dist/formatters/search.js +4 -1
- package/dist/formatters/search.js.map +1 -1
- package/dist/formatters/update.d.ts.map +1 -1
- package/dist/formatters/update.js +2 -0
- package/dist/formatters/update.js.map +1 -1
- package/dist/generators/__tests__/surface-profiles.test.d.ts +2 -0
- package/dist/generators/__tests__/surface-profiles.test.d.ts.map +1 -0
- package/dist/generators/__tests__/surface-profiles.test.js +89 -0
- package/dist/generators/__tests__/surface-profiles.test.js.map +1 -0
- package/dist/generators/adapters.d.ts +37 -4
- package/dist/generators/adapters.d.ts.map +1 -1
- package/dist/generators/adapters.js +147 -7
- package/dist/generators/adapters.js.map +1 -1
- package/dist/generators/portable-knowledge.d.ts +70 -9
- package/dist/generators/portable-knowledge.d.ts.map +1 -1
- package/dist/generators/portable-knowledge.js +208 -20
- package/dist/generators/portable-knowledge.js.map +1 -1
- package/dist/generators/portable-knowledge.test.js +457 -1
- package/dist/generators/portable-knowledge.test.js.map +1 -1
- package/dist/generators/surface-profiles.d.ts +27 -0
- package/dist/generators/surface-profiles.d.ts.map +1 -0
- package/dist/generators/surface-profiles.js +47 -0
- package/dist/generators/surface-profiles.js.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/repo-detect.d.ts +19 -0
- package/dist/lib/repo-detect.d.ts.map +1 -1
- package/dist/lib/repo-detect.js +25 -0
- package/dist/lib/repo-detect.js.map +1 -1
- package/dist/lib/strip.d.ts +1 -0
- package/dist/lib/strip.d.ts.map +1 -1
- package/dist/lib/strip.js +15 -0
- package/dist/lib/strip.js.map +1 -1
- package/package.json +2 -1
- package/templates/general/code-integrity.md +11 -0
- package/templates/general/getting-started.md +12 -0
- package/templates/node-ts/code-integrity.md +13 -0
- package/templates/node-ts/testing.md +12 -0
- package/templates/python/code-integrity.md +13 -0
- package/templates/python/testing.md +12 -0
package/dist/formatters/entry.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Entry formatter — full entry display with data, relations, and history.
|
|
3
3
|
* Chain: DEC-186 (CLI uses Convex view model with CLI-native formatting).
|
|
4
4
|
*/
|
|
5
|
+
import { stripControlChars } from '../lib/strip.js';
|
|
5
6
|
function sanitizeData(data) {
|
|
6
7
|
if (!data || typeof data !== 'object')
|
|
7
8
|
return undefined;
|
|
@@ -10,24 +11,26 @@ function sanitizeData(data) {
|
|
|
10
11
|
}
|
|
11
12
|
/** Format full entry for terminal output — data fields, relations (with type labels), last 10 history events. */
|
|
12
13
|
export function formatEntry(entry) {
|
|
14
|
+
// BET-269 C3: stripControlChars on all user-controlled strings before terminal output
|
|
15
|
+
const s = stripControlChars;
|
|
13
16
|
const lines = [];
|
|
14
17
|
const id = entry.entryId ?? '—';
|
|
15
18
|
const coll = entry.canonicalKey ?? '—';
|
|
16
|
-
lines.push(`${id} [${coll}] ${entry.name}`);
|
|
19
|
+
lines.push(`${s(id)} [${s(coll)}] ${s(entry.name)}`);
|
|
17
20
|
lines.push('');
|
|
18
|
-
lines.push(`Status: ${entry.status}${entry.workflowStatus ? ` / ${entry.workflowStatus}` : ''}`);
|
|
21
|
+
lines.push(`Status: ${s(entry.status)}${entry.workflowStatus ? ` / ${s(entry.workflowStatus)}` : ''}`);
|
|
19
22
|
if (entry.origin) {
|
|
20
|
-
const detail = entry.originDetail ? ` (${entry.originDetail})` : '';
|
|
21
|
-
lines.push(`Origin: ${entry.origin}${detail}`);
|
|
23
|
+
const detail = entry.originDetail ? ` (${s(entry.originDetail)})` : '';
|
|
24
|
+
lines.push(`Origin: ${s(entry.origin)}${detail}`);
|
|
22
25
|
}
|
|
23
26
|
if (entry.verificationStatus) {
|
|
24
|
-
lines.push(`Verification: ${entry.verificationStatus}`);
|
|
27
|
+
lines.push(`Verification: ${s(entry.verificationStatus)}`);
|
|
25
28
|
}
|
|
26
29
|
if (entry.sourceRef) {
|
|
27
|
-
lines.push(`Source ref: ${entry.sourceRef}`);
|
|
30
|
+
lines.push(`Source ref: ${s(entry.sourceRef)}`);
|
|
28
31
|
}
|
|
29
32
|
if (entry.sourceExcerpt) {
|
|
30
|
-
lines.push(`Source excerpt: ${entry.sourceExcerpt}`);
|
|
33
|
+
lines.push(`Source excerpt: ${s(entry.sourceExcerpt)}`);
|
|
31
34
|
}
|
|
32
35
|
lines.push('');
|
|
33
36
|
const data = sanitizeData(entry.data);
|
|
@@ -35,25 +38,25 @@ export function formatEntry(entry) {
|
|
|
35
38
|
lines.push('Data:');
|
|
36
39
|
for (const [key, val] of Object.entries(data)) {
|
|
37
40
|
const display = typeof val === 'string' ? val : JSON.stringify(val);
|
|
38
|
-
lines.push(` ${key}: ${display}`);
|
|
41
|
+
lines.push(` ${s(key)}: ${s(display)}`);
|
|
39
42
|
}
|
|
40
43
|
lines.push('');
|
|
41
44
|
}
|
|
42
45
|
if (Array.isArray(entry.tags) && entry.tags.length > 0) {
|
|
43
|
-
lines.push(`Tags: ${entry.tags.join(', ')}`);
|
|
46
|
+
lines.push(`Tags: ${entry.tags.map(s).join(', ')}`);
|
|
44
47
|
lines.push('');
|
|
45
48
|
}
|
|
46
49
|
if (Array.isArray(entry.labels) && entry.labels.length > 0) {
|
|
47
50
|
const slugs = entry.labels.map((l) => l.slug ?? l.name ?? '').filter(Boolean);
|
|
48
|
-
lines.push(`Labels: ${slugs.map((
|
|
51
|
+
lines.push(`Labels: ${slugs.map((slug) => `\`${s(slug)}\``).join(', ')}`);
|
|
49
52
|
lines.push('');
|
|
50
53
|
}
|
|
51
54
|
if (Array.isArray(entry.relations) && entry.relations.length > 0) {
|
|
52
55
|
lines.push('Relations:');
|
|
53
56
|
for (const r of entry.relations) {
|
|
54
57
|
const arrow = r.direction === 'outgoing' ? '→' : '←';
|
|
55
|
-
const other = r.otherEntryId ? `${r.otherEntryId}: ${r.otherName ?? ''}` : (r.otherName ?? '—');
|
|
56
|
-
lines.push(` ${arrow} ${r.type} ${other}`);
|
|
58
|
+
const other = r.otherEntryId ? `${s(r.otherEntryId)}: ${s(r.otherName ?? '')}` : s(r.otherName ?? '—');
|
|
59
|
+
lines.push(` ${arrow} ${s(r.type)} ${other}`);
|
|
57
60
|
}
|
|
58
61
|
lines.push('');
|
|
59
62
|
}
|
|
@@ -62,7 +65,7 @@ export function formatEntry(entry) {
|
|
|
62
65
|
lines.push('History (last 10):');
|
|
63
66
|
for (const h of last10) {
|
|
64
67
|
const date = new Date(h.timestamp).toISOString().split('T')[0];
|
|
65
|
-
lines.push(` ${date}: ${h.event}${h.changedBy ? ` (${h.changedBy})` : ''}${h.note ? ` — ${h.note}` : ''}`);
|
|
68
|
+
lines.push(` ${date}: ${s(h.event)}${h.changedBy ? ` (${s(h.changedBy)})` : ''}${h.note ? ` — ${s(h.note)}` : ''}`);
|
|
66
69
|
}
|
|
67
70
|
}
|
|
68
71
|
return lines.join('\n');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entry.js","sourceRoot":"","sources":["../../src/formatters/entry.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"entry.js","sourceRoot":"","sources":["../../src/formatters/entry.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import type { SearchResult } from './search.js';
|
|
5
5
|
import type { RepoContext } from '../lib/repo-detect.js';
|
|
6
|
+
import type { CodexValidationWarning } from '../generators/portable-knowledge.js';
|
|
6
7
|
export interface HandshakeReport {
|
|
7
8
|
filesWritten: string[];
|
|
8
9
|
filesSkipped: Array<{
|
|
@@ -12,6 +13,7 @@ export interface HandshakeReport {
|
|
|
12
13
|
matchedEntries: SearchResult[];
|
|
13
14
|
searchQueries: string[];
|
|
14
15
|
repo: RepoContext;
|
|
16
|
+
codexWarnings?: CodexValidationWarning[];
|
|
15
17
|
}
|
|
16
18
|
export declare function formatHandshakeReport(report: HandshakeReport): string;
|
|
17
19
|
//# sourceMappingURL=handshake.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handshake.d.ts","sourceRoot":"","sources":["../../src/formatters/handshake.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"handshake.d.ts","sourceRoot":"","sources":["../../src/formatters/handshake.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAElF,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,YAAY,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACtD,cAAc,EAAE,YAAY,EAAE,CAAC;IAC/B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,IAAI,EAAE,WAAW,CAAC;IAClB,aAAa,CAAC,EAAE,sBAAsB,EAAE,CAAC;CAC1C;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CA+DrE"}
|
|
@@ -42,6 +42,15 @@ export function formatHandshakeReport(report) {
|
|
|
42
42
|
}
|
|
43
43
|
lines.push('');
|
|
44
44
|
}
|
|
45
|
+
// Codex dead-reference warnings
|
|
46
|
+
if (report.codexWarnings && report.codexWarnings.length > 0) {
|
|
47
|
+
lines.push(`Codex warnings (${report.codexWarnings.length} dead reference(s) in projected skills):`);
|
|
48
|
+
for (const w of report.codexWarnings) {
|
|
49
|
+
lines.push(` ${w.skillName}: ${w.pattern} — "${w.line}"`);
|
|
50
|
+
}
|
|
51
|
+
lines.push(' (These references may not work in Codex. Consider transport sections or targets.)');
|
|
52
|
+
lines.push('');
|
|
53
|
+
}
|
|
45
54
|
lines.push('Tip: Add .productbrain/ to .gitignore (contains workspace-specific context).');
|
|
46
55
|
lines.push(' Adapter files (AGENTS.md, .codex/skills/, CLAUDE.md, .cursor/rules/, .claude/rules/, .github/) are safe to commit.');
|
|
47
56
|
lines.push('');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handshake.js","sourceRoot":"","sources":["../../src/formatters/handshake.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"handshake.js","sourceRoot":"","sources":["../../src/formatters/handshake.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/formatters/search.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../src/formatters/search.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,YAAY;IAC3B,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,MAAM,CAcnE"}
|
|
@@ -2,15 +2,18 @@
|
|
|
2
2
|
* Search formatter — scannable terminal output for chain.searchEntries results.
|
|
3
3
|
* Chain: DEC-186 (CLI uses Convex view model with CLI-native formatting).
|
|
4
4
|
*/
|
|
5
|
+
import { stripControlChars } from '../lib/strip.js';
|
|
5
6
|
export function formatSearchResults(results) {
|
|
6
7
|
if (results.length === 0) {
|
|
7
8
|
return 'No results found.';
|
|
8
9
|
}
|
|
10
|
+
// BET-269 C3: stripControlChars on all user-controlled strings before terminal output
|
|
11
|
+
const s = stripControlChars;
|
|
9
12
|
const lines = [];
|
|
10
13
|
for (const r of results) {
|
|
11
14
|
const id = r.entryId ?? r.name;
|
|
12
15
|
const coll = r.collectionSlug ?? '—';
|
|
13
|
-
lines.push(` ${id} [${coll}] ${r.name}`);
|
|
16
|
+
lines.push(` ${s(id)} [${s(coll)}] ${s(r.name)}`);
|
|
14
17
|
}
|
|
15
18
|
return lines.join('\n');
|
|
16
19
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/formatters/search.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/formatters/search.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AASpD,MAAM,UAAU,mBAAmB,CAAC,OAAuB;IACzD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,OAAO,mBAAmB,CAAC;IAC7B,CAAC;IAED,sFAAsF;IACtF,MAAM,CAAC,GAAG,iBAAiB,CAAC;IAC5B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,IAAI,CAAC;QAC/B,MAAM,IAAI,GAAG,CAAC,CAAC,cAAc,IAAI,GAAG,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/formatters/update.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,8DAA8D;IAC9D,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/formatters/update.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC,8DAA8D;IAC9D,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;CAC/B;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CA2CnE"}
|
|
@@ -21,12 +21,14 @@ export function formatUpdateReceipt(data) {
|
|
|
21
21
|
lines.push(` Fields: ${changes.join(', ')}`);
|
|
22
22
|
}
|
|
23
23
|
// BET-192 / FEAT-575: Surface normalization warnings — fields that were rejected/dropped.
|
|
24
|
+
// BET-271 S1: Include `pb fields` suggestion for rejected field warnings.
|
|
24
25
|
if (data.normalizationWarnings && data.normalizationWarnings.length > 0) {
|
|
25
26
|
lines.push('');
|
|
26
27
|
lines.push(' ⚠ Normalization warnings:');
|
|
27
28
|
for (const warning of data.normalizationWarnings) {
|
|
28
29
|
lines.push(` - ${warning}`);
|
|
29
30
|
}
|
|
31
|
+
lines.push(` Run \`pb fields\` to see valid fields for this entry.`);
|
|
30
32
|
}
|
|
31
33
|
// BET-192 / FEAT-575: Surface validation warnings — missing required fields, etc.
|
|
32
34
|
if (data.validationWarnings && data.validationWarnings.length > 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/formatters/update.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH,MAAM,UAAU,mBAAmB,CAAC,IAAuB;IACzD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,eAAe;IACf,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,IAAI,CAAC,MAAM;QAAE,OAAO,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACzD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;QACpC,IAAI,GAAG;YAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEhF,SAAS;IACT,IAAI,IAAI,CAAC,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,aAAa,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,0FAA0F;IAC1F,IAAI,IAAI,CAAC,qBAAqB,IAAI,IAAI,CAAC,qBAAqB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QAC1C,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACjD,KAAK,CAAC,IAAI,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC;QACjC,CAAC;
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/formatters/update.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAcH,MAAM,UAAU,mBAAmB,CAAC,IAAuB;IACzD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,eAAe;IACf,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,IAAI,CAAC,MAAM;QAAE,OAAO,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;IACzD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACnC,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;QACpC,IAAI,GAAG;YAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,WAAW,IAAI,CAAC,OAAO,KAAK,IAAI,CAAC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEhF,SAAS;IACT,IAAI,IAAI,CAAC,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1C,KAAK,CAAC,IAAI,CAAC,aAAa,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,0FAA0F;IAC1F,0EAA0E;IAC1E,IAAI,IAAI,CAAC,qBAAqB,IAAI,IAAI,CAAC,qBAAqB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QAC1C,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACjD,KAAK,CAAC,IAAI,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC;QACjC,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,2DAA2D,CAAC,CAAC;IAC1E,CAAC;IAED,kFAAkF;IAClF,IAAI,IAAI,CAAC,kBAAkB,IAAI,IAAI,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClE,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;QACvC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC9C,KAAK,CAAC,IAAI,CAAC,SAAS,OAAO,EAAE,CAAC,CAAC;QACjC,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IAE7C,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surface-profiles.test.d.ts","sourceRoot":"","sources":["../../../src/generators/__tests__/surface-profiles.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* surface-profiles — unit tests.
|
|
3
|
+
* BET-270 Slice 0: type system + registry.
|
|
4
|
+
*/
|
|
5
|
+
import { describe, expect, it } from 'vitest';
|
|
6
|
+
import { SURFACE_PROFILES, resolveSurfaceProfile } from '../surface-profiles.js';
|
|
7
|
+
// ── Helper ─────────────────────────────────────────────────────────────
|
|
8
|
+
function isValidProfile(profile) {
|
|
9
|
+
if (!profile || typeof profile !== 'object')
|
|
10
|
+
return false;
|
|
11
|
+
const p = profile;
|
|
12
|
+
return (['batch', 'interactive', 'passive'].includes(p.executionModel) &&
|
|
13
|
+
['multi-file', 'single-file'].includes(p.format) &&
|
|
14
|
+
['stateless', 'conversational', 'autonomous'].includes(p.sessionModel) &&
|
|
15
|
+
typeof p.tokenBudget === 'number' &&
|
|
16
|
+
p.tokenBudget > 0 &&
|
|
17
|
+
['orchestrated', 'direct', 'guided'].includes(p.workflowStyle));
|
|
18
|
+
}
|
|
19
|
+
// ── Registry ───────────────────────────────────────────────────────────
|
|
20
|
+
describe('SURFACE_PROFILES registry', () => {
|
|
21
|
+
it('defines all 4 known targets', () => {
|
|
22
|
+
expect(Object.keys(SURFACE_PROFILES).sort()).toEqual(['claude', 'codex', 'copilot', 'cursor']);
|
|
23
|
+
});
|
|
24
|
+
it.each(['claude', 'cursor', 'codex', 'copilot'])('%s profile has all required fields with correct types', (target) => {
|
|
25
|
+
expect(isValidProfile(SURFACE_PROFILES[target])).toBe(true);
|
|
26
|
+
});
|
|
27
|
+
it('claude profile has correct values', () => {
|
|
28
|
+
const p = SURFACE_PROFILES.claude;
|
|
29
|
+
expect(p.executionModel).toBe('interactive');
|
|
30
|
+
expect(p.format).toBe('multi-file');
|
|
31
|
+
expect(p.sessionModel).toBe('conversational');
|
|
32
|
+
expect(p.tokenBudget).toBe(50000);
|
|
33
|
+
expect(p.workflowStyle).toBe('orchestrated');
|
|
34
|
+
});
|
|
35
|
+
it('cursor profile has correct values', () => {
|
|
36
|
+
const p = SURFACE_PROFILES.cursor;
|
|
37
|
+
expect(p.executionModel).toBe('interactive');
|
|
38
|
+
expect(p.format).toBe('multi-file');
|
|
39
|
+
expect(p.sessionModel).toBe('conversational');
|
|
40
|
+
expect(p.tokenBudget).toBe(50000);
|
|
41
|
+
expect(p.workflowStyle).toBe('orchestrated');
|
|
42
|
+
});
|
|
43
|
+
it('codex profile has correct values', () => {
|
|
44
|
+
const p = SURFACE_PROFILES.codex;
|
|
45
|
+
expect(p.executionModel).toBe('batch');
|
|
46
|
+
expect(p.format).toBe('multi-file');
|
|
47
|
+
expect(p.sessionModel).toBe('autonomous');
|
|
48
|
+
expect(p.tokenBudget).toBe(100000);
|
|
49
|
+
expect(p.workflowStyle).toBe('direct');
|
|
50
|
+
});
|
|
51
|
+
it('copilot profile has correct values', () => {
|
|
52
|
+
const p = SURFACE_PROFILES.copilot;
|
|
53
|
+
expect(p.executionModel).toBe('passive');
|
|
54
|
+
expect(p.format).toBe('single-file');
|
|
55
|
+
expect(p.sessionModel).toBe('stateless');
|
|
56
|
+
expect(p.tokenBudget).toBe(30000);
|
|
57
|
+
expect(p.workflowStyle).toBe('guided');
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
// ── Resolver ──────────────────────────────────────────────────────────
|
|
61
|
+
describe('resolveSurfaceProfile', () => {
|
|
62
|
+
it.each(['claude', 'cursor', 'codex', 'copilot'])('resolves known target "%s" to a valid profile', (target) => {
|
|
63
|
+
const profile = resolveSurfaceProfile(target);
|
|
64
|
+
expect(isValidProfile(profile)).toBe(true);
|
|
65
|
+
});
|
|
66
|
+
it('resolves "claude" to the claude profile', () => {
|
|
67
|
+
expect(resolveSurfaceProfile('claude')).toBe(SURFACE_PROFILES.claude);
|
|
68
|
+
});
|
|
69
|
+
it('resolves "cursor" to the cursor profile', () => {
|
|
70
|
+
expect(resolveSurfaceProfile('cursor')).toBe(SURFACE_PROFILES.cursor);
|
|
71
|
+
});
|
|
72
|
+
it('resolves "codex" to the codex profile', () => {
|
|
73
|
+
expect(resolveSurfaceProfile('codex')).toBe(SURFACE_PROFILES.codex);
|
|
74
|
+
});
|
|
75
|
+
it('resolves "copilot" to the copilot profile', () => {
|
|
76
|
+
expect(resolveSurfaceProfile('copilot')).toBe(SURFACE_PROFILES.copilot);
|
|
77
|
+
});
|
|
78
|
+
it('returns codex profile as fallback for unknown targets', () => {
|
|
79
|
+
expect(resolveSurfaceProfile('unknown-tool')).toBe(SURFACE_PROFILES.codex);
|
|
80
|
+
});
|
|
81
|
+
it('returns codex profile for empty string', () => {
|
|
82
|
+
expect(resolveSurfaceProfile('')).toBe(SURFACE_PROFILES.codex);
|
|
83
|
+
});
|
|
84
|
+
it('fallback profile is a valid profile', () => {
|
|
85
|
+
const fallback = resolveSurfaceProfile('completely-unknown-surface');
|
|
86
|
+
expect(isValidProfile(fallback)).toBe(true);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
//# sourceMappingURL=surface-profiles.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surface-profiles.test.js","sourceRoot":"","sources":["../../../src/generators/__tests__/surface-profiles.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,10 +2,43 @@
|
|
|
2
2
|
* Adapter file generators — thin pointers for each AI tool.
|
|
3
3
|
* Each function returns the file content as a string.
|
|
4
4
|
*/
|
|
5
|
+
import type { SurfaceProfile } from './surface-profiles.js';
|
|
5
6
|
declare const MARKER = "auto-generated by pb handshake";
|
|
6
7
|
export { MARKER };
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
export interface AgentsMdOptions {
|
|
9
|
+
profile?: SurfaceProfile;
|
|
10
|
+
workspaceContext?: {
|
|
11
|
+
stage?: string;
|
|
12
|
+
focus?: string;
|
|
13
|
+
governanceMode?: string;
|
|
14
|
+
totalEntries?: number;
|
|
15
|
+
};
|
|
16
|
+
skills?: Array<{
|
|
17
|
+
name: string;
|
|
18
|
+
description: string;
|
|
19
|
+
triggers?: string[];
|
|
20
|
+
}>;
|
|
21
|
+
}
|
|
22
|
+
export declare function generateAgentsMd(timestamp: string, options?: AgentsMdOptions): string;
|
|
23
|
+
export declare function generateClaudeMd(timestamp: string, profile?: SurfaceProfile): string;
|
|
24
|
+
export declare function generateCursorMdc(timestamp: string, profile?: SurfaceProfile): string;
|
|
25
|
+
export interface CopilotMdOptions {
|
|
26
|
+
profile?: SurfaceProfile;
|
|
27
|
+
workspaceContext?: {
|
|
28
|
+
stage?: string;
|
|
29
|
+
focus?: string;
|
|
30
|
+
governanceMode?: string;
|
|
31
|
+
totalEntries?: number;
|
|
32
|
+
};
|
|
33
|
+
skills?: Array<{
|
|
34
|
+
name: string;
|
|
35
|
+
description: string;
|
|
36
|
+
triggers?: string[];
|
|
37
|
+
}>;
|
|
38
|
+
rules?: Array<{
|
|
39
|
+
name: string;
|
|
40
|
+
description: string;
|
|
41
|
+
}>;
|
|
42
|
+
}
|
|
43
|
+
export declare function generateCopilotMd(timestamp: string, options?: CopilotMdOptions): string;
|
|
11
44
|
//# sourceMappingURL=adapters.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../../src/generators/adapters.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,QAAA,MAAM,MAAM,mCAAmC,CAAC;AAEhD,OAAO,EAAE,MAAM,EAAE,CAAC;AAElB,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../../src/generators/adapters.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,QAAA,MAAM,MAAM,mCAAmC,CAAC;AAEhD,OAAO,EAAE,MAAM,EAAE,CAAC;AAElB,MAAM,WAAW,eAAe;IAC9B,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,gBAAgB,CAAC,EAAE;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAC5E;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,MAAM,CAgFrF;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM,CAsCpF;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM,CAkCrF;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,gBAAgB,CAAC,EAAE;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAC3E,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACtD;AAED,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAuIvF"}
|
|
@@ -4,7 +4,43 @@
|
|
|
4
4
|
*/
|
|
5
5
|
const MARKER = 'auto-generated by pb handshake';
|
|
6
6
|
export { MARKER };
|
|
7
|
-
export function generateAgentsMd(timestamp) {
|
|
7
|
+
export function generateAgentsMd(timestamp, options) {
|
|
8
|
+
const { workspaceContext, skills } = options ?? {};
|
|
9
|
+
// Workspace context section (only when data is available)
|
|
10
|
+
let workspaceSection = '';
|
|
11
|
+
if (workspaceContext && Object.values(workspaceContext).some((v) => v !== undefined)) {
|
|
12
|
+
const rows = [];
|
|
13
|
+
if (workspaceContext.stage !== undefined)
|
|
14
|
+
rows.push(`| Stage | \`${workspaceContext.stage}\` |`);
|
|
15
|
+
if (workspaceContext.focus !== undefined)
|
|
16
|
+
rows.push(`| Current focus | ${workspaceContext.focus} |`);
|
|
17
|
+
if (workspaceContext.governanceMode !== undefined)
|
|
18
|
+
rows.push(`| Governance mode | \`${workspaceContext.governanceMode}\` |`);
|
|
19
|
+
if (workspaceContext.totalEntries !== undefined)
|
|
20
|
+
rows.push(`| Chain entries | ${workspaceContext.totalEntries} |`);
|
|
21
|
+
workspaceSection = `
|
|
22
|
+
## Workspace Context
|
|
23
|
+
|
|
24
|
+
| Field | Value |
|
|
25
|
+
|-------|-------|
|
|
26
|
+
${rows.join('\n')}
|
|
27
|
+
`;
|
|
28
|
+
}
|
|
29
|
+
// Skill directory section (only when skills provided and non-empty)
|
|
30
|
+
let skillsSection = '';
|
|
31
|
+
if (skills && skills.length > 0) {
|
|
32
|
+
const rows = skills.map((s) => {
|
|
33
|
+
const triggers = s.triggers && s.triggers.length > 0 ? s.triggers.slice(0, 3).join(', ') : '—';
|
|
34
|
+
return `| \`${s.name}\` | ${s.description} | ${triggers} |`;
|
|
35
|
+
});
|
|
36
|
+
skillsSection = `
|
|
37
|
+
## Skill Directory
|
|
38
|
+
|
|
39
|
+
| Skill | Description | Triggers |
|
|
40
|
+
|-------|-------------|----------|
|
|
41
|
+
${rows.join('\n')}
|
|
42
|
+
`;
|
|
43
|
+
}
|
|
8
44
|
return `<!-- ${MARKER} — ${timestamp} -->
|
|
9
45
|
<!-- Re-run \`pb handshake\` to refresh. Do not edit manually. -->
|
|
10
46
|
|
|
@@ -13,7 +49,7 @@ export function generateAgentsMd(timestamp) {
|
|
|
13
49
|
Read \`.productbrain/context.md\` for full workspace briefing (stage, bets, governance, tensions).
|
|
14
50
|
Read \`.productbrain/briefing.md\` for entries matched to this repo.
|
|
15
51
|
Read \`.productbrain/soul.md\` when identity, working style, or collaboration preferences matter.
|
|
16
|
-
|
|
52
|
+
${workspaceSection}
|
|
17
53
|
## The Chain is the SSOT. Use \`pb\` before everything.
|
|
18
54
|
|
|
19
55
|
| Command | Purpose |
|
|
@@ -44,9 +80,13 @@ pb capture "INS: learned that X"
|
|
|
44
80
|
Close with \`pb session close\` — reviews what was captured, refreshes context for the next session.
|
|
45
81
|
|
|
46
82
|
All captures are drafts. The human reviews and commits in Product Brain Studio.
|
|
83
|
+
${skillsSection}
|
|
84
|
+
## Governance Summary
|
|
85
|
+
|
|
86
|
+
This workspace uses Product Brain governance. Decisions, standards, and tensions are tracked on the Chain. Use \`pb orient -b\` for current focus.
|
|
47
87
|
`;
|
|
48
88
|
}
|
|
49
|
-
export function generateClaudeMd(timestamp) {
|
|
89
|
+
export function generateClaudeMd(timestamp, profile) {
|
|
50
90
|
return `<!-- ${MARKER} — ${timestamp} -->
|
|
51
91
|
<!-- Re-run \`pb handshake\` to refresh. Do not edit manually. -->
|
|
52
92
|
|
|
@@ -85,7 +125,7 @@ Close with \`pb session close\` — reviews what was captured, refreshes context
|
|
|
85
125
|
All captures are drafts. The human reviews and commits in Product Brain Studio.
|
|
86
126
|
`;
|
|
87
127
|
}
|
|
88
|
-
export function generateCursorMdc(timestamp) {
|
|
128
|
+
export function generateCursorMdc(timestamp, profile) {
|
|
89
129
|
return `---
|
|
90
130
|
description: Product Brain Chain context — workspace knowledge for AI-assisted development
|
|
91
131
|
globs:
|
|
@@ -120,15 +160,38 @@ Close with \`pb session close\`. All captures are drafts — human reviews and c
|
|
|
120
160
|
<!-- ${MARKER} — ${timestamp} -->
|
|
121
161
|
`;
|
|
122
162
|
}
|
|
123
|
-
export function generateCopilotMd(timestamp) {
|
|
124
|
-
|
|
163
|
+
export function generateCopilotMd(timestamp, options) {
|
|
164
|
+
const { profile, workspaceContext, skills, rules } = options ?? {};
|
|
165
|
+
const budget = profile?.tokenBudget ?? 30000;
|
|
166
|
+
// Workspace context section (only when data is available)
|
|
167
|
+
let workspaceSection = '';
|
|
168
|
+
if (workspaceContext && Object.values(workspaceContext).some((v) => v !== undefined)) {
|
|
169
|
+
const rows = [];
|
|
170
|
+
if (workspaceContext.stage !== undefined)
|
|
171
|
+
rows.push(`| Stage | \`${workspaceContext.stage}\` |`);
|
|
172
|
+
if (workspaceContext.focus !== undefined)
|
|
173
|
+
rows.push(`| Current focus | ${workspaceContext.focus} |`);
|
|
174
|
+
if (workspaceContext.governanceMode !== undefined)
|
|
175
|
+
rows.push(`| Governance mode | \`${workspaceContext.governanceMode}\` |`);
|
|
176
|
+
if (workspaceContext.totalEntries !== undefined)
|
|
177
|
+
rows.push(`| Chain entries | ${workspaceContext.totalEntries} |`);
|
|
178
|
+
workspaceSection = `
|
|
179
|
+
## Workspace Context
|
|
180
|
+
|
|
181
|
+
| Field | Value |
|
|
182
|
+
|-------|-------|
|
|
183
|
+
${rows.join('\n')}
|
|
184
|
+
`;
|
|
185
|
+
}
|
|
186
|
+
// Build the invariant base (header + workspace + command ref + session lifecycle)
|
|
187
|
+
const base = `<!-- ${MARKER} — ${timestamp} -->
|
|
125
188
|
<!-- Re-run \`pb handshake\` to refresh. Do not edit manually. -->
|
|
126
189
|
|
|
127
190
|
# Product Brain Context
|
|
128
191
|
|
|
129
192
|
Read \`.productbrain/context.md\` for full workspace briefing (stage, bets, governance, tensions).
|
|
130
193
|
Read \`.productbrain/briefing.md\` for entries matched to this repo.
|
|
131
|
-
|
|
194
|
+
${workspaceSection}
|
|
132
195
|
## The Chain is the SSOT. Use \`pb\` before everything.
|
|
133
196
|
|
|
134
197
|
- \`pb orient -b\` — Current workspace focus
|
|
@@ -146,5 +209,82 @@ Before substantive implementation, review, diagnosis, or security-sensitive reas
|
|
|
146
209
|
Start with \`pb session start\`. Capture knowledge during work with \`pb capture "text"\`.
|
|
147
210
|
Close with \`pb session close\`. All captures are drafts — human reviews and commits.
|
|
148
211
|
`;
|
|
212
|
+
// When no enrichment options provided, return base for backward compat
|
|
213
|
+
if (!skills?.length && !rules?.length) {
|
|
214
|
+
return base;
|
|
215
|
+
}
|
|
216
|
+
// Build skill summaries and rule summaries as independent chunks
|
|
217
|
+
// so we can truncate from the end if needed
|
|
218
|
+
const skillChunks = [];
|
|
219
|
+
if (skills && skills.length > 0) {
|
|
220
|
+
skillChunks.push('\n## Skills\n');
|
|
221
|
+
for (const s of skills) {
|
|
222
|
+
let chunk = `\n### ${s.name}\n${s.description}\n`;
|
|
223
|
+
if (s.triggers && s.triggers.length > 0) {
|
|
224
|
+
chunk += `Triggers: ${s.triggers.slice(0, 3).join(', ')}\n`;
|
|
225
|
+
}
|
|
226
|
+
skillChunks.push(chunk);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const ruleChunks = [];
|
|
230
|
+
if (rules && rules.length > 0) {
|
|
231
|
+
ruleChunks.push('\n## Rules\n');
|
|
232
|
+
for (const r of rules) {
|
|
233
|
+
ruleChunks.push(`\n### ${r.name}\n${r.description}\n`);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
// All appendable chunks: skill section header + individual skills, then rule section header + individual rules
|
|
237
|
+
const allChunks = [...skillChunks, ...ruleChunks];
|
|
238
|
+
// Greedily append chunks while staying within budget
|
|
239
|
+
let result = base;
|
|
240
|
+
let omittedCount = 0;
|
|
241
|
+
const truncationNote = (n) => `\n<!-- Truncated: ${n} skills/rules omitted to stay within token budget -->\n`;
|
|
242
|
+
// Check if base already exceeds budget (rare, but handle gracefully)
|
|
243
|
+
if (base.length >= budget) {
|
|
244
|
+
return base;
|
|
245
|
+
}
|
|
246
|
+
// We need to find how many chunks fit. Reserve space for a truncation note if needed.
|
|
247
|
+
const allChunksText = allChunks.join('');
|
|
248
|
+
if (base.length + allChunksText.length <= budget) {
|
|
249
|
+
// Everything fits — no truncation needed
|
|
250
|
+
return base + allChunksText;
|
|
251
|
+
}
|
|
252
|
+
// Need to truncate. Try adding chunks one by one, reserving budget for the truncation note.
|
|
253
|
+
// We skip section headers (index 0 of skillChunks and index 0 of ruleChunks) if there are
|
|
254
|
+
// no item chunks that follow — but for simplicity, we include section headers as chunks and
|
|
255
|
+
// let the budget math handle them.
|
|
256
|
+
let accumulated = base;
|
|
257
|
+
let i = 0;
|
|
258
|
+
// Count total "items" (non-header chunks) for the omission note
|
|
259
|
+
// Headers are chunks whose content starts with '\n## '
|
|
260
|
+
const isHeader = (c) => c.trimStart().startsWith('## ');
|
|
261
|
+
const itemCount = allChunks.filter((c) => !isHeader(c)).length;
|
|
262
|
+
let fittedItemCount = 0;
|
|
263
|
+
while (i < allChunks.length) {
|
|
264
|
+
const chunk = allChunks[i];
|
|
265
|
+
const remaining = allChunks.slice(i + 1).join('');
|
|
266
|
+
const noteLen = itemCount - fittedItemCount > 0 ? truncationNote(itemCount - fittedItemCount).length : 0;
|
|
267
|
+
if (accumulated.length + chunk.length + remaining.length + noteLen <= budget) {
|
|
268
|
+
// Everything from here fits — just append the rest
|
|
269
|
+
accumulated += allChunks.slice(i).join('');
|
|
270
|
+
fittedItemCount = itemCount;
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
if (accumulated.length + chunk.length + noteLen <= budget) {
|
|
274
|
+
accumulated += chunk;
|
|
275
|
+
if (!isHeader(chunk))
|
|
276
|
+
fittedItemCount++;
|
|
277
|
+
i++;
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
// This chunk doesn't fit even with just the note — stop
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
omittedCount = itemCount - fittedItemCount;
|
|
285
|
+
if (omittedCount > 0) {
|
|
286
|
+
accumulated += truncationNote(omittedCount);
|
|
287
|
+
}
|
|
288
|
+
return accumulated;
|
|
149
289
|
}
|
|
150
290
|
//# sourceMappingURL=adapters.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"adapters.js","sourceRoot":"","sources":["../../src/generators/adapters.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"adapters.js","sourceRoot":"","sources":["../../src/generators/adapters.ts"],"names":[],"mappings":"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"}
|