@productbrain/cli 0.1.0-beta.4863 → 0.1.0-beta.4879
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__/capture.test.js +373 -20
- package/dist/__tests__/capture.test.js.map +1 -1
- package/dist/commands/admin/seed.js +11 -8
- package/dist/commands/admin/seed.js.map +1 -1
- package/dist/commands/admin/seed.test.js +23 -3
- package/dist/commands/admin/seed.test.js.map +1 -1
- package/dist/commands/capture.d.ts +3 -1
- package/dist/commands/capture.d.ts.map +1 -1
- package/dist/commands/capture.js +88 -116
- package/dist/commands/capture.js.map +1 -1
- package/dist/formatters/capture.d.ts.map +1 -1
- package/dist/formatters/capture.js +3 -1
- package/dist/formatters/capture.js.map +1 -1
- package/dist/generated/relationTypes.generated.d.ts +12 -0
- package/dist/generated/relationTypes.generated.d.ts.map +1 -0
- package/dist/generated/relationTypes.generated.js +11 -0
- package/dist/generated/relationTypes.generated.js.map +1 -0
- package/dist/index.js +3 -3
- package/dist/index.js.map +1 -1
- package/dist/lib/__tests__/legalRelationTypes.test.d.ts +2 -0
- package/dist/lib/__tests__/legalRelationTypes.test.d.ts.map +1 -0
- package/dist/lib/__tests__/legalRelationTypes.test.js +98 -0
- package/dist/lib/__tests__/legalRelationTypes.test.js.map +1 -0
- package/dist/lib/captureGrounding.d.ts +53 -0
- package/dist/lib/captureGrounding.d.ts.map +1 -0
- package/dist/lib/captureGrounding.js +108 -0
- package/dist/lib/captureGrounding.js.map +1 -0
- package/dist/lib/legalRelationTypes.d.ts +25 -0
- package/dist/lib/legalRelationTypes.d.ts.map +1 -0
- package/dist/lib/legalRelationTypes.js +94 -0
- package/dist/lib/legalRelationTypes.js.map +1 -0
- package/dist/registerEntryCommands.js +2 -2
- package/dist/registerEntryCommands.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WP-688 S4 review round 5 (bdB5K, cQFZ_): filterCreatableRelationTypes narrows a workspace's
|
|
3
|
+
* declared valid_relation_types down to verbs `pb relate`'s generic door can actually create.
|
|
4
|
+
* WP-688 S4 review round 5 (bcQiSg): resolveCreatableRelationTypes mirrors loadTypeMap's
|
|
5
|
+
* DB-first resolution — trust-accepted rows only, last-match-wins on duplicate canonical_key.
|
|
6
|
+
*/
|
|
7
|
+
import { describe, expect, it } from 'vitest';
|
|
8
|
+
import { filterCreatableRelationTypes, resolveCreatableRelationTypes } from '../legalRelationTypes.js';
|
|
9
|
+
describe('filterCreatableRelationTypes', () => {
|
|
10
|
+
it('returns an empty array when declared is not an array', () => {
|
|
11
|
+
expect(filterCreatableRelationTypes(undefined, false, true)).toEqual([]);
|
|
12
|
+
expect(filterCreatableRelationTypes(null, false, true)).toEqual([]);
|
|
13
|
+
expect(filterCreatableRelationTypes('informs', false, true)).toEqual([]);
|
|
14
|
+
});
|
|
15
|
+
it('excludes replaces and do_not_confuse_with regardless of target (direct-door-blocked)', () => {
|
|
16
|
+
expect(filterCreatableRelationTypes(['informs', 'replaces', 'do_not_confuse_with', 'governs'], false, true))
|
|
17
|
+
.toEqual(['informs', 'governs']);
|
|
18
|
+
});
|
|
19
|
+
it('excludes a verb outside the kernel ALLOWED_RELATION_TYPES allowlist (bdB5K)', () => {
|
|
20
|
+
expect(filterCreatableRelationTypes(['informs', 'depends_on', 'custom_hand_added'], false, true))
|
|
21
|
+
.toEqual(['informs', 'depends_on']);
|
|
22
|
+
});
|
|
23
|
+
it('excludes belongs_to/authority_domain only when the target is a domain (cQFZ_)', () => {
|
|
24
|
+
const declared = ['informs', 'belongs_to', 'authority_domain'];
|
|
25
|
+
expect(filterCreatableRelationTypes(declared, true, true)).toEqual(['informs']);
|
|
26
|
+
expect(filterCreatableRelationTypes(declared, false, true)).toEqual(['informs', 'belongs_to', 'authority_domain']);
|
|
27
|
+
});
|
|
28
|
+
it('drops non-string entries in the declared array', () => {
|
|
29
|
+
expect(filterCreatableRelationTypes(['informs', 42, null, 'governs'], false, true)).toEqual(['informs', 'governs']);
|
|
30
|
+
});
|
|
31
|
+
it('excludes anchored_to unless the source is a strategy entry (bcRgRI)', () => {
|
|
32
|
+
const declared = ['informs', 'anchored_to'];
|
|
33
|
+
expect(filterCreatableRelationTypes(declared, false, false)).toEqual(['informs']);
|
|
34
|
+
expect(filterCreatableRelationTypes(declared, false, true)).toEqual(['informs', 'anchored_to']);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
// Minimal parsable fields every fixture row below needs to pass isParsableSemanticTypeRow
|
|
38
|
+
// (kernel/entries/semanticTypes.ts:65-77's validity rule) unless a test is deliberately
|
|
39
|
+
// exercising the malformed-row-skip path.
|
|
40
|
+
const PARSABLE = { description: 'x', cardinality_rule: 'multiple' };
|
|
41
|
+
describe('resolveCreatableRelationTypes', () => {
|
|
42
|
+
it('when duplicate canonical_key rows exist, the LAST trust-accepted+parsable match wins (bcQiSg, mirrors loadTypeMap last-write-wins)', () => {
|
|
43
|
+
const typeRows = [
|
|
44
|
+
{ status: 'active', data: { canonical_key: 'goal', valid_relation_types: ['informs'], ...PARSABLE } },
|
|
45
|
+
{ status: 'active', data: { canonical_key: 'goal', valid_relation_types: ['depends_on', 'governs'], ...PARSABLE } },
|
|
46
|
+
];
|
|
47
|
+
expect(resolveCreatableRelationTypes(typeRows, 'goal', false)).toEqual(['depends_on', 'governs']);
|
|
48
|
+
});
|
|
49
|
+
it('skips a row whose status is not trust-accepted (draft/archived), even if it is the last match', () => {
|
|
50
|
+
const typeRows = [
|
|
51
|
+
{ status: 'active', data: { canonical_key: 'goal', valid_relation_types: ['informs'], ...PARSABLE } },
|
|
52
|
+
{ status: 'draft', data: { canonical_key: 'goal', valid_relation_types: ['depends_on'], ...PARSABLE } },
|
|
53
|
+
{ status: 'archived', data: { canonical_key: 'goal', valid_relation_types: ['governs'], ...PARSABLE } },
|
|
54
|
+
];
|
|
55
|
+
expect(resolveCreatableRelationTypes(typeRows, 'goal', false)).toEqual(['informs']);
|
|
56
|
+
});
|
|
57
|
+
it('treats status "accepted" as trust-accepted too (isTrustAccepted parity)', () => {
|
|
58
|
+
const typeRows = [{ status: 'accepted', data: { canonical_key: 'goal', valid_relation_types: ['informs'], ...PARSABLE } }];
|
|
59
|
+
expect(resolveCreatableRelationTypes(typeRows, 'goal', false)).toEqual(['informs']);
|
|
60
|
+
});
|
|
61
|
+
it('returns an empty array when no row matches the canonical key', () => {
|
|
62
|
+
const typeRows = [{ status: 'active', data: { canonical_key: 'other', valid_relation_types: ['informs'], ...PARSABLE } }];
|
|
63
|
+
expect(resolveCreatableRelationTypes(typeRows, 'goal', false)).toEqual([]);
|
|
64
|
+
});
|
|
65
|
+
it('handles a null/undefined typeRows list', () => {
|
|
66
|
+
expect(resolveCreatableRelationTypes(null, 'goal', false)).toEqual([]);
|
|
67
|
+
expect(resolveCreatableRelationTypes(undefined, 'goal', false)).toEqual([]);
|
|
68
|
+
});
|
|
69
|
+
it('still applies filterCreatableRelationTypes to the resolved row (bdB5K/cQFZ_ compose with bcQiSg)', () => {
|
|
70
|
+
const typeRows = [{ status: 'active', data: { canonical_key: 'insight', valid_relation_types: ['informs', 'belongs_to', 'custom_hand_added'], ...PARSABLE } }];
|
|
71
|
+
expect(resolveCreatableRelationTypes(typeRows, 'insight', true)).toEqual(['informs']);
|
|
72
|
+
});
|
|
73
|
+
it('skips a malformed LATER trust-accepted duplicate (missing description) rather than letting it overwrite a valid earlier row (bcRICo)', () => {
|
|
74
|
+
const typeRows = [
|
|
75
|
+
{ status: 'active', data: { canonical_key: 'goal', valid_relation_types: ['informs'], ...PARSABLE } },
|
|
76
|
+
{ status: 'active', data: { canonical_key: 'goal', valid_relation_types: ['depends_on'] /* no description */ } },
|
|
77
|
+
];
|
|
78
|
+
expect(resolveCreatableRelationTypes(typeRows, 'goal', false)).toEqual(['informs']);
|
|
79
|
+
});
|
|
80
|
+
it('skips a malformed LATER trust-accepted duplicate (invalid cardinality_rule) the same way', () => {
|
|
81
|
+
const typeRows = [
|
|
82
|
+
{ status: 'active', data: { canonical_key: 'goal', valid_relation_types: ['informs'], ...PARSABLE } },
|
|
83
|
+
{ status: 'active', data: { canonical_key: 'goal', valid_relation_types: ['depends_on'], description: 'x', cardinality_rule: 'not_a_real_rule' } },
|
|
84
|
+
];
|
|
85
|
+
expect(resolveCreatableRelationTypes(typeRows, 'goal', false)).toEqual(['informs']);
|
|
86
|
+
});
|
|
87
|
+
it('returns empty when every trust-accepted match for the key is malformed', () => {
|
|
88
|
+
const typeRows = [{ status: 'active', data: { canonical_key: 'goal', valid_relation_types: ['informs'] } }];
|
|
89
|
+
expect(resolveCreatableRelationTypes(typeRows, 'goal', false)).toEqual([]);
|
|
90
|
+
});
|
|
91
|
+
it('excludes anchored_to for a non-strategy canonicalKey, includes it for strategy (bcRgRI)', () => {
|
|
92
|
+
const typeRows = [{ status: 'active', data: { canonical_key: 'goal', valid_relation_types: ['informs', 'anchored_to'], ...PARSABLE } }];
|
|
93
|
+
expect(resolveCreatableRelationTypes(typeRows, 'goal', false)).toEqual(['informs']);
|
|
94
|
+
const strategyRows = [{ status: 'active', data: { canonical_key: 'strategy', valid_relation_types: ['informs', 'anchored_to'], ...PARSABLE } }];
|
|
95
|
+
expect(resolveCreatableRelationTypes(strategyRows, 'strategy', false)).toEqual(['informs', 'anchored_to']);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
//# sourceMappingURL=legalRelationTypes.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legalRelationTypes.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/legalRelationTypes.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `pb capture` grounding presentation helpers — extracted from capture.ts (WP-688 S4, TASK-105)
|
|
3
|
+
* purely to fund that file's shrink-only LOC budget (STD-2/DEC-1504); no behavior change.
|
|
4
|
+
* `promptYN` moves here as dead-on-arrival for the `--link-type` refusal path — it stays used
|
|
5
|
+
* only by `--strict`'s existing possible-duplicate confirmation, unchanged.
|
|
6
|
+
*/
|
|
7
|
+
/** WP-319 S3: Pre-write grounding result from chain.suggestLinksForCapture */
|
|
8
|
+
export type GroundingRelated = {
|
|
9
|
+
entryId: string;
|
|
10
|
+
name: string;
|
|
11
|
+
collectionSlug: string;
|
|
12
|
+
overlapRatio: number;
|
|
13
|
+
recommendedRelationType: string;
|
|
14
|
+
reasoning: string;
|
|
15
|
+
};
|
|
16
|
+
export type GroundingDuplicate = {
|
|
17
|
+
entryId: string;
|
|
18
|
+
name: string;
|
|
19
|
+
collectionSlug: string;
|
|
20
|
+
matchType: 'related' | 'possible_duplicate';
|
|
21
|
+
overlapRatio: number;
|
|
22
|
+
};
|
|
23
|
+
export type GroundingGovernance = {
|
|
24
|
+
entryId: string;
|
|
25
|
+
name: string;
|
|
26
|
+
collectionSlug: string;
|
|
27
|
+
severity: 'block' | 'warn' | 'inform';
|
|
28
|
+
};
|
|
29
|
+
export type GroundingResult = {
|
|
30
|
+
index: number;
|
|
31
|
+
related: GroundingRelated[];
|
|
32
|
+
duplicates: GroundingDuplicate[];
|
|
33
|
+
/** WP-319 S1: Present only after Convex S1 deploys to production. */
|
|
34
|
+
governance?: GroundingGovernance[];
|
|
35
|
+
v?: number;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Extract a known ID prefix hint from capture text.
|
|
39
|
+
* Pattern: "FLO: description" or "TEN: something broken" — prefix must be uppercase,
|
|
40
|
+
* followed by colon and optional whitespace, then the actual text.
|
|
41
|
+
* Returns the resolved collection slug and the cleaned text (prefix stripped).
|
|
42
|
+
*/
|
|
43
|
+
export declare function extractPrefixHint(text: string, prefixMap: Record<string, string>): {
|
|
44
|
+
resolvedCollection: string | null;
|
|
45
|
+
cleanText: string;
|
|
46
|
+
};
|
|
47
|
+
/** Print advisory grounding banner to stderr. Suppressed when grounding has no matches. */
|
|
48
|
+
export declare function printGroundingBanner(grounding: GroundingResult): void;
|
|
49
|
+
/** Print dry-run grounding preview to stdout (--suggest-only). */
|
|
50
|
+
export declare function printGroundingPreview(grounding: GroundingResult | null, entryName: string, collectionSlug: string): void;
|
|
51
|
+
/** Prompt the user with a y/N question. Resolves true for "y", false otherwise. */
|
|
52
|
+
export declare function promptYN(message: string): Promise<boolean>;
|
|
53
|
+
//# sourceMappingURL=captureGrounding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"captureGrounding.d.ts","sourceRoot":"","sources":["../../src/lib/captureGrounding.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,8EAA8E;AAC9E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,uBAAuB,EAAE,MAAM,CAAC;IAChC,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,SAAS,GAAG,oBAAoB,CAAC;IAC5C,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,UAAU,EAAE,kBAAkB,EAAE,CAAC;IACjC,qEAAqE;IACrE,UAAU,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACnC,CAAC,CAAC,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG;IAAE,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAO3I;AAID,2FAA2F;AAC3F,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,eAAe,GAAG,IAAI,CAoCrE;AAED,kEAAkE;AAClE,wBAAgB,qBAAqB,CACnC,SAAS,EAAE,eAAe,GAAG,IAAI,EACjC,SAAS,EAAE,MAAM,EACjB,cAAc,EAAE,MAAM,GACrB,IAAI,CA+CN;AAED,mFAAmF;AACnF,wBAAsB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAQhE"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `pb capture` grounding presentation helpers — extracted from capture.ts (WP-688 S4, TASK-105)
|
|
3
|
+
* purely to fund that file's shrink-only LOC budget (STD-2/DEC-1504); no behavior change.
|
|
4
|
+
* `promptYN` moves here as dead-on-arrival for the `--link-type` refusal path — it stays used
|
|
5
|
+
* only by `--strict`'s existing possible-duplicate confirmation, unchanged.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Extract a known ID prefix hint from capture text.
|
|
9
|
+
* Pattern: "FLO: description" or "TEN: something broken" — prefix must be uppercase,
|
|
10
|
+
* followed by colon and optional whitespace, then the actual text.
|
|
11
|
+
* Returns the resolved collection slug and the cleaned text (prefix stripped).
|
|
12
|
+
*/
|
|
13
|
+
export function extractPrefixHint(text, prefixMap) {
|
|
14
|
+
const match = text.match(/^([A-Z]{2,4}):\s*(.+)$/s);
|
|
15
|
+
if (!match)
|
|
16
|
+
return { resolvedCollection: null, cleanText: text };
|
|
17
|
+
const [, prefix, rest] = match;
|
|
18
|
+
const slug = prefixMap[prefix];
|
|
19
|
+
if (!slug)
|
|
20
|
+
return { resolvedCollection: null, cleanText: text };
|
|
21
|
+
return { resolvedCollection: slug, cleanText: rest.trim() };
|
|
22
|
+
}
|
|
23
|
+
// WP-319 S3: Grounding helpers — advisory output, stderr only.
|
|
24
|
+
/** Print advisory grounding banner to stderr. Suppressed when grounding has no matches. */
|
|
25
|
+
export function printGroundingBanner(grounding) {
|
|
26
|
+
const possibleDuplicates = grounding.duplicates.filter((d) => d.matchType === 'possible_duplicate');
|
|
27
|
+
const related = [
|
|
28
|
+
...grounding.related,
|
|
29
|
+
...grounding.duplicates.filter((d) => d.matchType === 'related'),
|
|
30
|
+
];
|
|
31
|
+
const governance = grounding.governance ?? [];
|
|
32
|
+
const hasGovernance = governance.length > 0;
|
|
33
|
+
if (possibleDuplicates.length === 0 && related.length === 0 && !hasGovernance) {
|
|
34
|
+
return; // Zero-noise floor: nothing to show
|
|
35
|
+
}
|
|
36
|
+
const lines = ['\n Grounding:'];
|
|
37
|
+
if (possibleDuplicates.length > 0) {
|
|
38
|
+
const label = possibleDuplicates.length === 1 ? 'Possible duplicate' : 'Possible duplicates';
|
|
39
|
+
const items = possibleDuplicates.map((d) => `${d.entryId} "${d.name}"`).join(', ');
|
|
40
|
+
lines.push(` ⚠ ${label}: ${items}`);
|
|
41
|
+
}
|
|
42
|
+
if (related.length > 0) {
|
|
43
|
+
const items = related
|
|
44
|
+
.slice(0, 3)
|
|
45
|
+
.map((r) => `${r.entryId} "${r.name}"`)
|
|
46
|
+
.join(', ');
|
|
47
|
+
lines.push(` ~ Related: ${items}`);
|
|
48
|
+
}
|
|
49
|
+
for (const gov of governance) {
|
|
50
|
+
const icon = gov.severity === 'block' ? '✗' : gov.severity === 'warn' ? '⚠' : 'ℹ';
|
|
51
|
+
lines.push(` ${icon} Governance [${gov.severity}]: ${gov.entryId} "${gov.name}"`);
|
|
52
|
+
}
|
|
53
|
+
lines.push('');
|
|
54
|
+
process.stderr.write(lines.join('\n') + '\n');
|
|
55
|
+
}
|
|
56
|
+
/** Print dry-run grounding preview to stdout (--suggest-only). */
|
|
57
|
+
export function printGroundingPreview(grounding, entryName, collectionSlug) {
|
|
58
|
+
process.stdout.write(`\n Grounding preview for: ${entryName.slice(0, 80)}\n`);
|
|
59
|
+
process.stdout.write(` Collection: ${collectionSlug}\n\n`);
|
|
60
|
+
if (!grounding) {
|
|
61
|
+
process.stdout.write(' No grounding data available (timeout or unavailable).\n\n');
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const possibleDuplicates = grounding.duplicates.filter((d) => d.matchType === 'possible_duplicate');
|
|
65
|
+
const related = [
|
|
66
|
+
...grounding.related,
|
|
67
|
+
...grounding.duplicates.filter((d) => d.matchType === 'related'),
|
|
68
|
+
];
|
|
69
|
+
const govCandidates = grounding.governance ?? [];
|
|
70
|
+
if (possibleDuplicates.length === 0 && related.length === 0 && govCandidates.length === 0) {
|
|
71
|
+
process.stdout.write(' No matches found — capture looks unique.\n\n');
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (possibleDuplicates.length > 0) {
|
|
75
|
+
process.stdout.write(' Possible duplicates:\n');
|
|
76
|
+
for (const d of possibleDuplicates) {
|
|
77
|
+
process.stdout.write(` · ${d.entryId} "${d.name}" (overlap: ${Math.round(d.overlapRatio * 100)}%)\n`);
|
|
78
|
+
}
|
|
79
|
+
process.stdout.write('\n');
|
|
80
|
+
}
|
|
81
|
+
if (related.length > 0) {
|
|
82
|
+
process.stdout.write(' Related entries:\n');
|
|
83
|
+
for (const r of related.slice(0, 5)) {
|
|
84
|
+
const relType = 'recommendedRelationType' in r ? r.recommendedRelationType : 'related';
|
|
85
|
+
process.stdout.write(` · ${r.entryId} "${r.name}" → ${relType}\n`);
|
|
86
|
+
}
|
|
87
|
+
process.stdout.write('\n');
|
|
88
|
+
}
|
|
89
|
+
if (govCandidates.length > 0) {
|
|
90
|
+
process.stdout.write(' Governance:\n');
|
|
91
|
+
for (const g of govCandidates) {
|
|
92
|
+
process.stdout.write(` · [${g.severity}] ${g.entryId} "${g.name}"\n`);
|
|
93
|
+
}
|
|
94
|
+
process.stdout.write('\n');
|
|
95
|
+
}
|
|
96
|
+
process.stdout.write(' Run without --suggest-only to create the entry.\n\n');
|
|
97
|
+
}
|
|
98
|
+
/** Prompt the user with a y/N question. Resolves true for "y", false otherwise. */
|
|
99
|
+
export async function promptYN(message) {
|
|
100
|
+
return new Promise((resolve) => {
|
|
101
|
+
process.stderr.write(message);
|
|
102
|
+
process.stdin.once('data', (data) => {
|
|
103
|
+
const answer = data.toString().trim().toLowerCase();
|
|
104
|
+
resolve(answer === 'y');
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=captureGrounding.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"captureGrounding.js","sourceRoot":"","sources":["../../src/lib/captureGrounding.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Filters a workspace-declared `valid_relation_types` array down to verbs `pb relate`'s
|
|
2
|
+
* generic door can actually create toward the given target. `targetIsDomain` should be
|
|
3
|
+
* `true` when the link target entry's canonicalKey is 'domain'; `sourceIsStrategy` should be
|
|
4
|
+
* `true` when the entry being captured has canonicalKey 'strategy'. */
|
|
5
|
+
export declare function filterCreatableRelationTypes(declared: unknown, targetIsDomain: boolean, sourceIsStrategy: boolean): string[];
|
|
6
|
+
type TypeRow = {
|
|
7
|
+
data?: {
|
|
8
|
+
canonical_key?: unknown;
|
|
9
|
+
valid_relation_types?: unknown;
|
|
10
|
+
description?: unknown;
|
|
11
|
+
cardinality_rule?: unknown;
|
|
12
|
+
} | null;
|
|
13
|
+
status?: string;
|
|
14
|
+
};
|
|
15
|
+
/** Resolves the declared `valid_relation_types` for `canonicalKey` out of a semantic-types
|
|
16
|
+
* listEntries result the SAME way loadTypeMap does (convex/chain/semanticTypes.ts:81-99):
|
|
17
|
+
* trust-accepted AND parsable rows only, and when duplicate canonical_key rows exist (a
|
|
18
|
+
* supported state — backfillTypeRegistryReconcile.test.ts:175-199 exercises an active
|
|
19
|
+
* duplicate) the LAST such match in listEntries' query order wins, mirroring loadTypeMap's
|
|
20
|
+
* Map.set()-overwrite-per-match loop over the same by_collection-indexed query — a malformed
|
|
21
|
+
* duplicate is skipped entirely rather than overwriting an earlier valid row (bcRICo). Then
|
|
22
|
+
* filters to what `pb relate` can create. */
|
|
23
|
+
export declare function resolveCreatableRelationTypes(typeRows: readonly TypeRow[] | null | undefined, canonicalKey: string, targetIsDomain: boolean): string[];
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=legalRelationTypes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legalRelationTypes.d.ts","sourceRoot":"","sources":["../../src/lib/legalRelationTypes.ts"],"names":[],"mappings":"AAgDA;;;wEAGwE;AACxE,wBAAgB,4BAA4B,CAAC,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,gBAAgB,EAAE,OAAO,GAAG,MAAM,EAAE,CAS5H;AAQD,KAAK,OAAO,GAAG;IACb,IAAI,CAAC,EAAE;QAAE,aAAa,CAAC,EAAE,OAAO,CAAC;QAAC,oBAAoB,CAAC,EAAE,OAAO,CAAC;QAAC,WAAW,CAAC,EAAE,OAAO,CAAC;QAAC,gBAAgB,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;IAC7H,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAcF;;;;;;;8CAO8C;AAC9C,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,SAAS,OAAO,EAAE,GAAG,IAAI,GAAG,SAAS,EAC/C,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,OAAO,GACtB,MAAM,EAAE,CASV"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WP-688 S4 review round 5 (bdB5K, cQFZ_): `pb capture`'s --link-type refusal door
|
|
3
|
+
* (commands/capture.ts) lists an entry's declared legal relation verbs as a `pb relate`
|
|
4
|
+
* recovery hint. "Declared" (the workspace's own semantic-type row, `valid_relation_types`)
|
|
5
|
+
* is NOT the same set as "creatable via pb relate's generic door" — guardRelation
|
|
6
|
+
* (convex/lib/guards.ts) hard-refuses some declared verbs outright:
|
|
7
|
+
* - replaces / do_not_confuse_with: always refused, routed to a different command
|
|
8
|
+
* (guards.ts:309-322).
|
|
9
|
+
* - Any verb outside the kernel ALLOWED_RELATION_TYPES set: refused regardless of what a
|
|
10
|
+
* workspace's own type row declares (guards.ts:302-307) — registry reconciliation
|
|
11
|
+
* deliberately preserves a customized `valid_relation_types` value even when it contains
|
|
12
|
+
* a verb the kernel allowlist doesn't recognize (registryReconcile.test.ts:131-147), so
|
|
13
|
+
* this is a supported persisted state, not malformed data.
|
|
14
|
+
* - belongs_to / authority_domain TOWARD a domain-tagged target (target canonicalKey ===
|
|
15
|
+
* 'domain'): requires ratification metadata (stagingEntryId + source) `pb relate` cannot
|
|
16
|
+
* supply (guards.ts:349-363).
|
|
17
|
+
* - anchored_to FROM a non-strategy source: its entire meaning is strategy-scope-anchor
|
|
18
|
+
* (WP-641 S2a) — predictStrategyAnchorViolation unconditionally rejects it whenever the
|
|
19
|
+
* source canonicalKey isn't 'strategy' (singletonCardinality.ts:339-341), regardless of
|
|
20
|
+
* target (round-5 finding bcRgRI).
|
|
21
|
+
* Centralized here so the filter isn't duplicated (or drifts) if another connector ever needs
|
|
22
|
+
* the same "legal AND creatable" list.
|
|
23
|
+
*
|
|
24
|
+
* WP-688 S4 review round 5 (bcQWqA): ALLOWED_RELATION_TYPES is read at RUNTIME (a filter, not a
|
|
25
|
+
* type check), so it cannot come from a bare `kernel/entries/relationTypes` value import —
|
|
26
|
+
* `kernel` is a devDependency-only, unpublished workspace package (present locally via monorepo
|
|
27
|
+
* linking, absent from the published `@productbrain/cli` npm package), so that import resolves
|
|
28
|
+
* here in dev/test but throws ERR_MODULE_NOT_FOUND for every real npm-installed `pb` command
|
|
29
|
+
* (index.ts statically imports capture.ts, which statically imports this file). Import the
|
|
30
|
+
* generated, CLI-owned copy instead — same pattern as sourceSurfaces.generated.ts (see
|
|
31
|
+
* scripts/generate-kernel-value-sets.mjs's header for the full rationale + retirement rule).
|
|
32
|
+
*/
|
|
33
|
+
import { ALLOWED_RELATION_TYPES as ALLOWED_RELATION_TYPES_LIST } from '../generated/relationTypes.generated.js';
|
|
34
|
+
const ALLOWED_RELATION_TYPES = new Set(ALLOWED_RELATION_TYPES_LIST);
|
|
35
|
+
/** Verbs guardRelation refuses outright regardless of ALLOWED_RELATION_TYPES membership — each
|
|
36
|
+
* routes to a different, specialized command instead of the generic relation door. */
|
|
37
|
+
const DIRECT_DOOR_BLOCKED = new Set(['replaces', 'do_not_confuse_with']);
|
|
38
|
+
/** Domain-tag verbs guardRelation only accepts via ratification metadata (guards.ts:349-363) —
|
|
39
|
+
* `pb relate` cannot supply it, so never recommend these toward a domain-tagged target. */
|
|
40
|
+
const DOMAIN_TAG_VERBS = new Set(['belongs_to', 'authority_domain']);
|
|
41
|
+
/** anchored_to only exists as a strategy-scope-anchor verb (WP-641 S2a) — never legal from a
|
|
42
|
+
* non-strategy source, regardless of target (bcRgRI). */
|
|
43
|
+
const STRATEGY_ONLY_VERBS = new Set(['anchored_to']);
|
|
44
|
+
/** Filters a workspace-declared `valid_relation_types` array down to verbs `pb relate`'s
|
|
45
|
+
* generic door can actually create toward the given target. `targetIsDomain` should be
|
|
46
|
+
* `true` when the link target entry's canonicalKey is 'domain'; `sourceIsStrategy` should be
|
|
47
|
+
* `true` when the entry being captured has canonicalKey 'strategy'. */
|
|
48
|
+
export function filterCreatableRelationTypes(declared, targetIsDomain, sourceIsStrategy) {
|
|
49
|
+
if (!Array.isArray(declared))
|
|
50
|
+
return [];
|
|
51
|
+
return declared.filter((t) => typeof t === 'string'
|
|
52
|
+
&& !DIRECT_DOOR_BLOCKED.has(t)
|
|
53
|
+
&& ALLOWED_RELATION_TYPES.has(t)
|
|
54
|
+
&& !(targetIsDomain && DOMAIN_TAG_VERBS.has(t))
|
|
55
|
+
&& !(!sourceIsStrategy && STRATEGY_ONLY_VERBS.has(t)));
|
|
56
|
+
}
|
|
57
|
+
/** Trust-accepted statuses (statusStateMachine.ts:67-69's isTrustAccepted, inlined rather than
|
|
58
|
+
* imported — same devDependency-only/unpublished-kernel constraint as ALLOWED_RELATION_TYPES). */
|
|
59
|
+
function isTrustAcceptedStatus(status) {
|
|
60
|
+
return status === 'accepted' || status === 'active';
|
|
61
|
+
}
|
|
62
|
+
/** Mirrors parseSemanticTypeDefData's validity rule (kernel/entries/semanticTypes.ts:65-77) —
|
|
63
|
+
* loadTypeMap skips a malformed row (missing/non-string description, or a cardinality_rule
|
|
64
|
+
* outside the 3-value enum) rather than letting it win, even when it's the LAST trust-accepted
|
|
65
|
+
* duplicate (round-5 finding bcRICo). Inlined rather than imported: same devDependency-only/
|
|
66
|
+
* unpublished-kernel constraint as ALLOWED_RELATION_TYPES above. */
|
|
67
|
+
function isParsableSemanticTypeRow(data) {
|
|
68
|
+
return typeof data?.description === 'string'
|
|
69
|
+
&& (data.cardinality_rule === 'singleton_per_workspace'
|
|
70
|
+
|| data.cardinality_rule === 'singleton_per_scope'
|
|
71
|
+
|| data.cardinality_rule === 'multiple');
|
|
72
|
+
}
|
|
73
|
+
/** Resolves the declared `valid_relation_types` for `canonicalKey` out of a semantic-types
|
|
74
|
+
* listEntries result the SAME way loadTypeMap does (convex/chain/semanticTypes.ts:81-99):
|
|
75
|
+
* trust-accepted AND parsable rows only, and when duplicate canonical_key rows exist (a
|
|
76
|
+
* supported state — backfillTypeRegistryReconcile.test.ts:175-199 exercises an active
|
|
77
|
+
* duplicate) the LAST such match in listEntries' query order wins, mirroring loadTypeMap's
|
|
78
|
+
* Map.set()-overwrite-per-match loop over the same by_collection-indexed query — a malformed
|
|
79
|
+
* duplicate is skipped entirely rather than overwriting an earlier valid row (bcRICo). Then
|
|
80
|
+
* filters to what `pb relate` can create. */
|
|
81
|
+
export function resolveCreatableRelationTypes(typeRows, canonicalKey, targetIsDomain) {
|
|
82
|
+
let declared;
|
|
83
|
+
for (const row of typeRows ?? []) {
|
|
84
|
+
if (row.data?.canonical_key !== canonicalKey)
|
|
85
|
+
continue;
|
|
86
|
+
if (!isTrustAcceptedStatus(row.status))
|
|
87
|
+
continue;
|
|
88
|
+
if (!isParsableSemanticTypeRow(row.data))
|
|
89
|
+
continue;
|
|
90
|
+
declared = row.data?.valid_relation_types;
|
|
91
|
+
}
|
|
92
|
+
return filterCreatableRelationTypes(declared, targetIsDomain, canonicalKey === 'strategy');
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=legalRelationTypes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"legalRelationTypes.js","sourceRoot":"","sources":["../../src/lib/legalRelationTypes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAAE,sBAAsB,IAAI,2BAA2B,EAAE,MAAM,yCAAyC,CAAC;AAEhH,MAAM,sBAAsB,GAAwB,IAAI,GAAG,CAAC,2BAA2B,CAAC,CAAC;AAEzF;uFACuF;AACvF,MAAM,mBAAmB,GAAwB,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,qBAAqB,CAAC,CAAC,CAAC;AAE9F;4FAC4F;AAC5F,MAAM,gBAAgB,GAAwB,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,kBAAkB,CAAC,CAAC,CAAC;AAE1F;0DAC0D;AAC1D,MAAM,mBAAmB,GAAwB,IAAI,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;AAE1E;;;wEAGwE;AACxE,MAAM,UAAU,4BAA4B,CAAC,QAAiB,EAAE,cAAuB,EAAE,gBAAyB;IAChH,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;QAAE,OAAO,EAAE,CAAC;IACxC,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CACxC,OAAO,CAAC,KAAK,QAAQ;WAClB,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC;WAC3B,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC;WAC7B,CAAC,CAAC,cAAc,IAAI,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;WAC5C,CAAC,CAAC,CAAC,gBAAgB,IAAI,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CACtD,CAAC;AACJ,CAAC;AAED;mGACmG;AACnG,SAAS,qBAAqB,CAAC,MAA0B;IACvD,OAAO,MAAM,KAAK,UAAU,IAAI,MAAM,KAAK,QAAQ,CAAC;AACtD,CAAC;AAOD;;;;qEAIqE;AACrE,SAAS,yBAAyB,CAAC,IAAqB;IACtD,OAAO,OAAO,IAAI,EAAE,WAAW,KAAK,QAAQ;WACvC,CAAC,IAAI,CAAC,gBAAgB,KAAK,yBAAyB;eAClD,IAAI,CAAC,gBAAgB,KAAK,qBAAqB;eAC/C,IAAI,CAAC,gBAAgB,KAAK,UAAU,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;;;8CAO8C;AAC9C,MAAM,UAAU,6BAA6B,CAC3C,QAA+C,EAC/C,YAAoB,EACpB,cAAuB;IAEvB,IAAI,QAAiB,CAAC;IACtB,KAAK,MAAM,GAAG,IAAI,QAAQ,IAAI,EAAE,EAAE,CAAC;QACjC,IAAI,GAAG,CAAC,IAAI,EAAE,aAAa,KAAK,YAAY;YAAE,SAAS;QACvD,IAAI,CAAC,qBAAqB,CAAC,GAAG,CAAC,MAAM,CAAC;YAAE,SAAS;QACjD,IAAI,CAAC,yBAAyB,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QACnD,QAAQ,GAAG,GAAG,CAAC,IAAI,EAAE,oBAAoB,CAAC;IAC5C,CAAC;IACD,OAAO,4BAA4B,CAAC,QAAQ,EAAE,cAAc,EAAE,YAAY,KAAK,UAAU,CAAC,CAAC;AAC7F,CAAC"}
|
|
@@ -14,7 +14,7 @@ export function registerEntryCommands(program) {
|
|
|
14
14
|
.option('-c, --collection <slug>', 'Explicit collection (skip auto-classification)')
|
|
15
15
|
.option('-f, --field <key=value>', 'Set a data field (repeatable; e.g. rationale="...")', (val, prev) => [...prev, val], [])
|
|
16
16
|
.option('-l, --link <entry-id>', 'Link new entry to an existing entry (TEN-705)')
|
|
17
|
-
.option('-t, --type <relation-type>', 'Relation type for --link (
|
|
17
|
+
.option('-t, --link-type <relation-type>', 'Relation type for --link — REQUIRED when --link is used (WP-688 S4): no default, the door refuses and lists the source entry\'s legal verbs if omitted')
|
|
18
18
|
.option('--source-ref <ref>', 'Source reference URI (BET-240 E2)')
|
|
19
19
|
.option('--source-excerpt <text>', 'Verbatim source excerpt (BET-240 E2)')
|
|
20
20
|
.option('--draft', 'Force the entry to draft regardless of workspace governance mode (TEN-2226)')
|
|
@@ -35,7 +35,7 @@ export function registerEntryCommands(program) {
|
|
|
35
35
|
}
|
|
36
36
|
await runCapture({
|
|
37
37
|
text: text || opts.name || '', name: opts.name, description: opts.description, collection: opts.collection,
|
|
38
|
-
field: opts.field, link: opts.link,
|
|
38
|
+
field: opts.field, link: opts.link, linkType: opts.linkType, sourceRef: opts.sourceRef, sourceExcerpt: opts.sourceExcerpt,
|
|
39
39
|
draft: opts.draft, json: opts.json, suggestOnly: opts.suggestOnly, strict: opts.strict,
|
|
40
40
|
ownerTeam: opts.ownerTeam, ownerRole: opts.ownerRole,
|
|
41
41
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registerEntryCommands.js","sourceRoot":"","sources":["../src/registerEntryCommands.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAE9D,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,MAAM,QAAQ,GAAG,OAAO;SACrB,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,kFAAkF,CAAC,CAAC;IAEnG,QAAQ;SACL,OAAO,CAAC,mBAAmB,CAAC;SAC5B,WAAW,CAAC,kFAAkF,CAAC;SAC/F,MAAM,CAAC,mBAAmB,EAAE,uCAAuC,CAAC;SACpE,MAAM,CAAC,0BAA0B,EAAE,8CAA8C,CAAC;SAClF,MAAM,CAAC,yBAAyB,EAAE,gDAAgD,CAAC;SACnF,MAAM,CAAC,yBAAyB,EAAE,qDAAqD,EAAE,CAAC,GAAW,EAAE,IAAc,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,EAAE,EAAc,CAAC;SACzJ,MAAM,CAAC,uBAAuB,EAAE,+CAA+C,CAAC;SAChF,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"registerEntryCommands.js","sourceRoot":"","sources":["../src/registerEntryCommands.ts"],"names":[],"mappings":"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"}
|