typeglish 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.
Files changed (51) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +13 -0
  3. package/README.md +301 -0
  4. package/dist/chunk-3NQ3VYO6.js +566 -0
  5. package/dist/chunk-3NQ3VYO6.js.map +1 -0
  6. package/dist/chunk-KRYC4OTL.js +3573 -0
  7. package/dist/chunk-KRYC4OTL.js.map +1 -0
  8. package/dist/chunk-NLQIL5WD.js +25 -0
  9. package/dist/chunk-NLQIL5WD.js.map +1 -0
  10. package/dist/chunk-PR4QN5HX.js +39 -0
  11. package/dist/chunk-PR4QN5HX.js.map +1 -0
  12. package/dist/chunk-PXAMTGYY.js +3 -0
  13. package/dist/chunk-PXAMTGYY.js.map +1 -0
  14. package/dist/chunk-VMACILYN.js +140 -0
  15. package/dist/chunk-VMACILYN.js.map +1 -0
  16. package/dist/chunk-Y64EAEYB.js +10919 -0
  17. package/dist/chunk-Y64EAEYB.js.map +1 -0
  18. package/dist/chunk-YH4ZLQ4G.js +4260 -0
  19. package/dist/chunk-YH4ZLQ4G.js.map +1 -0
  20. package/dist/chunk-ZKMHZHID.js +56 -0
  21. package/dist/chunk-ZKMHZHID.js.map +1 -0
  22. package/dist/cli.d.ts +1 -0
  23. package/dist/cli.js +447 -0
  24. package/dist/cli.js.map +1 -0
  25. package/dist/compile-DViQS2oG.d.ts +310 -0
  26. package/dist/diagnostics-BWJ_oMd8.d.ts +49 -0
  27. package/dist/exhaustiveness-VBVWCX5W.js +123 -0
  28. package/dist/exhaustiveness-VBVWCX5W.js.map +1 -0
  29. package/dist/index-Df_QnTgq.d.ts +313 -0
  30. package/dist/index.d.ts +3 -0
  31. package/dist/index.js +7 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/mcp.d.ts +11 -0
  34. package/dist/mcp.js +36378 -0
  35. package/dist/mcp.js.map +1 -0
  36. package/dist/monaco.css +46 -0
  37. package/dist/monaco.d.ts +43 -0
  38. package/dist/monaco.js +971 -0
  39. package/dist/monaco.js.map +1 -0
  40. package/dist/node.d.ts +21 -0
  41. package/dist/node.js +8 -0
  42. package/dist/node.js.map +1 -0
  43. package/dist/spell-node.d.ts +8 -0
  44. package/dist/spell-node.js +23 -0
  45. package/dist/spell-node.js.map +1 -0
  46. package/dist/spell.d.ts +18 -0
  47. package/dist/spell.js +4 -0
  48. package/dist/spell.js.map +1 -0
  49. package/dist/z3-MWU3GSVT.js +5 -0
  50. package/dist/z3-MWU3GSVT.js.map +1 -0
  51. package/package.json +160 -0
