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,56 @@
1
+ import nspell from 'nspell';
2
+
3
+ // src/lib/spell.ts
4
+ var DOMAIN_WORDS = [
5
+ "xml",
6
+ "sigil",
7
+ "sigils",
8
+ "typeglish",
9
+ "enum",
10
+ "enums",
11
+ "bool",
12
+ "bools",
13
+ "expr",
14
+ "eval",
15
+ "evals",
16
+ "iff",
17
+ "backend",
18
+ "backends",
19
+ "transclude",
20
+ "transcludes",
21
+ "transcluded",
22
+ "unclosed",
23
+ "unimported",
24
+ "unreferenced",
25
+ "unmeasurable",
26
+ "defeasible",
27
+ "deontic",
28
+ "enforceability",
29
+ "freeform",
30
+ "dedupe",
31
+ "dedupes",
32
+ "deduped",
33
+ "checkmark",
34
+ "checkmarks",
35
+ "substep",
36
+ "substeps",
37
+ "http",
38
+ "https"
39
+ ];
40
+ function createDictionary(en, gb, custom = []) {
41
+ const us = nspell(en.aff, en.dic);
42
+ const uk = nspell(gb.aff, gb.dic);
43
+ for (const w of DOMAIN_WORDS) us.add(w);
44
+ for (const w of custom) if (w.trim() !== "") us.add(w.trim());
45
+ return {
46
+ isWord: (w) => us.correct(w) || uk.correct(w),
47
+ suggest: (w) => [.../* @__PURE__ */ new Set([...us.suggest(w), ...uk.suggest(w)])].slice(0, 5),
48
+ add: (w) => {
49
+ us.add(w);
50
+ }
51
+ };
52
+ }
53
+
54
+ export { createDictionary };
55
+ //# sourceMappingURL=chunk-ZKMHZHID.js.map
56
+ //# sourceMappingURL=chunk-ZKMHZHID.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/spell.ts"],"names":[],"mappings":";;;AAyCA,IAAM,YAAA,GAAe;AAAA,EACnB,KAAA;AAAA,EAAO,OAAA;AAAA,EAAS,QAAA;AAAA,EAAU,WAAA;AAAA,EAC1B,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,MAAA;AAAA,EAClC,MAAA;AAAA,EAAQ,OAAA;AAAA,EAAS,KAAA;AAAA,EAAO,SAAA;AAAA,EAAW,UAAA;AAAA,EACnC,YAAA;AAAA,EAAc,aAAA;AAAA,EAAe,aAAA;AAAA,EAC7B,UAAA;AAAA,EAAY,YAAA;AAAA,EAAc,cAAA;AAAA,EAAgB,cAAA;AAAA,EAC1C,YAAA;AAAA,EAAc,SAAA;AAAA,EAAW,gBAAA;AAAA,EAAkB,UAAA;AAAA,EAC3C,QAAA;AAAA,EAAU,SAAA;AAAA,EAAW,SAAA;AAAA,EACrB,WAAA;AAAA,EAAa,YAAA;AAAA,EAAc,SAAA;AAAA,EAAW,UAAA;AAAA,EAAY,MAAA;AAAA,EAAQ;AAC5D,CAAA;AAEO,SAAS,gBAAA,CACd,EAAA,EACA,EAAA,EACA,MAAA,GAA4B,EAAC,EACjB;AACZ,EAAA,MAAM,EAAA,GAAK,MAAA,CAAO,EAAA,CAAG,GAAA,EAAK,GAAG,GAAG,CAAA;AAChC,EAAA,MAAM,EAAA,GAAK,MAAA,CAAO,EAAA,CAAG,GAAA,EAAK,GAAG,GAAG,CAAA;AAEhC,EAAA,KAAA,MAAW,CAAA,IAAK,YAAA,EAAc,EAAA,CAAG,GAAA,CAAI,CAAC,CAAA;AACtC,EAAA,KAAA,MAAW,CAAA,IAAK,MAAA,EAAQ,IAAI,CAAA,CAAE,IAAA,EAAK,KAAM,EAAA,EAAI,EAAA,CAAG,GAAA,CAAI,CAAA,CAAE,IAAA,EAAM,CAAA;AAC5D,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,CAAC,CAAA,KAAM,EAAA,CAAG,QAAQ,CAAC,CAAA,IAAK,EAAA,CAAG,OAAA,CAAQ,CAAC,CAAA;AAAA,IAC5C,OAAA,EAAS,CAAC,CAAA,KAAM,CAAC,mBAAG,IAAI,GAAA,CAAI,CAAC,GAAG,EAAA,CAAG,OAAA,CAAQ,CAAC,CAAA,EAAG,GAAG,EAAA,CAAG,OAAA,CAAQ,CAAC,CAAC,CAAC,CAAC,CAAA,CAAE,KAAA,CAAM,CAAA,EAAG,CAAC,CAAA;AAAA,IAC7E,GAAA,EAAK,CAAC,CAAA,KAAM;AACV,MAAA,EAAA,CAAG,IAAI,CAAC,CAAA;AAAA,IACV;AAAA,GACF;AACF","file":"chunk-ZKMHZHID.js","sourcesContent":["// ── typeglish/spell — the dictionary tier ─────────────────────────────────────────────────────────────\n// Spell-checking is part of compiling, but — exactly like the Z3 numeric tier — it can't live in the\n// SYNCHRONOUS, zero-dependency core: a real dictionary is ~1 MB and loads async. So it ships as this separate,\n// opt-in module. A consumer folds it into any compile the way the CLI folds in checkNumeric:\n//\n// import { compile } from 'typeglish';\n// import { loadDictionary } from 'typeglish/spell'; // Node; a browser builds its own (see below)\n// const dict = await loadDictionary();\n// compile(source, { isWord: dict.isWord }); // now catches arbitrary misspellings\n//\n// `createDictionary` is the pure builder (hand it aff/dic text) and is host-agnostic — Node and the browser\n// share it. The Node convenience loader lives in the `./spell` export's `node` build (spell-node.ts); a browser\n// supplies its own fetched bytes to createDictionary (see src/web/dictionary.ts). This file has no I/O and no\n// node:fs, so it is safe in any bundle.\nimport nspell from 'nspell';\n\nimport type { SpellChecker } from '../core/compile';\n\nexport interface Dictionary {\n /** True when the word is spelled correctly in US OR British English (or is a supplied custom word). */\n isWord: SpellChecker;\n /** Up to five ranked corrections, merged across both variants. */\n suggest: (word: string) => string[];\n /** Teach the live checker a word so it stops being flagged. */\n add: (word: string) => void;\n}\n\n/** Raw hunspell dictionary text: the `.aff` affix rules + the `.dic` word list, decoded to UTF-8 strings. */\nexport interface DictionarySource {\n aff: string;\n dic: string;\n}\n\n/**\n * Build a checker from US + British hunspell sources. A word is \"known\" when EITHER variant accepts it, so\n * color/colour and organize/organise both pass while genuine typos fail both; suggestions merge across the two.\n * Pure (no I/O), so it runs identically in Node and the browser — each host just supplies the source text.\n */\n// TypeGlish's own vocabulary — words the language's docs, prompts, and UI use constantly that hunspell\n// lacks (several appear verbatim in the checker's own messages: \"unmeasurable\", \"enforceability\").\n// Built in (not user-custom) so a fresh install never flags the language's own terminology.\nconst DOMAIN_WORDS = [\n 'xml', 'sigil', 'sigils', 'typeglish',\n 'enum', 'enums', 'bool', 'bools', 'expr',\n 'eval', 'evals', 'iff', 'backend', 'backends',\n 'transclude', 'transcludes', 'transcluded',\n 'unclosed', 'unimported', 'unreferenced', 'unmeasurable',\n 'defeasible', 'deontic', 'enforceability', 'freeform',\n 'dedupe', 'dedupes', 'deduped',\n 'checkmark', 'checkmarks', 'substep', 'substeps', 'http', 'https',\n] as const;\n\nexport function createDictionary(\n en: DictionarySource,\n gb: DictionarySource,\n custom: readonly string[] = [],\n): Dictionary {\n const us = nspell(en.aff, en.dic);\n const uk = nspell(gb.aff, gb.dic);\n // Custom words go into the US instance; isWord consults it first, so a single add is enough to clear a flag.\n for (const w of DOMAIN_WORDS) us.add(w);\n for (const w of custom) if (w.trim() !== '') us.add(w.trim());\n return {\n isWord: (w) => us.correct(w) || uk.correct(w),\n suggest: (w) => [...new Set([...us.suggest(w), ...uk.suggest(w)])].slice(0, 5),\n add: (w) => {\n us.add(w);\n },\n };\n}\n"]}
package/dist/cli.d.ts ADDED
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/cli.js ADDED
@@ -0,0 +1,447 @@
1
+ #!/usr/bin/env node
2
+ import { loadGlishConfig, checkSource, toPosix, DEFAULT_OUT_DIR, parseManifest, MANIFEST_FILE, sourceKey, artifactPathFor, buildPrompt, upsertManifest, scoreSource, parseMin, renderAgentReference, findUp, DIAGNOSTIC_CODES, blocks, sha256, canonicalize } from './chunk-3NQ3VYO6.js';
3
+ import './chunk-NLQIL5WD.js';
4
+ import { resolve as resolve$1 } from './chunk-KRYC4OTL.js';
5
+ import './chunk-YH4ZLQ4G.js';
6
+ import './chunk-Y64EAEYB.js';
7
+ import './chunk-PR4QN5HX.js';
8
+ import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
9
+ import { resolve, dirname } from 'path';
10
+ import { fileURLToPath } from 'url';
11
+ import { parseArgs } from 'util';
12
+
13
+ // src/lib/cli-format.ts
14
+ function formatText(results) {
15
+ const out = [];
16
+ for (const { file, report } of results) {
17
+ for (const d of report.diagnostics) {
18
+ out.push(`${file}:${d.range.line}:${d.range.column} ${d.effectiveSeverity.padEnd(5)} ${d.code} ${d.message}`);
19
+ }
20
+ }
21
+ const totals = results.reduce(
22
+ (a, { report }) => ({ error: a.error + report.counts.error, warn: a.warn + report.counts.warn, info: a.info + report.counts.info }),
23
+ { error: 0, warn: 0, info: 0 }
24
+ );
25
+ if (out.length > 0) out.push("");
26
+ const ok = totals.error === 0;
27
+ out.push(`${ok ? "\u2713" : "\u2717"} ${results.length} file${results.length === 1 ? "" : "s"} \u2014 ${totals.error} error, ${totals.warn} warning, ${totals.info} info`);
28
+ return out.join("\n");
29
+ }
30
+ function anyBlocking(results) {
31
+ return results.some((r) => !r.report.ok);
32
+ }
33
+
34
+ // src/lib/deploy-gate.ts
35
+ var GATE_CONFIG_FILE = ".typeglish/deploy-gate.json";
36
+ var DEFAULT_GATE_CONFIG = {
37
+ mode: "deny",
38
+ tools: ["voiceflow_agent_instructions", "voiceflow_agent_global_prompt", "voiceflow_behavior"],
39
+ minChars: 80
40
+ };
41
+ function resolveGateConfig(text) {
42
+ if (text === null) return DEFAULT_GATE_CONFIG;
43
+ try {
44
+ const raw = JSON.parse(text);
45
+ return {
46
+ mode: raw.mode === "ask" || raw.mode === "off" || raw.mode === "deny" ? raw.mode : DEFAULT_GATE_CONFIG.mode,
47
+ tools: Array.isArray(raw.tools) ? raw.tools.map(String) : DEFAULT_GATE_CONFIG.tools,
48
+ minChars: typeof raw.minChars === "number" && raw.minChars > 0 ? raw.minChars : DEFAULT_GATE_CONFIG.minChars
49
+ };
50
+ } catch {
51
+ return DEFAULT_GATE_CONFIG;
52
+ }
53
+ }
54
+ function toolSuffix(toolName) {
55
+ const i = toolName.lastIndexOf("__");
56
+ return i === -1 ? toolName : toolName.slice(i + 2);
57
+ }
58
+ function flattenRichText(node) {
59
+ if (typeof node === "string") return node;
60
+ if (Array.isArray(node)) return node.map(flattenRichText).join("");
61
+ if (node !== null && typeof node === "object" && "text" in node) return flattenRichText(node.text);
62
+ return "";
63
+ }
64
+ function candidateTexts(input, minChars) {
65
+ const found = /* @__PURE__ */ new Set();
66
+ const consider = (s) => {
67
+ if (s.trim().length >= minChars) found.add(s);
68
+ };
69
+ const walk = (node) => {
70
+ if (typeof node === "string") {
71
+ consider(node);
72
+ return;
73
+ }
74
+ if (Array.isArray(node)) {
75
+ const flat = node.map(flattenRichText);
76
+ consider(flat.join(""));
77
+ consider(flat.join("\n"));
78
+ for (const item of node) walk(item);
79
+ return;
80
+ }
81
+ if (node !== null && typeof node === "object") {
82
+ for (const value of Object.values(node)) walk(value);
83
+ }
84
+ };
85
+ walk(input);
86
+ return [...found];
87
+ }
88
+ var READ_OPS = /* @__PURE__ */ new Set(["get", "list", "search", "read", "retrieve", "describe"]);
89
+ function evaluateGate(toolName, toolInput, manifest, config) {
90
+ if (config.mode === "off") return { action: "pass" };
91
+ const suffix = toolSuffix(toolName);
92
+ const operation = toolInput?.operation;
93
+ const isReadOp = typeof operation === "string" && READ_OPS.has(operation.toLowerCase());
94
+ if (isReadOp) return { action: "pass" };
95
+ const configured = config.tools.includes(suffix);
96
+ const heuristic = !configured && suffix.startsWith("voiceflow_") && typeof operation === "string";
97
+ if (!configured && !heuristic) return { action: "pass" };
98
+ const candidates = candidateTexts(toolInput, config.minChars);
99
+ if (candidates.length === 0) return { action: "pass" };
100
+ const known = new Set((manifest?.builds ?? []).map((b) => b.artifactSha256));
101
+ const match = candidates.map((c) => sha256(canonicalize(c))).find((h) => known.has(h));
102
+ if (match !== void 0) {
103
+ const entry = (manifest?.builds ?? []).find((b) => b.artifactSha256 === match);
104
+ return { action: "verified", entry };
105
+ }
106
+ const reason = manifest === null ? `This prompt payload is not TypeGlish-verified: no build manifest found (.typeglish/build-manifest.json). Author the prompt as a .tg file, run \`typeglish check\` until clean, run \`typeglish build <file>\`, then deploy the exact contents of the built artifact (.typeglish/dist/<name>.txt) unmodified.` : `This prompt payload does not match any \`typeglish build\` artifact in the manifest. Deploy the exact contents of a built artifact (.typeglish/dist/<name>.txt) unmodified \u2014 if you edited the prompt, edit the .tg source instead, re-run \`typeglish check\` and \`typeglish build\`, and send the fresh artifact.`;
107
+ const escape = ` If this write is intentionally not TypeGlish-managed, set TYPEGLISH_DEPLOY_GATE=off or adjust ${GATE_CONFIG_FILE}.`;
108
+ return { action: config.mode, reason: reason + escape };
109
+ }
110
+
111
+ // src/lib/claude-hook.ts
112
+ var SILENT = { stdout: null, exitCode: 0 };
113
+ async function postEdit(payloadText, deps) {
114
+ let payload;
115
+ try {
116
+ payload = JSON.parse(payloadText);
117
+ } catch {
118
+ return SILENT;
119
+ }
120
+ const filePath = payload.tool_input?.file_path;
121
+ if (filePath === void 0 || !/\.tg$/i.test(filePath)) return SILENT;
122
+ const source = deps.readFile(filePath);
123
+ if (source === null) return SILENT;
124
+ const glishConfig = deps.loadGlish(filePath);
125
+ const compileOpts = glishConfig === void 0 ? void 0 : { glishConfig };
126
+ const { report, checkMode } = await checkSource(source, {}, compileOpts);
127
+ const text = formatText([{ file: filePath, checkMode, report }]);
128
+ if (!report.ok) {
129
+ return {
130
+ stdout: JSON.stringify({
131
+ decision: "block",
132
+ reason: `${text}
133
+
134
+ These are compile errors in TypeGlish source \u2014 fix them now. \`typeglish --explain <code>\` explains any code; a diagnostic's fix field is mechanically applicable.`
135
+ }),
136
+ exitCode: 0
137
+ };
138
+ }
139
+ if (report.counts.warn > 0) {
140
+ return {
141
+ stdout: JSON.stringify({
142
+ hookSpecificOutput: {
143
+ hookEventName: "PostToolUse",
144
+ additionalContext: `typeglish: ${filePath} compiles (${checkMode} tier) with advisories:
145
+ ${text}`
146
+ }
147
+ }),
148
+ exitCode: 0
149
+ };
150
+ }
151
+ return SILENT;
152
+ }
153
+ function deployGate(payloadText, deps) {
154
+ let payload;
155
+ try {
156
+ payload = JSON.parse(payloadText);
157
+ } catch {
158
+ return SILENT;
159
+ }
160
+ const toolName = payload.tool_name;
161
+ if (toolName === void 0) return SILENT;
162
+ const envMode = deps.env("TYPEGLISH_DEPLOY_GATE")?.toLowerCase();
163
+ if (envMode === "off") return SILENT;
164
+ const cwd = payload.cwd ?? ".";
165
+ const config = resolveGateConfig(deps.readUp(GATE_CONFIG_FILE, cwd));
166
+ if (envMode === "ask" || envMode === "deny") config.mode = envMode;
167
+ if (config.mode === "off") return SILENT;
168
+ const manifest = parseManifest(deps.readUp(MANIFEST_FILE, cwd));
169
+ const verdict = evaluateGate(toolName, payload.tool_input, manifest, config);
170
+ if (verdict.action === "pass") return SILENT;
171
+ if (verdict.action === "verified") {
172
+ const { entry } = verdict;
173
+ const current = deps.readFile(resolve(cwd, entry.source));
174
+ const stale = current !== null && sha256(canonicalize(current)) !== entry.sourceSha256;
175
+ return {
176
+ stdout: JSON.stringify({
177
+ hookSpecificOutput: {
178
+ hookEventName: "PreToolUse",
179
+ additionalContext: `typeglish: payload verified \u2014 matches ${entry.artifact} (built from ${entry.source}, ${entry.checkMode} tier).` + (stale ? ` NOTE: ${entry.source} changed AFTER this build \u2014 if that change should ship, run \`typeglish build ${entry.source}\` and deploy the fresh artifact.` : "")
180
+ }
181
+ }),
182
+ exitCode: 0
183
+ };
184
+ }
185
+ return {
186
+ stdout: JSON.stringify({
187
+ hookSpecificOutput: {
188
+ hookEventName: "PreToolUse",
189
+ permissionDecision: verdict.action,
190
+ permissionDecisionReason: verdict.reason
191
+ }
192
+ }),
193
+ exitCode: 0
194
+ };
195
+ }
196
+ async function runClaudeHook(kind, payloadText, deps) {
197
+ if (kind === "post-edit") return postEdit(payloadText, deps);
198
+ if (kind === "deploy-gate") return deployGate(payloadText, deps);
199
+ return SILENT;
200
+ }
201
+
202
+ // src/lib/cli.ts
203
+ var HELP = `typeglish \u2014 the typed-English prompt compiler
204
+
205
+ Usage:
206
+ typeglish check <file...> [--strict] [--json] validate; exits 1 when any file has a blocking error
207
+ typeglish build <file...> [build options] compile passing files to artifacts + record the manifest
208
+ typeglish score <file> [--min B|80] [--json] the deterministic TG score; exits 1 below --min
209
+ typeglish resolve <file> [--vars '<json>'] apply conditionals, print the resolved SOURCE (a .tg \u2014
210
+ the deployable prompt is what \`build\` writes)
211
+ typeglish reference print the language reference (agents: read this first)
212
+ typeglish mcp serve check/build/score/explain/reference over MCP stdio
213
+ typeglish --explain <code> what a diagnostic code means (e.g. logic/contradiction)
214
+ typeglish --version | --help
215
+
216
+ Build options:
217
+ --out-dir <dir> artifact directory (default: .typeglish/dist)
218
+ --vars '<json>' input bag \u2014 conditionals compile away; omitted = template build (unbound switches
219
+ stay as conditional prose, runtime {curly} variables pass through)
220
+ --bundle also write <artifact>.agent.json \u2014 the $CONFIG / $TOOL agent bundle
221
+
222
+ Options:
223
+ --strict escalate every IMPORTANT finding (correctness defects) to a blocking error
224
+ --json machine-readable output on stdout (agents: parse this, not the text)
225
+ --vars a JSON object of input values, e.g. '{"tier":"premium"}'
226
+ --min score floor \u2014 a grade (A\u2013F) or a number; the CI gate
227
+
228
+ The check runs the full tier (Z3 proofs) when the optional z3-solver peer is installed, else the
229
+ synchronous checker; build records which as checkMode in .typeglish/build-manifest.json.`;
230
+ function explain(code) {
231
+ const info = DIAGNOSTIC_CODES[code];
232
+ if (info !== void 0) {
233
+ const gate = blocks(code) ? " \u2014 blocks compilation" : "";
234
+ return { found: true, text: `${code} (${info.severity}${gate})
235
+ ${info.summary}` };
236
+ }
237
+ const near = Object.keys(DIAGNOSTIC_CODES).filter((k) => k.includes(code)).sort();
238
+ if (near.length > 0) {
239
+ return { found: true, text: near.map((k) => `${k.padEnd(34)} ${DIAGNOSTIC_CODES[k]?.severity ?? ""} ${DIAGNOSTIC_CODES[k]?.summary ?? ""}`).join("\n") };
240
+ }
241
+ return { found: false, text: `typeglish --explain: unknown code "${code}" \u2014 codes look like category/name (e.g. logic/contradiction)` };
242
+ }
243
+ function cliVersion() {
244
+ try {
245
+ const pkgPath = findUp("package.json", dirname(fileURLToPath(import.meta.url)));
246
+ if (pkgPath !== null) {
247
+ const version = JSON.parse(readFileSync(pkgPath, "utf8")).version;
248
+ if (version !== void 0) return version;
249
+ }
250
+ } catch {
251
+ }
252
+ return "0.0.0-dev";
253
+ }
254
+ var MANIFEST_PATH = MANIFEST_FILE;
255
+ async function main() {
256
+ const { values, positionals } = parseArgs({
257
+ allowPositionals: true,
258
+ options: {
259
+ json: { type: "boolean", default: false },
260
+ strict: { type: "boolean", default: false },
261
+ vars: { type: "string" },
262
+ "out-dir": { type: "string" },
263
+ bundle: { type: "boolean", default: false },
264
+ min: { type: "string" },
265
+ explain: { type: "string" },
266
+ version: { type: "boolean", short: "v", default: false },
267
+ help: { type: "boolean", short: "h", default: false }
268
+ }
269
+ });
270
+ const [command, ...files] = positionals;
271
+ if (values.version) {
272
+ process.stdout.write(`${cliVersion()}
273
+ `);
274
+ return;
275
+ }
276
+ if (values.explain !== void 0) {
277
+ const { text, found } = explain(values.explain);
278
+ process.stdout.write(`${text}
279
+ `);
280
+ process.exitCode = found ? 0 : 2;
281
+ return;
282
+ }
283
+ if (values.help || command === void 0) {
284
+ process.stdout.write(`${HELP}
285
+ `);
286
+ return;
287
+ }
288
+ if (command === "check") {
289
+ if (files.length === 0) {
290
+ process.stderr.write("typeglish check: no files given\n");
291
+ process.exitCode = 2;
292
+ return;
293
+ }
294
+ const policy = values.strict ? { escalateImportance: "important" } : {};
295
+ const results = [];
296
+ for (const file of files) {
297
+ const abs = resolve(file);
298
+ const glishConfig = loadGlishConfig(dirname(abs));
299
+ const { report, checkMode } = await checkSource(readFileSync(abs, "utf8"), policy, glishConfig === void 0 ? void 0 : { glishConfig });
300
+ results.push({ file, checkMode, report });
301
+ }
302
+ process.stdout.write(`${values.json ? JSON.stringify(results, null, 2) : formatText(results)}
303
+ `);
304
+ process.exitCode = anyBlocking(results) ? 1 : 0;
305
+ return;
306
+ }
307
+ if (command === "build") {
308
+ if (files.length === 0) {
309
+ process.stderr.write("typeglish build: no files given\n");
310
+ process.exitCode = 2;
311
+ return;
312
+ }
313
+ const cwd = process.cwd();
314
+ const outDir = toPosix(values["out-dir"] ?? DEFAULT_OUT_DIR);
315
+ const vars = values.vars !== void 0 ? JSON.parse(values.vars) : void 0;
316
+ const version = cliVersion();
317
+ const jsonOut = [];
318
+ let manifest = parseManifest(existsSync(MANIFEST_PATH) ? readFileSync(MANIFEST_PATH, "utf8") : null);
319
+ let failed = false;
320
+ for (const file of files) {
321
+ const abs = resolve(file);
322
+ const source = readFileSync(abs, "utf8");
323
+ const srcKey = sourceKey(cwd, abs);
324
+ const artifactRel = artifactPathFor(srcKey, outDir);
325
+ const outcome = await buildPrompt(
326
+ source,
327
+ { source: srcKey, artifact: artifactRel },
328
+ { vars, strict: values.strict, glishConfig: loadGlishConfig(dirname(abs)), version, bundle: values.bundle }
329
+ );
330
+ if (!outcome.ok || outcome.entry === void 0 || outcome.artifact === void 0) {
331
+ failed = true;
332
+ const why = outcome.error ?? formatText([{ file, checkMode: outcome.checkMode, report: outcome.report }]);
333
+ process.stderr.write(`typeglish build: ${srcKey} refused \u2014 nothing written
334
+ ${why}
335
+ `);
336
+ jsonOut.push({ file: srcKey, ok: false, checkMode: outcome.checkMode, error: outcome.error, counts: outcome.report.counts });
337
+ continue;
338
+ }
339
+ const artifactAbs = resolve(cwd, artifactRel);
340
+ mkdirSync(dirname(artifactAbs), { recursive: true });
341
+ writeFileSync(artifactAbs, outcome.artifact);
342
+ if (outcome.agentJson !== void 0) writeFileSync(artifactAbs.replace(/\.txt$/, ".agent.json"), outcome.agentJson);
343
+ manifest = upsertManifest(manifest, outcome.entry);
344
+ jsonOut.push({ file: srcKey, ok: true, checkMode: outcome.checkMode, entry: outcome.entry });
345
+ if (!values.json) {
346
+ process.stdout.write(`\u2713 built ${artifactRel} \u2190 ${srcKey} (${outcome.entry.artifactSha256.slice(0, 12)}, ${outcome.checkMode})
347
+ `);
348
+ }
349
+ }
350
+ if (manifest !== null && manifest.builds.length > 0) {
351
+ mkdirSync(dirname(MANIFEST_PATH), { recursive: true });
352
+ writeFileSync(MANIFEST_PATH, `${JSON.stringify(manifest, null, 2)}
353
+ `);
354
+ }
355
+ if (values.json) process.stdout.write(`${JSON.stringify(jsonOut, null, 2)}
356
+ `);
357
+ process.exitCode = failed ? 1 : 0;
358
+ return;
359
+ }
360
+ if (command === "score") {
361
+ const file = files[0];
362
+ if (file === void 0) {
363
+ process.stderr.write("typeglish score: no file given\n");
364
+ process.exitCode = 2;
365
+ return;
366
+ }
367
+ const abs = resolve(file);
368
+ const glishConfig = loadGlishConfig(dirname(abs));
369
+ const { card, tiers } = await scoreSource(readFileSync(abs, "utf8"), glishConfig === void 0 ? void 0 : { glishConfig });
370
+ if (values.json) {
371
+ process.stdout.write(`${JSON.stringify({ file, tiers, card }, null, 2)}
372
+ `);
373
+ } else {
374
+ const gateLabel = card.gate.pass ? "PASS" : "FAIL";
375
+ const ran = [`base`, ...tiers.z3 ? ["z3"] : [], ...tiers.spell ? ["spell"] : []].join("+");
376
+ process.stdout.write(`${file} \u2014 ${card.grade} (${card.number}/100) gate: ${gateLabel} tiers: ${ran}
377
+ `);
378
+ if (!card.gate.pass) for (const r of card.gate.reasons) process.stdout.write(` \u2716 ${r.slice(0, 110)}
379
+ `);
380
+ for (const d of card.ledger.slice(0, 10)) {
381
+ process.stdout.write(` L${d.line + 1} ${d.source.padEnd(28)} \u2212${d.points} ${d.message.slice(0, 78)}
382
+ `);
383
+ }
384
+ }
385
+ const min = values.min !== void 0 ? parseMin(values.min) : null;
386
+ if (min !== null && (!card.gate.pass || card.number < min)) {
387
+ process.stderr.write(`score ${card.number} (${card.grade}) below --min ${min}${card.gate.pass ? "" : " (gate failed)"}
388
+ `);
389
+ process.exitCode = 1;
390
+ }
391
+ return;
392
+ }
393
+ if (command === "reference") {
394
+ process.stdout.write(renderAgentReference());
395
+ return;
396
+ }
397
+ if (command === "mcp") {
398
+ const { startMcpServer } = await import('./mcp.js');
399
+ await startMcpServer({ cwd: process.cwd(), version: cliVersion() });
400
+ return;
401
+ }
402
+ if (command === "claude-hook") {
403
+ const kind = files[0] ?? "";
404
+ const payload = readFileSync(0, "utf8");
405
+ const readFile = (path) => {
406
+ try {
407
+ return readFileSync(path, "utf8");
408
+ } catch {
409
+ return null;
410
+ }
411
+ };
412
+ const verdict = await runClaudeHook(kind, payload, {
413
+ readFile,
414
+ loadGlish: (filePath) => loadGlishConfig(dirname(resolve(filePath))),
415
+ readUp: (fileName, fromDir) => {
416
+ const hit = findUp(fileName, resolve(fromDir));
417
+ return hit === null ? null : readFile(hit);
418
+ },
419
+ env: (name) => process.env[name]
420
+ });
421
+ if (verdict.stdout !== null) process.stdout.write(`${verdict.stdout}
422
+ `);
423
+ process.exitCode = verdict.exitCode;
424
+ return;
425
+ }
426
+ if (command === "resolve") {
427
+ const file = files[0];
428
+ if (file === void 0) {
429
+ process.stderr.write("typeglish resolve: no file given\n");
430
+ process.exitCode = 2;
431
+ return;
432
+ }
433
+ const bag = values.vars ? JSON.parse(values.vars) : {};
434
+ process.stdout.write(resolve$1(readFileSync(file, "utf8"), bag));
435
+ return;
436
+ }
437
+ process.stderr.write(`typeglish: unknown command "${command}" \u2014 try \`typeglish --help\`
438
+ `);
439
+ process.exitCode = 2;
440
+ }
441
+ main().catch((err) => {
442
+ process.stderr.write(`typeglish: ${err instanceof Error ? err.message : String(err)}
443
+ `);
444
+ process.exitCode = 1;
445
+ });
446
+ //# sourceMappingURL=cli.js.map
447
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/cli-format.ts","../src/lib/deploy-gate.ts","../src/lib/claude-hook.ts","../src/lib/cli.ts"],"names":["resolvePath","resolve"],"mappings":"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","file":"cli.js","sourcesContent":["// ── CLI output formatting ───────────────────────────────────────────────────────────────────────────────\n// Pure: report(s) → text. Kept out of cli.ts (which reads argv + files + calls process.exit on load) so it's\n// unit-testable on its own. The line format follows the compiler convention `file:line:col severity code`,\n// which editors and CI log parsers already understand.\n\nimport type { TgReport } from '../core/report';\n\nexport interface FileReport {\n file: string;\n report: TgReport;\n /** Which tier produced the report: 'full' (Z3) or 'sync' (optional peer absent). Absent = unknown/legacy. */\n checkMode?: 'full' | 'sync';\n}\n\n/** Compiler-style diagnostics plus a one-line summary. Blocking (effective-error) findings sort first. */\nexport function formatText(results: FileReport[]): string {\n const out: string[] = [];\n for (const { file, report } of results) {\n for (const d of report.diagnostics) {\n out.push(`${file}:${d.range.line}:${d.range.column} ${d.effectiveSeverity.padEnd(5)} ${d.code} ${d.message}`);\n }\n }\n const totals = results.reduce(\n (a, { report }) => ({ error: a.error + report.counts.error, warn: a.warn + report.counts.warn, info: a.info + report.counts.info }),\n { error: 0, warn: 0, info: 0 },\n );\n if (out.length > 0) out.push('');\n const ok = totals.error === 0;\n out.push(`${ok ? '✓' : '✗'} ${results.length} file${results.length === 1 ? '' : 's'} — ${totals.error} error, ${totals.warn} warning, ${totals.info} info`);\n return out.join('\\n');\n}\n\n/** Did any file have a blocking (effective-error) diagnostic? Drives the CLI exit code. */\nexport function anyBlocking(results: FileReport[]): boolean {\n return results.some((r) => !r.report.ok);\n}\n","// ── The deploy gate — \"only compiled prompts ship\" as a mechanical check ────────────────────────────────\n// A PreToolUse hook fires on MCP calls; this module decides. The claim it verifies: the outgoing prompt\n// payload was produced, byte-for-byte (modulo canonicalization), by a PASSING `typeglish build` — proven by\n// hashing every plausible prompt string in the tool input and testing membership against the build\n// manifest's artifact hashes. No match → deny, with the fix in the message (author .tg → check → build →\n// deploy the artifact verbatim). Match → NO decision is emitted: the write proceeds through Claude Code's\n// NORMAL permission flow. The gate never auto-approves; it can only refuse or stay out of the way.\n//\n// Voiceflow reality (captured live from the MCP schemas): prompt payloads are RICH-TEXT ARRAYS — items are\n// strings, {text: <recursive>} spans, or reference objects ({variableID}, {resourceID}, {secretID},\n// {entityID}) — and tool names carry host-variable prefixes (mcp__voiceflow__* project-scoped,\n// mcp__<uuid>__* account connectors). So matching is by tool-name SUFFIX, and candidate texts come from a\n// recursive walk that flattens rich text the way the platform renders it.\n\nimport { canonicalize, sha256 } from './build';\nimport type { BuildManifest, ManifestEntry } from './build';\n\nexport interface GateConfig {\n /** deny (default — the gate is the product) · ask (human arbitrates) · off. */\n mode: 'deny' | 'ask' | 'off';\n /** Tool-name SUFFIXES gated whenever a mutating call carries prompt text. Extend via .typeglish/deploy-gate.json. */\n tools: string[];\n /** The heuristic tier's floor: other mutating voiceflow_* calls gate only when a candidate is at least this long. */\n minChars: number;\n}\n\nexport const GATE_CONFIG_FILE = '.typeglish/deploy-gate.json';\n\nexport const DEFAULT_GATE_CONFIG: GateConfig = {\n mode: 'deny',\n tools: ['voiceflow_agent_instructions', 'voiceflow_agent_global_prompt', 'voiceflow_behavior'],\n minChars: 80,\n};\n\n/** Merge a parsed config file over the defaults; malformed input counts as absent. */\nexport function resolveGateConfig(text: string | null): GateConfig {\n if (text === null) return DEFAULT_GATE_CONFIG;\n try {\n const raw = JSON.parse(text) as Partial<GateConfig>;\n return {\n mode: raw.mode === 'ask' || raw.mode === 'off' || raw.mode === 'deny' ? raw.mode : DEFAULT_GATE_CONFIG.mode,\n tools: Array.isArray(raw.tools) ? raw.tools.map(String) : DEFAULT_GATE_CONFIG.tools,\n minChars: typeof raw.minChars === 'number' && raw.minChars > 0 ? raw.minChars : DEFAULT_GATE_CONFIG.minChars,\n };\n } catch {\n return DEFAULT_GATE_CONFIG;\n }\n}\n\n/** The tool's own name, with any host-assigned `mcp__<server>__` prefix stripped. */\nexport function toolSuffix(toolName: string): string {\n const i = toolName.lastIndexOf('__');\n return i === -1 ? toolName : toolName.slice(i + 2);\n}\n\n/** Voiceflow rich text → the plain string the platform renders: strings pass through, {text} spans recurse,\n * reference objects ({variableID} & co.) contribute nothing. */\nfunction flattenRichText(node: unknown): string {\n if (typeof node === 'string') return node;\n if (Array.isArray(node)) return node.map(flattenRichText).join('');\n if (node !== null && typeof node === 'object' && 'text' in node) return flattenRichText((node as { text: unknown }).text);\n return '';\n}\n\n/** Every plausible prompt string in a tool input: standalone strings, plus each array flattened as rich\n * text — joined both tightly ('') and by lines ('\\n'), since an author may pass one string or a list of\n * blocks. Deduplicated; only candidates >= minChars survive (short ids/enums are never prompts). */\nexport function candidateTexts(input: unknown, minChars: number): string[] {\n const found = new Set<string>();\n const consider = (s: string): void => {\n if (s.trim().length >= minChars) found.add(s);\n };\n const walk = (node: unknown): void => {\n if (typeof node === 'string') {\n consider(node);\n return;\n }\n if (Array.isArray(node)) {\n const flat = node.map(flattenRichText);\n consider(flat.join(''));\n consider(flat.join('\\n'));\n for (const item of node) walk(item);\n return;\n }\n if (node !== null && typeof node === 'object') {\n for (const value of Object.values(node)) walk(value);\n }\n };\n walk(input);\n return [...found];\n}\n\n/** Operations that only read — never gated. Anything else (update/create/patch/…, or absent) counts as mutating\n * for the configured tool set; the heuristic tier additionally requires an explicit mutating operation. */\nconst READ_OPS = new Set(['get', 'list', 'search', 'read', 'retrieve', 'describe']);\n\nexport type GateVerdict =\n | { action: 'pass' }\n | { action: 'verified'; entry: ManifestEntry }\n | { action: 'deny' | 'ask'; reason: string };\n\nexport function evaluateGate(toolName: string, toolInput: unknown, manifest: BuildManifest | null, config: GateConfig): GateVerdict {\n if (config.mode === 'off') return { action: 'pass' };\n const suffix = toolSuffix(toolName);\n const operation = (toolInput as { operation?: unknown } | null)?.operation;\n const isReadOp = typeof operation === 'string' && READ_OPS.has(operation.toLowerCase());\n if (isReadOp) return { action: 'pass' };\n\n const configured = config.tools.includes(suffix);\n // The heuristic tier: an unlisted voiceflow_* tool gates only on an EXPLICIT mutating operation — an\n // unknown surface without an operation field is left alone rather than false-denied.\n const heuristic = !configured && suffix.startsWith('voiceflow_') && typeof operation === 'string';\n if (!configured && !heuristic) return { action: 'pass' };\n\n const candidates = candidateTexts(toolInput, config.minChars);\n if (candidates.length === 0) return { action: 'pass' }; // no prompt-sized text — a settings/metadata write\n\n const known = new Set((manifest?.builds ?? []).map((b) => b.artifactSha256));\n const match = candidates.map((c) => sha256(canonicalize(c))).find((h) => known.has(h));\n if (match !== undefined) {\n const entry = (manifest?.builds ?? []).find((b) => b.artifactSha256 === match) as ManifestEntry;\n return { action: 'verified', entry };\n }\n\n const reason =\n manifest === null\n ? `This prompt payload is not TypeGlish-verified: no build manifest found (.typeglish/build-manifest.json). ` +\n `Author the prompt as a .tg file, run \\`typeglish check\\` until clean, run \\`typeglish build <file>\\`, ` +\n `then deploy the exact contents of the built artifact (.typeglish/dist/<name>.txt) unmodified.`\n : `This prompt payload does not match any \\`typeglish build\\` artifact in the manifest. ` +\n `Deploy the exact contents of a built artifact (.typeglish/dist/<name>.txt) unmodified — if you edited the prompt, ` +\n `edit the .tg source instead, re-run \\`typeglish check\\` and \\`typeglish build\\`, and send the fresh artifact.`;\n const escape = ` If this write is intentionally not TypeGlish-managed, set TYPEGLISH_DEPLOY_GATE=off or adjust ${GATE_CONFIG_FILE}.`;\n return { action: config.mode, reason: reason + escape };\n}\n","// ── Claude Code hook logic — versioned WITH the compiler ────────────────────────────────────────────────\n// The plugin's hooks.json calls a tiny dependency-free shim (plugin/scripts/tg-hook.mjs) which pipes the\n// hook's stdin JSON into `typeglish claude-hook <kind>`. ALL protocol logic lives here, in TypeScript,\n// unit-tested and released with the compiler — the shim only resolves the binary. If Claude Code's hook\n// JSON schema ever moves, this one module is the whole blast radius.\n//\n// Kinds:\n// post-edit — PostToolUse on Write|Edit. A settled edit to a `.tg` file re-checks it: blocking errors\n// come back as {decision: \"block\", reason} so the agent self-corrects immediately; warnings ride\n// along as additionalContext; a clean file stays silent. Fail-open by design: a missing file, non-.tg\n// path, or unparseable payload produces NO output — a broken toolchain must never block editing.\n// deploy-gate — PreToolUse on MCP calls. Verifies the outgoing prompt payload against the build\n// manifest (deploy-gate.ts) and denies unverified prompt pushes. A verified payload emits NO\n// permissionDecision — the write proceeds through the NORMAL permission flow (the gate never\n// auto-approves) — plus a context note naming the matched artifact, with a staleness advisory when\n// the .tg source changed after the build.\n\nimport { resolve as resolvePath } from 'node:path';\n\nimport type { ReportCompileOptions } from '../core/report';\nimport { MANIFEST_FILE, canonicalize, checkSource, parseManifest, sha256 } from './build';\nimport { formatText } from './cli-format';\nimport { GATE_CONFIG_FILE, evaluateGate, resolveGateConfig } from './deploy-gate';\n\n/** The slice of the PostToolUse stdin payload the hook reads. */\ninterface PostEditPayload {\n tool_input?: { file_path?: string };\n}\n\n/** The slice of the PreToolUse stdin payload the gate reads. */\ninterface DeployGatePayload {\n tool_name?: string;\n tool_input?: unknown;\n cwd?: string;\n}\n\n/** Injected effects — the CLI wires node:fs + project discovery; tests pass fakes. */\nexport interface HookDeps {\n /** Read a file's current contents, or null when unreadable. */\n readFile: (path: string) => string | null;\n /** The nearest glish.tgc source for a file's directory (project.ts loadGlishConfig), or undefined. */\n loadGlish: (filePath: string) => string | undefined;\n /** Walk up from a directory and read the first `fileName` hit (project.ts findUp + read), or null. */\n readUp: (fileName: string, fromDir: string) => string | null;\n /** Environment lookup (TYPEGLISH_DEPLOY_GATE). */\n env: (name: string) => string | undefined;\n}\n\nexport interface HookVerdict {\n /** JSON for stdout, or null for silence. */\n stdout: string | null;\n exitCode: number;\n}\n\nconst SILENT: HookVerdict = { stdout: null, exitCode: 0 };\n\nasync function postEdit(payloadText: string, deps: HookDeps): Promise<HookVerdict> {\n let payload: PostEditPayload;\n try {\n payload = JSON.parse(payloadText) as PostEditPayload;\n } catch {\n return SILENT; // unparseable hook payload — never block editing over our own plumbing\n }\n const filePath = payload.tool_input?.file_path;\n if (filePath === undefined || !/\\.tg$/i.test(filePath)) return SILENT;\n\n const source = deps.readFile(filePath);\n if (source === null) return SILENT;\n\n const glishConfig = deps.loadGlish(filePath);\n const compileOpts: ReportCompileOptions | undefined = glishConfig === undefined ? undefined : { glishConfig };\n const { report, checkMode } = await checkSource(source, {}, compileOpts);\n\n const text = formatText([{ file: filePath, checkMode, report }]);\n if (!report.ok) {\n return {\n stdout: JSON.stringify({\n decision: 'block',\n reason: `${text}\\n\\nThese are compile errors in TypeGlish source — fix them now. \\`typeglish --explain <code>\\` explains any code; a diagnostic's fix field is mechanically applicable.`,\n }),\n exitCode: 0,\n };\n }\n if (report.counts.warn > 0) {\n return {\n stdout: JSON.stringify({\n hookSpecificOutput: {\n hookEventName: 'PostToolUse',\n additionalContext: `typeglish: ${filePath} compiles (${checkMode} tier) with advisories:\\n${text}`,\n },\n }),\n exitCode: 0,\n };\n }\n return SILENT; // clean — silence is the success signal\n}\n\nfunction deployGate(payloadText: string, deps: HookDeps): HookVerdict {\n let payload: DeployGatePayload;\n try {\n payload = JSON.parse(payloadText) as DeployGatePayload;\n } catch {\n return SILENT;\n }\n const toolName = payload.tool_name;\n if (toolName === undefined) return SILENT;\n\n const envMode = deps.env('TYPEGLISH_DEPLOY_GATE')?.toLowerCase();\n if (envMode === 'off') return SILENT;\n\n const cwd = payload.cwd ?? '.';\n const config = resolveGateConfig(deps.readUp(GATE_CONFIG_FILE, cwd));\n if (envMode === 'ask' || envMode === 'deny') config.mode = envMode;\n if (config.mode === 'off') return SILENT;\n\n const manifest = parseManifest(deps.readUp(MANIFEST_FILE, cwd));\n const verdict = evaluateGate(toolName, payload.tool_input, manifest, config);\n\n if (verdict.action === 'pass') return SILENT;\n if (verdict.action === 'verified') {\n const { entry } = verdict;\n const current = deps.readFile(resolvePath(cwd, entry.source));\n const stale = current !== null && sha256(canonicalize(current)) !== entry.sourceSha256;\n return {\n stdout: JSON.stringify({\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n additionalContext:\n `typeglish: payload verified — matches ${entry.artifact} (built from ${entry.source}, ${entry.checkMode} tier).` +\n (stale ? ` NOTE: ${entry.source} changed AFTER this build — if that change should ship, run \\`typeglish build ${entry.source}\\` and deploy the fresh artifact.` : ''),\n },\n }),\n exitCode: 0,\n };\n }\n return {\n stdout: JSON.stringify({\n hookSpecificOutput: {\n hookEventName: 'PreToolUse',\n permissionDecision: verdict.action,\n permissionDecisionReason: verdict.reason,\n },\n }),\n exitCode: 0,\n };\n}\n\n/** Run one hook kind over the raw stdin payload. Returns what to print and how to exit. */\nexport async function runClaudeHook(kind: string, payloadText: string, deps: HookDeps): Promise<HookVerdict> {\n if (kind === 'post-edit') return postEdit(payloadText, deps);\n if (kind === 'deploy-gate') return deployGate(payloadText, deps);\n // An unknown kind is a version skew between plugin and CLI — fail open, say nothing.\n return SILENT;\n}\n","#!/usr/bin/env node\n// ── typeglish CLI ───────────────────────────────────────────────────────────────────────────────────────\n// `npx typeglish check **/*.tg` — validate prompt files in CI with zero code; `typeglish build` — compile\n// passing files into deployable artifacts + the provenance manifest the deploy gate verifies against;\n// `typeglish resolve` — apply the conditionals for a given input bag. Checks run the FULL tier (reportFull,\n// Z3) when the optional z3-solver peer is present and fall back to the synchronous checker otherwise — but\n// ONLY on the missing peer: a genuine solver crash surfaces (MissingSolverError is the one degradable case).\n//\n// Agent contract: `--json` puts machine-readable data on stdout; status and diagnostics go to stderr.\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { dirname, resolve as resolvePath } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { parseArgs } from 'node:util';\n\nimport { renderAgentReference } from '../core/agent-doc';\nimport { DIAGNOSTIC_CODES, blocks } from '../core/codes';\nimport { resolve as resolveTg } from '../core/compile';\nimport type { Bag } from '../core/compile';\nimport type { StrictnessPolicy } from '../core/report';\nimport { type BuildManifest, DEFAULT_OUT_DIR, MANIFEST_FILE, artifactPathFor, buildPrompt, checkSource, parseManifest, sourceKey, toPosix, upsertManifest } from './build';\nimport { runClaudeHook } from './claude-hook';\nimport { type FileReport, anyBlocking, formatText } from './cli-format';\nimport { findUp, loadGlishConfig } from './project';\nimport { parseMin, scoreSource } from './score';\n\nconst HELP = `typeglish — the typed-English prompt compiler\n\nUsage:\n typeglish check <file...> [--strict] [--json] validate; exits 1 when any file has a blocking error\n typeglish build <file...> [build options] compile passing files to artifacts + record the manifest\n typeglish score <file> [--min B|80] [--json] the deterministic TG score; exits 1 below --min\n typeglish resolve <file> [--vars '<json>'] apply conditionals, print the resolved SOURCE (a .tg —\n the deployable prompt is what \\`build\\` writes)\n typeglish reference print the language reference (agents: read this first)\n typeglish mcp serve check/build/score/explain/reference over MCP stdio\n typeglish --explain <code> what a diagnostic code means (e.g. logic/contradiction)\n typeglish --version | --help\n\nBuild options:\n --out-dir <dir> artifact directory (default: .typeglish/dist)\n --vars '<json>' input bag — conditionals compile away; omitted = template build (unbound switches\n stay as conditional prose, runtime {curly} variables pass through)\n --bundle also write <artifact>.agent.json — the $CONFIG / $TOOL agent bundle\n\nOptions:\n --strict escalate every IMPORTANT finding (correctness defects) to a blocking error\n --json machine-readable output on stdout (agents: parse this, not the text)\n --vars a JSON object of input values, e.g. '{\"tier\":\"premium\"}'\n --min score floor — a grade (A–F) or a number; the CI gate\n\nThe check runs the full tier (Z3 proofs) when the optional z3-solver peer is installed, else the\nsynchronous checker; build records which as checkMode in .typeglish/build-manifest.json.`;\n\n/** `--explain <code>`: the rustc pattern over the diagnostic-code registry (codes.ts, the SSOT). */\nfunction explain(code: string): { text: string; found: boolean } {\n const info = DIAGNOSTIC_CODES[code];\n if (info !== undefined) {\n const gate = blocks(code) ? ' — blocks compilation' : '';\n return { found: true, text: `${code} (${info.severity}${gate})\\n ${info.summary}` };\n }\n const near = Object.keys(DIAGNOSTIC_CODES).filter((k) => k.includes(code)).sort();\n if (near.length > 0) {\n return { found: true, text: near.map((k) => `${k.padEnd(34)} ${DIAGNOSTIC_CODES[k]?.severity ?? ''} ${DIAGNOSTIC_CODES[k]?.summary ?? ''}`).join('\\n') };\n }\n return { found: false, text: `typeglish --explain: unknown code \"${code}\" — codes look like category/name (e.g. logic/contradiction)` };\n}\n\n/** The installed package version — walk up from this module (dist/ or src/lib/) to package.json. */\nfunction cliVersion(): string {\n try {\n const pkgPath = findUp('package.json', dirname(fileURLToPath(import.meta.url)));\n if (pkgPath !== null) {\n const version = (JSON.parse(readFileSync(pkgPath, 'utf8')) as { version?: string }).version;\n if (version !== undefined) return version;\n }\n } catch {\n // fall through — a broken install still gets a usable CLI\n }\n return '0.0.0-dev';\n}\n\nconst MANIFEST_PATH = MANIFEST_FILE;\n\nasync function main(): Promise<void> {\n const { values, positionals } = parseArgs({\n allowPositionals: true,\n options: {\n json: { type: 'boolean', default: false },\n strict: { type: 'boolean', default: false },\n vars: { type: 'string' },\n 'out-dir': { type: 'string' },\n bundle: { type: 'boolean', default: false },\n min: { type: 'string' },\n explain: { type: 'string' },\n version: { type: 'boolean', short: 'v', default: false },\n help: { type: 'boolean', short: 'h', default: false },\n },\n });\n const [command, ...files] = positionals;\n\n if (values.version) {\n process.stdout.write(`${cliVersion()}\\n`);\n return;\n }\n if (values.explain !== undefined) {\n const { text, found } = explain(values.explain);\n process.stdout.write(`${text}\\n`);\n process.exitCode = found ? 0 : 2;\n return;\n }\n if (values.help || command === undefined) {\n process.stdout.write(`${HELP}\\n`);\n return;\n }\n\n if (command === 'check') {\n if (files.length === 0) {\n process.stderr.write('typeglish check: no files given\\n');\n process.exitCode = 2;\n return;\n }\n const policy: StrictnessPolicy = values.strict ? { escalateImportance: 'important' } : {};\n const results: FileReport[] = [];\n for (const file of files) {\n const abs = resolvePath(file);\n const glishConfig = loadGlishConfig(dirname(abs));\n const { report, checkMode } = await checkSource(readFileSync(abs, 'utf8'), policy, glishConfig === undefined ? undefined : { glishConfig });\n results.push({ file, checkMode, report });\n }\n process.stdout.write(`${values.json ? JSON.stringify(results, null, 2) : formatText(results)}\\n`);\n process.exitCode = anyBlocking(results) ? 1 : 0;\n return;\n }\n\n if (command === 'build') {\n if (files.length === 0) {\n process.stderr.write('typeglish build: no files given\\n');\n process.exitCode = 2;\n return;\n }\n const cwd = process.cwd();\n const outDir = toPosix(values['out-dir'] ?? DEFAULT_OUT_DIR);\n const vars = values.vars !== undefined ? (JSON.parse(values.vars) as Bag) : undefined;\n const version = cliVersion();\n const jsonOut: object[] = [];\n let manifest: BuildManifest | null = parseManifest(existsSync(MANIFEST_PATH) ? readFileSync(MANIFEST_PATH, 'utf8') : null);\n let failed = false;\n\n for (const file of files) {\n const abs = resolvePath(file);\n const source = readFileSync(abs, 'utf8');\n const srcKey = sourceKey(cwd, abs);\n const artifactRel = artifactPathFor(srcKey, outDir);\n const outcome = await buildPrompt(\n source,\n { source: srcKey, artifact: artifactRel },\n { vars, strict: values.strict, glishConfig: loadGlishConfig(dirname(abs)), version, bundle: values.bundle },\n );\n\n if (!outcome.ok || outcome.entry === undefined || outcome.artifact === undefined) {\n failed = true;\n const why = outcome.error ?? formatText([{ file, checkMode: outcome.checkMode, report: outcome.report }]);\n process.stderr.write(`typeglish build: ${srcKey} refused — nothing written\\n${why}\\n`);\n jsonOut.push({ file: srcKey, ok: false, checkMode: outcome.checkMode, error: outcome.error, counts: outcome.report.counts });\n continue;\n }\n\n const artifactAbs = resolvePath(cwd, artifactRel);\n mkdirSync(dirname(artifactAbs), { recursive: true });\n writeFileSync(artifactAbs, outcome.artifact);\n if (outcome.agentJson !== undefined) writeFileSync(artifactAbs.replace(/\\.txt$/, '.agent.json'), outcome.agentJson);\n manifest = upsertManifest(manifest, outcome.entry);\n jsonOut.push({ file: srcKey, ok: true, checkMode: outcome.checkMode, entry: outcome.entry });\n if (!values.json) {\n process.stdout.write(`✓ built ${artifactRel} ← ${srcKey} (${outcome.entry.artifactSha256.slice(0, 12)}, ${outcome.checkMode})\\n`);\n }\n }\n\n if (manifest !== null && manifest.builds.length > 0) {\n mkdirSync(dirname(MANIFEST_PATH), { recursive: true });\n writeFileSync(MANIFEST_PATH, `${JSON.stringify(manifest, null, 2)}\\n`);\n }\n if (values.json) process.stdout.write(`${JSON.stringify(jsonOut, null, 2)}\\n`);\n process.exitCode = failed ? 1 : 0;\n return;\n }\n\n if (command === 'score') {\n const file = files[0];\n if (file === undefined) {\n process.stderr.write('typeglish score: no file given\\n');\n process.exitCode = 2;\n return;\n }\n const abs = resolvePath(file);\n const glishConfig = loadGlishConfig(dirname(abs));\n const { card, tiers } = await scoreSource(readFileSync(abs, 'utf8'), glishConfig === undefined ? undefined : { glishConfig });\n if (values.json) {\n process.stdout.write(`${JSON.stringify({ file, tiers, card }, null, 2)}\\n`);\n } else {\n const gateLabel = card.gate.pass ? 'PASS' : 'FAIL';\n const ran = [`base`, ...(tiers.z3 ? ['z3'] : []), ...(tiers.spell ? ['spell'] : [])].join('+');\n process.stdout.write(`${file} — ${card.grade} (${card.number}/100) gate: ${gateLabel} tiers: ${ran}\\n`);\n if (!card.gate.pass) for (const r of card.gate.reasons) process.stdout.write(` ✖ ${r.slice(0, 110)}\\n`);\n for (const d of card.ledger.slice(0, 10)) {\n process.stdout.write(` L${d.line + 1} ${d.source.padEnd(28)} −${d.points} ${d.message.slice(0, 78)}\\n`);\n }\n }\n const min = values.min !== undefined ? parseMin(values.min) : null;\n if (min !== null && (!card.gate.pass || card.number < min)) {\n process.stderr.write(`score ${card.number} (${card.grade}) below --min ${min}${card.gate.pass ? '' : ' (gate failed)'}\\n`);\n process.exitCode = 1;\n }\n return;\n }\n\n if (command === 'reference') {\n process.stdout.write(renderAgentReference());\n return;\n }\n\n if (command === 'mcp') {\n // Dynamic import: the SDK chunk loads only here — check/build startup stays SDK-free.\n const { startMcpServer } = await import('./mcp');\n await startMcpServer({ cwd: process.cwd(), version: cliVersion() });\n return;\n }\n\n // Plumbing for the Claude Code plugin (plugin/scripts/tg-hook.mjs pipes the hook's stdin JSON here).\n // Not in --help on purpose: it speaks the hook protocol, not the human one.\n if (command === 'claude-hook') {\n const kind = files[0] ?? '';\n const payload = readFileSync(0, 'utf8'); // fd 0 = stdin\n const readFile = (path: string): string | null => {\n try {\n return readFileSync(path, 'utf8');\n } catch {\n return null;\n }\n };\n const verdict = await runClaudeHook(kind, payload, {\n readFile,\n loadGlish: (filePath) => loadGlishConfig(dirname(resolvePath(filePath))),\n readUp: (fileName, fromDir) => {\n const hit = findUp(fileName, resolvePath(fromDir));\n return hit === null ? null : readFile(hit);\n },\n env: (name) => process.env[name],\n });\n if (verdict.stdout !== null) process.stdout.write(`${verdict.stdout}\\n`);\n process.exitCode = verdict.exitCode;\n return;\n }\n\n if (command === 'resolve') {\n const file = files[0];\n if (file === undefined) {\n process.stderr.write('typeglish resolve: no file given\\n');\n process.exitCode = 2;\n return;\n }\n const bag = values.vars ? (JSON.parse(values.vars) as Bag) : {};\n process.stdout.write(resolveTg(readFileSync(file, 'utf8'), bag));\n return;\n }\n\n process.stderr.write(`typeglish: unknown command \"${command}\" — try \\`typeglish --help\\`\\n`);\n process.exitCode = 2;\n}\n\nmain().catch((err: unknown) => {\n process.stderr.write(`typeglish: ${err instanceof Error ? err.message : String(err)}\\n`);\n process.exitCode = 1;\n});\n"]}