@directive-run/cli 1.14.0 → 1.16.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 +19 -4
- package/dist/cli.js +140 -91
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +41 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +41 -8
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/cli.js
CHANGED
|
@@ -1,17 +1,50 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {existsSync,readFileSync,mkdirSync,writeFileSync,readdirSync}from'fs';import {resolve,join,relative,dirname}from'path';import*as
|
|
2
|
+
import {existsSync,readFileSync,mkdirSync,writeFileSync,readdirSync}from'fs';import {resolve,join,relative,dirname}from'path';import*as g from'@clack/prompts';import m from'picocolors';import {getAllExamples,getExample,getKnowledge}from'@directive-run/knowledge';var O="directive";var oe="<!-- directive:start -->",Y="<!-- directive:end -->";var Pe=[{id:"cursor",name:"Cursor",signals:[".cursor",".cursorrules"],outputPath:".cursorrules"},{id:"claude",name:"Claude Code",signals:[".claude"],outputPath:".claude/CLAUDE.md"},{id:"copilot",name:"GitHub Copilot",signals:[".github"],outputPath:".github/copilot-instructions.md"},{id:"windsurf",name:"Windsurf",signals:[".windsurfrules"],outputPath:".windsurfrules"},{id:"cline",name:"Cline",signals:[".clinerules"],outputPath:".clinerules"}];function rt(e){let t=[];for(let r of Pe)r.signals.some(n=>existsSync(join(e,n)))&&t.push({name:r.name,id:r.id,outputPath:join(e,r.outputPath)});return t}function ie(e){let t=Pe.find(r=>r.id===e);if(!t)throw new Error(`Unknown tool: ${e}`);return t}function qe(){return Pe.map(e=>e.id)}function X(e,t){let r=e.indexOf(oe),s=e.indexOf(Y),n=`${oe}
|
|
3
3
|
${t}
|
|
4
|
-
${
|
|
4
|
+
${Y}`;if(r!==-1&&s!==-1&&s>r)return e.slice(0,r)+n+e.slice(s+Y.length);let o=e.endsWith(`
|
|
5
5
|
`)?`
|
|
6
6
|
`:`
|
|
7
7
|
|
|
8
|
-
`;return e+o+n
|
|
9
|
-
`}function
|
|
8
|
+
`;return `${e+o+n}
|
|
9
|
+
`}function V(e){return e.includes(oe)&&e.includes(Y)}var cr=[{file:"pnpm-workspace.yaml",tool:"pnpm"},{file:"turbo.json",tool:"turbo"}];function We(e){let t=resolve(e);for(;t!==dirname(t);){for(let s of cr)if(existsSync(join(t,s.file)))return {isMonorepo:true,rootDir:t,tool:s.tool};let r=join(t,"package.json");if(existsSync(r))try{if(JSON.parse(readFileSync(r,"utf-8")).workspaces){let n=existsSync(join(t,"yarn.lock"))?"yarn":"npm";return {isMonorepo:!0,rootDir:t,tool:n}}}catch{}t=dirname(t);}return {isMonorepo:false,rootDir:e}}function ot(){let e=getKnowledge("core-patterns"),t=getKnowledge("anti-patterns"),r=getKnowledge("naming"),s=getKnowledge("schema-types");return `# Directive \u2014 Complete AI Coding Rules
|
|
10
10
|
|
|
11
11
|
> Constraint-driven runtime for TypeScript. Declare requirements, let the runtime resolve them.
|
|
12
12
|
> https://directive.run | \`npm install @directive-run/core\`
|
|
13
13
|
> Full reference with examples: https://directive.run/llms.txt
|
|
14
14
|
|
|
15
|
+
## When to reach for Directive
|
|
16
|
+
|
|
17
|
+
Directive is to **business state and agent orchestration** what XState
|
|
18
|
+
is to state machines and React Query is to server state \u2014 a runtime
|
|
19
|
+
that takes declarative rules ("what must be true") and runs the
|
|
20
|
+
resolvers ("how to make it true"). The unique claim only Directive can
|
|
21
|
+
make: **state and AI agents share the same runtime**. \`@directive-run/ai\`
|
|
22
|
+
is the only state-library ecosystem that ships LLM orchestration as a
|
|
23
|
+
sibling concept to facts/constraints/resolvers.
|
|
24
|
+
|
|
25
|
+
It is NOT a Redux replacement for cross-cutting global UI state. It is
|
|
26
|
+
a constraint engine you compose alongside Redux / Zustand / Jotai /
|
|
27
|
+
React Query / TanStack Query.
|
|
28
|
+
|
|
29
|
+
**Reach for Directive when:**
|
|
30
|
+
|
|
31
|
+
- The same business rule has to fire across React, Vue, server, and
|
|
32
|
+
background workers. Directive runs the same module in every runtime.
|
|
33
|
+
- A constraint should drive a side-effect (fetch, validate, cancel,
|
|
34
|
+
retry) declaratively, without writing imperative thunks.
|
|
35
|
+
- You are orchestrating LLM agents and need typed, replayable state +
|
|
36
|
+
guardrails + budgets + audit trails + checkpoints.
|
|
37
|
+
- You want time-travel debugging, audit logs, or rules-diff replay on
|
|
38
|
+
state mutations without instrumenting every component.
|
|
39
|
+
|
|
40
|
+
**Do NOT reach for Directive for:**
|
|
41
|
+
|
|
42
|
+
- Plain UI state (use signals / Zustand / Jotai).
|
|
43
|
+
- Server-state caching only (use React Query / TanStack Query
|
|
44
|
+
\u2014 though you can layer \`@directive-run/query\` on top when you need
|
|
45
|
+
the constraint engine alongside fetching).
|
|
46
|
+
- State machines that don't react to external facts (use XState).
|
|
47
|
+
|
|
15
48
|
## Core Patterns
|
|
16
49
|
|
|
17
50
|
${e}
|
|
@@ -30,7 +63,7 @@ ${t}
|
|
|
30
63
|
| 22 | \`facts.cache.push(item)\` in orchestrator | \`facts.cache = [...facts.cache, item]\` |
|
|
31
64
|
| 23 | Returning data from orchestrator \`resolve\` | Resolvers return \`void\` \u2014 mutate \`context.facts\` |
|
|
32
65
|
| 24 | Forgetting \`orchestrator.start()\` multi-agent | Single: implicit. Multi: must call \`start()\` |
|
|
33
|
-
| 25 | Catching \`Error\` not \`GuardrailError\` | \`GuardrailError\` has \`.guardrailName\`, \`.
|
|
66
|
+
| 25 | Catching \`Error\` not \`GuardrailError\` | \`GuardrailError\` has \`.guardrailName\`, \`.code\`, \`.userMessage\` |
|
|
34
67
|
| 26 | \`from '@directive-run/ai'\` for adapters | Subpath: \`from '@directive-run/ai/openai'\` |
|
|
35
68
|
| 27 | Assuming \`{ input_tokens }\` structure | Normalized: \`{ inputTokens, outputTokens }\` |
|
|
36
69
|
| 28 | Same CircuitBreaker across agents | Create separate instances per dependency |
|
|
@@ -226,7 +259,7 @@ for await (const chunk of streamResult.stream) {
|
|
|
226
259
|
\`\`\`
|
|
227
260
|
|
|
228
261
|
Backpressure: \`"buffer"\` (default), \`"block"\`, \`"drop"\`
|
|
229
|
-
`}function
|
|
262
|
+
`}function Se(){return '# Directive \u2014 AI Coding Rules\n\n> Constraint-driven runtime for TypeScript. `npm install @directive-run/core`\n> Full reference: https://directive.run/llms.txt\n\n## When to reach for Directive\n\nDirective is to **business state** what XState is to state machines and\nReact Query is to server state \u2014 a runtime that takes declarative rules\n("what must be true") and runs the resolvers ("how to make it true") for\nyou. It is NOT a Redux replacement for cross-cutting global UI state;\nit is a constraint engine you compose alongside Redux / Zustand / Jotai\n/ React Query.\n\nReach for Directive when:\n\n- The same business rule has to fire across React, Vue, server, and\n background workers. Directive runs the same module in every runtime.\n- You want a constraint to drive a side-effect (fetch, validate,\n cancel, retry) declaratively, without writing imperative thunks.\n- You are orchestrating LLM agents and need typed, replayable state +\n guardrails + budgets. `@directive-run/ai` is the only state-library\n ecosystem that ships AI orchestration as a sibling concept.\n- You want time-travel debugging, audit logs, or rules-diff replay on\n state mutations without instrumenting every component.\n\nYou do NOT need Directive for plain UI state (use signals / Zustand /\nJotai), simple server-state caching (use React Query / TanStack Query),\nor state machines that don\'t react to external facts (use XState).\n\n## Schema Shape (CRITICAL)\n\n```typescript\nimport { createModule, createSystem, t } from "@directive-run/core";\n\nconst myModule = createModule("name", {\n schema: {\n facts: { count: t.number(), items: t.array<string>() },\n derivations: { total: "number" },\n events: { increment: "void", addItem: "string" },\n requirements: { FETCH_DATA: { url: "string" } },\n },\n init: (facts) => { facts.count = 0; facts.items = []; },\n derive: {\n total: (facts) => facts.items.length + facts.count,\n },\n events: {\n increment: (facts) => { facts.count += 1; },\n addItem: (facts, item) => { facts.items = [...facts.items, item]; },\n },\n constraints: {\n fetchWhenReady: {\n when: (facts) => facts.count > 0 && facts.items.length === 0,\n require: (facts) => ({ type: "FETCH_DATA", url: "/api/items" }),\n },\n },\n resolvers: {\n fetchData: {\n requirement: "FETCH_DATA",\n resolve: async (req, context) => {\n const data = await fetch(req.url).then(r => r.json());\n context.facts.items = data;\n },\n },\n },\n});\n\nconst system = createSystem({ module: myModule });\nawait system.settle();\n```\n\n## Top 10 Anti-Patterns\n\n| # | WRONG | CORRECT |\n|---|-------|---------|\n| 1 | `facts.profile as ResourceState<Profile>` | Remove cast \u2014 schema provides types |\n| 2 | `{ phase: t.string() }` flat schema | `schema: { facts: { phase: t.string() } }` |\n| 3 | `facts.items` in multi-module | `facts.self.items` |\n| 4 | `t.map()`, `t.set()`, `t.promise()` | Don\'t exist. Use `t.object<Map<K,V>>()` |\n| 5 | `(req, ctx)` in resolver | `(req, context)` \u2014 never abbreviate |\n| 6 | `createModule("n", { phase: t.string() })` | Must wrap: `schema: { facts: { ... } }` |\n| 7 | `system.dispatch(\'login\', {...})` | `system.events.login({...})` |\n| 8 | `facts.items.push(item)` | `facts.items = [...facts.items, item]` |\n| 9 | `useEvent`/`DirectiveProvider` top-level imports | `useEvents`; `createDirectiveContext(system).Provider` |\n| 10 | `facts[\'auth::status\']` | `facts.auth.status` dot notation |\n\n## Naming\n\n- `req` = requirement (not request). Parameter: `(req, context)`\n- `derive` / derivations \u2014 never "computed" or "selectors"\n- Resolvers return `void` \u2014 mutate `context.facts` instead\n- Always use braces for returns: `if (x) { return y; }`\n- Multi-module: `facts.self.fieldName` for own module facts\n- Events: `system.events.eventName(payload)` \u2014 not `system.dispatch()`\n- Import from main: `import { createModule } from \'@directive-run/core\'`\n\n## Schema Types That Exist\n\n`t.string<T>()`, `t.number()`, `t.boolean()`, `t.array<T>()`, `t.object<T>()`,\n`t.enum("a","b")`, `t.literal(value)`, `t.nullable(inner)`, `t.optional(inner)`, `t.union(...)`\n\nChainable: `.default()`, `.validate()`, `.transform()`, `.brand<>()`, `.refine()`\n\n**DO NOT USE** (hallucinations): `t.map()`, `t.set()`, `t.date()`, `t.tuple()`, `t.record()`, `t.promise()`, `t.any()`\n\n## Key Pattern: Constraint \u2192 Requirement \u2192 Resolver\n\nWhen the user wants "do X when Y": create THREE things:\n1. **Constraint**: `when: (facts) => Y_condition` \u2192 `require: { type: "DO_X" }`\n2. **Resolver**: handles "DO_X", calls API, sets `context.facts`\n3. They are **decoupled**. Constraint declares need, resolver fulfills it.\n'}function ae(){return Se()+"\n## Anti-Patterns 11-19\n\n| # | WRONG | CORRECT |\n|---|-------|---------|\n| 11 | Returning data from `resolve` | Resolvers return `void` \u2014 mutate `context.facts` |\n| 12 | Async logic in `init` | `init` is synchronous, facts assignment only |\n| 13 | `await system.start()` without settle | Add `await system.settle()` after start |\n| 14 | Missing `crossModuleDeps` | Declare `crossModuleDeps: { auth: authSchema }` |\n| 15 | `require: \"TYPE\"` string literal | `require: { type: \"TYPE\" }` object form |\n| 16 | Passthrough derivation `(f) => f.count` | Remove \u2014 read fact directly |\n| 17 | `from '@directive-run/core/module'` | `from '@directive-run/core'` (main export) |\n| 18 | `async when()` without `deps` | Add `deps: ['factName']` for async constraints |\n| 19 | No error boundary on resolver | Use try-catch or module error boundary config |\n"+`
|
|
230
263
|
## Multi-Module
|
|
231
264
|
|
|
232
265
|
\`\`\`typescript
|
|
@@ -259,40 +292,44 @@ const result = await orchestrator.run(agent, "analyze this");
|
|
|
259
292
|
- Subpath imports: \`from '@directive-run/ai/anthropic'\` not \`from '@directive-run/ai'\`
|
|
260
293
|
- Token usage normalized: \`{ inputTokens, outputTokens }\` (not provider-specific)
|
|
261
294
|
- \`facts.cache = [...facts.cache, item]\` not \`facts.cache.push(item)\`
|
|
262
|
-
`}function
|
|
263
|
-
|
|
264
|
-
${
|
|
265
|
-
|
|
295
|
+
`}function it(){return ae()}function at(){return ae()}var ur={cursor:Se,claude:ot,copilot:ae,windsurf:at,cline:it};function me(e){let t=ur[e];if(!t)throw new Error(`No template for tool: ${e}`);return t()}function Ue(e){let t={force:false,merge:false,tools:[],dir:process.cwd()};for(let r=0;r<e.length;r++)switch(e[r]){case "--force":t.force=true;break;case "--merge":t.merge=true;break;case "--tool":{let n=e[++r];n&&t.tools.push(n);break}case "--dir":{let n=e[++r];n&&(t.dir=n);break}}return t}async function ct(e){let t=Ue(e);g.intro(m.bgCyan(m.black(" directive ai-rules ")));let r=We(t.dir),s=t.dir;if(r.isMonorepo&&r.rootDir!==t.dir){let i=await g.select({message:"Monorepo detected. Where should AI rules be installed?",options:[{value:"root",label:`Monorepo root (${relative(t.dir,r.rootDir)||"."})`,hint:"recommended"},{value:"workspace",label:`Current workspace (${relative(r.rootDir,t.dir)})`}]});g.isCancel(i)&&(g.cancel("Cancelled."),process.exit(0)),i==="root"&&(s=r.rootDir);}let n;if(t.tools.length>0)n=t.tools.map(i=>{let c=ie(i);return {name:c.name,id:c.id,outputPath:join(s,c.outputPath)}});else {let i=rt(s);if(i.length>0){let c=await g.multiselect({message:`Detected ${i.length} AI tool(s). Which should get Directive rules?`,options:i.map(a=>({value:a.id,label:a.name,hint:relative(s,a.outputPath)})),initialValues:i.map(a=>a.id),required:true});g.isCancel(c)&&(g.cancel("Cancelled."),process.exit(0)),n=c.map(a=>{let l=ie(a);return {name:l.name,id:l.id,outputPath:join(s,l.outputPath)}});}else {let c=await g.multiselect({message:"No AI tools detected. Which tools do you use?",options:qe().map(a=>{let l=ie(a);return {value:a,label:l.name}}),required:true});g.isCancel(c)&&(g.cancel("Cancelled."),process.exit(0)),n=c.map(a=>{let l=ie(a);return {name:l.name,id:l.id,outputPath:join(s,l.outputPath)}});}}n.length===0&&(g.cancel("No tools selected."),process.exit(0));let o=g.spinner();for(let i of n){o.start(`Generating ${i.name} rules...`);let c=me(i.id),a=i.outputPath,l=existsSync(a);if(o.stop(`Generated ${i.name} rules.`),l&&!t.force){let u=readFileSync(a,"utf-8");if(t.merge){U(a,X(u,c)),g.log.success(`${m.green("Merged")} Directive section into ${m.dim(relative(s,a))}`);continue}if(V(u)){let d=await g.select({message:`${relative(s,a)} already has a Directive section. What should we do?`,options:[{value:"merge",label:"Update Directive section only",hint:"recommended"},{value:"overwrite",label:"Overwrite entire file"},{value:"skip",label:"Skip this file"}]});g.isCancel(d)&&(g.cancel("Cancelled."),process.exit(0)),d==="merge"?(U(a,X(u,c)),g.log.success(`${m.green("Updated")} ${m.dim(relative(s,a))}`)):d==="overwrite"?(U(a,c),g.log.success(`${m.green("Wrote")} ${m.dim(relative(s,a))}`)):g.log.info(`Skipped ${m.dim(relative(s,a))}`);}else {let d=await g.select({message:`${relative(s,a)} already exists. What should we do?`,options:[{value:"append",label:"Append Directive section",hint:"preserves existing content"},{value:"overwrite",label:"Overwrite entire file"},{value:"skip",label:"Skip this file"}]});g.isCancel(d)&&(g.cancel("Cancelled."),process.exit(0)),d==="append"?(U(a,X(u,c)),g.log.success(`${m.green("Appended")} to ${m.dim(relative(s,a))}`)):d==="overwrite"?(U(a,c),g.log.success(`${m.green("Wrote")} ${m.dim(relative(s,a))}`)):g.log.info(`Skipped ${m.dim(relative(s,a))}`);}}else U(a,c),g.log.success(`${m.green("Created")} ${m.dim(relative(s,a))}`);}g.outro(`Done! Run ${m.cyan(`${O} ai-rules init --merge`)} anytime to update.`);}function U(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}function mr(e){let t={dir:process.cwd(),force:false};for(let r=0;r<e.length;r++){let s=e[r];if(s==="--force")t.force=true;else if(s==="--dir"){let n=e[++r];n&&(t.dir=n);}}return t}async function ze(e){let t=mr(e),r=We(t.dir),s=r.isMonorepo&&r.rootDir!==t.dir?r.rootDir:t.dir;s!==t.dir&&console.log(m.dim(`Monorepo detected \u2014 installing at root (${relative(t.dir,s)||"."})`));let o=qe().map(l=>{let u=ie(l);return {id:u.id,name:u.name,outputPath:join(s,u.outputPath)}}),i=0,c=0,a=0;for(let l of o){let u=me(l.id),d=`${oe}
|
|
296
|
+
${u}
|
|
297
|
+
${Y}`,f=l.outputPath,h=relative(s,f);if(!existsSync(f)){U(f,`${d}
|
|
298
|
+
`),console.log(`${m.green("\u2713")} ${l.name.padEnd(20)} ${m.dim(h)}`),i++;continue}let $=readFileSync(f,"utf-8");if(t.force){U(f,`${d}
|
|
299
|
+
`),console.log(`${m.yellow("\u21BB")} ${l.name.padEnd(20)} ${m.dim(h)} ${m.dim("(overwrote)")}`),i++;continue}if(V($)){U(f,X($,u)),console.log(`${m.green("\u2713")} ${l.name.padEnd(20)} ${m.dim(h)} ${m.dim("(merged section)")}`),c++;continue}console.log(`${m.dim("\xB7")} ${l.name.padEnd(20)} ${m.dim(h)} ${m.dim("(exists, no Directive section \u2014 pass --force to overwrite)")}`),a++;}console.log(""),console.log(m.green(`Installed Directive AI rules for ${o.length} tools.`)),console.log(m.dim(` ${i} written \xB7 ${c} merged \xB7 ${a} skipped (existing non-Directive content preserved)`)),console.log(""),console.log(m.dim("Next steps:")),console.log(m.dim(" \u2022 Restart your AI assistant so it picks up the new rules file.")),console.log(m.dim(` \u2022 Run ${m.cyan(`${O} ai-rules update`)} after each ${m.cyan("@directive-run/*")} version bump.`)),console.log(m.dim(` \u2022 For Claude Code, the plugin (${m.cyan("/plugin install directive@directive-plugins")}) is the canonical install \u2014 these files are the fallback for non-Claude editors.`));}async function lt(e){let r=Ue(e).dir,s=[{id:"cursor",path:join(r,".cursorrules")},{id:"claude",path:join(r,".claude/CLAUDE.md")},{id:"copilot",path:join(r,".github/copilot-instructions.md")},{id:"windsurf",path:join(r,".windsurfrules")},{id:"cline",path:join(r,".clinerules")}],n=0;for(let o of s){if(!existsSync(o.path))continue;let i=readFileSync(o.path,"utf-8");if(!V(i))continue;let c=me(o.id),a=X(i,c);U(o.path,a),console.log(`${m.green("Updated")} ${m.dim(relative(r,o.path))}`),n++;}console.log(n===0?m.dim(`No existing rule files found. Run ${m.cyan(`${O} ai-rules init`)} first.`):m.green(`
|
|
300
|
+
Updated ${n} file(s) to latest knowledge version.`));}async function ut(e){let r=Ue(e).dir,s=[{id:"cursor",path:join(r,".cursorrules"),name:"Cursor"},{id:"claude",path:join(r,".claude/CLAUDE.md"),name:"Claude Code"},{id:"copilot",path:join(r,".github/copilot-instructions.md"),name:"GitHub Copilot"},{id:"windsurf",path:join(r,".windsurfrules"),name:"Windsurf"},{id:"cline",path:join(r,".clinerules"),name:"Cline"}],n=0,o=0;for(let i of s){if(!existsSync(i.path))continue;let c=readFileSync(i.path,"utf-8");if(!V(c))continue;n++;let a=me(i.id);X(c,a)!==c?(console.log(`${m.red("\u2717")} ${i.name} rules are ${m.yellow("stale")}`),o++):console.log(`${m.green("\u2713")} ${i.name} rules are ${m.green("current")}`);}if(n===0){console.log(m.dim("No rule files found to check."));return}o>0?(console.log(`
|
|
301
|
+
${m.yellow(`${o} file(s) are stale.`)} Run ${m.cyan(`${O} ai-rules update`)} to refresh.`),process.exit(1)):console.log(m.green(`
|
|
302
|
+
All rule files are current.`));}async function L(e){let t=resolve(e);if(!existsSync(t))throw new Error(`File not found: ${t}`);try{let r=await import(t);if(r.default&&Z(r.default))return r.default;if(r.system&&Z(r.system))return r.system;for(let s of Object.keys(r))if(Z(r[s]))return r[s];throw new Error(`No Directive system found in ${m.dim(e)}
|
|
266
303
|
Export a system as default or named "system":
|
|
267
304
|
|
|
268
|
-
${
|
|
269
|
-
${
|
|
305
|
+
${m.cyan("export default")} createSystem({ module: myModule });
|
|
306
|
+
${m.cyan("export const system")} = createSystem({ module: myModule });`)}catch(r){throw r instanceof Error&&r.message.includes("No Directive system")?r:new Error(`Failed to load ${m.dim(e)}: ${r instanceof Error?r.message:String(r)}
|
|
270
307
|
|
|
271
308
|
Make sure the file is valid TypeScript and tsx is installed:
|
|
272
|
-
${
|
|
309
|
+
${m.cyan("npm install -D tsx")}`)}}function Z(e){if(typeof e!="object"||e===null)return false;let t=e;return typeof t.inspect=="function"&&typeof t.start=="function"&&typeof t.stop=="function"&&"facts"in t}async function pt(e){let t=resolve(e);if(!existsSync(t))throw new Error(`File not found: ${t}`);let r;try{r=await import(t);}catch(o){throw new Error(`Failed to load ${m.dim(e)}: ${o instanceof Error?o.message:String(o)}
|
|
273
310
|
|
|
274
311
|
Make sure the file is valid TypeScript and tsx is installed:
|
|
275
|
-
${
|
|
276
|
-
Expected an object with inspect/start/stop/facts. The factory must call sys.start() before returning.`);return c};throw
|
|
312
|
+
${m.cyan("npm install -D tsx")}`)}let s=[["createSystem",r.createSystem],["systemFactory",r.systemFactory],["default",r.default]];for(let[o,i]of s)if(typeof i=="function")return async()=>{let c=await Promise.resolve(i());if(!Z(c))throw new Error(`Factory '${o}' from ${m.dim(e)} returned a value that is not a started Directive system.
|
|
313
|
+
Expected an object with inspect/start/stop/facts. The factory must call sys.start() before returning.`);return c};throw Z(r.default)||Z(r.system)||Object.values(r).some(Z)?new Error(`Found a started Directive system in ${m.dim(e)}, but bisect needs a factory.
|
|
277
314
|
Bisect instantiates a fresh system for every midpoint replay (so each attempt is hermetic),
|
|
278
|
-
which means it can't reuse a singleton instance the way ${
|
|
315
|
+
which means it can't reuse a singleton instance the way ${m.cyan("directive replay")} does.
|
|
279
316
|
|
|
280
317
|
Wrap the existing export in a function:
|
|
281
318
|
|
|
282
|
-
${
|
|
319
|
+
${m.cyan("export function createSystem()")} {
|
|
283
320
|
const sys = createSystem({ module: yourModule });
|
|
284
321
|
sys.start();
|
|
285
322
|
return sys;
|
|
286
|
-
}`):new Error(`No system factory found in ${
|
|
323
|
+
}`):new Error(`No system factory found in ${m.dim(e)}
|
|
287
324
|
Bisect needs to instantiate a fresh system per midpoint replay. Export one of:
|
|
288
325
|
|
|
289
|
-
${
|
|
290
|
-
${
|
|
291
|
-
${
|
|
326
|
+
${m.cyan("export function createSystem()")} { ... return sys; }
|
|
327
|
+
${m.cyan("export const systemFactory")} = () => { ... return sys; };
|
|
328
|
+
${m.cyan("export default")} () => { ... return sys; };
|
|
292
329
|
|
|
293
330
|
The factory MUST call sys.start() and return the started system.
|
|
294
|
-
(Did you forget ${
|
|
295
|
-
Install it: npm install --save-dev @directive-run/timeline`)),e&&console.error(
|
|
331
|
+
(Did you forget ${m.cyan("sys.start()")} before returning?)`)}async function ce(e=false){try{return await import('@directive-run/timeline')}catch(t){console.error(m.red(`error: @directive-run/timeline not installed in this project.
|
|
332
|
+
Install it: npm install --save-dev @directive-run/timeline`)),e&&console.error(m.dim(t.message)),process.exit(1);}}function $r(e){let t={json:false,noDeterminismCheck:false,verbose:false},r="";for(let s=0;s<e.length;s++){let n=e[s];switch(n){case "--system":case "-s":{let o=e[++s];o&&(t.systemPath=o);break}case "--assert":case "-a":{let o=e[++s];o&&(t.assertExpr=o);break}case "--max-frames":{let o=e[++s],i=o?Number.parseInt(o,10):Number.NaN;Number.isFinite(i)&&i>0&&(t.maxFrames=i);break}case "--no-determinism-check":t.noDeterminismCheck=true;break;case "--json":t.json=true;break;case "--verbose":case "-v":t.verbose=true;break;default:n&&!n.startsWith("-")&&!r&&(r=n);}}return {jsonPath:r,opts:t}}function je(){console.error(`
|
|
296
333
|
Usage: directive bisect <timeline.json> --system <factory.ts> --assert <expr>
|
|
297
334
|
|
|
298
335
|
Binary-search a recorded timeline for the first frame that triggers a
|
|
@@ -327,29 +364,29 @@ Examples:
|
|
|
327
364
|
--assert 'facts.count >= 0'
|
|
328
365
|
|
|
329
366
|
directive bisect crash.json -s factory.ts -a 'facts.status !== "error"' --json
|
|
330
|
-
`);}function
|
|
331
|
-
expression: ${e}`)}return r=>{let s=r?.facts;return !!t(s,r)}}async function
|
|
332
|
-
(bisect needs a factory to instantiate a fresh system per midpoint)`)),
|
|
333
|
-
(assertion distinguishes 'good' from 'bad' system state)`)),
|
|
367
|
+
`);}function vr(e){let t;try{t=new Function("facts","system",`"use strict"; return (${e});`);}catch(r){throw new Error(`Failed to compile --assert expression: ${r.message}
|
|
368
|
+
expression: ${e}`)}return r=>{let s=r?.facts;return !!t(s,r)}}async function ht(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(je(),process.exit(e.length===0?1:0));let{jsonPath:t,opts:r}=$r(e);t||(console.error(m.red("error: missing <timeline.json> argument")),je(),process.exit(1)),r.systemPath||(console.error(m.red("error: --system <path> is required"),m.dim(`
|
|
369
|
+
(bisect needs a factory to instantiate a fresh system per midpoint)`)),je(),process.exit(1)),r.assertExpr||(console.error(m.red("error: --assert <expression> is required"),m.dim(`
|
|
370
|
+
(assertion distinguishes 'good' from 'bad' system state)`)),je(),process.exit(1));let s=resolve(t);existsSync(s)||(console.error(m.red(`error: timeline file not found: ${s}`)),process.exit(1));let n;try{n=readFileSync(s,"utf8");}catch(w){console.error(m.red(`error: failed to read ${s}: ${w.message}`)),process.exit(1);}let o;try{o=JSON.parse(n);}catch(w){console.error(m.red(`error: ${s} is not valid JSON: ${w.message}`)),process.exit(1);}let{deserializeTimeline:i,bisectTimeline:c}=await ce(r.verbose),a;try{a=i(o);}catch(w){console.error(m.red(`error: timeline JSON failed validation: ${w.message}`)),process.exit(1);}let l;try{l=vr(r.assertExpr);}catch(w){console.error(m.red(`error: ${w.message}`)),process.exit(1);}let u;try{u=await pt(r.systemPath);}catch(w){console.error(m.red(`error: failed to load system factory: ${w.message}`)),process.exit(1);}r.verbose&&console.error(m.dim(`bisecting ${a.frames.length} frames with assertion: ${r.assertExpr}`));let d=await c(a,u,l,{maxFrames:r.maxFrames,determinismCheck:!r.noDeterminismCheck});if(r.json){let w={firstFailingFrameIndex:d.firstFailingFrameIndex??null,iterations:d.iterations,noFailureFound:d.noFailureFound,failsOnEmptyReplay:d.failsOnEmptyReplay,nonDeterministic:d.nonDeterministic};console.log(JSON.stringify(w,null,2)),process.exit(0);}d.nonDeterministic&&(console.error(m.red("\u2717 bisect aborted: timeline is non-deterministic")),console.error(m.dim(` Two full-timeline replays produced different oracle verdicts.
|
|
334
371
|
Bisection is unreliable on non-deterministic timelines.
|
|
335
372
|
Either fix the timeline source (deterministic clocks/seeds)
|
|
336
|
-
or re-run with --no-determinism-check if you accept the risk.`)),process.exit(2)),
|
|
373
|
+
or re-run with --no-determinism-check if you accept the risk.`)),process.exit(2)),d.noFailureFound&&(console.error(m.yellow("\u26A0 no failure to bisect: assertion passes on the full timeline")),console.error(m.dim(` The recorded timeline does not exhibit the bug your
|
|
337
374
|
--assert expression checks. Verify the assertion or
|
|
338
|
-
try a different bad.json.`)),process.exit(0)),
|
|
375
|
+
try a different bad.json.`)),process.exit(0)),d.failsOnEmptyReplay&&(console.error(m.yellow("\u26A0 assertion fails BEFORE any frame replays \u2014 bug is in initialization")),console.error(m.dim(` The freshly-started system already violates the assertion.
|
|
339
376
|
Bisect cannot narrow further. Inspect the system factory
|
|
340
|
-
or initial fact values.`)),process.exit(0));let d
|
|
377
|
+
or initial fact values.`)),process.exit(0));let f=d.firstFailingFrameIndex??-1,h=d.firstFailingFrame,$=h?.event.type??"<unknown>";console.log(`${m.green("\u2713")} bisect complete: ${m.bold(`first failing frame is #${f}`)} ${m.dim(`(${$})`)}`),console.log(m.dim(` \u2022 iterations: ${d.iterations} | timeline frames: ${a.frames.length}`)),r.verbose&&h&&(console.log(m.dim(" \u2022 frame:")),console.log(m.dim(` ${JSON.stringify(h,null,2).split(`
|
|
341
378
|
`).join(`
|
|
342
|
-
`)}`))),process.exit(2);}function
|
|
343
|
-
`);for(let r of t){let s=r.trim();if(s.startsWith("// Example:")||s.startsWith("// Source:")||s.startsWith("// Extracted"))continue;let n=s.match(/^\*\s+(.+?)(?:\s*\*\/)?$/);if(n?.[1]&&!n[1].startsWith("@"))return n[1];if(s.startsWith("//")&&s.length>3)return s.slice(2).trim();if(s!==""&&!s.startsWith("//")&&!s.startsWith("/*")&&!s.startsWith("*"))break}return ""}async function
|
|
379
|
+
`)}`))),process.exit(2);}function br(e){let t={dir:process.cwd()};for(let r=0;r<e.length;r++)if(e[r]==="--dir"){let s=e[++r];s&&(t.dir=s);}return t}function xr(e){let t=join(e,"package.json");if(!existsSync(t))return {label:"@directive-run/core installed",passed:false,message:"No package.json found",fix:"Run `npm init` to create a package.json"};let r=JSON.parse(readFileSync(t,"utf-8")),s={...r.dependencies,...r.devDependencies};return s["@directive-run/core"]?{label:"@directive-run/core installed",passed:true,message:`v${s["@directive-run/core"]}`}:{label:"@directive-run/core installed",passed:false,message:"Not found in dependencies",fix:"Run `npm install @directive-run/core`"}}function kr(e){let t=join(e,"package.json");if(!existsSync(t))return {label:"Package version compatibility",passed:true,message:"Skipped (no package.json)"};let r=JSON.parse(readFileSync(t,"utf-8")),s={...r.dependencies,...r.devDependencies},n=Object.keys(s).filter(o=>o.startsWith("@directive-run/"));return n.length<=1?{label:"Package version compatibility",passed:true,message:n.length===0?"No packages found":"Single package"}:{label:"Package version compatibility",passed:true,message:`${n.length} packages: ${n.join(", ")}`}}function Sr(e){let t=join(e,"tsconfig.json");if(!existsSync(t))return {label:"TypeScript configuration",passed:false,message:"No tsconfig.json found",fix:"Run `tsc --init` to create a TypeScript configuration"};try{let s=readFileSync(t,"utf-8").replace(/\/\/.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,""),o=JSON.parse(s).compilerOptions||{},i=[];return o.strict!==!0&&i.push("strict mode not enabled"),o.moduleResolution&&!["bundler","nodenext","node16"].includes(o.moduleResolution.toLowerCase())&&i.push(`moduleResolution is "${o.moduleResolution}"`),i.length>0?{label:"TypeScript configuration",passed:!1,message:i.join(", "),fix:'Set "strict": true and "moduleResolution": "bundler" in tsconfig.json'}:{label:"TypeScript configuration",passed:!0,message:"strict mode, correct module resolution"}}catch{return {label:"TypeScript configuration",passed:true,message:"Found (could not parse for detailed checks)"}}}function Ar(e){let t=join(e,"node_modules");if(!existsSync(t))return {label:"No duplicate Directive instances",passed:true,message:"No node_modules found"};let r=[];try{let s=join(t,"@directive-run");if(existsSync(s)){let n=readdirSync(s);for(let o of n){let i=join(s,o,"node_modules","@directive-run","core");existsSync(i)&&r.push(`@directive-run/${o}/node_modules/@directive-run/core`);}}}catch{}return r.length>0?{label:"No duplicate Directive instances",passed:false,message:`Found ${r.length} duplicate(s): ${r.join(", ")}`,fix:"Run `npm dedupe` or check for version mismatches"}:{label:"No duplicate Directive instances",passed:true,message:"No duplicates detected"}}function jr(e){let t=[".cursorrules",".claude/CLAUDE.md",".github/copilot-instructions.md",".windsurfrules",".clinerules"],r=[];for(let s of t){let n=join(e,s);if(existsSync(n)){let o=readFileSync(n,"utf-8");V(o)&&r.push(s);}}return r.length===0?{label:"AI coding rules",passed:true,message:"Not installed (optional)"}:{label:"AI coding rules",passed:true,message:`Installed for: ${r.join(", ")}`}}async function gt(e){let t=br(e);console.log(),console.log(m.bold(m.cyan("Directive Doctor"))),console.log(m.dim("\u2500".repeat(40))),console.log();let r=[xr(t.dir),kr(t.dir),Sr(t.dir),Ar(t.dir),jr(t.dir)],s=0;for(let n of r){let o=n.passed?m.green("\u2713"):m.red("\u2717");console.log(`${o} ${m.bold(n.label)}`),console.log(` ${m.dim(n.message)}`),!n.passed&&n.fix&&(console.log(` ${m.yellow("Fix:")} ${n.fix}`),s++),console.log();}s>0?(console.log(m.yellow(`${s} issue(s) found. See suggested fixes above.`)),process.exit(1)):console.log(m.green("All checks passed!"));}var vt={"Getting Started":["counter","contact-form","auth-flow"],"Core Patterns":["async-chains","batch-resolver","debounce-constraints","error-boundaries","feature-flags","multi-module","optimistic-updates","pagination","permissions"],"Real-World":["dashboard-loader","form-wizard","newsletter","notifications","shopping-cart","theme-locale","url-sync","websocket","server"],Games:["checkers","sudoku","goal-heist","ab-testing"],AI:["ai-orchestrator","ai-checkpoint","ai-guardrails","fraud-analysis","provider-routing","topic-guard","dynamic-modules","time-machine"]};function Cr(e){for(let[t,r]of Object.entries(vt))if(r.includes(e))return t;return "Other"}function Tr(e){let t=e.split(`
|
|
380
|
+
`);for(let r of t){let s=r.trim();if(s.startsWith("// Example:")||s.startsWith("// Source:")||s.startsWith("// Extracted"))continue;let n=s.match(/^\*\s+(.+?)(?:\s*\*\/)?$/);if(n?.[1]&&!n[1].startsWith("@"))return n[1];if(s.startsWith("//")&&s.length>3)return s.slice(2).trim();if(s!==""&&!s.startsWith("//")&&!s.startsWith("/*")&&!s.startsWith("*"))break}return ""}async function wt(e){let t;for(let i=0;i<e.length;i++)e[i]==="--filter"&&(t=e[++i]?.toLowerCase());let r=getAllExamples();console.log(),console.log(m.bold(m.cyan("Directive Examples"))),console.log(m.dim("\u2500".repeat(50))),console.log();let s=new Map;for(let[i,c]of r){let a=Cr(i);t&&!a.toLowerCase().includes(t)&&!i.includes(t)||(s.has(a)||s.set(a,[]),s.get(a).push({name:i,desc:Tr(c)}));}if(s.size===0){console.log(m.dim("No examples match the filter."));return}let n=Object.keys(vt),o=[...s.keys()].sort((i,c)=>(n.indexOf(i)??99)-(n.indexOf(c)??99));for(let i of o){let c=s.get(i);console.log(m.bold(i));for(let a of c){let l=a.desc?m.dim(` \u2014 ${a.desc}`):"";console.log(` ${m.cyan(a.name)}${l}`);}console.log();}console.log(m.dim(`${r.size} examples available. Run ${m.cyan("directive examples copy <name>")} to extract one.`));}async function bt(e,t){let r=process.cwd();for(let a=0;a<t.length;a++)if(t[a]==="--dest"){let l=t[++a];l&&(r=l);}e||(console.error("Usage: directive examples copy <name> [--dest <dir>]"),process.exit(1));let s=getExample(e);s||(console.error(`Example "${e}" not found.`),console.error(`Run ${m.cyan("directive examples list")} to see available examples.`),process.exit(1));let n=s.replace(/from\s+["']@directive-run\/core\/plugins["']/g,'from "@directive-run/core/plugins"').replace(/from\s+["']@directive-run\/core["']/g,'from "@directive-run/core"').replace(/from\s+["']@directive-run\/ai["']/g,'from "@directive-run/ai"'),o=join(r,`${e}.ts`);existsSync(o)&&(console.error(`File already exists: ${relative(process.cwd(),o)}`),process.exit(1));let i=dirname(o);existsSync(i)||mkdirSync(i,{recursive:true}),writeFileSync(o,n,"utf-8");let c=relative(process.cwd(),o);console.log(`${m.green("Copied")} ${m.cyan(e)} \u2192 ${m.dim(c)}`);}function Mr(e){let t={},r="",s;for(let n=0;n<e.length;n++){let o=e[n];if(o==="--module"){let i=e[++n];i&&(t.module=i);}else o&&!o.startsWith("-")&&(r?s||(s=o):r=o);}return {filePath:r,requirementId:s,opts:t}}async function kt(e){let{filePath:t,requirementId:r}=Mr(e);t||(console.error("Usage: directive explain <file> [requirement-id]"),process.exit(1));let s=await L(t);s.isRunning||s.start();let n=s.inspect();if(r){let o=s.explain(r);if(!o){if(console.error(`Requirement "${r}" not found.
|
|
344
381
|
|
|
345
|
-
Current requirements:`),n.unmet.length===0)console.log(
|
|
346
|
-
`);for(let o of n.unmet){console.log(`${
|
|
347
|
-
`)}function
|
|
382
|
+
Current requirements:`),n.unmet.length===0)console.log(m.dim(" (no unmet requirements)"));else for(let i of n.unmet)console.log(` ${m.cyan(i.id)} \u2014 ${i.requirement.type} (from ${i.fromConstraint})`);s.stop(),process.exit(1);}console.log(),console.log(m.bold(m.cyan("Requirement Explanation"))),console.log(m.dim("\u2500".repeat(40))),console.log(),console.log(o),console.log();}else if(console.log(),console.log(m.bold(m.cyan("All Requirements"))),console.log(m.dim("\u2500".repeat(40))),console.log(),n.unmet.length===0){console.log(m.green("All requirements are met.")),console.log();let o=Object.entries(n.resolvers);if(o.length>0){console.log(m.bold("Recent Resolver Activity:"));for(let[i,c]of o){let a=xt(c.state),l=c.duration!==void 0?` (${c.duration}ms)`:"";console.log(` ${m.cyan(i)} ${a}${l}`);}console.log();}}else {console.log(`${m.yellow(String(n.unmet.length))} unmet requirement(s):
|
|
383
|
+
`);for(let o of n.unmet){console.log(`${m.yellow("\u25CF")} ${m.bold(o.requirement.type)} (id: ${m.dim(o.id)})`),console.log(` From constraint: ${m.cyan(o.fromConstraint)}`);let i={...o.requirement};delete i.type,Object.keys(i).length>0&&console.log(` Payload: ${JSON.stringify(i)}`);let a=n.resolvers[o.id];a?console.log(` Resolver: ${xt(a.state)}${a.error?` \u2014 ${a.error}`:""}`):n.resolverDefs.some(u=>u.requirement===o.requirement.type||u.requirement==="(predicate)")||console.log(` ${m.red("No resolver registered for this type")}`),console.log();}console.log(m.dim(`Run ${m.cyan("directive explain <file> <requirement-id>")} for detailed explanation.`));}s.stop();}function xt(e){switch(e){case "resolved":return m.green("resolved");case "errored":return m.red("errored");case "inflight":return m.yellow("inflight");case "pending":return m.yellow("pending");case "cancelled":return m.dim("cancelled");default:return m.dim(e)}}function qr(e){let t={ascii:false,open:true},r="";for(let s=0;s<e.length;s++){let n=e[s];switch(n){case "--ascii":t.ascii=true;break;case "--no-open":t.open=false;break;case "--output":{let o=e[++s];o&&(t.output=o);break}default:n&&!n.startsWith("-")&&!r&&(r=n);}}return {filePath:r,opts:t}}function Ir(e){let t=[];t.push(m.bold("Dependency Graph")),t.push(m.dim("\u2550".repeat(50))),t.push("");let r=new Map;for(let c of e.constraints)r.set(c.id,{reqTypes:new Set,active:c.active,priority:c.priority});for(let c of e.unmet){let a=r.get(c.fromConstraint);a&&a.reqTypes.add(c.requirement.type);}let s=new Map;for(let c of e.resolverDefs)s.has(c.requirement)||s.set(c.requirement,[]),s.get(c.requirement).push(c.id);t.push(m.bold("Constraints \u2192 Requirements \u2192 Resolvers")),t.push("");for(let[c,a]of r){let l=a.active?m.green("\u25CF"):m.dim("\u25CB");if(t.push(`${l} ${m.cyan(c)} (priority: ${a.priority})`),a.reqTypes.size>0)for(let u of a.reqTypes){t.push(` \u2514\u2500\u25B6 ${m.yellow(u)}`);let d=s.get(u)||[];if(d.length>0)for(let f of d)t.push(` \u2514\u2500\u25B6 ${m.magenta(f)}`);else t.push(` \u2514\u2500\u25B6 ${m.red("(no resolver)")}`);}else t.push(` \u2514\u2500\u25B6 ${m.dim("(no active requirements)")}`);t.push("");}let n=new Set;for(let c of s.values())for(let a of c)n.add(a);if(e.resolverDefs.map(c=>c.id).filter(c=>!n.has(c)).length>0){t.push(m.bold("Standalone Resolvers:"));for(let c of e.resolverDefs)n.has(c.id)||t.push(` ${m.magenta(c.id)} handles ${m.yellow(c.requirement)}`);}return t.join(`
|
|
384
|
+
`)}function Fr(e,t){let r=[],s=[],a=Object.keys(t);for(let p=0;p<a.length;p++){let v=a[p];r.push({id:`fact-${v}`,label:v,type:"fact",x:40,y:60+p*50,color:"#3b82f6"});}for(let p=0;p<e.constraints.length;p++){let v=e.constraints[p];r.push({id:`constraint-${v.id}`,label:v.id,type:"constraint",x:260,y:60+p*50,color:v.active?"#22c55e":"#6b7280"});}let l=new Set;for(let p of e.unmet)l.add(p.requirement.type);let u=0;for(let p of l)r.push({id:`req-${p}`,label:p,type:"requirement",x:480,y:60+u*50,color:"#eab308"}),u++;for(let p=0;p<e.resolverDefs.length;p++){let v=e.resolverDefs[p];r.push({id:`resolver-${v.id}`,label:v.id,type:"resolver",x:700,y:60+p*50,color:"#a855f7"});}for(let p of e.unmet)s.push({from:`constraint-${p.fromConstraint}`,to:`req-${p.requirement.type}`});for(let p of e.resolverDefs)l.has(p.requirement)&&s.push({from:`req-${p.requirement}`,to:`resolver-${p.id}`});let d=new Map(r.map(p=>[p.id,p])),f=960,h=Math.max(...r.map(p=>p.y))+50+20,$=s.map(p=>{let v=d.get(p.from),D=d.get(p.to);return !v||!D?"":`<line x1="${v.x+90}" y1="${v.y+15}" x2="${D.x}" y2="${D.y+15}" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#arrow)"/>`}).join(`
|
|
348
385
|
`),w=r.map(p=>`<g>
|
|
349
386
|
<rect x="${p.x}" y="${p.y}" width="180" height="30" rx="6" fill="${p.color}" opacity="0.15" stroke="${p.color}" stroke-width="1.5"/>
|
|
350
|
-
<text x="${p.x+90}" y="${p.y+19}" text-anchor="middle" font-size="12" font-family="monospace" fill="${p.color}">${
|
|
387
|
+
<text x="${p.x+90}" y="${p.y+19}" text-anchor="middle" font-size="12" font-family="monospace" fill="${p.color}">${Wr(p.label)}</text>
|
|
351
388
|
</g>`).join(`
|
|
352
|
-
`),W=["Facts","Constraints","Requirements","Resolvers"].map((p,
|
|
389
|
+
`),W=["Facts","Constraints","Requirements","Resolvers"].map((p,v)=>`<text x="${40+v*220+90}" y="35" text-anchor="middle" font-size="14" font-weight="bold" font-family="system-ui" fill="#e2e8f0">${p}</text>`).join(`
|
|
353
390
|
`);return `<!DOCTYPE html>
|
|
354
391
|
<html>
|
|
355
392
|
<head>
|
|
@@ -360,7 +397,7 @@ Current requirements:`),n.unmet.length===0)console.log(g.dim(" (no unmet requir
|
|
|
360
397
|
</style>
|
|
361
398
|
</head>
|
|
362
399
|
<body>
|
|
363
|
-
<svg width="${
|
|
400
|
+
<svg width="${f}" height="${h}" xmlns="http://www.w3.org/2000/svg">
|
|
364
401
|
<defs>
|
|
365
402
|
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
|
|
366
403
|
<path d="M 0 0 L 10 5 L 0 10 z" fill="#94a3b8"/>
|
|
@@ -371,7 +408,7 @@ Current requirements:`),n.unmet.length===0)console.log(g.dim(" (no unmet requir
|
|
|
371
408
|
${w}
|
|
372
409
|
</svg>
|
|
373
410
|
</body>
|
|
374
|
-
</html>`}function
|
|
411
|
+
</html>`}function Wr(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}async function St(e){let{filePath:t,opts:r}=qr(e);t||(console.error("Usage: directive graph <file> [--ascii] [--no-open] [--output <path>]"),process.exit(1));let s=await L(t);s.isRunning||s.start();let n=s.inspect();if(r.ascii){console.log(Ir(n)),s.stop();return}let o={};if(s.facts)for(let a of Object.keys(s.facts))try{o[a]=s.facts[a];}catch{o[a]=null;}let i=Fr(n,o),c=r.output||join(process.cwd(),".directive-graph.html");if(writeFileSync(c,i,"utf-8"),console.log(`${m.green("Generated")} ${m.dim(c)}`),r.open)try{let{execFile:a}=await import('child_process'),l=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";a(l,[c]),console.log(m.dim("Opened in browser."));}catch{console.log(m.dim(`Open ${c} in your browser to view the graph.`));}s.stop();}function Jr(e){let t={dir:process.cwd(),noInteractive:false};for(let r=0;r<e.length;r++)switch(e[r]){case "--template":{let n=e[++r];n&&(t.template=n);break}case "--dir":{let n=e[++r];n&&(t.dir=n);break}case "--no-interactive":t.noInteractive=true;break}return t}function Kr(e){return existsSync(join(e,"pnpm-lock.yaml"))?"pnpm":existsSync(join(e,"bun.lockb"))||existsSync(join(e,"bun.lock"))?"bun":existsSync(join(e,"yarn.lock"))?"yarn":"npm"}function Gr(e,t){switch(e){case "pnpm":return `pnpm add ${t}`;case "yarn":return `yarn add ${t}`;case "bun":return `bun add ${t}`;default:return `npm install ${t}`}}function Le(e){return {counter:{id:"counter",label:"Counter (minimal)",hint:"schema + init + derive + events \u2014 simplest starting point",files:[{path:`src/${e}.ts`,content:Br(e)},{path:"src/main.ts",content:Hr(e)}],deps:["@directive-run/core"]},"auth-flow":{id:"auth-flow",label:"Auth flow (constraints + resolvers)",hint:"login flow with constraints, resolvers, retry, and effects",files:[{path:`src/${e}.ts`,content:Qr(e)},{path:"src/main.ts",content:Yr(e)}],deps:["@directive-run/core"]},"ai-orchestrator":{id:"ai-orchestrator",label:"AI orchestrator",hint:"agent orchestrator with guardrails and streaming",files:[{path:`src/${e}.ts`,content:Xr(e)},{path:"src/main.ts",content:Vr(e)}],deps:["@directive-run/core","@directive-run/ai"]}}}function Br(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
|
|
375
412
|
|
|
376
413
|
const schema = {
|
|
377
414
|
facts: {
|
|
@@ -390,7 +427,7 @@ const schema = {
|
|
|
390
427
|
},
|
|
391
428
|
} satisfies ModuleSchema;
|
|
392
429
|
|
|
393
|
-
export const ${
|
|
430
|
+
export const ${ue(e)} = createModule("${e}", {
|
|
394
431
|
schema,
|
|
395
432
|
|
|
396
433
|
init: (facts) => {
|
|
@@ -418,7 +455,7 @@ export const ${ae(e)} = createModule("${e}", {
|
|
|
418
455
|
},
|
|
419
456
|
},
|
|
420
457
|
});
|
|
421
|
-
`}function
|
|
458
|
+
`}function Hr(e){let t=ue(e);return `import { createSystem } from "@directive-run/core";
|
|
422
459
|
import { ${t} } from "./${e}.js";
|
|
423
460
|
|
|
424
461
|
const system = createSystem({
|
|
@@ -444,7 +481,7 @@ system.events.increment();
|
|
|
444
481
|
system.events.increment();
|
|
445
482
|
|
|
446
483
|
export default system;
|
|
447
|
-
`}function
|
|
484
|
+
`}function Qr(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
|
|
448
485
|
|
|
449
486
|
type AuthStatus = "idle" | "authenticating" | "authenticated" | "expired";
|
|
450
487
|
|
|
@@ -471,7 +508,7 @@ const schema = {
|
|
|
471
508
|
},
|
|
472
509
|
} satisfies ModuleSchema;
|
|
473
510
|
|
|
474
|
-
export const ${
|
|
511
|
+
export const ${ue(e)} = createModule("${e}", {
|
|
475
512
|
schema,
|
|
476
513
|
|
|
477
514
|
init: (facts) => {
|
|
@@ -548,7 +585,7 @@ export const ${ae(e)} = createModule("${e}", {
|
|
|
548
585
|
},
|
|
549
586
|
},
|
|
550
587
|
});
|
|
551
|
-
`}function
|
|
588
|
+
`}function Yr(e){let t=ue(e);return `import { createSystem } from "@directive-run/core";
|
|
552
589
|
import { ${t} } from "./${e}.js";
|
|
553
590
|
|
|
554
591
|
const system = createSystem({
|
|
@@ -569,7 +606,7 @@ console.log("authenticated:", system.read("isAuthenticated"));
|
|
|
569
606
|
console.log("token:", system.facts.token);
|
|
570
607
|
|
|
571
608
|
export default system;
|
|
572
|
-
`}function
|
|
609
|
+
`}function Xr(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
|
|
573
610
|
import {
|
|
574
611
|
createAgentOrchestrator,
|
|
575
612
|
createAgentMemory,
|
|
@@ -603,7 +640,7 @@ const schema = {
|
|
|
603
640
|
},
|
|
604
641
|
} satisfies ModuleSchema;
|
|
605
642
|
|
|
606
|
-
export const ${
|
|
643
|
+
export const ${ue(e)} = createModule("${e}", {
|
|
607
644
|
schema,
|
|
608
645
|
|
|
609
646
|
init: (facts) => {
|
|
@@ -677,7 +714,7 @@ export const memory = createAgentMemory({
|
|
|
677
714
|
// maxTokenBudget: 50000,
|
|
678
715
|
// memory,
|
|
679
716
|
// });
|
|
680
|
-
`}function
|
|
717
|
+
`}function Vr(e){let t=ue(e);return `import { createSystem } from "@directive-run/core";
|
|
681
718
|
import { ${t} } from "./${e}.js";
|
|
682
719
|
|
|
683
720
|
const system = createSystem({
|
|
@@ -696,20 +733,20 @@ await system.settle();
|
|
|
696
733
|
console.log("output:", system.facts.output);
|
|
697
734
|
|
|
698
735
|
export default system;
|
|
699
|
-
`}function
|
|
700
|
-
${
|
|
701
|
-
${
|
|
702
|
-
${
|
|
703
|
-
`);for(let[s,n]of r){let o=
|
|
704
|
-
`)}function
|
|
705
|
-
`);for(let r of e){let s=r.disabled?
|
|
706
|
-
`)}function
|
|
707
|
-
`);for(let s of e){let n=t[s.id],o=n?
|
|
708
|
-
`)}function
|
|
709
|
-
`);for(let r of e)t.push(` ${
|
|
710
|
-
`)}function
|
|
711
|
-
`);let r=Date.now();for(let s of e){let n=r-s.startedAt;t.push(` ${
|
|
712
|
-
`)}function
|
|
736
|
+
`}function ue(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}function Zr(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}async function At(e){let t=Jr(e);g.intro(m.bgCyan(m.black(" directive init ")));let r;if(t.noInteractive)r="my-module";else {let d=await g.text({message:"Module name:",placeholder:"my-module",defaultValue:"my-module",validate:f=>{if(!/^[a-z][a-z0-9-]*$/.test(f))return "Must start with a letter, use lowercase letters, numbers, and hyphens"}});g.isCancel(d)&&(g.cancel("Cancelled."),process.exit(0)),r=d;}let s;if(t.template){let d=Le(r);t.template in d||(g.log.error(`Unknown template: ${t.template}. Available: ${Object.keys(d).join(", ")}`),process.exit(1)),s=t.template;}else if(t.noInteractive)s="counter";else {let d=Le(r),f=await g.select({message:"Project template:",options:Object.values(d).map(h=>({value:h.id,label:h.label,hint:h.hint}))});g.isCancel(f)&&(g.cancel("Cancelled."),process.exit(0)),s=f;}let o=Le(r)[s],i=Kr(t.dir);g.log.info(`Package manager: ${m.cyan(i)}`);let c=g.spinner();c.start("Creating project files...");let l=0;for(let d of o.files){let f=join(t.dir,d.path);if(existsSync(f)){l++;continue}Zr(f,d.content);}c.stop("Project files created.");for(let d of o.files){let f=join(t.dir,d.path),h=relative(t.dir,f);existsSync(f)&&g.log.success(`${m.green("Created")} ${m.dim(h)}`);}l>0&&g.log.warn(`Skipped ${l} file(s) that already exist.`);let u=Gr(i,o.deps.join(" "));g.outro(`Next steps:
|
|
737
|
+
${m.cyan(u)}
|
|
738
|
+
${m.cyan(`${O} ai-rules init`)}
|
|
739
|
+
${m.dim("Start building!")}`);}function en(e){let t={json:false},r="";for(let s=0;s<e.length;s++){let n=e[s];switch(n){case "--json":t.json=true;break;case "--module":{let o=e[++s];o&&(t.module=o);break}default:n&&!n.startsWith("-")&&!r&&(r=n);}}return {filePath:r,opts:t}}function tn(e){let t=[];t.push(m.bold("Facts:"));let r=Object.entries(e);if(r.length===0)return t.push(" (none)"),t.join(`
|
|
740
|
+
`);for(let[s,n]of r){let o=cn(n);t.push(` ${m.cyan(s)} = ${o}`);}return t.join(`
|
|
741
|
+
`)}function rn(e){let t=[];if(t.push(m.bold("Constraints:")),e.length===0)return t.push(" (none)"),t.join(`
|
|
742
|
+
`);for(let r of e){let s=r.disabled?m.dim("disabled"):r.active?m.green("active"):m.dim("inactive"),n=r.hitCount>0?m.yellow(` (${r.hitCount} hits)`):"";t.push(` ${m.cyan(r.id)} ${s} priority=${r.priority}${n}`);}return t.join(`
|
|
743
|
+
`)}function nn(e,t){let r=[];if(r.push(m.bold("Resolvers:")),e.length===0)return r.push(" (none)"),r.join(`
|
|
744
|
+
`);for(let s of e){let n=t[s.id],o=n?an(n.state,n.error,n.duration):m.dim("idle");r.push(` ${m.cyan(s.id)} \u2192 ${s.requirement} ${o}`);}return r.join(`
|
|
745
|
+
`)}function sn(e){let t=[];if(t.push(m.bold("Unmet Requirements:")),e.length===0)return t.push(` ${m.green("(all requirements met)")}`),t.join(`
|
|
746
|
+
`);for(let r of e)t.push(` ${m.yellow(r.requirement.type)} (id: ${m.dim(r.id)}) from ${m.dim(r.fromConstraint)}`);return t.join(`
|
|
747
|
+
`)}function on(e){let t=[];if(t.push(m.bold("Inflight:")),e.length===0)return t.push(` ${m.green("(none)")}`),t.join(`
|
|
748
|
+
`);let r=Date.now();for(let s of e){let n=r-s.startedAt;t.push(` ${m.cyan(s.resolverId)} \u2192 req ${m.dim(s.id)} ${m.yellow(`${n}ms`)}`);}return t.join(`
|
|
749
|
+
`)}function an(e,t,r){let s=r!==void 0?` ${r}ms`:"";switch(e){case "resolved":return m.green(`resolved${s}`);case "errored":return m.red(`errored${s}${t?` \u2014 ${t}`:""}`);case "inflight":return m.yellow("inflight");case "cancelled":return m.dim("cancelled");default:return m.dim(e)}}function cn(e){return e===null?m.dim("null"):e===void 0?m.dim("undefined"):typeof e=="string"?e.length>60?`"${e.slice(0,57)}..."`:`"${e}"`:typeof e=="number"||typeof e=="boolean"?String(e):Array.isArray(e)?`[${e.length} items]`:JSON.stringify(e).slice(0,60)}function ln(e){let t=[];new Set(e.unmet.map(o=>o.requirement.type));new Set(e.resolverDefs.map(o=>o.requirement));for(let o of e.resolverDefs)o.requirement;for(let o of e.unmet)e.resolverDefs.some(c=>c.requirement===o.requirement.type||c.requirement==="(predicate)")||t.push(`No resolver for requirement type "${o.requirement.type}"`);return t}async function jt(e){let{filePath:t,opts:r}=en(e);t||(console.error("Usage: directive inspect <file> [--json] [--module <name>]"),process.exit(1));let s=await L(t);s.isRunning||s.start();let n=s.inspect();if(r.json){let c={};if(s.facts)for(let a of Object.keys(s.facts))try{c[a]=s.facts[a];}catch{c[a]="(error reading)";}console.log(JSON.stringify({facts:c,...n},null,2)),s.stop();return}console.log(),console.log(m.bold(m.cyan("Directive System Inspection"))),console.log(m.dim("\u2500".repeat(40))),console.log();let o={};if(s.facts)for(let c of Object.keys(s.facts))try{o[c]=s.facts[c];}catch{o[c]="(error reading)";}console.log(tn(o)),console.log(),console.log(rn(n.constraints)),console.log(),console.log(nn(n.resolverDefs,n.resolvers)),console.log(),console.log(sn(n.unmet)),console.log(),n.inflight.length>0&&(console.log(on(n.inflight)),console.log());let i=ln(n);if(i.length>0){console.log(m.bold(m.yellow("Warnings:")));for(let c of i)console.log(` ${m.yellow("\u26A0")} ${c}`);console.log();}s.stop();}function Ot(e){let t={with:[],minimal:false,dir:process.cwd()};for(let r=0;r<e.length;r++)switch(e[r]){case "--with":{let n=e[++r];n&&(t.with=n.split(",").map(o=>o.trim()));break}case "--minimal":t.minimal=true;break;case "--dir":{let n=e[++r];n&&(t.dir=n);break}}return t}var Et=["derive","events","constraints","resolvers","effects"];function pn(e,t){let r=Dt(e),s=t.includes("constraints"),n=t.includes("resolvers"),i=`import { ${["type ModuleSchema","createModule","t"].join(", ")} } from "@directive-run/core";
|
|
713
750
|
|
|
714
751
|
`;return i+=`const schema = {
|
|
715
752
|
`,i+=` facts: {
|
|
@@ -778,7 +815,7 @@ export default system;
|
|
|
778
815
|
`,i+=` },
|
|
779
816
|
`,i+=` },
|
|
780
817
|
`),i+=`});
|
|
781
|
-
`,i}function
|
|
818
|
+
`,i}function mn(e){let t=Dt(e);return `import { type ModuleSchema, createModule, createSystem, t } from "@directive-run/core";
|
|
782
819
|
import {
|
|
783
820
|
createAgentOrchestrator,
|
|
784
821
|
createAgentMemory,
|
|
@@ -909,9 +946,9 @@ export const memory = createAgentMemory({
|
|
|
909
946
|
export const system = createSystem({
|
|
910
947
|
module: ${t},
|
|
911
948
|
});
|
|
912
|
-
`}function
|
|
913
|
-
Must start with a letter, use lowercase letters, numbers, and hyphens.`),process.exit(1));let s;r.minimal?s=[]:r.with.length>0?s=r.with.filter(a=>
|
|
914
|
-
Must start with a letter, use lowercase letters, numbers, and hyphens.`),process.exit(1));let s=Ct(r.dir),n=join(s,`${e}.ts`);existsSync(n)&&(console.error(`File already exists: ${relative(r.dir,n)}`),process.exit(1));let o=dn(e);Dt(n,o);let i=relative(r.dir,n);console.log(`${g.green("Created")} ${g.dim(i)}`),console.log(g.dim(" AI orchestrator with memory, guardrails, and streaming"));}var pe=typeof process<"u"&&process.env?.NODE_ENV!=="production";function ce(e,t=50){let r=new WeakSet;function s(a){if(a===null)return "null";if(a===void 0)return "undefined";let l=typeof a;if(l==="string")return JSON.stringify(a);if(l==="number"||l==="boolean")return String(a);if(l==="function")return '"[function]"';if(l==="symbol")return '"[symbol]"'}function n(a,l){if(r.has(a))return '"[circular]"';r.add(a);let u=l();return r.delete(a),u}function o(a,l){return n(a,()=>`[${a.map(u=>c(u,l+1)).join(",")}]`)}function i(a,l){return n(a,()=>`{${Object.keys(a).sort().map(u=>`${JSON.stringify(u)}:${c(a[u],l+1)}`).join(",")}}`)}function c(a,l){if(l>t)return '"[max depth exceeded]"';if(typeof a=="bigint")return `${a.toString()}n`;let u=s(a);if(u!==void 0)return u;if(a instanceof Date)return `D:${a.toISOString()}`;if(a instanceof RegExp)return `R:${a.source}:${a.flags}`;if(a instanceof Map){let f=[...a.entries()].sort();return `M:${c(f,l+1)}`}if(a instanceof Set){let f=[...a].sort();return `S:${c(f,l+1)}`}return Array.isArray(a)?o(a,l):typeof a=="object"?i(a,l):'"[unknown]"'}return c(e,0)}var J=new Set(["$eq","$ne","$in","$nin","$exists","$gt","$gte","$lt","$lte","$between","$matches","$startsWith","$endsWith","$contains","$changed"]),Nt=new Set(["$all","$any","$not"]);var K=64;function I(e){return typeof e!="object"||e===null||Array.isArray(e)?false:!(e instanceof Date)&&!(e instanceof RegExp)}function Oe(e){if(typeof e!="object"||e===null||Array.isArray(e))return false;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function Je(e){if(!I(e))return false;let t=0,r=false;for(let s of Object.keys(e)){if(s.startsWith("$"))r=true,J.has(s)||he(`predicate: unknown operator "${s}" \u2014 looks like a typo. Known operators: ${[...J].join(", ")}`);else if(r||t===0)return false;t++;}return r?t>0:false}function Pt(e){return e===null?false:Array.isArray(e)?e.every(t=>Oe(t)&&"fact"in t&&"op"in t):Oe(e)}function me(e,t,r="",s=new WeakSet,n=0){if(n>K){pe&&console.warn(`[Directive] predicate depth limit (${K}) exceeded \u2014 flatten the predicate or split it into multiple constraints. If this is unexpected, check for a cyclic spec object.`),t.bail?.("depth");return}if(Array.isArray(e)){e.forEach((i,c)=>{if(!I(i))return;let a=i;if(typeof a.fact=="string"&&typeof a.op=="string"){let l=r?`${r}[${c}]`:`[${c}]`;t.operator?.(r?`${r}.${a.fact}`:a.fact,a.op,a.value,`${l}.value`);}});return}if(!I(e))return;if(s.has(e)){pe&&console.warn("[Directive] walkPredicate: cyclic predicate spec"),t.bail?.("cycle");return}s.add(e);let o=e;for(let i of ["$all","$any","$not"])if(i in o){if(t.combinator?.(i)===false)return;let c=i==="$not"?[o.$not]:o[i]??[];for(let a of c)me(a,t,r,s,n+1);return}for(let i of Object.keys(o)){let c=r?`${r}.${i}`:i;if(i.startsWith("$")){t.strayOperatorKey?.(i,c);continue}let a=o[i];if(Je(a)){let l=a;for(let u of Object.keys(l))t.operator?.(c,u,l[u],`${c}.${u}`);continue}if(Oe(a)){if(t.nested?.(i)===false)continue;me(a,t,c,s,n+1);continue}t.literal?.(c,a);}}function qt(e,t=""){function r(n,o,i,c){if(typeof n=="bigint")throw new Error(`[Directive] validatePredicate: bigint operand at "${o}" is not JSON-serializable (JSON.stringify throws on bigint).`);if(n instanceof Set)throw new Error(`[Directive] validatePredicate: Set operand at "${o}" is not JSON-serializable (serializes to {} and loses all members).`);if(n instanceof Map)throw new Error(`[Directive] validatePredicate: Map operand at "${o}" is not JSON-serializable (serializes to {} and loses all entries).`);if(n instanceof RegExp)throw new Error(`[Directive] validatePredicate: RegExp operand at "${o}" is not JSON-serializable (a regex lost to JSON.parse becomes {}). Only a direct $matches operand may be a RegExp.`);if(!(n===null||typeof n!="object")&&!(c>K)&&!i.has(n)){if(i.add(n),Array.isArray(n)){n.forEach((a,l)=>{r(a,`${o}[${l}]`,i,c+1);});return}for(let a of Object.keys(n))r(n[a],o?`${o}.${a}`:a,i,c+1);}}function s(n,o,i){if(typeof n=="bigint")throw new Error(`[Directive] validatePredicate: bigint operand at "${i}" is not JSON-serializable (JSON.stringify throws on bigint).`);if(n instanceof Set)throw new Error(`[Directive] validatePredicate: Set operand at "${i}" is not JSON-serializable (serializes to {} and loses all members).`);if(n instanceof Map)throw new Error(`[Directive] validatePredicate: Map operand at "${i}" is not JSON-serializable (serializes to {} and loses all entries).`);if(o==="$matches"&&!(n instanceof RegExp))throw new Error(`[Directive] validatePredicate: $matches operand at "${i}" must be a RegExp; got ${n===null?"null":typeof n}. A regex lost to JSON.parse becomes {} \u2014 reify with new RegExp(pattern, flags) before installing.`);if(Array.isArray(n))n.forEach((c,a)=>{r(c,`${i}[${a}]`,new WeakSet,1);});else if(Oe(n))for(let c of Object.keys(n))r(n[c],`${i}.${c}`,new WeakSet,1);}if(e instanceof Set)throw new Error(`[Directive] validatePredicate: Set operand${t?` at "${t}"`:""} is not JSON-serializable (serializes to {} and loses all members).`);if(e instanceof Map)throw new Error(`[Directive] validatePredicate: Map operand${t?` at "${t}"`:""} is not JSON-serializable (serializes to {} and loses all entries).`);me(e,{operator(n,o,i,c){s(i,o,t?`${t}.${c}`:c);},literal(n,o){s(o,"",t?`${t}.${n}`:n);}});}function pn(){return {ids:new WeakMap,next:{v:1},pairs:new Set}}function Mt(e,t){let r=e.ids.get(t);return r===void 0&&(r=e.next.v++,e.ids.set(t,r)),r}function q(e,t,r){if(Object.is(e,t))return true;if(e instanceof Date&&t instanceof Date)return e.getTime()===t.getTime();if(typeof e!="object"||typeof t!="object"||e===null||t===null)return false;let s=r??pn(),n=`${Mt(s,e)}:${Mt(s,t)}`;if(s.pairs.has(n))return true;if(s.pairs.add(n),Array.isArray(e)||Array.isArray(t))return !Array.isArray(e)||!Array.isArray(t)||e.length!==t.length?false:e.every((c,a)=>q(c,t[a],s));if(e instanceof Set||t instanceof Set){if(!(e instanceof Set)||!(t instanceof Set)||e.size!==t.size)return false;let c=[...t];return [...e].every(a=>c.some(l=>q(a,l,s)))}if(e instanceof Map||t instanceof Map){if(!(e instanceof Map)||!(t instanceof Map)||e.size!==t.size)return false;let c=[...t.entries()],a=new Array(c.length).fill(false);for(let[l,u]of e){let f=false;for(let d=0;d<c.length;d++){if(a[d])continue;let[m,$]=c[d];if(q(l,m,s)&&q(u,$,s)){a[d]=true,f=true;break}}if(!f)return false}return true}let o=Object.keys(e),i=Object.keys(t);return o.length!==i.length?false:o.every(c=>Object.hasOwn(t,c)&&q(e[c],t[c],s))}function De(e){if(e instanceof Date)return e.getTime();if(typeof e=="number"||typeof e=="bigint"||typeof e=="string")return e}function Le(e,t,r){let s=De(t),n=De(r);if(s===void 0||n===void 0||typeof s!=typeof n)return false;switch(e){case "$gt":return s>n;case "$gte":return s>=n;case "$lt":return s<n;case "$lte":return s<=n;default:return false}}function Ce(e,t,r,s){switch(e){case "$eq":return q(t,r);case "$ne":return !q(t,r);case "$in":return Array.isArray(r)&&r.some(n=>q(t,n));case "$nin":return Array.isArray(r)&&!r.some(n=>q(t,n));case "$exists":return r===(t!==void 0);case "$changed":return !q(t,s);case "$gt":case "$gte":case "$lt":case "$lte":return Le(e,t,r);case "$between":{if(!Array.isArray(r)||r.length!==2)return false;let n=De(r[0]),o=De(r[1]);return n!==void 0&&o!==void 0&&typeof n==typeof o&&n>o?(he("$between: reversed pair \u2014 [min, max] required"),false):Le("$gte",t,r[0])&&Le("$lte",t,r[1])}case "$matches":{if(!(r instanceof RegExp))throw new Error("[Directive] $matches: operand must be a RegExp (string operands are no longer accepted; pass /pattern/flags directly).");return typeof t!="string"?false:r.test(t)}case "$startsWith":return typeof t!="string"?false:t.startsWith(String(r));case "$endsWith":return typeof t!="string"?false:t.endsWith(String(r));case "$contains":return typeof t=="string"?t.includes(String(r)):Array.isArray(t)?t.some(n=>q(n,r)):t instanceof Set?t.has(r):false;default:return false}}function he(e){pe&&console.warn(`[Directive] ${e}`);}function mn(e,t,r,s){if(Je(e)){let n=Object.keys(e);n.length>1&&he(`predicate: operator object has ${n.length} operators (${n.join(", ")}) \u2014 write the array form or $all instead. The runtime ANDs them as a best-effort fallback.`);for(let o of n)if(!Ce(o,t,e[o],r))return false;return true}return I(e)?te(e,I(t)?t:Object.create(null),I(r)?r:void 0,s+1):q(t,e)}function te(e,t,r,s=0){if(s>K)return he(`predicate depth limit (${K}) exceeded \u2014 flatten the predicate or split it into multiple constraints. If this is unexpected, check for a cyclic spec object.`),false;if(Array.isArray(e))return e.every(n=>{if(!I(n))return false;let{fact:o,op:i,value:c}=n;return Ce(i,t?.[o],c,r?.[o])});if(!I(e))return !!e;if("$all"in e)return e.$all.every(n=>te(n,t,r,s+1));if("$any"in e)return e.$any.some(n=>te(n,t,r,s+1));if("$not"in e)return !te(e.$not,t,r,s+1);for(let n of Object.keys(e)){if(J.has(n))return he(`predicate: operator "${n}" mixed with fact keys \u2014 wrap operators in a per-fact object`),false;if(!mn(e[n],t?.[n],r?.[n],s))return false}return true}function ge(e,t,r,s=""){let n=[];if(Array.isArray(e)){for(let o of e){if(!I(o))continue;let{fact:i,op:c,value:a}=o,l=t?.[i];n.push({path:s+i,op:c,expected:a,actual:l,pass:Ce(c,l,a,r?.[i])});}return n}if(!I(e))return n;for(let o of ["$all","$any","$not"])if(o in e){let i=o==="$not"?[e.$not]:e[o],c=[];for(let u of i)c.push(...ge(u,t,r,s));let a=c.filter(u=>u.pass).length,l;return o==="$all"?l=c.length===0||a===c.length:o==="$any"?l=c.length>0&&a>0:l=!c.every(u=>u.pass),n.push({path:s||o,op:o,expected:i.length,actual:a,pass:l,children:c}),n}for(let o of Object.keys(e)){if(J.has(o))continue;let i=e[o],c=t?.[o],a=s+o;if(Je(i))for(let l of Object.keys(i))n.push({path:a,op:l,expected:i[l],actual:c,pass:Ce(l,c,i[l],r?.[o])});else I(i)?n.push(...ge(i,I(c)?c:Object.create(null),I(r?.[o])?r?.[o]:void 0,`${a}.`)):n.push({path:a,op:"$eq",expected:i,actual:c,pass:q(c,i)});}return n}var le=1e6;function It(e,t){try{qt(e);}catch(s){let n=s instanceof Error?s.message:String(s);throw new Error(`[Directive] replayUnder: the ${t} predicate is invalid \u2014 ${n}`)}if(!Pt(e)){let s=e===null||typeof e!="object"?`${typeof e} \u2014 ${JSON.stringify(e)}`:JSON.stringify(e).slice(0,80);throw new Error(`[Directive] replayUnder: the ${t} predicate is not a valid FactPredicate (got ${s})`)}let r;if(me(e,{operator(s,n){r===void 0&&n.startsWith("$")&&!J.has(n)&&(r=n);},strayOperatorKey(s){r===void 0&&!J.has(s)&&!Nt.has(s)&&(r=s);}}),r!==void 0)throw new Error(`[Directive] replayUnder: the ${t} predicate uses an unknown operator "${r}" \u2014 known operators: ${[...J].join(", ")}`)}function ye(e){if(e&&typeof e=="object"&&!Array.isArray(e)&&Array.isArray(e.snapshots))return hn(e);let t=Array.isArray(e)?e:e&&typeof e=="object"&&Array.isArray(e.frames)?e.frames:null;if(!t)throw new Error("[Directive] toReplayFrames: history must be a JSON array of frames, an object with a `frames` array, or a history export with a `snapshots` array");if(t.length>le)throw new Error(`[Directive] toReplayFrames: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${le}) \u2014 split or down-sample the history`);return t.map((r,s)=>{if(r&&typeof r=="object"&&"facts"in r){let n=r,o={id:n.id??`#${s}`,facts:n.facts??{}};return typeof n.timestamp=="number"&&(o.timestamp=n.timestamp),o}return {id:`#${s}`,facts:r??{}}})}function hn(e){let t=typeof e=="string"?JSON.parse(e):e;if(Array.isArray(t))return Ft(t);if(!t||typeof t!="object")throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");let r=t;if(r.version!==void 0&&r.version!==1)throw new Error(`[Directive] framesFromHistory: unsupported history export version ${JSON.stringify(r.version)} \u2014 expected 1`);if(!Array.isArray(r.snapshots))throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");return Ft(r.snapshots)}function Ft(e){if(!Array.isArray(e))throw new Error("[Directive] framesFromSnapshots: expected an array of fact-state snapshots");if(e.length>le)throw new Error(`[Directive] framesFromSnapshots: history has ${e.length} snapshots, exceeds the MAX_REPLAY_FRAMES limit (${le}) \u2014 split or down-sample the history`);for(let t=0;t<e.length;t++){let r=e[t];if(!r||typeof r!="object"||!("facts"in r))throw new Error(`[Directive] framesFromSnapshots: snapshot at index ${t} is not a { facts, ... } object`)}return ye(e)}function Re(e){let{frames:t,original:r,proposed:s,entityKey:n}=e,o=e.maxSamples??20,i=o>0?o:0;if(t.length>le)throw new Error(`[Directive] replayUnder: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${le}) \u2014 split or down-sample the history`);It(r,"original"),It(s,"proposed");let c=0,a=0,l=0,u=0,f=0,d=[],m=[],$=n?new Set:void 0,w=n?new Set:void 0,F;for(let p of t){let y=p.facts,D=te(r,y,F),_=te(s,y,F);D&&(c++,$?.add(y[n])),_&&(a++,w?.add(y[n])),D===_?f++:!D&&_?(l++,d.length<i&&d.push(Wt(p,r,s,F))):(u++,m.length<i&&m.push(Wt(p,r,s,F))),F=y;}let W={framesEvaluated:t.length,original:{matched:c},proposed:{matched:a},delta:a-c,newMatchCount:l,lostMatchCount:u,unchanged:f,newMatches:d,lostMatches:m};return $&&w&&(W.original.matchedEntities=$.size,W.proposed.matchedEntities=w.size),W}function Wt(e,t,r,s){let n=e.facts,o={frameId:e.id,facts:n,originalExplain:ge(t,n,s),proposedExplain:ge(r,n,s)};return e.timestamp!==void 0&&(o.timestamp=e.timestamp),o}var _t=1e4,zt=5e7;function gn(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===1&&typeof e.$hole=="string"}function Ke(e,t,r=new Set,s=0){if(s>K)throw new Error(`[Directive] sweepUnder: template exceeds MAX_PREDICATE_DEPTH (${K}) \u2014 flatten the template or split the sweep`);if(gn(e)){let n=e.$hole;if(!(n in t))throw new Error(`[Directive] sweepUnder: template references hole "${n}" but sweep has no values for it`);return t[n]}if(e===null||typeof e!="object")return e;if(r.has(e))throw new Error("[Directive] sweepUnder: template contains a cycle \u2014 predicate templates must be a tree");r.add(e);try{if(Array.isArray(e))return e.map(o=>Ke(o,t,r,s+1));let n={};for(let[o,i]of Object.entries(e))n[o]=Ke(i,t,r,s+1);return n}finally{r.delete(e);}}function*Lt(e,t){if(e.length===0){yield {};return}let r=e[0],s=e.slice(1),n=t[r]??[];for(let o of n)for(let i of Lt(s,t))yield {[r]:o,...i};}function yn(e){let t=1;for(let r of Object.values(e))t*=r.length;return t}function Jt(e){let{frames:t,original:r,template:s,sweep:n,objective:o=y=>y.proposed.matched,entityKey:i,maxSamples:c=0}=e,a=Object.keys(n);if(a.length===0)throw new Error("[Directive] sweepUnder: `sweep` must contain at least one hole name");let l=yn(n);if(l>_t)throw new Error(`[Directive] sweepUnder: grid has ${l} points, exceeds the MAX_SWEEP_POINTS limit (${_t}) \u2014 narrow the sweep ranges or split the run`);if(l===0)throw new Error("[Directive] sweepUnder: at least one hole has zero candidate values");let u=l*t.length;if(u>zt)throw new Error(`[Directive] sweepUnder: ${l} points \xD7 ${t.length} frames = ${u} per-frame evaluations, exceeds the MAX_SWEEP_EVALUATIONS limit (${zt}) \u2014 narrow the sweep, down-sample the history, or split the run`);let f=false,d=y=>{let D;try{D=o(y);}catch(_){return f||(f=true,console.warn(`[Directive] sweepUnder: objective threw \u2014 point will not rank (${_.message})`)),Number.NEGATIVE_INFINITY}return typeof D!="number"||!Number.isFinite(D)?(f||(f=true,console.warn(`[Directive] sweepUnder: objective returned a non-finite number (${String(D)}) \u2014 point will not rank`)),Number.NEGATIVE_INFINITY):D},m=Re({frames:t,original:r,proposed:r,entityKey:i,maxSamples:c}),$={values:{},report:m,score:d(m)},w=[],F=0,W=Number.NEGATIVE_INFINITY;for(let y of Lt(a,n)){let D=Ke(s,y),_=Re({frames:t,original:r,proposed:D,entityKey:i,maxSamples:c}),Me=d(_);Me>W&&(W=Me,F=w.length),w.push({values:y,report:_,score:Me});}let p=w[F];return {points:w,bestIndex:F,best:p,baseline:$}}function Ut(e){let t=e&&typeof e=="object"&&!Array.isArray(e)&&"constraints"in e?e.constraints:e;if(Array.isArray(t)){let r={};for(let s of t){if(!s||typeof s!="object"||!("id"in s))throw new Error("[Directive] diffRules: array entries must be `{ id, whenSpec }` objects");let n=s;if(typeof n.id!="string")throw new Error("[Directive] diffRules: constraint `id` must be a string");r[n.id]=n.whenSpec;}return r}if(t&&typeof t=="object")return t;throw new Error("[Directive] diffRules: expected a `{ id: whenSpec }` map, an array of `{ id, whenSpec }`, or `{ constraints: ... }`")}var $n=new Set(["$eq","$ne","$in","$nin","$exists","$gt","$gte","$lt","$lte","$between","$matches","$startsWith","$endsWith","$contains","$changed"]),vn=new Set(["$all","$any","$not"]);function Kt(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function wn(e){if(!Kt(e))return false;let t=Object.keys(e);if(t.length===0)return false;let r=false;for(let s of t){if(!s.startsWith("$"))return false;$n.has(s)&&(r=true);}return r}function B(e,t="",r=[]){if(e===null||typeof e!="object")return r;if(Array.isArray(e)){for(let s of e)if(s&&typeof s=="object"&&"fact"in s&&"op"in s){let n=s;r.push({path:t?`${t}.${String(n.fact)}`:String(n.fact),op:String(n.op),value:n.value});}return r}if("$all"in e&&Array.isArray(e.$all))return e.$all.forEach((s,n)=>{B(s,`${t}$all[${n}]`,r);}),r;if("$any"in e&&Array.isArray(e.$any))return e.$any.forEach((s,n)=>{B(s,`${t}$any[${n}]`,r);}),r;if("$not"in e)return B(e.$not,`${t}$not`,r),r;for(let[s,n]of Object.entries(e)){let o=t?`${t}.${s}`:s;if(wn(n))for(let[i,c]of Object.entries(n))r.push({path:o,op:i,value:c});else Kt(n)&&!vn.has(s)?B(n,o,r):r.push({path:o,op:"$eq",value:n});}return r}function G(e){return typeof e=="number"&&Number.isFinite(e)}function bn(e,t,r){switch(e){case "$gte":case "$gt":if(G(t)&&G(r)){if(r<t)return "relaxed";if(r>t)return "tightened"}return null;case "$lte":case "$lt":if(G(t)&&G(r)){if(r>t)return "relaxed";if(r<t)return "tightened"}return null;case "$between":{if(Array.isArray(t)&&Array.isArray(r)&&t.length===2&&r.length===2&&G(t[0])&&G(t[1])&&G(r[0])&&G(r[1])){let s=t[1]-t[0],n=r[1]-r[0];if(n>s)return "relaxed";if(n<s)return "tightened"}return null}case "$in":case "$nin":{if(Array.isArray(t)&&Array.isArray(r))if(e==="$in"){if(r.length>t.length)return "relaxed";if(r.length<t.length)return "tightened"}else {if(r.length>t.length)return "tightened";if(r.length<t.length)return "relaxed"}return null}case "$contains":{if(Array.isArray(t)&&Array.isArray(r)){if(r.length>t.length)return "relaxed";if(r.length<t.length)return "tightened"}return null}default:return null}}function Gt(e){let t=Ut(e.before),r=Ut(e.after),s=[...new Set([...Object.keys(t),...Object.keys(r)])].sort(),n=[],o={added:0,removed:0,changed:0,unchanged:0,totalClauseChanges:0};for(let i of s){let c=t[i],a=r[i],l=i in t,u=i in r;if(l&&!u){let d=B(c),m=d.length===0?[{path:"(function-form predicate)",kind:"removed"}]:d.map($=>({path:$.path,kind:"removed",before:{op:$.op,value:$.value}}));Ge(m),n.push({id:i,status:"removed",changes:m}),o.removed++,o.totalClauseChanges+=m.length;continue}if(!l&&u){let d=B(a),m=d.length===0?[{path:"(function-form predicate)",kind:"added"}]:d.map($=>({path:$.path,kind:"added",after:{op:$.op,value:$.value}}));Ge(m),n.push({id:i,status:"added",changes:m}),o.added++,o.totalClauseChanges+=m.length;continue}let f=xn(c,a);f.length===0?(n.push({id:i,status:"unchanged",changes:[]}),o.unchanged++):(n.push({id:i,status:"changed",changes:f}),o.changed++,o.totalClauseChanges+=f.length);}return {constraints:n,summary:o}}function xn(e,t){if(e!==void 0&&t!==void 0&&(e===null||t===null||typeof e!="object"||typeof t!="object"))return ce(e)===ce(t)?[]:[{path:"",kind:"changed",before:{op:"$eq",value:e},after:{op:"$eq",value:t}}];let r=e===void 0?[]:B(e),s=t===void 0?[]:B(t),n=l=>`${l.path}::${l.op}`,o=new Map(r.map(l=>[n(l),l])),i=new Map(s.map(l=>[n(l),l])),c=new Set([...o.keys(),...i.keys()]),a=[];for(let l of c){let u=o.get(l),f=i.get(l);if(u&&!f){a.push({path:u.path,kind:"removed",before:{op:u.op,value:u.value}});continue}if(!u&&f){a.push({path:f.path,kind:"added",after:{op:f.op,value:f.value}});continue}if(u&&f){if(ce(u.value)===ce(f.value))continue;let d=bn(u.op,u.value,f.value);a.push({path:u.path,kind:d??"changed",before:{op:u.op,value:u.value},after:{op:f.op,value:f.value}});}}return Ge(a),a}function Ge(e){e.sort((t,r)=>{let s=t.path.localeCompare(r.path);if(s!==0)return s;let n=t.before?.op??t.after?.op??"",o=r.before?.op??r.after?.op??"";return n.localeCompare(o)});}function jn(e){let t={maxSamples:20,json:false};for(let r=0;r<e.length;r++)switch(e[r]){case "--history":{let n=e[++r];n&&(t.historyPath=n);break}case "--proposed":case "-p":{let n=e[++r];n&&(t.proposedPath=n);break}case "--original":case "-o":{let n=e[++r];n&&(t.originalPath=n);break}case "--max-samples":{let n=e[++r],o=n?Number.parseInt(n,10):Number.NaN;Number.isFinite(o)&&o>=0&&(t.maxSamples=o);break}case "--entity-key":{let n=e[++r];n&&(t.entityKey=n);break}case "--json":t.json=true;break}return t}function Te(){console.error(`
|
|
949
|
+
`}function Dt(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}function Rt(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}function Ct(e){return join(e,"src")}async function Tt(e,t){let r=Ot(t);(!e||!/^[a-z][a-z0-9-]*$/.test(e))&&(console.error(`Invalid module name: ${e||"(none)"}
|
|
950
|
+
Must start with a letter, use lowercase letters, numbers, and hyphens.`),process.exit(1));let s;r.minimal?s=[]:r.with.length>0?s=r.with.filter(a=>Et.includes(a)):s=Et;let n=Ct(r.dir),o=join(n,`${e}.ts`);existsSync(o)&&(console.error(`File already exists: ${relative(r.dir,o)}`),process.exit(1));let i=pn(e,s);Rt(o,i);let c=relative(r.dir,o);console.log(`${m.green("Created")} ${m.dim(c)}`),s.length===0?console.log(m.dim(" Minimal module (schema + init only)")):console.log(m.dim(` Sections: ${s.join(", ")}`));}async function Mt(e,t){let r=Ot(t);(!e||!/^[a-z][a-z0-9-]*$/.test(e))&&(console.error(`Invalid orchestrator name: ${e||"(none)"}
|
|
951
|
+
Must start with a letter, use lowercase letters, numbers, and hyphens.`),process.exit(1));let s=Ct(r.dir),n=join(s,`${e}.ts`);existsSync(n)&&(console.error(`File already exists: ${relative(r.dir,n)}`),process.exit(1));let o=mn(e);Rt(n,o);let i=relative(r.dir,n);console.log(`${m.green("Created")} ${m.dim(i)}`),console.log(m.dim(" AI orchestrator with memory, guardrails, and streaming"));}var ge=typeof process<"u"&&process.env?.NODE_ENV!=="production";function de(e,t=50){let r=new WeakSet;function s(a){if(a===null)return "null";if(a===void 0)return "undefined";let l=typeof a;if(l==="string")return JSON.stringify(a);if(l==="number"||l==="boolean")return String(a);if(l==="function")return '"[function]"';if(l==="symbol")return '"[symbol]"'}function n(a,l){if(r.has(a))return '"[circular]"';r.add(a);let u=l();return r.delete(a),u}function o(a,l){return n(a,()=>`[${a.map(u=>c(u,l+1)).join(",")}]`)}function i(a,l){return n(a,()=>`{${Object.keys(a).sort().map(u=>`${JSON.stringify(u)}:${c(a[u],l+1)}`).join(",")}}`)}function c(a,l){if(l>t)return '"[max depth exceeded]"';if(typeof a=="bigint")return `${a.toString()}n`;let u=s(a);if(u!==void 0)return u;if(a instanceof Date)return `D:${a.toISOString()}`;if(a instanceof RegExp)return `R:${a.source}:${a.flags}`;if(a instanceof Map){let d=[...a.entries()].sort();return `M:${c(d,l+1)}`}if(a instanceof Set){let d=[...a].sort();return `S:${c(d,l+1)}`}return Array.isArray(a)?o(a,l):typeof a=="object"?i(a,l):'"[unknown]"'}return c(e,0)}var K=new Set(["$eq","$ne","$in","$nin","$exists","$gt","$gte","$lt","$lte","$between","$matches","$startsWith","$endsWith","$contains","$changed"]),Pt=new Set(["$all","$any","$not"]);var G=64;function I(e){return typeof e!="object"||e===null||Array.isArray(e)?false:!(e instanceof Date)&&!(e instanceof RegExp)}function De(e){if(typeof e!="object"||e===null||Array.isArray(e))return false;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function Be(e){if(!I(e))return false;let t=0,r=false;for(let s of Object.keys(e)){if(s.startsWith("$"))r=true,K.has(s)||$e(`predicate: unknown operator "${s}" \u2014 looks like a typo. Known operators: ${[...K].join(", ")}`);else if(r||t===0)return false;t++;}return r?t>0:false}function qt(e){return e===null?false:Array.isArray(e)?e.every(t=>De(t)&&"fact"in t&&"op"in t):De(e)}function ye(e,t,r="",s=new WeakSet,n=0){if(n>G){ge&&console.warn(`[Directive] predicate depth limit (${G}) exceeded \u2014 flatten the predicate or split it into multiple constraints. If this is unexpected, check for a cyclic spec object.`),t.bail?.("depth");return}if(Array.isArray(e)){e.forEach((i,c)=>{if(!I(i))return;let a=i;if(typeof a.fact=="string"&&typeof a.op=="string"){let l=r?`${r}[${c}]`:`[${c}]`;t.operator?.(r?`${r}.${a.fact}`:a.fact,a.op,a.value,`${l}.value`);}});return}if(!I(e))return;if(s.has(e)){ge&&console.warn("[Directive] walkPredicate: cyclic predicate spec"),t.bail?.("cycle");return}s.add(e);let o=e;for(let i of ["$all","$any","$not"])if(i in o){if(t.combinator?.(i)===false)return;let c=i==="$not"?[o.$not]:o[i]??[];for(let a of c)ye(a,t,r,s,n+1);return}for(let i of Object.keys(o)){let c=r?`${r}.${i}`:i;if(i.startsWith("$")){t.strayOperatorKey?.(i,c);continue}let a=o[i];if(Be(a)){let l=a;for(let u of Object.keys(l))t.operator?.(c,u,l[u],`${c}.${u}`);continue}if(De(a)){if(t.nested?.(i)===false)continue;ye(a,t,c,s,n+1);continue}t.literal?.(c,a);}}function It(e,t=""){function r(n,o,i,c){if(typeof n=="bigint")throw new Error(`[Directive] validatePredicate: bigint operand at "${o}" is not JSON-serializable (JSON.stringify throws on bigint).`);if(n instanceof Set)throw new Error(`[Directive] validatePredicate: Set operand at "${o}" is not JSON-serializable (serializes to {} and loses all members).`);if(n instanceof Map)throw new Error(`[Directive] validatePredicate: Map operand at "${o}" is not JSON-serializable (serializes to {} and loses all entries).`);if(n instanceof RegExp)throw new Error(`[Directive] validatePredicate: RegExp operand at "${o}" is not JSON-serializable (a regex lost to JSON.parse becomes {}). Only a direct $matches operand may be a RegExp.`);if(!(n===null||typeof n!="object")&&!(c>G)&&!i.has(n)){if(i.add(n),Array.isArray(n)){n.forEach((a,l)=>{r(a,`${o}[${l}]`,i,c+1);});return}for(let a of Object.keys(n))r(n[a],o?`${o}.${a}`:a,i,c+1);}}function s(n,o,i){if(typeof n=="bigint")throw new Error(`[Directive] validatePredicate: bigint operand at "${i}" is not JSON-serializable (JSON.stringify throws on bigint).`);if(n instanceof Set)throw new Error(`[Directive] validatePredicate: Set operand at "${i}" is not JSON-serializable (serializes to {} and loses all members).`);if(n instanceof Map)throw new Error(`[Directive] validatePredicate: Map operand at "${i}" is not JSON-serializable (serializes to {} and loses all entries).`);if(o==="$matches"&&!(n instanceof RegExp))throw new Error(`[Directive] validatePredicate: $matches operand at "${i}" must be a RegExp; got ${n===null?"null":typeof n}. A regex lost to JSON.parse becomes {} \u2014 reify with new RegExp(pattern, flags) before installing.`);if(Array.isArray(n))n.forEach((c,a)=>{r(c,`${i}[${a}]`,new WeakSet,1);});else if(De(n))for(let c of Object.keys(n))r(n[c],`${i}.${c}`,new WeakSet,1);}if(e instanceof Set)throw new Error(`[Directive] validatePredicate: Set operand${t?` at "${t}"`:""} is not JSON-serializable (serializes to {} and loses all members).`);if(e instanceof Map)throw new Error(`[Directive] validatePredicate: Map operand${t?` at "${t}"`:""} is not JSON-serializable (serializes to {} and loses all entries).`);ye(e,{operator(n,o,i,c){s(i,o,t?`${t}.${c}`:c);},literal(n,o){s(o,"",t?`${t}.${n}`:n);}});}function hn(){return {ids:new WeakMap,next:{v:1},pairs:new Set}}function Nt(e,t){let r=e.ids.get(t);return r===void 0&&(r=e.next.v++,e.ids.set(t,r)),r}function q(e,t,r){if(Object.is(e,t))return true;if(e instanceof Date&&t instanceof Date)return e.getTime()===t.getTime();if(typeof e!="object"||typeof t!="object"||e===null||t===null)return false;let s=r??hn(),n=`${Nt(s,e)}:${Nt(s,t)}`;if(s.pairs.has(n))return true;if(s.pairs.add(n),Array.isArray(e)||Array.isArray(t))return !Array.isArray(e)||!Array.isArray(t)||e.length!==t.length?false:e.every((c,a)=>q(c,t[a],s));if(e instanceof Set||t instanceof Set){if(!(e instanceof Set)||!(t instanceof Set)||e.size!==t.size)return false;let c=[...t];return [...e].every(a=>c.some(l=>q(a,l,s)))}if(e instanceof Map||t instanceof Map){if(!(e instanceof Map)||!(t instanceof Map)||e.size!==t.size)return false;let c=[...t.entries()],a=new Array(c.length).fill(false);for(let[l,u]of e){let d=false;for(let f=0;f<c.length;f++){if(a[f])continue;let[h,$]=c[f];if(q(l,h,s)&&q(u,$,s)){a[f]=true,d=true;break}}if(!d)return false}return true}let o=Object.keys(e),i=Object.keys(t);return o.length!==i.length?false:o.every(c=>Object.hasOwn(t,c)&&q(e[c],t[c],s))}function Re(e){if(e instanceof Date)return e.getTime();if(typeof e=="number"||typeof e=="bigint"||typeof e=="string")return e}function Ge(e,t,r){let s=Re(t),n=Re(r);if(s===void 0||n===void 0||typeof s!=typeof n)return false;switch(e){case "$gt":return s>n;case "$gte":return s>=n;case "$lt":return s<n;case "$lte":return s<=n;default:return false}}function Ce(e,t,r,s){switch(e){case "$eq":return q(t,r);case "$ne":return !q(t,r);case "$in":return Array.isArray(r)&&r.some(n=>q(t,n));case "$nin":return Array.isArray(r)&&!r.some(n=>q(t,n));case "$exists":return r===(t!==void 0);case "$changed":return !q(t,s);case "$gt":case "$gte":case "$lt":case "$lte":return Ge(e,t,r);case "$between":{if(!Array.isArray(r)||r.length!==2)return false;let n=Re(r[0]),o=Re(r[1]);return n!==void 0&&o!==void 0&&typeof n==typeof o&&n>o?($e("$between: reversed pair \u2014 [min, max] required"),false):Ge("$gte",t,r[0])&&Ge("$lte",t,r[1])}case "$matches":{if(!(r instanceof RegExp))throw new Error("[Directive] $matches: operand must be a RegExp (string operands are no longer accepted; pass /pattern/flags directly).");return typeof t!="string"?false:r.test(t)}case "$startsWith":return typeof t!="string"?false:t.startsWith(String(r));case "$endsWith":return typeof t!="string"?false:t.endsWith(String(r));case "$contains":return typeof t=="string"?t.includes(String(r)):Array.isArray(t)?t.some(n=>q(n,r)):t instanceof Set?t.has(r):false;default:return false}}function $e(e){ge&&console.warn(`[Directive] ${e}`);}function gn(e,t,r,s){if(Be(e)){let n=Object.keys(e);n.length>1&&$e(`predicate: operator object has ${n.length} operators (${n.join(", ")}) \u2014 write the array form or $all instead. The runtime ANDs them as a best-effort fallback.`);for(let o of n)if(!Ce(o,t,e[o],r))return false;return true}return I(e)?se(e,I(t)?t:Object.create(null),I(r)?r:void 0,s+1):q(t,e)}function se(e,t,r,s=0){if(s>G)return $e(`predicate depth limit (${G}) exceeded \u2014 flatten the predicate or split it into multiple constraints. If this is unexpected, check for a cyclic spec object.`),false;if(Array.isArray(e))return e.every(n=>{if(!I(n))return false;let{fact:o,op:i,value:c}=n;return Ce(i,t?.[o],c,r?.[o])});if(!I(e))return !!e;if("$all"in e)return e.$all.every(n=>se(n,t,r,s+1));if("$any"in e)return e.$any.some(n=>se(n,t,r,s+1));if("$not"in e)return !se(e.$not,t,r,s+1);for(let n of Object.keys(e)){if(K.has(n))return $e(`predicate: operator "${n}" mixed with fact keys \u2014 wrap operators in a per-fact object`),false;if(!gn(e[n],t?.[n],r?.[n],s))return false}return true}function ve(e,t,r,s=""){let n=[];if(Array.isArray(e)){for(let o of e){if(!I(o))continue;let{fact:i,op:c,value:a}=o,l=t?.[i];n.push({path:s+i,op:c,expected:a,actual:l,pass:Ce(c,l,a,r?.[i])});}return n}if(!I(e))return n;for(let o of ["$all","$any","$not"])if(o in e){let i=o==="$not"?[e.$not]:e[o],c=[];for(let u of i)c.push(...ve(u,t,r,s));let a=c.filter(u=>u.pass).length,l;return o==="$all"?l=c.length===0||a===c.length:o==="$any"?l=c.length>0&&a>0:l=!c.every(u=>u.pass),n.push({path:s||o,op:o,expected:i.length,actual:a,pass:l,children:c}),n}for(let o of Object.keys(e)){if(K.has(o))continue;let i=e[o],c=t?.[o],a=s+o;if(Be(i))for(let l of Object.keys(i))n.push({path:a,op:l,expected:i[l],actual:c,pass:Ce(l,c,i[l],r?.[o])});else I(i)?n.push(...ve(i,I(c)?c:Object.create(null),I(r?.[o])?r?.[o]:void 0,`${a}.`)):n.push({path:a,op:"$eq",expected:i,actual:c,pass:q(c,i)});}return n}var fe=1e6;function Ft(e,t){try{It(e);}catch(s){let n=s instanceof Error?s.message:String(s);throw new Error(`[Directive] replayUnder: the ${t} predicate is invalid \u2014 ${n}`)}if(!qt(e)){let s=e===null||typeof e!="object"?`${typeof e} \u2014 ${JSON.stringify(e)}`:JSON.stringify(e).slice(0,80);throw new Error(`[Directive] replayUnder: the ${t} predicate is not a valid FactPredicate (got ${s})`)}let r;if(ye(e,{operator(s,n){r===void 0&&n.startsWith("$")&&!K.has(n)&&(r=n);},strayOperatorKey(s){r===void 0&&!K.has(s)&&!Pt.has(s)&&(r=s);}}),r!==void 0)throw new Error(`[Directive] replayUnder: the ${t} predicate uses an unknown operator "${r}" \u2014 known operators: ${[...K].join(", ")}`)}function we(e){if(e&&typeof e=="object"&&!Array.isArray(e)&&Array.isArray(e.snapshots))return yn(e);let t=Array.isArray(e)?e:e&&typeof e=="object"&&Array.isArray(e.frames)?e.frames:null;if(!t)throw new Error("[Directive] toReplayFrames: history must be a JSON array of frames, an object with a `frames` array, or a history export with a `snapshots` array");if(t.length>fe)throw new Error(`[Directive] toReplayFrames: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${fe}) \u2014 split or down-sample the history`);return t.map((r,s)=>{if(r&&typeof r=="object"&&"facts"in r){let n=r,o={id:n.id??`#${s}`,facts:n.facts??{}};return typeof n.timestamp=="number"&&(o.timestamp=n.timestamp),o}return {id:`#${s}`,facts:r??{}}})}function yn(e){let t=typeof e=="string"?JSON.parse(e):e;if(Array.isArray(t))return Wt(t);if(!t||typeof t!="object")throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");let r=t;if(r.version!==void 0&&r.version!==1)throw new Error(`[Directive] framesFromHistory: unsupported history export version ${JSON.stringify(r.version)} \u2014 expected 1`);if(!Array.isArray(r.snapshots))throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");return Wt(r.snapshots)}function Wt(e){if(!Array.isArray(e))throw new Error("[Directive] framesFromSnapshots: expected an array of fact-state snapshots");if(e.length>fe)throw new Error(`[Directive] framesFromSnapshots: history has ${e.length} snapshots, exceeds the MAX_REPLAY_FRAMES limit (${fe}) \u2014 split or down-sample the history`);for(let t=0;t<e.length;t++){let r=e[t];if(!r||typeof r!="object"||!("facts"in r))throw new Error(`[Directive] framesFromSnapshots: snapshot at index ${t} is not a { facts, ... } object`)}return we(e)}function Te(e){let{frames:t,original:r,proposed:s,entityKey:n}=e,o=e.maxSamples??20,i=o>0?o:0;if(t.length>fe)throw new Error(`[Directive] replayUnder: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${fe}) \u2014 split or down-sample the history`);Ft(r,"original"),Ft(s,"proposed");let c=0,a=0,l=0,u=0,d=0,f=[],h=[],$=n?new Set:void 0,w=n?new Set:void 0,F;for(let p of t){let v=p.facts,D=se(r,v,F),_=se(s,v,F);D&&(c++,$?.add(v[n])),_&&(a++,w?.add(v[n])),D===_?d++:!D&&_?(l++,f.length<i&&f.push(_t(p,r,s,F))):(u++,h.length<i&&h.push(_t(p,r,s,F))),F=v;}let W={framesEvaluated:t.length,original:{matched:c},proposed:{matched:a},delta:a-c,newMatchCount:l,lostMatchCount:u,unchanged:d,newMatches:f,lostMatches:h};return $&&w&&(W.original.matchedEntities=$.size,W.proposed.matchedEntities=w.size),W}function _t(e,t,r,s){let n=e.facts,o={frameId:e.id,facts:n,originalExplain:ve(t,n,s),proposedExplain:ve(r,n,s)};return e.timestamp!==void 0&&(o.timestamp=e.timestamp),o}var Ut=1e4,zt=5e7;function $n(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===1&&typeof e.$hole=="string"}function He(e,t,r=new Set,s=0){if(s>G)throw new Error(`[Directive] sweepUnder: template exceeds MAX_PREDICATE_DEPTH (${G}) \u2014 flatten the template or split the sweep`);if($n(e)){let n=e.$hole;if(!(n in t))throw new Error(`[Directive] sweepUnder: template references hole "${n}" but sweep has no values for it`);return t[n]}if(e===null||typeof e!="object")return e;if(r.has(e))throw new Error("[Directive] sweepUnder: template contains a cycle \u2014 predicate templates must be a tree");r.add(e);try{if(Array.isArray(e))return e.map(o=>He(o,t,r,s+1));let n={};for(let[o,i]of Object.entries(e))n[o]=He(i,t,r,s+1);return n}finally{r.delete(e);}}function*Jt(e,t){if(e.length===0){yield {};return}let r=e[0],s=e.slice(1),n=t[r]??[];for(let o of n)for(let i of Jt(s,t))yield {[r]:o,...i};}function vn(e){let t=1;for(let r of Object.values(e))t*=r.length;return t}function Kt(e){let{frames:t,original:r,template:s,sweep:n,objective:o=v=>v.proposed.matched,entityKey:i,maxSamples:c=0}=e,a=Object.keys(n);if(a.length===0)throw new Error("[Directive] sweepUnder: `sweep` must contain at least one hole name");let l=vn(n);if(l>Ut)throw new Error(`[Directive] sweepUnder: grid has ${l} points, exceeds the MAX_SWEEP_POINTS limit (${Ut}) \u2014 narrow the sweep ranges or split the run`);if(l===0)throw new Error("[Directive] sweepUnder: at least one hole has zero candidate values");let u=l*t.length;if(u>zt)throw new Error(`[Directive] sweepUnder: ${l} points \xD7 ${t.length} frames = ${u} per-frame evaluations, exceeds the MAX_SWEEP_EVALUATIONS limit (${zt}) \u2014 narrow the sweep, down-sample the history, or split the run`);let d=false,f=v=>{let D;try{D=o(v);}catch(_){return d||(d=true,console.warn(`[Directive] sweepUnder: objective threw \u2014 point will not rank (${_.message})`)),Number.NEGATIVE_INFINITY}return typeof D!="number"||!Number.isFinite(D)?(d||(d=true,console.warn(`[Directive] sweepUnder: objective returned a non-finite number (${String(D)}) \u2014 point will not rank`)),Number.NEGATIVE_INFINITY):D},h=Te({frames:t,original:r,proposed:r,entityKey:i,maxSamples:c}),$={values:{},report:h,score:f(h)},w=[],F=0,W=Number.NEGATIVE_INFINITY;for(let v of Jt(a,n)){let D=He(s,v),_=Te({frames:t,original:r,proposed:D,entityKey:i,maxSamples:c}),Ne=f(_);Ne>W&&(W=Ne,F=w.length),w.push({values:v,report:_,score:Ne});}let p=w[F];return {points:w,bestIndex:F,best:p,baseline:$}}function Lt(e){let t=e&&typeof e=="object"&&!Array.isArray(e)&&"constraints"in e?e.constraints:e;if(Array.isArray(t)){let r={};for(let s of t){if(!s||typeof s!="object"||!("id"in s))throw new Error("[Directive] diffRules: array entries must be `{ id, whenSpec }` objects");let n=s;if(typeof n.id!="string")throw new Error("[Directive] diffRules: constraint `id` must be a string");r[n.id]=n.whenSpec;}return r}if(t&&typeof t=="object")return t;throw new Error("[Directive] diffRules: expected a `{ id: whenSpec }` map, an array of `{ id, whenSpec }`, or `{ constraints: ... }`")}var wn=new Set(["$eq","$ne","$in","$nin","$exists","$gt","$gte","$lt","$lte","$between","$matches","$startsWith","$endsWith","$contains","$changed"]),bn=new Set(["$all","$any","$not"]);function Gt(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function xn(e){if(!Gt(e))return false;let t=Object.keys(e);if(t.length===0)return false;let r=false;for(let s of t){if(!s.startsWith("$"))return false;wn.has(s)&&(r=true);}return r}function H(e,t="",r=[]){if(e===null||typeof e!="object")return r;if(Array.isArray(e)){for(let s of e)if(s&&typeof s=="object"&&"fact"in s&&"op"in s){let n=s;r.push({path:t?`${t}.${String(n.fact)}`:String(n.fact),op:String(n.op),value:n.value});}return r}if("$all"in e&&Array.isArray(e.$all))return e.$all.forEach((s,n)=>{H(s,`${t}$all[${n}]`,r);}),r;if("$any"in e&&Array.isArray(e.$any))return e.$any.forEach((s,n)=>{H(s,`${t}$any[${n}]`,r);}),r;if("$not"in e)return H(e.$not,`${t}$not`,r),r;for(let[s,n]of Object.entries(e)){let o=t?`${t}.${s}`:s;if(xn(n))for(let[i,c]of Object.entries(n))r.push({path:o,op:i,value:c});else Gt(n)&&!bn.has(s)?H(n,o,r):r.push({path:o,op:"$eq",value:n});}return r}function B(e){return typeof e=="number"&&Number.isFinite(e)}function kn(e,t,r){switch(e){case "$gte":case "$gt":if(B(t)&&B(r)){if(r<t)return "relaxed";if(r>t)return "tightened"}return null;case "$lte":case "$lt":if(B(t)&&B(r)){if(r>t)return "relaxed";if(r<t)return "tightened"}return null;case "$between":{if(Array.isArray(t)&&Array.isArray(r)&&t.length===2&&r.length===2&&B(t[0])&&B(t[1])&&B(r[0])&&B(r[1])){let s=t[1]-t[0],n=r[1]-r[0];if(n>s)return "relaxed";if(n<s)return "tightened"}return null}case "$in":case "$nin":{if(Array.isArray(t)&&Array.isArray(r))if(e==="$in"){if(r.length>t.length)return "relaxed";if(r.length<t.length)return "tightened"}else {if(r.length>t.length)return "tightened";if(r.length<t.length)return "relaxed"}return null}case "$contains":{if(Array.isArray(t)&&Array.isArray(r)){if(r.length>t.length)return "relaxed";if(r.length<t.length)return "tightened"}return null}default:return null}}function Bt(e){let t=Lt(e.before),r=Lt(e.after),s=[...new Set([...Object.keys(t),...Object.keys(r)])].sort(),n=[],o={added:0,removed:0,changed:0,unchanged:0,totalClauseChanges:0};for(let i of s){let c=t[i],a=r[i],l=i in t,u=i in r;if(l&&!u){let f=H(c),h=f.length===0?[{path:"(function-form predicate)",kind:"removed"}]:f.map($=>({path:$.path,kind:"removed",before:{op:$.op,value:$.value}}));Qe(h),n.push({id:i,status:"removed",changes:h}),o.removed++,o.totalClauseChanges+=h.length;continue}if(!l&&u){let f=H(a),h=f.length===0?[{path:"(function-form predicate)",kind:"added"}]:f.map($=>({path:$.path,kind:"added",after:{op:$.op,value:$.value}}));Qe(h),n.push({id:i,status:"added",changes:h}),o.added++,o.totalClauseChanges+=h.length;continue}let d=Sn(c,a);d.length===0?(n.push({id:i,status:"unchanged",changes:[]}),o.unchanged++):(n.push({id:i,status:"changed",changes:d}),o.changed++,o.totalClauseChanges+=d.length);}return {constraints:n,summary:o}}function Sn(e,t){if(e!==void 0&&t!==void 0&&(e===null||t===null||typeof e!="object"||typeof t!="object"))return de(e)===de(t)?[]:[{path:"",kind:"changed",before:{op:"$eq",value:e},after:{op:"$eq",value:t}}];let r=e===void 0?[]:H(e),s=t===void 0?[]:H(t),n=l=>`${l.path}::${l.op}`,o=new Map(r.map(l=>[n(l),l])),i=new Map(s.map(l=>[n(l),l])),c=new Set([...o.keys(),...i.keys()]),a=[];for(let l of c){let u=o.get(l),d=i.get(l);if(u&&!d){a.push({path:u.path,kind:"removed",before:{op:u.op,value:u.value}});continue}if(!u&&d){a.push({path:d.path,kind:"added",after:{op:d.op,value:d.value}});continue}if(u&&d){if(de(u.value)===de(d.value))continue;let f=kn(u.op,u.value,d.value);a.push({path:u.path,kind:f??"changed",before:{op:u.op,value:u.value},after:{op:d.op,value:d.value}});}}return Qe(a),a}function Qe(e){e.sort((t,r)=>{let s=t.path.localeCompare(r.path);if(s!==0)return s;let n=t.before?.op??t.after?.op??"",o=r.before?.op??r.after?.op??"";return n.localeCompare(o)});}function On(e){let t={maxSamples:20,json:false};for(let r=0;r<e.length;r++)switch(e[r]){case "--history":{let n=e[++r];n&&(t.historyPath=n);break}case "--proposed":case "-p":{let n=e[++r];n&&(t.proposedPath=n);break}case "--original":case "-o":{let n=e[++r];n&&(t.originalPath=n);break}case "--max-samples":{let n=e[++r],o=n?Number.parseInt(n,10):Number.NaN;Number.isFinite(o)&&o>=0&&(t.maxSamples=o);break}case "--entity-key":{let n=e[++r];n&&(t.entityKey=n);break}case "--json":t.json=true;break}return t}function Me(){console.error(`
|
|
915
952
|
Usage: directive replay-under --history <frames.json> --proposed <spec.json>
|
|
916
953
|
|
|
917
954
|
Replay a recorded fact-frame history through a proposed constraint
|
|
@@ -935,13 +972,13 @@ Examples:
|
|
|
935
972
|
--original current-rule.json --proposed tightened-rule.json
|
|
936
973
|
directive replay-under --history sessions.json \\
|
|
937
974
|
--original a.json --proposed b.json --entity-key userId --json
|
|
938
|
-
`);}function
|
|
939
|
-
${
|
|
975
|
+
`);}function Ye(e,t){let r=resolve(e);existsSync(r)||(console.error(m.red(`error: ${t} file not found: ${r}`)),process.exit(1));try{return JSON.parse(readFileSync(r,"utf8"))}catch(s){console.error(m.red(`error: failed to parse ${t} (${r}): `)+s.message),process.exit(1);}}function Dn(e){try{return we(e)}catch(t){console.error(m.red(`error: ${t.message}`)),process.exit(1);}}function Ht(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===0}function Qt(e){let t=Object.entries(e).slice(0,6).map(([s,n])=>`${s}=${JSON.stringify(n)}`),r=Object.keys(e).length-t.length;return t.join(" ")+(r>0?m.dim(` +${r} more`):"")}function Rn(e,t){let{original:r,proposed:s,delta:n}=e,o=n>0?m.green(`+${n}`):n<0?m.red(`${n}`):m.dim("\xB10");if(console.log(`
|
|
976
|
+
${m.bold("replay-under")} \u2014 predicate backtest
|
|
940
977
|
`),console.log(` frames evaluated ${e.framesEvaluated}`),console.log(` original spec matched ${r.matched} frames`),console.log(` proposed spec matched ${s.matched} frames (${o})`),t&&r.matchedEntities!==void 0&&s.matchedEntities!==void 0&&(console.log(`
|
|
941
|
-
original spec matched across ${r.matchedEntities} ${t}s`),console.log(` proposed spec matched across ${s.matchedEntities} ${t}s`)),console.log(""),console.log(` ${
|
|
942
|
-
${
|
|
943
|
-
${
|
|
944
|
-
${i} of ${c} diff frames sampled \u2014 --json for the full report`)),console.log("");}async function
|
|
978
|
+
original spec matched across ${r.matchedEntities} ${t}s`),console.log(` proposed spec matched across ${s.matchedEntities} ${t}s`)),console.log(""),console.log(` ${m.green(`+${e.newMatchCount}`)} new matches ${m.dim("frames that now match the rule")}`),console.log(` ${m.red(`-${e.lostMatchCount}`)} lost matches ${m.dim("frames that no longer match")}`),e.newMatches.length>0){console.log(`
|
|
979
|
+
${m.green("sample new matches:")}`);for(let a of e.newMatches.slice(0,8))console.log(` frame ${a.frameId} ${m.dim(Qt(a.facts))}`);}if(e.lostMatches.length>0){console.log(`
|
|
980
|
+
${m.red("sample lost matches:")}`);for(let a of e.lostMatches.slice(0,8))console.log(` frame ${a.frameId} ${m.dim(Qt(a.facts))}`);}let i=e.newMatches.length+e.lostMatches.length,c=e.newMatchCount+e.lostMatchCount;i<c&&console.log(m.dim(`
|
|
981
|
+
${i} of ${c} diff frames sampled \u2014 --json for the full report`)),console.log("");}async function Yt(e){(e.includes("--help")||e.length===0)&&(Me(),process.exit(e.length===0?1:0));let t=On(e);t.historyPath||(console.error(m.red("error: --history <frames.json> is required")),Me(),process.exit(1)),t.proposedPath||(console.error(m.red("error: --proposed <spec.json> is required")),Me(),process.exit(1)),t.originalPath||(console.error(m.red("error: --original <spec.json> is required")+m.dim("\n (v1 cannot recover the constraint's current `when` from a live system)")),Me(),process.exit(1));let r=Dn(Ye(t.historyPath,"--history")),s=Ye(t.originalPath,"--original"),n=Ye(t.proposedPath,"--proposed");Ht(s)&&console.error(m.yellow("warning: --original is an empty predicate {} \u2014 it matches every frame")),Ht(n)&&console.error(m.yellow("warning: --proposed is an empty predicate {} \u2014 it matches every frame"));let o;try{o=Te({frames:r,original:s,proposed:n,maxSamples:t.maxSamples,entityKey:t.entityKey});}catch(i){console.error(m.red(`error: ${i.message}`)),process.exit(1);}if(t.json){console.log(JSON.stringify(o,null,2));return}Rn(o,t.entityKey);}function Nn(e){let t={json:false,dispatchableOnly:true,verbose:false},r="";for(let s=0;s<e.length;s++){let n=e[s];switch(n){case "--system":case "-s":{let o=e[++s];o&&(t.systemPath=o);break}case "--max-frames":{let o=e[++s],i=o?Number.parseInt(o,10):Number.NaN;Number.isFinite(i)&&i>0&&(t.maxFrames=i);break}case "--all-frames":case "--no-dispatchable-only":t.dispatchableOnly=false;break;case "--json":t.json=true;break;case "--verbose":case "-v":t.verbose=true;break;default:n&&!n.startsWith("-")&&!r&&(r=n);}}return {jsonPath:r,opts:t}}function Xe(){console.error(`
|
|
945
982
|
Usage: directive replay <timeline.json> [options]
|
|
946
983
|
|
|
947
984
|
Replay a serialized Directive timeline against a fresh system.
|
|
@@ -963,8 +1000,8 @@ Examples:
|
|
|
963
1000
|
directive replay bug-1234.json --system src/app/system.ts
|
|
964
1001
|
directive replay error.json --system src/system.ts --json
|
|
965
1002
|
directive replay error.json --system src/system.ts --verbose
|
|
966
|
-
`);}async function
|
|
967
|
-
(replay needs a fresh system to dispatch against)`)),
|
|
1003
|
+
`);}async function Xt(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(Xe(),process.exit(e.length===0?1:0));let{jsonPath:t,opts:r}=Nn(e);t||(console.error(m.red("error: missing <timeline.json> argument")),Xe(),process.exit(1)),r.systemPath||(console.error(m.red("error: --system <path> is required"),m.dim(`
|
|
1004
|
+
(replay needs a fresh system to dispatch against)`)),Xe(),process.exit(1));let s=resolve(t);existsSync(s)||(console.error(m.red(`error: timeline file not found: ${s}`)),process.exit(1));let n;try{n=readFileSync(s,"utf8");}catch(f){console.error(m.red(`error: failed to read ${s}: ${f.message}`)),process.exit(1);}let o;try{o=JSON.parse(n);}catch(f){console.error(m.red(`error: ${s} is not valid JSON: ${f.message}`)),process.exit(1);}let{deserializeTimeline:i,replayTimeline:c}=await ce(r.verbose),a;try{a=i(o);}catch(f){console.error(m.red(`error: timeline JSON failed validation: ${f.message}`)),process.exit(1);}let l;try{l=await L(r.systemPath);}catch(f){console.error(m.red(`error: failed to load system file: ${f.message}`)),process.exit(1);}let u=l;if(typeof u.dispatch!="function"&&(console.error(m.red("error: loaded system has no dispatch() method. The --system file must export a started Directive system or a factory.")),process.exit(1)),typeof u.start=="function")try{u.start();}catch{}let d=await c(a,u,{dispatchableOnly:r.dispatchableOnly,maxFrames:r.maxFrames});if(r.json)console.log(JSON.stringify(d,null,2));else {let{dispatched:f,skipped:h,truncated:$}=d,w=f>0;console.log(`${w?m.green("\u2713"):m.yellow("\u26A0")} replay complete:`,m.bold(`${f} dispatched`),m.dim(`/ ${h} skipped`),$>0?m.yellow(`/ ${$} TRUNCATED`):""),f===0&&console.error(m.yellow("warning: 0 frames dispatched. Either the timeline contains only non-dispatchable frames (system lifecycle, derivations, etc.) or the system shape doesn't match what the timeline recorded.")),$>0&&console.error(m.yellow(`warning: ${$} frames truncated by --max-frames cap. Raise it with --max-frames <n> if you need them.`));}process.exit(0);}function Fn(e){let t={json:false,markdown:false};for(let r=0;r<e.length;r++)switch(e[r]){case "--before":case "-b":{let n=e[++r];n&&(t.beforePath=n);break}case "--after":case "-a":{let n=e[++r];n&&(t.afterPath=n);break}case "--json":t.json=true;break;case "--markdown":case "--md":t.markdown=true;break}return t}function Ve(){console.error(`
|
|
968
1005
|
Usage: directive rules-diff --before <a.json> --after <b.json>
|
|
969
1006
|
|
|
970
1007
|
Structural diff between two snapshots of constraint whenSpec. Reports
|
|
@@ -990,10 +1027,10 @@ Or pull one from a git ref:
|
|
|
990
1027
|
git show HEAD~1:path/to/snapshot.json > before.json
|
|
991
1028
|
git show HEAD:path/to/snapshot.json > after.json
|
|
992
1029
|
directive rules-diff --before before.json --after after.json
|
|
993
|
-
`);}function Vt(e,t){let r=resolve(e);existsSync(r)||(console.error(
|
|
994
|
-
${
|
|
995
|
-
`),console.log(` ${
|
|
996
|
-
`);for(let s of r){if(s.status==="unchanged")continue;let n=s.status==="added"?
|
|
1030
|
+
`);}function Vt(e,t){let r=resolve(e);existsSync(r)||(console.error(m.red(`error: ${t} file not found: ${r}`)),process.exit(1));try{return JSON.parse(readFileSync(r,"utf8"))}catch(s){console.error(m.red(`error: failed to parse ${t} (${r}): `)+s.message),process.exit(1);}}function Wn(e){switch(e){case "added":return m.green("+");case "removed":return m.red("-");case "relaxed":return m.green("\u25B2");case "tightened":return m.red("\u25BD");default:return m.yellow("~")}}function Q(e){return e?e.op==="$eq"?JSON.stringify(e.value):`${e.op} ${JSON.stringify(e.value)}`:"\u2014"}function be(e){return e.replace(/\|/g,"\\|").replace(/`/g,"'").replace(/</g,"<").replace(/>/g,">")}function _n(e){let{summary:t,constraints:r}=e;console.log(`
|
|
1031
|
+
${m.bold("rules-diff")} \u2014 structural predicate diff
|
|
1032
|
+
`),console.log(` ${m.green(`+${t.added}`)} added ${m.red(`-${t.removed}`)} removed ${m.yellow(`~${t.changed}`)} changed ${m.dim(`\xB7${t.unchanged} unchanged`)}`),console.log(` ${t.totalClauseChanges} clause-level change${t.totalClauseChanges===1?"":"s"}
|
|
1033
|
+
`);for(let s of r){if(s.status==="unchanged")continue;let n=s.status==="added"?m.green("ADDED"):s.status==="removed"?m.red("REMOVED"):m.yellow("CHANGED");console.log(` ${m.bold(s.id)} ${n}`);for(let o of s.changes){let i=m.cyan(o.path||"(predicate)"),c=Wn(o.kind);if(o.kind==="added")console.log(` ${c} ${i} ${Q(o.after)}`);else if(o.kind==="removed")console.log(` ${c} ${i} ${Q(o.before)}`);else {let a=o.kind==="relaxed"?m.green("relaxed"):o.kind==="tightened"?m.red("tightened"):m.yellow("changed");console.log(` ${c} ${i} ${Q(o.before)} ${m.dim("\u2192")} ${Q(o.after)} ${m.dim(`[${a}]`)}`);}}console.log("");}}function Un(e){let{summary:t,constraints:r}=e;console.log("## \u{1F4CB} Rules diff"),console.log(""),console.log(`**+${t.added} added \xB7 -${t.removed} removed \xB7 ~${t.changed} changed \xB7 \xB7${t.unchanged} unchanged** \u2014 ${t.totalClauseChanges} clause change${t.totalClauseChanges===1?"":"s"}`),console.log("");for(let s of r){if(s.status==="unchanged")continue;let n=s.status==="added"?"\u{1F195} ADDED":s.status==="removed"?"\u{1F5D1} REMOVED":"\u270F\uFE0F CHANGED";console.log(`### \`${s.id}\` \u2014 ${n}`),console.log(""),console.log("| | path | change |"),console.log("|---|---|---|");for(let o of s.changes){let i=`\`${be(o.path||"(predicate)")}\``,c;o.kind==="added"?c=`| \u2795 | ${i} | ${be(Q(o.after))} |`:o.kind==="removed"?c=`| \u2796 | ${i} | ${be(Q(o.before))} |`:c=`| ${o.kind==="relaxed"?"\u25B2 relaxed":o.kind==="tightened"?"\u25BD tightened":"\u2194 changed"} | ${i} | ${be(Q(o.before))} \u2192 ${be(Q(o.after))} |`,console.log(c);}console.log("");}}async function Zt(e){(e.includes("--help")||e.length===0)&&(Ve(),process.exit(e.length===0?1:0));let t=Fn(e);t.beforePath||(console.error(m.red("error: --before <a.json> is required")),Ve(),process.exit(1)),t.afterPath||(console.error(m.red("error: --after <b.json> is required")),Ve(),process.exit(1));let r=Vt(t.beforePath,"--before"),s=Vt(t.afterPath,"--after"),n;try{n=Bt({before:r,after:s});}catch(o){console.error(m.red(`error: ${o.message}`)),process.exit(1);}if(t.json){console.log(JSON.stringify(n,null,2));return}if(t.markdown){Un(n);return}_n(n);}function Kn(e){let t={json:false,verbose:false},r=[];for(let s=0;s<e.length;s++){let n=e[s];switch(n){case "--json":t.json=true;break;case "--verbose":case "-v":t.verbose=true;break;default:n&&!n.startsWith("-")&&r.push(n);}}return {aPath:r[0]??"",bPath:r[1]??"",opts:t}}function er(){console.error(`
|
|
997
1034
|
Usage: directive timeline diff <a.json> <b.json>
|
|
998
1035
|
|
|
999
1036
|
Compare two serialized Directive timelines as a structured causal-graph
|
|
@@ -1017,7 +1054,7 @@ Exit codes:
|
|
|
1017
1054
|
Examples:
|
|
1018
1055
|
directive timeline diff baseline.json regression.json
|
|
1019
1056
|
directive timeline diff a.json b.json --json | jq .constraintFires
|
|
1020
|
-
`);}function
|
|
1057
|
+
`);}function xe(e){return e>0?m.green(`+${e}`):e<0?m.red(`${e}`):m.dim(" 0")}function tr(e){return e.length===0?[m.dim(" (no differences)")]:e.map(t=>` ${m.bold(t.id.padEnd(28))} ${String(t.aCount).padStart(4)} \u2192 ${String(t.bCount).padStart(4)} (${xe(t.delta)})`)}function Gn(e){return e.length===0?[m.dim(" (no differences)")]:e.map(t=>` ${m.bold(t.resolver.padEnd(28))} starts ${t.aStarts}\u2192${t.bStarts} (${xe(t.bStarts-t.aStarts)}) completes ${t.aCompletes}\u2192${t.bCompletes} (${xe(t.bCompletes-t.aCompletes)}) errors ${t.aErrors}\u2192${t.bErrors} (${xe(t.bErrors-t.aErrors)})`)}function Bn(e){return e.length===0?[m.dim(" (no new errors)")]:e.map(t=>{let r=t.side==="a"?m.cyan("a-only"):m.yellow("b-only"),s=(()=>{try{return JSON.stringify(t.error)}catch{return `[${typeof t.error}]`}})();return ` ${r} frame #${t.frameIndex} ${m.bold(t.kind)} '${t.id}' ${m.dim(s)}`})}function rr(e){let t=resolve(e);existsSync(t)||(console.error(m.red(`error: timeline file not found: ${t}`)),process.exit(1));let r;try{r=readFileSync(t,"utf8");}catch(s){console.error(m.red(`error: failed to read ${t}: ${s.message}`)),process.exit(1);}try{return JSON.parse(r)}catch(s){console.error(m.red(`error: ${t} is not valid JSON: ${s.message}`)),process.exit(1);}}async function nr(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(er(),process.exit(e.length===0?1:0));let{aPath:t,bPath:r,opts:s}=Kn(e);(!t||!r)&&(console.error(m.red("error: both <a.json> and <b.json> are required")),er(),process.exit(1));let{deserializeTimeline:n,diffTimelines:o}=await ce(s.verbose),i=rr(t),c=rr(r),a,l;try{a=n(i),l=n(c);}catch(d){console.error(m.red(`error: timeline JSON failed validation: ${d.message}`)),process.exit(1);}let u=o(a,l);s.json&&(console.log(JSON.stringify(u,null,2)),process.exit(u.identical?0:2)),u.identical&&(console.log(m.green("\u2713 identical:"),`both timelines have ${u.aFrameCount} frames and the same causal shape.`),process.exit(0)),console.log(m.bold("Timeline diff"),m.dim(`(${t} vs ${r})`)),console.log(""),console.log(`Frames: ${u.aFrameCount} \u2192 ${u.bFrameCount} (${xe(u.frameCountDelta)})`),console.log(""),console.log(m.bold("Constraint fires:"));for(let d of tr(u.constraintFires))console.log(d);console.log(""),console.log(m.bold("Mutations:"));for(let d of tr(u.mutations))console.log(d);console.log(""),console.log(m.bold("Resolver runs:"));for(let d of Gn(u.resolverRuns))console.log(d);console.log(""),console.log(m.bold("New errors:"));for(let d of Bn(u.newErrors))console.log(d);console.log(""),process.exit(2);}function Xn(e){let t={sweepArgs:[],json:false};for(let r=0;r<e.length;r++)switch(e[r]){case "--history":{let n=e[++r];n&&(t.historyPath=n);break}case "--original":case "-o":{let n=e[++r];n&&(t.originalPath=n);break}case "--template":case "-t":{let n=e[++r];n&&(t.templatePath=n);break}case "--sweep":case "-s":{let n=e[++r];n&&t.sweepArgs.push(n);break}case "--entity-key":{let n=e[++r];n&&(t.entityKey=n);break}case "--json":t.json=true;break}return t}function ke(){console.error(`
|
|
1021
1058
|
Usage: directive tune --history <frames.json> --original <orig.json> \\
|
|
1022
1059
|
--template <tmpl.json> --sweep <key:range>
|
|
1023
1060
|
|
|
@@ -1040,13 +1077,13 @@ Example:
|
|
|
1040
1077
|
directive tune --history sessions.json \\
|
|
1041
1078
|
--original current.json --template proposed-template.json \\
|
|
1042
1079
|
--sweep threshold:25..200:25
|
|
1043
|
-
`);}function
|
|
1044
|
-
${
|
|
1080
|
+
`);}function Ze(e,t){let r=resolve(e);existsSync(r)||(console.error(m.red(`error: ${t} file not found: ${r}`)),process.exit(1));try{return JSON.parse(readFileSync(r,"utf8"))}catch(s){console.error(m.red(`error: failed to parse ${t} (${r}): `)+s.message),process.exit(1);}}function Vn(e){try{return we(e)}catch(t){console.error(m.red(`error: ${t.message}`)),process.exit(1);}}function Zn(e){let t=e.indexOf(":");t<1&&(console.error(m.red(`error: --sweep ${e}: missing ':' between hole name and values`)),process.exit(1));let r=e.slice(0,t),s=e.slice(t+1),n=s.match(/^(-?\d+(?:\.\d+)?)\.\.(-?\d+(?:\.\d+)?)(?::(-?\d+(?:\.\d+)?))?$/);if(n){let[,c,a,l]=n,u=Number(c),d=Number(a),f=l?Number(l):1;f<=0&&(console.error(m.red(`error: --sweep ${e}: step must be positive`)),process.exit(1)),d<u&&(console.error(m.red(`error: --sweep ${e}: end (${d}) must be >= start (${u})`)),process.exit(1));let h=[];for(let $=u;$<=d+1e-9;$+=f)h.push(Math.round($*1e6)/1e6);return [r,h]}let o=s.split(",").map(c=>c.trim()).filter(c=>c.length>0);o.length===0&&(console.error(m.red(`error: --sweep ${e}: no values after ':'`)),process.exit(1));let i=o.map(c=>{let a=Number(c);return Number.isNaN(a)?c:a});return [r,i]}var et=["\u2581","\u2582","\u2583","\u2584","\u2585","\u2586","\u2587","\u2588"];function es(e,t){let r=e.points;Math.max(...r.map(f=>f.report.proposed.matched));let n=e.baseline.report.original.matched,o=r.map(f=>f.score),i=Math.min(...o),a=Math.max(...o)-i,l=r.map(f=>{let h=a>0?(f.score-i)/a:0;return et[Math.min(et.length-1,Math.round(h*(et.length-1)))]}).join("");console.log(`
|
|
1081
|
+
${m.bold("directive tune")} \u2014 parameter sweep`),console.log(`
|
|
1045
1082
|
frames evaluated ${r[0]?.report.framesEvaluated??0}`),console.log(` baseline (current) matched ${n} frames`),console.log(` points evaluated ${r.length}
|
|
1046
|
-
`),console.log(` sparkline ${
|
|
1047
|
-
`);let u=Object.keys(r[0]?.values??{}),
|
|
1048
|
-
${
|
|
1049
|
-
`);}async function
|
|
1083
|
+
`),console.log(` sparkline ${m.cyan(l)}
|
|
1084
|
+
`);let u=Object.keys(r[0]?.values??{}),d=`${u.map(f=>f.padEnd(12)).join(" ")} ${"matched".padStart(8)} ${"delta".padStart(7)}${t?` ${`${t}s`.padStart(8)}`:""} bar`;console.log(m.dim(` ${d}`));for(let f of r){let h=u.map(_=>String(f.values[_]??"").padEnd(12)).join(" "),$=f.report.proposed.matched,w=f.report.delta,F=t?String(f.report.proposed.matchedEntities??"").padStart(8):"",W=w>0?m.green(`+${w}`.padStart(7)):w<0?m.red(`${w}`.padStart(7)):m.dim("\xB10".padStart(7)),p=a>0?Math.round((f.score-i)/a*24):0,v=`${h} ${String($).padStart(8)} ${W}${t?` ${F}`:""} ${"\u2588".repeat(p).padEnd(24)}`,D=f===e.best;console.log(D?m.green(` ${v}`):` ${v}`);}console.log(`
|
|
1085
|
+
${m.bold(m.green("best"))} \u2014 ${u.map(f=>`${f}=${e.best.values[f]}`).join(", ")} \u2192 matched ${e.best.report.proposed.matched} (score ${e.best.score})
|
|
1086
|
+
`);}async function sr(e){(e.includes("--help")||e.length===0)&&(ke(),process.exit(e.length===0?1:0));let t=Xn(e);t.historyPath||(console.error(m.red("error: --history <frames.json> is required")),ke(),process.exit(1)),t.originalPath||(console.error(m.red("error: --original <spec.json> is required")),ke(),process.exit(1)),t.templatePath||(console.error(m.red("error: --template <spec.json> is required")),ke(),process.exit(1)),t.sweepArgs.length===0&&(console.error(m.red("error: at least one --sweep <key:range> is required")),ke(),process.exit(1));let r=Vn(Ze(t.historyPath,"--history")),s=Ze(t.originalPath,"--original"),n=Ze(t.templatePath,"--template"),o={};for(let c of t.sweepArgs){let[a,l]=Zn(c);o[a]=l;}let i;try{i=Kt({frames:r,original:s,template:n,sweep:o,entityKey:t.entityKey});}catch(c){console.error(m.red(`error: ${c.message}`)),process.exit(1);}if(t.json){console.log(JSON.stringify(i,null,2));return}es(i,t.entityKey);}var ts=`
|
|
1050
1087
|
${O} \u2014 CLI tools for Directive
|
|
1051
1088
|
|
|
1052
1089
|
Usage: ${O} <command> [options]
|
|
@@ -1059,7 +1096,12 @@ Commands:
|
|
|
1059
1096
|
explain <file> [req-id] Explain why a requirement exists
|
|
1060
1097
|
graph <file> Visual dependency graph
|
|
1061
1098
|
doctor Health check for project setup
|
|
1062
|
-
|
|
1099
|
+
install One-shot: drop AI rules for every
|
|
1100
|
+
supported assistant (Cursor, Copilot,
|
|
1101
|
+
Windsurf, Cline, Codex, Claude). No
|
|
1102
|
+
prompts. Alias for ai-rules install.
|
|
1103
|
+
ai-rules install Same as above (non-interactive)
|
|
1104
|
+
ai-rules init Interactive install (prompts per tool)
|
|
1063
1105
|
ai-rules update Refresh rules to latest version
|
|
1064
1106
|
ai-rules check Validate rules are current (CI)
|
|
1065
1107
|
examples list Browse available examples
|
|
@@ -1101,6 +1143,12 @@ graph options:
|
|
|
1101
1143
|
--no-open Don't open in browser
|
|
1102
1144
|
--output <path> Output file path
|
|
1103
1145
|
|
|
1146
|
+
install / ai-rules install options:
|
|
1147
|
+
--force Overwrite existing files (default: merge
|
|
1148
|
+
Directive section when present, otherwise
|
|
1149
|
+
skip files without a Directive section)
|
|
1150
|
+
--dir <path> Target directory (default: cwd)
|
|
1151
|
+
|
|
1104
1152
|
ai-rules init options:
|
|
1105
1153
|
--force Overwrite existing files without asking
|
|
1106
1154
|
--merge Use section markers to update only the Directive section
|
|
@@ -1110,14 +1158,15 @@ ai-rules init options:
|
|
|
1110
1158
|
examples options:
|
|
1111
1159
|
--filter <category> Filter by category or name
|
|
1112
1160
|
--dest <dir> Destination directory for copy
|
|
1113
|
-
`.trim();async function
|
|
1161
|
+
`.trim();async function rs(){let e=process.argv.slice(2),t=e[0];if((e.length===0||t==="--help"||t==="-h")&&(console.log(ts),process.exit(0)),t==="--version"||t==="-v"){let{readFileSync:n}=await import('fs'),{fileURLToPath:o}=await import('url'),{dirname:i,join:c}=await import('path'),a=i(o(import.meta.url)),l=JSON.parse(n(c(a,"..","package.json"),"utf-8"));console.log(l.version),process.exit(0);}let s=e[0];switch(s){case "init":{await At(e.slice(1));break}case "new":{let n=e[1],o=e[2];n==="module"?(o||(console.error("Usage: directive new module <name>"),process.exit(1)),await Tt(o,e.slice(3))):n==="orchestrator"?(o||(console.error("Usage: directive new orchestrator <name>"),process.exit(1)),await Mt(o,e.slice(3))):(console.error(`Unknown subcommand: ${n??"(none)"}
|
|
1114
1162
|
Usage: ${O} new module <name>
|
|
1115
|
-
${O} new orchestrator <name>`),process.exit(1));break}case "inspect":{await
|
|
1116
|
-
Usage: ${O} ai-rules
|
|
1163
|
+
${O} new orchestrator <name>`),process.exit(1));break}case "inspect":{await jt(e.slice(1));break}case "explain":{await kt(e.slice(1));break}case "graph":{await St(e.slice(1));break}case "doctor":{await gt(e.slice(1));break}case "install":{await ze(e.slice(1));break}case "ai-rules":{let n=e[1];n==="init"?await ct(e.slice(2)):n==="install"?await ze(e.slice(2)):n==="update"?await lt(e.slice(2)):n==="check"?await ut(e.slice(2)):(console.error(`Unknown subcommand: ${n??"(none)"}
|
|
1164
|
+
Usage: ${O} ai-rules install
|
|
1165
|
+
${O} ai-rules init
|
|
1117
1166
|
${O} ai-rules update
|
|
1118
|
-
${O} ai-rules check`),process.exit(1));break}case "examples":{let n=e[1];if(n==="list")await
|
|
1167
|
+
${O} ai-rules check`),process.exit(1));break}case "examples":{let n=e[1];if(n==="list")await wt(e.slice(2));else if(n==="copy"){let o=e[2];o||(console.error("Usage: directive examples copy <name>"),process.exit(1)),await bt(o,e.slice(3));}else console.error(`Unknown subcommand: ${n??"(none)"}
|
|
1119
1168
|
Usage: ${O} examples list [--filter <category>]
|
|
1120
|
-
${O} examples copy <name> [--dest <dir>]`),process.exit(1);break}case "replay":{await
|
|
1169
|
+
${O} examples copy <name> [--dest <dir>]`),process.exit(1);break}case "replay":{await Xt(e.slice(1));break}case "replay-under":{await Yt(e.slice(1));break}case "tune":{await sr(e.slice(1));break}case "rules-diff":{await Zt(e.slice(1));break}case "bisect":{await ht(e.slice(1));break}case "timeline":{let n=e[1];n==="diff"?await nr(e.slice(2)):(console.error(`Unknown subcommand: ${n??"(none)"}
|
|
1121
1170
|
Usage: ${O} timeline diff <a.json> <b.json>`),process.exit(1));break}default:console.error(`Unknown command: ${s}
|
|
1122
|
-
Run '${O} --help' for usage.`),process.exit(1);}}
|
|
1171
|
+
Run '${O} --help' for usage.`),process.exit(1);}}rs().catch(e=>{console.error(e.message||e),process.exit(1);});//# sourceMappingURL=cli.js.map
|
|
1123
1172
|
//# sourceMappingURL=cli.js.map
|