@@ -0,0 +1,25 @@
1
+ import { structuralDiagnostics, numericDiagnostics, report } from './chunk-KRYC4OTL.js';
2
+
3
+ // src/core/report-full.ts
4
+ var MissingSolverError = class extends Error {
5
+ constructor(cause) {
6
+ super('reportFull needs the optional peer dependency "z3-solver" for the Z3 checks \u2014 install it with `npm i z3-solver`.', { cause });
7
+ this.name = "MissingSolverError";
8
+ }
9
+ };
10
+ async function reportFull(source, opts = {}) {
11
+ let exhaustiveness;
12
+ let z3;
13
+ try {
14
+ [exhaustiveness, z3] = await Promise.all([import('./exhaustiveness-VBVWCX5W.js'), import('./z3-MWU3GSVT.js')]);
15
+ } catch (cause) {
16
+ throw new MissingSolverError(cause);
17
+ }
18
+ const [structural, numeric] = await Promise.all([exhaustiveness.predicateExhaustiveness(source), z3.checkNumeric(source)]);
19
+ const extra = [...structuralDiagnostics(structural, source), ...numericDiagnostics(numeric, source)];
20
+ return report(source, { policy: opts.policy, extraDiagnostics: extra, compile: opts.compile });
21
+ }
22
+
23
+ export { MissingSolverError, reportFull };
24
+ //# sourceMappingURL=chunk-NLQIL5WD.js.map
25
+ //# sourceMappingURL=chunk-NLQIL5WD.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/report-full.ts"],"names":[],"mappings":";;;AAiBO,IAAM,kBAAA,GAAN,cAAiC,KAAA,CAAM;AAAA,EAC5C,YAAY,KAAA,EAAgB;AAC1B,IAAA,KAAA,CAAM,uHAAA,EAAoH,EAAE,KAAA,EAAO,CAAA;AACnI,IAAA,IAAA,CAAK,IAAA,GAAO,oBAAA;AAAA,EACd;AACF;AAQA,eAAsB,UAAA,CAAW,MAAA,EAAgB,IAAA,GAAsE,EAAC,EAAsB;AAC5I,EAAA,IAAI,cAAA;AACJ,EAAA,IAAI,EAAA;AACJ,EAAA,IAAI;AACF,IAAA,CAAC,cAAA,EAAgB,EAAE,CAAA,GAAI,MAAM,OAAA,CAAQ,GAAA,CAAI,CAAC,OAAO,8BAAyB,CAAA,EAAG,OAAO,kBAAa,CAAC,CAAC,CAAA;AAAA,EACrG,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,IAAI,mBAAmB,KAAK,CAAA;AAAA,EACpC;AACA,EAAA,MAAM,CAAC,UAAA,EAAY,OAAO,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI,CAAC,cAAA,CAAe,uBAAA,CAAwB,MAAM,CAAA,EAAG,EAAA,CAAG,YAAA,CAAa,MAAM,CAAC,CAAC,CAAA;AACzH,EAAA,MAAM,KAAA,GAAQ,CAAC,GAAG,qBAAA,CAAsB,UAAA,EAAY,MAAM,CAAA,EAAG,GAAG,kBAAA,CAAmB,OAAA,EAAS,MAAM,CAAC,CAAA;AACnG,EAAA,OAAO,MAAA,CAAO,MAAA,EAAQ,EAAE,MAAA,EAAQ,IAAA,CAAK,MAAA,EAAQ,gBAAA,EAAkB,KAAA,EAAO,OAAA,EAAS,IAAA,CAAK,OAAA,EAAS,CAAA;AAC/F","file":"chunk-NLQIL5WD.js","sourcesContent":["// ── reportFull — the complete check in one call ─────────────────────────────────────────────────────────\n// report() runs the SYNCHRONOUS checker. The full check also needs the Z3 solver (predicate-chain\n// exhaustiveness + numeric conflicts), which is server-side and pulls z3's wasm — so a consumer would\n// otherwise have to discover and wire four functions across two modules. reportFull does it in one async call:\n// run the solver, fold its findings into the SAME TgReport report() returns. Node-only; z3-solver is an OPTIONAL\n// peer (kept out of the core install) and is dynamically imported here.\n//\n// Failure taxonomy matters to callers: a MISSING peer is the expected, degradable case (the CLI falls back to\n// the sync check and records `checkMode: 'sync'`), while a solver that LOADED but then crashed is a real bug\n// that must surface. So only the dynamic import is wrapped — as the typed MissingSolverError — and everything\n// after it propagates untouched.\n\nimport { numericDiagnostics, structuralDiagnostics } from './compile';\nimport { report } from './report';\nimport type { ReportCompileOptions, StrictnessPolicy, TgReport } from './report';\n\n/** Thrown when the optional `z3-solver` peer isn't installed — the one failure a caller may degrade on. */\nexport class MissingSolverError extends Error {\n constructor(cause: unknown) {\n super('reportFull needs the optional peer dependency \"z3-solver\" for the Z3 checks — install it with `npm i z3-solver`.', { cause });\n this.name = 'MissingSolverError';\n }\n}\n\n/**\n * The complete TypeGlish check in one `await`: the synchronous compiler PLUS the Z3 solver\n * (predicate-chain exhaustiveness + numeric conflicts), folded into the same {@link TgReport}. Requires the\n * optional peer `z3-solver`; throws {@link MissingSolverError} if it isn't installed. Any other solver\n * failure propagates as-is — do not degrade on it.\n */\nexport async function reportFull(source: string, opts: { policy?: StrictnessPolicy; compile?: ReportCompileOptions } = {}): Promise<TgReport> {\n let exhaustiveness: typeof import('./solver/exhaustiveness');\n let z3: typeof import('./solver/z3');\n try {\n [exhaustiveness, z3] = await Promise.all([import('./solver/exhaustiveness'), import('./solver/z3')]);\n } catch (cause) {\n throw new MissingSolverError(cause);\n }\n const [structural, numeric] = await Promise.all([exhaustiveness.predicateExhaustiveness(source), z3.checkNumeric(source)]);\n const extra = [...structuralDiagnostics(structural, source), ...numericDiagnostics(numeric, source)];\n return report(source, { policy: opts.policy, extraDiagnostics: extra, compile: opts.compile });\n}\n"]}
@@ -0,0 +1,39 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
8
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
9
+ }) : x)(function(x) {
10
+ if (typeof require !== "undefined") return require.apply(this, arguments);
11
+ throw Error('Dynamic require of "' + x + '" is not supported');
12
+ });
13
+ var __commonJS = (cb, mod) => function __require2() {
14
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
15
+ };
16
+ var __export = (target, all) => {
17
+ for (var name in all)
18
+ __defProp(target, name, { get: all[name], enumerable: true });
19
+ };
20
+ var __copyProps = (to, from, except, desc) => {
21
+ if (from && typeof from === "object" || typeof from === "function") {
22
+ for (let key of __getOwnPropNames(from))
23
+ if (!__hasOwnProp.call(to, key) && key !== except)
24
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
25
+ }
26
+ return to;
27
+ };
28
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
29
+ // If the importer is in node compatibility mode or this is not an ESM
30
+ // file that has been converted to a CommonJS file using a Babel-
31
+ // compatible transform (i.e. "__esModule" has not been set), then set
32
+ // "default" to the CommonJS "module.exports" for node compatibility.
33
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
34
+ mod
35
+ ));
36
+
37
+ export { __commonJS, __export, __require, __toESM };
38
+ //# sourceMappingURL=chunk-PR4QN5HX.js.map
39
+ //# sourceMappingURL=chunk-PR4QN5HX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-PR4QN5HX.js"}
@@ -0,0 +1,3 @@
1
+
2
+ //# sourceMappingURL=chunk-PXAMTGYY.js.map
3
+ //# sourceMappingURL=chunk-PXAMTGYY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-PXAMTGYY.js"}
@@ -0,0 +1,140 @@
1
+ import { lower, atomKey, normAtom } from './chunk-Y64EAEYB.js';
2
+ import { init } from 'z3-solver';
3
+
4
+ var ctxPromise;
5
+ function z3() {
6
+ ctxPromise ??= init().then(({ Context }) => Context("typeglish"));
7
+ return ctxPromise;
8
+ }
9
+ function lowerCond(ctx, cond, atoms) {
10
+ switch (cond.t) {
11
+ case "true":
12
+ return ctx.Bool.val(true);
13
+ case "false":
14
+ return ctx.Bool.val(false);
15
+ case "atom": {
16
+ let a = atoms.get(cond.key);
17
+ if (!a) {
18
+ a = ctx.Bool.const(cond.key);
19
+ atoms.set(cond.key, a);
20
+ }
21
+ return a;
22
+ }
23
+ case "not":
24
+ return ctx.Not(lowerCond(ctx, cond.f, atoms));
25
+ case "and":
26
+ return cond.fs.length ? ctx.And(...cond.fs.map((f) => lowerCond(ctx, f, atoms))) : ctx.Bool.val(true);
27
+ case "or":
28
+ return cond.fs.length ? ctx.Or(...cond.fs.map((f) => lowerCond(ctx, f, atoms))) : ctx.Bool.val(false);
29
+ }
30
+ }
31
+ async function satisfiable(cond) {
32
+ const ctx = await z3();
33
+ const solver = new ctx.Solver();
34
+ solver.add(lowerCond(ctx, cond, /* @__PURE__ */ new Map()));
35
+ return await solver.check() === "sat";
36
+ }
37
+ async function checkLogic(text) {
38
+ const directives = lower(text).nodes.filter((n) => n.kind === "directive");
39
+ const [deontic, numeric] = await Promise.all([
40
+ checkDirectiveConsistency(directives),
41
+ checkNumericConsistency(directives)
42
+ ]);
43
+ return [...deontic, ...numeric];
44
+ }
45
+ async function checkNumeric(text) {
46
+ const directives = lower(text).nodes.filter((n) => n.kind === "directive");
47
+ return checkNumericConsistency(directives);
48
+ }
49
+ async function checkDirectiveConsistency(directives) {
50
+ const byAtom = /* @__PURE__ */ new Map();
51
+ for (const d of directives) {
52
+ const key = atomKey(d);
53
+ const list = byAtom.get(key);
54
+ if (list) list.push(d);
55
+ else byAtom.set(key, [d]);
56
+ }
57
+ const ctx = await z3();
58
+ const conflicts = [];
59
+ const seen = /* @__PURE__ */ new Set();
60
+ for (const [atom, ds] of byAtom) {
61
+ const obligations = ds.filter((d) => d.deontic === "obligate");
62
+ const prohibitions = ds.filter((d) => d.deontic === "prohibit");
63
+ for (const o of obligations) {
64
+ for (const p of prohibitions) {
65
+ const solver = new ctx.Solver();
66
+ const atoms = /* @__PURE__ */ new Map();
67
+ solver.add(lowerCond(ctx, o.cond, atoms));
68
+ solver.add(lowerCond(ctx, p.cond, atoms));
69
+ if (await solver.check() !== "sat") continue;
70
+ const lines = [.../* @__PURE__ */ new Set([o.line, p.line])].sort((a, b) => a - b);
71
+ const key = `${atom}|${lines.join(",")}`;
72
+ if (seen.has(key)) continue;
73
+ seen.add(key);
74
+ const canonical = o.action.key !== normAtom(o.action.text) || p.action.key !== normAtom(p.action.text);
75
+ const name = canonical ? o.action.text === p.action.text ? o.action.text : `${o.action.text}" vs "${p.action.text}` : atom;
76
+ conflicts.push({ atom, lines, message: `Logical conflict \u2014 "${name}" is both required and forbidden.` });
77
+ }
78
+ }
79
+ }
80
+ return conflicts;
81
+ }
82
+ function rangeExpr(ctx, x, c) {
83
+ switch (c.op) {
84
+ case "le":
85
+ return x.le(c.n);
86
+ case "ge":
87
+ return x.ge(c.n);
88
+ case "lt":
89
+ return x.lt(c.n);
90
+ case "gt":
91
+ return x.gt(c.n);
92
+ case "eq":
93
+ return x.eq(c.n);
94
+ }
95
+ }
96
+ async function checkNumericConsistency(directives) {
97
+ const bounded = directives.filter((d) => d.deontic === "obligate" && d.numeric !== null);
98
+ const byQuantity = /* @__PURE__ */ new Map();
99
+ for (const d of bounded) {
100
+ const key = `${d.subject}:${d.numeric.quantity}`;
101
+ const list = byQuantity.get(key);
102
+ if (list) list.push(d);
103
+ else byQuantity.set(key, [d]);
104
+ }
105
+ const ctx = await z3();
106
+ const conflicts = [];
107
+ const seen = /* @__PURE__ */ new Set();
108
+ for (const [key, ds] of byQuantity) {
109
+ for (let i = 0; i < ds.length; i += 1) {
110
+ for (let j = i + 1; j < ds.length; j += 1) {
111
+ const a = ds[i];
112
+ const b = ds[j];
113
+ const guards = new ctx.Solver();
114
+ const atoms = /* @__PURE__ */ new Map();
115
+ guards.add(lowerCond(ctx, a.cond, atoms));
116
+ guards.add(lowerCond(ctx, b.cond, atoms));
117
+ if (await guards.check() !== "sat") continue;
118
+ const range = new ctx.Solver();
119
+ const x = ctx.Int.const("q");
120
+ range.add(rangeExpr(ctx, x, a.numeric));
121
+ range.add(rangeExpr(ctx, x, b.numeric));
122
+ if (await range.check() === "sat") continue;
123
+ const lines = [.../* @__PURE__ */ new Set([a.line, b.line])].sort((m, n) => m - n);
124
+ const k = `${key}|${lines.join(",")}`;
125
+ if (seen.has(k)) continue;
126
+ seen.add(k);
127
+ conflicts.push({
128
+ atom: key,
129
+ lines,
130
+ message: `Numeric conflict \u2014 "${a.numeric.text}" and "${b.numeric.text}" can't both hold.`
131
+ });
132
+ }
133
+ }
134
+ }
135
+ return conflicts;
136
+ }
137
+
138
+ export { checkDirectiveConsistency, checkLogic, checkNumeric, checkNumericConsistency, satisfiable, z3 };
139
+ //# sourceMappingURL=chunk-VMACILYN.js.map
140
+ //# sourceMappingURL=chunk-VMACILYN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/solver/z3.ts"],"names":[],"mappings":"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","file":"chunk-VMACILYN.js","sourcesContent":["import { init } from 'z3-solver';\n\nimport { atomKey, lower } from '../ir';\nimport { normAtom } from '../predicate';\nimport type { Cond, DirectiveIR, NumericConstraint } from '../ir';\n\n// z3-solver loads a wasm module (and spins up worker threads); build the context once, lazily, and\n// reuse it. Its high-level API is heavily generic, so threading its types here is impractical — this\n// thin boundary stays `any`-typed; the safety is in the IR types on the way in and the tests out.\ntype Z3 = any; // eslint-disable-line @typescript-eslint/no-explicit-any\n\nlet ctxPromise: Promise<Z3> | undefined;\n/** The shared Z3 context — built once, lazily, and reused (consts from different contexts can't mix, so every\n * server-side check must share this one). Exported so the conditional-layer exhaustiveness check reuses it. */\nexport function z3(): Promise<Z3> {\n ctxPromise ??= init().then(({ Context }) => Context('typeglish'));\n return ctxPromise;\n}\n\n/** Lower an IR condition to a Z3 boolean expression, interning each atom as a Z3 Bool const. */\nfunction lowerCond(ctx: Z3, cond: Cond, atoms: Map<string, Z3>): Z3 {\n switch (cond.t) {\n case 'true':\n return ctx.Bool.val(true);\n case 'false':\n return ctx.Bool.val(false);\n case 'atom': {\n let a = atoms.get(cond.key);\n if (!a) {\n a = ctx.Bool.const(cond.key);\n atoms.set(cond.key, a);\n }\n return a;\n }\n case 'not':\n return ctx.Not(lowerCond(ctx, cond.f, atoms));\n case 'and':\n return cond.fs.length ? ctx.And(...cond.fs.map((f) => lowerCond(ctx, f, atoms))) : ctx.Bool.val(true);\n case 'or':\n return cond.fs.length ? ctx.Or(...cond.fs.map((f) => lowerCond(ctx, f, atoms))) : ctx.Bool.val(false);\n }\n}\n\n/** Is the condition satisfiable? Z3-backed — full propositional reasoning, no atom cap. */\nexport async function satisfiable(cond: Cond): Promise<boolean> {\n const ctx = await z3();\n const solver = new ctx.Solver();\n solver.add(lowerCond(ctx, cond, new Map<string, Z3>()));\n return (await solver.check()) === 'sat';\n}\n\nexport interface LogicConflict {\n atom: string;\n lines: number[];\n message: string;\n}\n\n/**\n * Deontic consistency over the IR: an action both obligated (MUST/ALWAYS) and prohibited\n * (NEVER/MUST NOT) under conditions that can co-occur. The two guards are conjoined and handed to\n * Z3 — the conflict is real only if (condA AND condB) is satisfiable, so disjoint branches\n * (IF c … / IF NOT c …) never trip it, but an unconditional pair always does.\n */\n/** Top-level entry: lower a prompt's raw text to its IR and run the Z3 deontic-consistency check.\n * This is the boundary the app calls — text in, conflicts out. Quoted spans never reach here as\n * directives (the grammar reads a leading-quote clause as prose), so they're inert by construction. */\nexport async function checkLogic(text: string): Promise<LogicConflict[]> {\n const directives = lower(text).nodes.filter((n): n is DirectiveIR => n.kind === 'directive');\n const [deontic, numeric] = await Promise.all([\n checkDirectiveConsistency(directives),\n checkNumericConsistency(directives),\n ]);\n return [...deontic, ...numeric];\n}\n\n/** Numeric-only check from raw text — the live Tier-2: the SMT conflicts the synchronous brute-force\n * tier can't decide. Deontic stays in the instant tier, so this never duplicates it. */\nexport async function checkNumeric(text: string): Promise<LogicConflict[]> {\n const directives = lower(text).nodes.filter((n): n is DirectiveIR => n.kind === 'directive');\n return checkNumericConsistency(directives);\n}\n\nexport async function checkDirectiveConsistency(directives: DirectiveIR[]): Promise<LogicConflict[]> {\n const byAtom = new Map<string, DirectiveIR[]>();\n for (const d of directives) {\n const key = atomKey(d);\n const list = byAtom.get(key);\n if (list) list.push(d);\n else byAtom.set(key, [d]);\n }\n const ctx = await z3();\n const conflicts: LogicConflict[] = [];\n const seen = new Set<string>();\n for (const [atom, ds] of byAtom) {\n const obligations = ds.filter((d) => d.deontic === 'obligate');\n const prohibitions = ds.filter((d) => d.deontic === 'prohibit');\n for (const o of obligations) {\n for (const p of prohibitions) {\n const solver = new ctx.Solver();\n const atoms = new Map<string, Z3>();\n solver.add(lowerCond(ctx, o.cond, atoms));\n solver.add(lowerCond(ctx, p.cond, atoms));\n if ((await solver.check()) !== 'sat') continue;\n const lines = [...new Set([o.line, p.line])].sort((a, b) => a - b);\n const key = `${atom}|${lines.join(',')}`;\n if (seen.has(key)) continue;\n seen.add(key);\n // Canonical predicate keys are machine identities; show the authors' words instead.\n const canonical = o.action.key !== normAtom(o.action.text) || p.action.key !== normAtom(p.action.text);\n const name = canonical\n ? o.action.text === p.action.text\n ? o.action.text\n : `${o.action.text}\" vs \"${p.action.text}`\n : atom;\n conflicts.push({ atom, lines, message: `Logical conflict — \"${name}\" is both required and forbidden.` });\n }\n }\n }\n return conflicts;\n}\n\nfunction rangeExpr(ctx: Z3, x: Z3, c: NumericConstraint): Z3 {\n switch (c.op) {\n case 'le':\n return x.le(c.n);\n case 'ge':\n return x.ge(c.n);\n case 'lt':\n return x.lt(c.n);\n case 'gt':\n return x.gt(c.n);\n case 'eq':\n return x.eq(c.n);\n }\n}\n\n/**\n * Numeric (SMT) consistency: two obligations bounding the SAME quantity to ranges that can't overlap\n * — `at most 3 sentences` and `at least 5 sentences` — under conditions that can co-occur. This is the\n * theory propositional brute-force can't reach: each bound alone is satisfiable, and only integer\n * arithmetic decides their conjunction is empty.\n */\nexport async function checkNumericConsistency(directives: DirectiveIR[]): Promise<LogicConflict[]> {\n type Bound = DirectiveIR & { numeric: NumericConstraint };\n const bounded = directives.filter((d): d is Bound => d.deontic === 'obligate' && d.numeric !== null);\n const byQuantity = new Map<string, Bound[]>();\n for (const d of bounded) {\n const key = `${d.subject}:${d.numeric.quantity}`;\n const list = byQuantity.get(key);\n if (list) list.push(d);\n else byQuantity.set(key, [d]);\n }\n const ctx = await z3();\n const conflicts: LogicConflict[] = [];\n const seen = new Set<string>();\n for (const [key, ds] of byQuantity) {\n for (let i = 0; i < ds.length; i += 1) {\n for (let j = i + 1; j < ds.length; j += 1) {\n const a = ds[i]!;\n const b = ds[j]!;\n // The bounds clash only where both directives apply — skip disjoint guards.\n const guards = new ctx.Solver();\n const atoms = new Map<string, Z3>();\n guards.add(lowerCond(ctx, a.cond, atoms));\n guards.add(lowerCond(ctx, b.cond, atoms));\n if ((await guards.check()) !== 'sat') continue;\n // Can one integer satisfy both bounds? If not, the prompt is over-constrained.\n const range = new ctx.Solver();\n const x = ctx.Int.const('q');\n range.add(rangeExpr(ctx, x, a.numeric));\n range.add(rangeExpr(ctx, x, b.numeric));\n if ((await range.check()) === 'sat') continue;\n const lines = [...new Set([a.line, b.line])].sort((m, n) => m - n);\n const k = `${key}|${lines.join(',')}`;\n if (seen.has(k)) continue;\n seen.add(k);\n conflicts.push({\n atom: key,\n lines,\n message: `Numeric conflict — \"${a.numeric.text}\" and \"${b.numeric.text}\" can't both hold.`,\n });\n }\n }\n }\n return conflicts;\n}\n"]}