@cavelang/canonical 0.1.0

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/README.md ADDED
@@ -0,0 +1,100 @@
1
+ # @cavelang/canonical
2
+
3
+ The CAVE semantic layer: verb registry, the §13.4 canonicalization
4
+ pipeline, the shared standard prelude, and the canonical emitter. Sits
5
+ between `@cavelang/parser` (pure syntax) and `@cavelang/store` (persistence).
6
+
7
+ ```ts
8
+ import { canonicalizeText, standardRegistry, emit } from '@cavelang/canonical'
9
+ import { Key } from '@cavelang/core'
10
+
11
+ const result = canonicalizeText('packages/api PART-OF monorepo', standardRegistry)
12
+ result.claims[0].claim.verb // 'CONTAINS' — primary direction
13
+ result.claims[0].claim.raw // 'packages/api PART-OF monorepo' — as written
14
+ emit(result) // 'monorepo CONTAINS packages/api\n'
15
+ ```
16
+
17
+ ## Registry (spec §5.5)
18
+
19
+ Inverse pairs are declared in-band — `CONTAINS REVERSE PART-OF` is an
20
+ ordinary claim whose subject and object happen to be verbs. The registry is
21
+ an immutable value threaded through the pipeline, so a declaration takes
22
+ effect for *subsequent* lines only. Rules:
23
+
24
+ - the **primary** is the left side of the first declaration;
25
+ - redeclaring the mirror is a no-op;
26
+ - a conflicting declaration is rejected with a problem — first wins;
27
+ - no verb is born with an inverse; `standardRegistry` (and the equivalent
28
+ `standardPrelude` CAVE text) carries the eight §5.5 pairs as the "shared
29
+ prelude" the spec allows.
30
+
31
+ ## Pipeline (spec §13.4)
32
+
33
+ `canonicalize(document, registry?)` → `{ claims, edges, registry, problems }`
34
+
35
+ - **Inverse resolution**: a relational claim with an inverse verb swaps
36
+ subject/object and takes the primary verb *before* keying — a forward
37
+ claim and its inverse reading share one `Key.of` value: one fact, two
38
+ names, one belief series. `raw` keeps the author's text.
39
+ - **Continuations** (§8.3): a bare-verb line inherits the parent's subject
40
+ *as written*; if the verb is an inverse, canonicalization then flips it.
41
+ Continuations are independent sibling claims — no edges.
42
+ - **Qualifiers** (§8.1–8.2): `WHEN`/`VIA`/`BECAUSE` lines become claim
43
+ nodes joined to the parent by role edges. `UNLESS x` normalizes to
44
+ role `WHEN` + negated condition. Condition shapes:
45
+ - bare entity → `x EXISTS` claim (negated for `NOT x`);
46
+ - comparison → `left EXCEEDS value` (metric payload); `>`→`EXCEEDS`,
47
+ other operators keep their symbol as the verb;
48
+ - full claim → canonicalized as usual (inverse resolution applies).
49
+ - **Grouped claims** (§8.4): indented full triples stay independent and
50
+ link to their parent with the `QUALIFIES` edge role (§13.2's role list).
51
+ - **Declarations**: `A REVERSE B` and `X IS verb` claims update the
52
+ registry after the line itself is canonicalized.
53
+
54
+ ## Emitter
55
+
56
+ `emit(result)` produces canonical text — the spec's MUSTs for emitters:
57
+
58
+ - colon attribute form (`revenue: 20B USD/yr`), even when the input used
59
+ the legacy colonless form (§3.4);
60
+ - primary verb direction (§5.5);
61
+ - `WHEN NOT x`, never `UNLESS` (§8.2);
62
+ - §3.2 anatomy order: payload, `+/- delta`, `(Nσ)`, contexts, tags,
63
+ `@ N%` (omitted at 100%), `!`, `; comment`.
64
+
65
+ Emission is stable: `emit ∘ canonicalize ∘ emit ≡ emit`, and claim keys
66
+ survive the round trip (tested).
67
+
68
+ ## Design decisions
69
+
70
+ - **"As written" inheritance**: a continuation under an inverse-form parent
71
+ (`packages/api PART-OF monorepo` + ` CONTAINS x`) inherits the parent's
72
+ *written* subject (`packages/api`), matching §8.3's mechanical rule, then
73
+ canonicalizes independently — including in-band declarations, which work
74
+ from continuations exactly as from full lines (§5.4).
75
+ - **The inverse swap re-classifies endpoints symmetrically**: a date/number
76
+ endpoint is a metric payload in one direction and a subject term in the
77
+ other, so `deploy PRECEDES 2026-01-01` and `2026-01-01 FOLLOWS deploy`
78
+ land on one claim key. Qualifier negation always emits as the `WHEN NOT …`
79
+ prefix — a claim-internal `VERB NOT` after a symbolic comparison operator
80
+ would invert the condition on reparse.
81
+ - **Undeclared inverse continuations** (§8.3 calls them ill-formed) cannot
82
+ be *detected* — `PART-OF` without a declaration is just an unknown verb,
83
+ so the line canonicalizes forward with the inherited subject. Loading the
84
+ standard prelude first gives the intended reading.
85
+ - **Comparison verbs**: only `>` has a standard verb (`EXCEEDS`); `<`,
86
+ `>=`, `<=`, `=`, `!=` keep their symbol as the stored verb. They appear
87
+ only as condition claims.
88
+ - **Three-way negation XOR** for qualifier conditions: inner `NOT`,
89
+ qualifier-level `NOT`, and `UNLESS` each flip the condition's negation.
90
+
91
+ ## Tests
92
+
93
+ ```
94
+ pnpm --filter @cavelang/canonical test
95
+ ```
96
+
97
+ Covers the §5.5 inverse semantics (shared keys, negation riding the row,
98
+ belief series through either name), §8.3 continuation table, §8.2
99
+ equivalent forms, the §21 worked example including its inverse reads, and
100
+ emitter round-trip stability.
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Canonicalization pipeline (spec §13.4).
3
+ *
4
+ * Turns a parsed document into canonical claims plus qualifier edges:
5
+ *
6
+ * 1. verbs are already uppercase (parser enforces the lexical shape);
7
+ * 2. inverse verbs swap subject/object and substitute the primary (§5.5);
8
+ * 3. continuation lines fill their inherited endpoint from the parent (§8.3);
9
+ * 4. entity whitespace normalizes to `-`, proper-noun casing preserved;
10
+ * 5. `raw` keeps the line exactly as written;
11
+ * 6–10. confidence, `~`, multipliers, tag splitting are handled by the
12
+ * parser and `@cavelang/core`;
13
+ * 11. claim keys are computed on the canonical form (`Key.of`);
14
+ * 12. contexts/tags ride on each claim for the store's side tables.
15
+ *
16
+ * Qualifier lines become claim nodes joined to their parent by edges
17
+ * (§8.1); `UNLESS x` normalizes to `WHEN` + negated condition (§8.2);
18
+ * grouped full claims link to their parent with the `QUALIFIES` role
19
+ * (§13.2). `REVERSE` and extension-verb declarations update the registry
20
+ * in-band, affecting subsequent lines (§5.4, §5.5).
21
+ */
22
+ import { Claim } from '@cavelang/core';
23
+ import { type Ast } from '@cavelang/parser';
24
+ import * as Registry from './registry.ts';
25
+ /** Edge roles persisted in `cave_edge` (spec §13.2). */
26
+ export type EdgeRole = 'WHEN' | 'VIA' | 'BECAUSE' | 'QUALIFIES';
27
+ /** A canonical claim with its 1-based source line. */
28
+ export type Entry = {
29
+ readonly claim: Claim.t;
30
+ readonly line: number;
31
+ };
32
+ /** Edge between claim indices (into `Result.claims`). */
33
+ export type Edge = {
34
+ readonly parent: number;
35
+ readonly role: EdgeRole;
36
+ readonly child: number;
37
+ };
38
+ export type Problem = {
39
+ readonly line: number;
40
+ readonly message: string;
41
+ };
42
+ export type Result = {
43
+ readonly claims: readonly Entry[];
44
+ readonly edges: readonly Edge[];
45
+ /** Registry after processing — input registry plus in-band declarations. */
46
+ readonly registry: Registry.t;
47
+ readonly problems: readonly Problem[];
48
+ };
49
+ /** Canonicalizes a parsed document. */
50
+ export declare const canonicalize: (document: Ast.Document, registry?: Registry.t) => Result;
51
+ /**
52
+ * Parses and canonicalizes CAVE text in one step. Parser diagnostics merge
53
+ * into `problems`.
54
+ */
55
+ export declare const canonicalizeText: (input: string, registry?: Registry.t) => Result;
56
+ //# sourceMappingURL=canonicalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonicalize.d.ts","sourceRoot":"","sources":["../../src/canonicalize.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,OAAO,EAAE,KAAK,EAAuB,MAAM,gBAAgB,CAAA;AAC3D,OAAO,EAAiB,KAAK,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAC1D,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AAEzC,wDAAwD;AACxD,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,GAAG,WAAW,CAAA;AAE/D,sDAAsD;AACtD,MAAM,MAAM,KAAK,GAAG;IAClB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,yDAAyD;AACzD,MAAM,MAAM,IAAI,GAAG;IACjB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;IACvB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,MAAM,GAAG;IACnB,QAAQ,CAAC,MAAM,EAAE,SAAS,KAAK,EAAE,CAAA;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,IAAI,EAAE,CAAA;IAC/B,4EAA4E;IAC5E,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAA;IAC7B,QAAQ,CAAC,QAAQ,EAAE,SAAS,OAAO,EAAE,CAAA;CACtC,CAAA;AAwDD,uCAAuC;AACvC,eAAO,MAAM,YAAY,GAAI,UAAU,GAAG,CAAC,QAAQ,EAAE,WAAU,QAAQ,CAAC,CAAkB,KAAG,MA8I5F,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,EAAE,WAAU,QAAQ,CAAC,CAAkB,KAAG,MAavF,CAAA"}
@@ -0,0 +1,227 @@
1
+ /**
2
+ * Canonicalization pipeline (spec §13.4).
3
+ *
4
+ * Turns a parsed document into canonical claims plus qualifier edges:
5
+ *
6
+ * 1. verbs are already uppercase (parser enforces the lexical shape);
7
+ * 2. inverse verbs swap subject/object and substitute the primary (§5.5);
8
+ * 3. continuation lines fill their inherited endpoint from the parent (§8.3);
9
+ * 4. entity whitespace normalizes to `-`, proper-noun casing preserved;
10
+ * 5. `raw` keeps the line exactly as written;
11
+ * 6–10. confidence, `~`, multipliers, tag splitting are handled by the
12
+ * parser and `@cavelang/core`;
13
+ * 11. claim keys are computed on the canonical form (`Key.of`);
14
+ * 12. contexts/tags ride on each claim for the store's side tables.
15
+ *
16
+ * Qualifier lines become claim nodes joined to their parent by edges
17
+ * (§8.1); `UNLESS x` normalizes to `WHEN` + negated condition (§8.2);
18
+ * grouped full claims link to their parent with the `QUALIFIES` role
19
+ * (§13.2). `REVERSE` and extension-verb declarations update the registry
20
+ * in-band, affecting subsequent lines (§5.4, §5.5).
21
+ */
22
+ import { Claim, Entity, Value, Verb } from '@cavelang/core';
23
+ import { parseDocument } from '@cavelang/parser';
24
+ import * as Registry from "./registry.js";
25
+ const roleOf = {
26
+ WHEN: 'WHEN',
27
+ UNLESS: 'WHEN',
28
+ VIA: 'VIA',
29
+ BECAUSE: 'BECAUSE'
30
+ };
31
+ /** `>` maps to the standard `EXCEEDS`; other operators keep their symbol. */
32
+ const comparisonVerb = (op) => op === '>' ? 'EXCEEDS' : op;
33
+ const normalizeTerm = (term) => term.kind === 'entity' ? Claim.entity(Entity.normalize(term.text)) : term;
34
+ /**
35
+ * Term ↔ payload conversion for the §5.5 inverse swap. The parser
36
+ * classifies a date/number endpoint as a metric payload but a subject is
37
+ * always a term; swapping must re-classify both directions the same way,
38
+ * or `deploy PRECEDES 2026-01-01` and `2026-01-01 FOLLOWS deploy` would
39
+ * key differently — two keys for one fact.
40
+ */
41
+ const termOfPayload = (payload) => {
42
+ switch (payload.kind) {
43
+ case 'relation':
44
+ return payload.object;
45
+ case 'metric':
46
+ return payload.value.kind === 'code' ? Claim.code(payload.value.raw) :
47
+ payload.value.kind === 'text' ? Claim.text(payload.value.raw) :
48
+ Claim.entity(Entity.normalize(payload.value.raw));
49
+ default:
50
+ return undefined;
51
+ }
52
+ };
53
+ const payloadOfTerm = (term) => {
54
+ if (term.kind === 'entity') {
55
+ const value = Value.parse(term.text);
56
+ if (value.kind === 'number' || value.kind === 'date') {
57
+ return Claim.metric(value);
58
+ }
59
+ }
60
+ return Claim.relation(term);
61
+ };
62
+ const initOf = (meta) => ({
63
+ contexts: meta.contexts,
64
+ tags: meta.tags,
65
+ importance: meta.importance,
66
+ ...meta.conf !== undefined ? { conf: meta.conf } : {},
67
+ ...meta.delta !== undefined ? { delta: meta.delta } : {},
68
+ ...meta.sigmaLevel !== undefined ? { sigmaLevel: meta.sigmaLevel } : {},
69
+ ...meta.comment !== undefined ? { comment: meta.comment } : {}
70
+ });
71
+ /** Canonicalizes a parsed document. */
72
+ export const canonicalize = (document, registry = Registry.empty) => {
73
+ const claims = [];
74
+ const edges = [];
75
+ const problems = [];
76
+ /** line index → claim index + the subject as (virtually) written, for §8.3 inheritance. */
77
+ const byLine = new Map();
78
+ const problem = (line, message) => {
79
+ problems.push({ line, message });
80
+ };
81
+ /** Canonicalizes one full claim body — §13.4 steps 2 and 4 plus assembly. */
82
+ const buildClaim = (full, raw, line) => {
83
+ const writtenSubject = normalizeTerm(full.subject);
84
+ let subject = writtenSubject;
85
+ let verb = full.verb;
86
+ let payload = full.payload;
87
+ if (payload.kind === 'relation') {
88
+ payload = Claim.relation(normalizeTerm(payload.object));
89
+ }
90
+ const { primary, isInverse } = Registry.primaryOf(registry, verb);
91
+ if (isInverse) {
92
+ const objectTerm = termOfPayload(payload);
93
+ if (objectTerm === undefined) {
94
+ problem(line, `inverse verb ${verb} needs an object to swap with — keeping the line as written (spec §5.5)`);
95
+ }
96
+ else {
97
+ payload = payloadOfTerm(subject);
98
+ subject = objectTerm;
99
+ verb = primary;
100
+ }
101
+ }
102
+ const claim = Claim.of({
103
+ subject,
104
+ verb,
105
+ negated: full.negated,
106
+ payload,
107
+ raw,
108
+ ...initOf(full.meta)
109
+ });
110
+ return { claim, writtenSubject };
111
+ };
112
+ const append = (claim, line, writtenSubject, lineIndex) => {
113
+ const index = claims.length;
114
+ claims.push({ claim, line });
115
+ byLine.set(lineIndex, { index, writtenSubject });
116
+ return index;
117
+ };
118
+ /** In-band declarations take effect for subsequent lines (spec §5.4, §5.5). */
119
+ const applyDeclarations = (claim, line) => {
120
+ if (claim.payload.kind !== 'relation' || claim.negated) {
121
+ return;
122
+ }
123
+ const object = claim.payload.object;
124
+ if (claim.verb === Verb.REVERSE && claim.subject.kind === 'entity' && object.kind === 'entity') {
125
+ const declared = Registry.declareReverse(registry, claim.subject.text, object.text);
126
+ registry = declared.registry;
127
+ if (!declared.ok) {
128
+ problem(line, declared.problem);
129
+ }
130
+ return;
131
+ }
132
+ if (claim.verb === 'IS' && object.kind === 'entity' && object.text === 'verb' &&
133
+ claim.subject.kind === 'entity' && Verb.isVerbToken(claim.subject.text)) {
134
+ registry = Registry.declareVerb(registry, claim.subject.text);
135
+ }
136
+ };
137
+ /** Builds the condition claim of a qualifier line (spec §8.2). */
138
+ const conditionOf = (payload, unless) => {
139
+ switch (payload.kind) {
140
+ case 'claim':
141
+ return {
142
+ ...payload.claim,
143
+ negated: payload.claim.negated !== (payload.negated !== unless)
144
+ };
145
+ case 'entity':
146
+ return {
147
+ subject: payload.term,
148
+ verb: 'EXISTS',
149
+ negated: payload.negated !== unless,
150
+ payload: Claim.none,
151
+ meta: payload.meta
152
+ };
153
+ case 'comparison':
154
+ return {
155
+ subject: payload.left,
156
+ verb: comparisonVerb(payload.op),
157
+ negated: payload.negated !== unless,
158
+ payload: Claim.metric(payload.value),
159
+ meta: payload.meta
160
+ };
161
+ }
162
+ };
163
+ document.lines.forEach((line, lineIndex) => {
164
+ switch (line.kind) {
165
+ case 'claim': {
166
+ const { claim, writtenSubject } = buildClaim(line.claim, line.raw, line.line);
167
+ const index = append(claim, line.line, writtenSubject, lineIndex);
168
+ if (line.parent !== undefined) {
169
+ const parent = byLine.get(line.parent);
170
+ if (parent !== undefined) {
171
+ edges.push({ parent: parent.index, role: 'QUALIFIES', child: index });
172
+ }
173
+ }
174
+ applyDeclarations(claim, line.line);
175
+ return;
176
+ }
177
+ case 'continuation': {
178
+ const parent = byLine.get(line.parent);
179
+ if (parent === undefined) {
180
+ problem(line.line, 'continuation has no canonicalized parent');
181
+ return;
182
+ }
183
+ const full = { subject: parent.writtenSubject, ...line.body };
184
+ const { claim, writtenSubject } = buildClaim(full, line.raw, line.line);
185
+ append(claim, line.line, writtenSubject, lineIndex);
186
+ // §8.3: each continuation is an ordinary independent claim, so an
187
+ // in-band declaration works here exactly as on a full line (§5.4).
188
+ applyDeclarations(claim, line.line);
189
+ return;
190
+ }
191
+ case 'qualifier': {
192
+ const parent = byLine.get(line.parent);
193
+ if (parent === undefined) {
194
+ problem(line.line, 'qualifier has no canonicalized parent');
195
+ return;
196
+ }
197
+ const full = conditionOf(line.payload, line.qualifier === 'UNLESS');
198
+ const { claim, writtenSubject } = buildClaim(full, line.raw, line.line);
199
+ const index = append(claim, line.line, writtenSubject, lineIndex);
200
+ edges.push({ parent: parent.index, role: roleOf[line.qualifier], child: index });
201
+ return;
202
+ }
203
+ default:
204
+ return;
205
+ }
206
+ });
207
+ return { claims, edges, registry, problems };
208
+ };
209
+ /**
210
+ * Parses and canonicalizes CAVE text in one step. Parser diagnostics merge
211
+ * into `problems`.
212
+ */
213
+ export const canonicalizeText = (input, registry = Registry.empty) => {
214
+ const document = parseDocument(input);
215
+ const result = canonicalize(document, registry);
216
+ if (document.diagnostics.length === 0) {
217
+ return result;
218
+ }
219
+ return {
220
+ ...result,
221
+ problems: [
222
+ ...document.diagnostics.map(diagnostic => ({ line: diagnostic.line, message: diagnostic.message })),
223
+ ...result.problems
224
+ ]
225
+ };
226
+ };
227
+ //# sourceMappingURL=canonicalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonicalize.js","sourceRoot":"","sources":["../../src/canonicalize.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Canonical emitter.
3
+ *
4
+ * Emits canonical CAVE text from canonical claims: colon attribute form
5
+ * (§3.4 — emitters MUST produce it), primary verb direction (§5.5),
6
+ * `WHEN NOT` rather than `UNLESS` (§8.2), metadata in the §3.2 anatomy
7
+ * order. Qualifier edges re-indent under their parent; grouped claims
8
+ * (`QUALIFIES` edges) re-indent as full lines.
9
+ */
10
+ import { Claim } from '@cavelang/core';
11
+ import type * as Canonicalize from './canonicalize.ts';
12
+ /** @returns one canonical line for a claim (no indentation). */
13
+ export declare const emitClaim: (claim: Claim.t) => string;
14
+ /**
15
+ * Emits a whole canonicalization result as canonical CAVE text: top-level
16
+ * claims in claim order, children indented two spaces per level.
17
+ */
18
+ export declare const emit: (result: Pick<Canonicalize.Result, "claims" | "edges">) => string;
19
+ //# sourceMappingURL=emit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit.d.ts","sourceRoot":"","sources":["../../src/emit.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,KAAK,EAA0B,MAAM,gBAAgB,CAAA;AAC9D,OAAO,KAAK,KAAK,YAAY,MAAM,mBAAmB,CAAA;AAyCtD,gEAAgE;AAChE,eAAO,MAAM,SAAS,GAAI,OAAO,KAAK,CAAC,CAAC,KAAG,MAW1C,CAAA;AAgBD;;;GAGG;AACH,eAAO,MAAM,IAAI,GAAI,QAAQ,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAG,MA+B5E,CAAA"}
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Canonical emitter.
3
+ *
4
+ * Emits canonical CAVE text from canonical claims: colon attribute form
5
+ * (§3.4 — emitters MUST produce it), primary verb direction (§5.5),
6
+ * `WHEN NOT` rather than `UNLESS` (§8.2), metadata in the §3.2 anatomy
7
+ * order. Qualifier edges re-indent under their parent; grouped claims
8
+ * (`QUALIFIES` edges) re-indent as full lines.
9
+ */
10
+ import { Claim, Confidence, Tag, Value } from '@cavelang/core';
11
+ const payloadText = (payload) => {
12
+ switch (payload.kind) {
13
+ case 'relation':
14
+ return Claim.formatTerm(payload.object);
15
+ case 'attribute':
16
+ return `${payload.attribute}: ${Value.format(payload.value)}`;
17
+ case 'metric':
18
+ return Value.format(payload.value);
19
+ case 'none':
20
+ return undefined;
21
+ }
22
+ };
23
+ const metaText = (claim) => {
24
+ const parts = [];
25
+ if (claim.delta !== undefined) {
26
+ parts.push(`+/- ${Value.format(claim.delta)}`);
27
+ }
28
+ if (claim.sigmaLevel !== undefined) {
29
+ parts.push(`(${claim.sigmaLevel}σ)`);
30
+ }
31
+ for (const context of claim.contexts) {
32
+ parts.push(`@${context}`);
33
+ }
34
+ for (const tag of claim.tags) {
35
+ parts.push(Tag.format(tag));
36
+ }
37
+ if (claim.conf !== 1) {
38
+ parts.push(`@ ${Confidence.format(claim.conf)}`);
39
+ }
40
+ if (claim.importance) {
41
+ parts.push('!');
42
+ }
43
+ if (claim.comment !== undefined) {
44
+ parts.push(`; ${claim.comment}`);
45
+ }
46
+ return parts;
47
+ };
48
+ /** @returns one canonical line for a claim (no indentation). */
49
+ export const emitClaim = (claim) => {
50
+ const parts = [Claim.formatTerm(claim.subject), claim.verb];
51
+ if (claim.negated) {
52
+ parts.push('NOT');
53
+ }
54
+ const payload = payloadText(claim.payload);
55
+ if (payload !== undefined) {
56
+ parts.push(payload);
57
+ }
58
+ parts.push(...metaText(claim));
59
+ return parts.join(' ');
60
+ };
61
+ /**
62
+ * @returns the qualifier-payload text of a condition claim. Negation always
63
+ * emits as a `NOT` *prefix* — the §8.2 canonical `WHEN NOT x` shape — never
64
+ * as the claim-internal `VERB NOT` form: a postfix `NOT` after a symbolic
65
+ * comparison verb (`WHEN cpu >= NOT 900`) would be unreadable to the
66
+ * parser and silently invert the condition on round trip.
67
+ */
68
+ const conditionText = (claim) => {
69
+ const body = claim.verb === 'EXISTS' && claim.payload.kind === 'none' ?
70
+ [Claim.formatTerm(claim.subject), ...metaText(claim)].join(' ') :
71
+ emitClaim({ ...claim, negated: false });
72
+ return claim.negated ? `NOT ${body}` : body;
73
+ };
74
+ /**
75
+ * Emits a whole canonicalization result as canonical CAVE text: top-level
76
+ * claims in claim order, children indented two spaces per level.
77
+ */
78
+ export const emit = (result) => {
79
+ const childEdges = new Map();
80
+ const isChild = new Set();
81
+ for (const edge of result.edges) {
82
+ isChild.add(edge.child);
83
+ const existing = childEdges.get(edge.parent);
84
+ if (existing === undefined) {
85
+ childEdges.set(edge.parent, [edge]);
86
+ }
87
+ else {
88
+ existing.push(edge);
89
+ }
90
+ }
91
+ const lines = [];
92
+ const emitAt = (index, depth, role) => {
93
+ const { claim } = result.claims[index];
94
+ const indent = ' '.repeat(depth);
95
+ if (role === undefined || role === 'QUALIFIES') {
96
+ lines.push(`${indent}${emitClaim(claim)}`);
97
+ }
98
+ else {
99
+ lines.push(`${indent}${role} ${conditionText(claim)}`);
100
+ }
101
+ for (const edge of childEdges.get(index) ?? []) {
102
+ emitAt(edge.child, depth + 1, edge.role);
103
+ }
104
+ };
105
+ result.claims.forEach((_, index) => {
106
+ if (!isChild.has(index)) {
107
+ emitAt(index, 0, undefined);
108
+ }
109
+ });
110
+ return lines.length === 0 ? '' : `${lines.join('\n')}\n`;
111
+ };
112
+ //# sourceMappingURL=emit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"emit.js","sourceRoot":"","sources":["../../src/emit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * `@cavelang/canonical` — the CAVE semantic layer (spec §5.4, §5.5, §8, §13.4).
3
+ *
4
+ * Verb registry with in-band `REVERSE`/extension declarations, the
5
+ * canonicalization pipeline (inverse resolution, continuation expansion,
6
+ * qualifier edges, `UNLESS` normalization), the shared standard prelude and
7
+ * the canonical emitter.
8
+ *
9
+ * ```ts
10
+ * import { canonicalizeText, standardRegistry, emit } from '@cavelang/canonical'
11
+ *
12
+ * const result = canonicalizeText('packages/api PART-OF monorepo', standardRegistry)
13
+ * result.claims[0].claim // monorepo CONTAINS packages/api — one fact, two names
14
+ * emit(result) // canonical text, primary direction
15
+ * ```
16
+ */
17
+ export * as Registry from './registry.ts';
18
+ export { canonicalize, canonicalizeText } from './canonicalize.ts';
19
+ export type { Edge, EdgeRole, Entry, Problem, Result } from './canonicalize.ts';
20
+ export { emit, emitClaim } from './emit.ts';
21
+ export { standardPrelude, standardRegistry } from './prelude.ts';
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAClE,YAAY,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAA;AAC/E,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * `@cavelang/canonical` — the CAVE semantic layer (spec §5.4, §5.5, §8, §13.4).
3
+ *
4
+ * Verb registry with in-band `REVERSE`/extension declarations, the
5
+ * canonicalization pipeline (inverse resolution, continuation expansion,
6
+ * qualifier edges, `UNLESS` normalization), the shared standard prelude and
7
+ * the canonical emitter.
8
+ *
9
+ * ```ts
10
+ * import { canonicalizeText, standardRegistry, emit } from '@cavelang/canonical'
11
+ *
12
+ * const result = canonicalizeText('packages/api PART-OF monorepo', standardRegistry)
13
+ * result.claims[0].claim // monorepo CONTAINS packages/api — one fact, two names
14
+ * emit(result) // canonical text, primary direction
15
+ * ```
16
+ */
17
+ export * as Registry from "./registry.js";
18
+ export { canonicalize, canonicalizeText } from "./canonicalize.js";
19
+ export { emit, emitClaim } from "./emit.js";
20
+ export { standardPrelude, standardRegistry } from "./prelude.js";
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAElE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,WAAW,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The shared standard prelude (spec §5.5).
3
+ *
4
+ * Standard verbs SHOULD carry inverse declarations; emitters MAY prepend
5
+ * them to a document or keep them in a shared prelude. This module is that
6
+ * shared prelude: the spec's declaration block as CAVE text, plus a
7
+ * pre-built registry for callers that want inverse-aware reads without
8
+ * ingesting the text first.
9
+ */
10
+ import * as Registry from './registry.ts';
11
+ /** The spec §5.5 declaration block, verbatim. */
12
+ export declare const standardPrelude = "REVERSE IS verb ; declares that two verbs name the same edge read in opposite directions\nREVERSE HAS arity: 2\nCONTAINS REVERSE PART-OF\nCAUSE REVERSE CAUSED-BY\nPRECEDES REVERSE FOLLOWS\nUSES REVERSE USED-BY\nNEEDS REVERSE NEEDED-BY\nENABLES REVERSE ENABLED-BY\nBLOCKS REVERSE BLOCKED-BY\nEXTENDS REVERSE EXTENDED-BY\n";
13
+ /** Registry with the standard §5.5 inverse pairs declared. */
14
+ export declare const standardRegistry: Registry.t;
15
+ //# sourceMappingURL=prelude.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prelude.d.ts","sourceRoot":"","sources":["../../src/prelude.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAA;AAEzC,iDAAiD;AACjD,eAAO,MAAM,eAAe,qUAU3B,CAAA;AAaD,8DAA8D;AAC9D,eAAO,MAAM,gBAAgB,EAAE,QAAQ,CAAC,CAIa,CAAA"}