@directive-run/cli 1.4.0 → 1.6.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/dist/cli.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import*as p from'@clack/prompts';import {existsSync,readFileSync,mkdirSync,writeFileSync,readdirSync}from'fs';import {resolve,join,relative,dirname}from'path';import f from'picocolors';import {getAllExamples,getExample,getKnowledge}from'@directive-run/knowledge';var x="directive";var V="<!-- directive:start -->",H="<!-- directive:end -->";var oe=[{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 he(e){let t=[];for(let r of oe)r.signals.some(o=>existsSync(join(e,o)))&&t.push({name:r.name,id:r.id,outputPath:join(e,r.outputPath)});return t}function K(e){let t=oe.find(r=>r.id===e);if(!t)throw new Error(`Unknown tool: ${e}`);return t}function ye(){return oe.map(e=>e.id)}function L(e,t){let r=e.indexOf(V),s=e.indexOf(H),o=`${V}
2
+ import {existsSync,readFileSync,mkdirSync,writeFileSync,readdirSync}from'fs';import {resolve,join,relative,dirname}from'path';import*as m from'@clack/prompts';import g from'picocolors';import {getAllExamples,getExample,getKnowledge}from'@directive-run/knowledge';var R="directive";var ue="<!-- directive:start -->",re="<!-- directive:end -->";var ke=[{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 Fe(e){let t=[];for(let r of ke)r.signals.some(n=>existsSync(join(e,n)))&&t.push({name:r.name,id:r.id,outputPath:join(e,r.outputPath)});return t}function ne(e){let t=ke.find(r=>r.id===e);if(!t)throw new Error(`Unknown tool: ${e}`);return t}function ze(){return ke.map(e=>e.id)}function H(e,t){let r=e.indexOf(ue),s=e.indexOf(re),n=`${ue}
3
3
  ${t}
4
- ${H}`;if(r!==-1&&s!==-1&&s>r)return e.slice(0,r)+o+e.slice(s+H.length);let i=e.endsWith(`
4
+ ${re}`;if(r!==-1&&s!==-1&&s>r)return e.slice(0,r)+n+e.slice(s+re.length);let o=e.endsWith(`
5
5
  `)?`
6
6
  `:`
7
7
 
8
- `;return e+i+o+`
9
- `}function G(e){return e.includes(V)&&e.includes(H)}var ot=[{file:"pnpm-workspace.yaml",tool:"pnpm"},{file:"turbo.json",tool:"turbo"}];function be(e){let t=resolve(e);for(;t!==dirname(t);){for(let s of ot)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 o=existsSync(join(t,"yarn.lock"))?"yarn":"npm";return {isMonorepo:!0,rootDir:t,tool:o}}}catch{}t=dirname(t);}return {isMonorepo:false,rootDir:e}}function xe(){let e=getKnowledge("core-patterns"),t=getKnowledge("anti-patterns"),r=getKnowledge("naming"),s=getKnowledge("schema-types");return `# Directive \u2014 Complete AI Coding Rules
8
+ `;return e+o+n+`
9
+ `}function V(e){return e.includes(ue)&&e.includes(re)}var Nt=[{file:"pnpm-workspace.yaml",tool:"pnpm"},{file:"turbo.json",tool:"turbo"}];function Ue(e){let t=resolve(e);for(;t!==dirname(t);){for(let s of Nt)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 Be(){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\`
@@ -226,7 +226,7 @@ for await (const chunk of streamResult.stream) {
226
226
  \`\`\`
227
227
 
228
228
  Backpressure: \`"buffer"\` (default), \`"block"\`, \`"drop"\`
229
- `}function Q(){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## 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 | `useDirective(system)` | `useSelector(system, s => s.facts.count)` |\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 z(){return Q()+"\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"+`
229
+ `}function fe(){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## 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 | `useDirective(system)` | `useSelector(system, s => s.facts.count)` |\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 Y(){return fe()+"\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
230
  ## Multi-Module
231
231
 
232
232
  \`\`\`typescript
@@ -259,10 +259,119 @@ const result = await orchestrator.run(agent, "analyze this");
259
259
  - Subpath imports: \`from '@directive-run/ai/anthropic'\` not \`from '@directive-run/ai'\`
260
260
  - Token usage normalized: \`{ inputTokens, outputTokens }\` (not provider-specific)
261
261
  - \`facts.cache = [...facts.cache, item]\` not \`facts.cache.push(item)\`
262
- `}function $e(){return z()}function ke(){return z()}var at={cursor:Q,claude:xe,copilot:z,windsurf:ke,cline:$e};function Z(e){let t=at[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 o=e[++r];o&&t.tools.push(o);break}case "--dir":{let o=e[++r];o&&(t.dir=o);break}}return t}async function Se(e){let t=ue(e);p.intro(f.bgCyan(f.black(" directive ai-rules ")));let r=be(t.dir),s=t.dir;if(r.isMonorepo&&r.rootDir!==t.dir){let n=await p.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)})`}]});p.isCancel(n)&&(p.cancel("Cancelled."),process.exit(0)),n==="root"&&(s=r.rootDir);}let o;if(t.tools.length>0)o=t.tools.map(n=>{let a=K(n);return {name:a.name,id:a.id,outputPath:join(s,a.outputPath)}});else {let n=he(s);if(n.length>0){let a=await p.multiselect({message:`Detected ${n.length} AI tool(s). Which should get Directive rules?`,options:n.map(c=>({value:c.id,label:c.name,hint:relative(s,c.outputPath)})),initialValues:n.map(c=>c.id),required:true});p.isCancel(a)&&(p.cancel("Cancelled."),process.exit(0)),o=a.map(c=>{let m=K(c);return {name:m.name,id:m.id,outputPath:join(s,m.outputPath)}});}else {let a=await p.multiselect({message:"No AI tools detected. Which tools do you use?",options:ye().map(c=>{let m=K(c);return {value:c,label:m.name}}),required:true});p.isCancel(a)&&(p.cancel("Cancelled."),process.exit(0)),o=a.map(c=>{let m=K(c);return {name:m.name,id:m.id,outputPath:join(s,m.outputPath)}});}}o.length===0&&(p.cancel("No tools selected."),process.exit(0));let i=p.spinner();for(let n of o){i.start(`Generating ${n.name} rules...`);let a=Z(n.id),c=n.outputPath,m=existsSync(c);if(i.stop(`Generated ${n.name} rules.`),m&&!t.force){let d=readFileSync(c,"utf-8");if(t.merge){q(c,L(d,a)),p.log.success(`${f.green("Merged")} Directive section into ${f.dim(relative(s,c))}`);continue}if(G(d)){let l=await p.select({message:`${relative(s,c)} 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"}]});p.isCancel(l)&&(p.cancel("Cancelled."),process.exit(0)),l==="merge"?(q(c,L(d,a)),p.log.success(`${f.green("Updated")} ${f.dim(relative(s,c))}`)):l==="overwrite"?(q(c,a),p.log.success(`${f.green("Wrote")} ${f.dim(relative(s,c))}`)):p.log.info(`Skipped ${f.dim(relative(s,c))}`);}else {let l=await p.select({message:`${relative(s,c)} 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"}]});p.isCancel(l)&&(p.cancel("Cancelled."),process.exit(0)),l==="append"?(q(c,L(d,a)),p.log.success(`${f.green("Appended")} to ${f.dim(relative(s,c))}`)):l==="overwrite"?(q(c,a),p.log.success(`${f.green("Wrote")} ${f.dim(relative(s,c))}`)):p.log.info(`Skipped ${f.dim(relative(s,c))}`);}}else q(c,a),p.log.success(`${f.green("Created")} ${f.dim(relative(s,c))}`);}p.outro(`Done! Run ${f.cyan(`${x} ai-rules init --merge`)} anytime to update.`);}function q(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}async function Ce(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")}],o=0;for(let i of s){if(!existsSync(i.path))continue;let n=readFileSync(i.path,"utf-8");if(!G(n))continue;let a=Z(i.id),c=L(n,a);q(i.path,c),console.log(`${f.green("Updated")} ${f.dim(relative(r,i.path))}`),o++;}console.log(o===0?f.dim(`No existing rule files found. Run ${f.cyan(`${x} ai-rules init`)} first.`):f.green(`
263
- Updated ${o} file(s) to latest knowledge version.`));}async function Re(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"}],o=0,i=0;for(let n of s){if(!existsSync(n.path))continue;let a=readFileSync(n.path,"utf-8");if(!G(a))continue;o++;let c=Z(n.id);L(a,c)!==a?(console.log(`${f.red("\u2717")} ${n.name} rules are ${f.yellow("stale")}`),i++):console.log(`${f.green("\u2713")} ${n.name} rules are ${f.green("current")}`);}if(o===0){console.log(f.dim("No rule files found to check."));return}i>0?(console.log(`
264
- ${f.yellow(`${i} file(s) are stale.`)} Run ${f.cyan(`${x} ai-rules update`)} to refresh.`),process.exit(1)):console.log(f.green(`
265
- All rule files are current.`));}function gt(e){let t={dir:process.cwd(),noInteractive:false};for(let r=0;r<e.length;r++)switch(e[r]){case "--template":{let o=e[++r];o&&(t.template=o);break}case "--dir":{let o=e[++r];o&&(t.dir=o);break}case "--no-interactive":t.noInteractive=true;break}return t}function ht(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 yt(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 me(e){return {counter:{id:"counter",label:"Counter (minimal)",hint:"schema + init + derive + events \u2014 simplest starting point",files:[{path:`src/${e}.ts`,content:vt(e)},{path:"src/main.ts",content:bt(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:wt(e)},{path:"src/main.ts",content:xt(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:$t(e)},{path:"src/main.ts",content:kt(e)}],deps:["@directive-run/core","@directive-run/ai"]}}}function vt(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
262
+ `}function Le(){return Y()}function Ke(){return Y()}var zt={cursor:fe,claude:Be,copilot:Y,windsurf:Ke,cline:Le};function de(e){let t=zt[e];if(!t)throw new Error(`No template for tool: ${e}`);return t()}function De(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 Je(e){let t=De(e);m.intro(g.bgCyan(g.black(" directive ai-rules ")));let r=Ue(t.dir),s=t.dir;if(r.isMonorepo&&r.rootDir!==t.dir){let i=await m.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)})`}]});m.isCancel(i)&&(m.cancel("Cancelled."),process.exit(0)),i==="root"&&(s=r.rootDir);}let n;if(t.tools.length>0)n=t.tools.map(i=>{let a=ne(i);return {name:a.name,id:a.id,outputPath:join(s,a.outputPath)}});else {let i=Fe(s);if(i.length>0){let a=await m.multiselect({message:`Detected ${i.length} AI tool(s). Which should get Directive rules?`,options:i.map(l=>({value:l.id,label:l.name,hint:relative(s,l.outputPath)})),initialValues:i.map(l=>l.id),required:true});m.isCancel(a)&&(m.cancel("Cancelled."),process.exit(0)),n=a.map(l=>{let c=ne(l);return {name:c.name,id:c.id,outputPath:join(s,c.outputPath)}});}else {let a=await m.multiselect({message:"No AI tools detected. Which tools do you use?",options:ze().map(l=>{let c=ne(l);return {value:l,label:c.name}}),required:true});m.isCancel(a)&&(m.cancel("Cancelled."),process.exit(0)),n=a.map(l=>{let c=ne(l);return {name:c.name,id:c.id,outputPath:join(s,c.outputPath)}});}}n.length===0&&(m.cancel("No tools selected."),process.exit(0));let o=m.spinner();for(let i of n){o.start(`Generating ${i.name} rules...`);let a=de(i.id),l=i.outputPath,c=existsSync(l);if(o.stop(`Generated ${i.name} rules.`),c&&!t.force){let f=readFileSync(l,"utf-8");if(t.merge){_(l,H(f,a)),m.log.success(`${g.green("Merged")} Directive section into ${g.dim(relative(s,l))}`);continue}if(V(f)){let u=await m.select({message:`${relative(s,l)} 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"}]});m.isCancel(u)&&(m.cancel("Cancelled."),process.exit(0)),u==="merge"?(_(l,H(f,a)),m.log.success(`${g.green("Updated")} ${g.dim(relative(s,l))}`)):u==="overwrite"?(_(l,a),m.log.success(`${g.green("Wrote")} ${g.dim(relative(s,l))}`)):m.log.info(`Skipped ${g.dim(relative(s,l))}`);}else {let u=await m.select({message:`${relative(s,l)} 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"}]});m.isCancel(u)&&(m.cancel("Cancelled."),process.exit(0)),u==="append"?(_(l,H(f,a)),m.log.success(`${g.green("Appended")} to ${g.dim(relative(s,l))}`)):u==="overwrite"?(_(l,a),m.log.success(`${g.green("Wrote")} ${g.dim(relative(s,l))}`)):m.log.info(`Skipped ${g.dim(relative(s,l))}`);}}else _(l,a),m.log.success(`${g.green("Created")} ${g.dim(relative(s,l))}`);}m.outro(`Done! Run ${g.cyan(`${R} ai-rules init --merge`)} anytime to update.`);}function _(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}async function Ge(e){let r=De(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 a=de(o.id),l=H(i,a);_(o.path,l),console.log(`${g.green("Updated")} ${g.dim(relative(r,o.path))}`),n++;}console.log(n===0?g.dim(`No existing rule files found. Run ${g.cyan(`${R} ai-rules init`)} first.`):g.green(`
263
+ Updated ${n} file(s) to latest knowledge version.`));}async function He(e){let r=De(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 a=readFileSync(i.path,"utf-8");if(!V(a))continue;n++;let l=de(i.id);H(a,l)!==a?(console.log(`${g.red("\u2717")} ${i.name} rules are ${g.yellow("stale")}`),o++):console.log(`${g.green("\u2713")} ${i.name} rules are ${g.green("current")}`);}if(n===0){console.log(g.dim("No rule files found to check."));return}o>0?(console.log(`
264
+ ${g.yellow(`${o} file(s) are stale.`)} Run ${g.cyan(`${R} ai-rules update`)} to refresh.`),process.exit(1)):console.log(g.green(`
265
+ All rule files are current.`));}async function P(e){let t=resolve(e);if(!existsSync(t))throw new Error(`File not found: ${t}`);try{let r=await import(t);if(r.default&&U(r.default))return r.default;if(r.system&&U(r.system))return r.system;for(let s of Object.keys(r))if(U(r[s]))return r[s];throw new Error(`No Directive system found in ${g.dim(e)}
266
+ Export a system as default or named "system":
267
+
268
+ ${g.cyan("export default")} createSystem({ module: myModule });
269
+ ${g.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 ${g.dim(e)}: ${r instanceof Error?r.message:String(r)}
270
+
271
+ Make sure the file is valid TypeScript and tsx is installed:
272
+ ${g.cyan("npm install -D tsx")}`)}}function U(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 Xe(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 ${g.dim(e)}: ${o instanceof Error?o.message:String(o)}
273
+
274
+ Make sure the file is valid TypeScript and tsx is installed:
275
+ ${g.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 a=await Promise.resolve(i());if(!U(a))throw new Error(`Factory '${o}' from ${g.dim(e)} returned a value that is not a started Directive system.
276
+ Expected an object with inspect/start/stop/facts. The factory must call sys.start() before returning.`);return a};throw U(r.default)||U(r.system)||Object.values(r).some(U)?new Error(`Found a started Directive system in ${g.dim(e)}, but bisect needs a factory.
277
+ 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 ${g.cyan("directive replay")} does.
279
+
280
+ Wrap the existing export in a function:
281
+
282
+ ${g.cyan("export function createSystem()")} {
283
+ const sys = createSystem({ module: yourModule });
284
+ sys.start();
285
+ return sys;
286
+ }`):new Error(`No system factory found in ${g.dim(e)}
287
+ Bisect needs to instantiate a fresh system per midpoint replay. Export one of:
288
+
289
+ ${g.cyan("export function createSystem()")} { ... return sys; }
290
+ ${g.cyan("export const systemFactory")} = () => { ... return sys; };
291
+ ${g.cyan("export default")} () => { ... return sys; };
292
+
293
+ The factory MUST call sys.start() and return the started system.
294
+ (Did you forget ${g.cyan("sys.start()")} before returning?)`)}async function X(e=false){try{return await import('@directive-run/timeline')}catch(t){console.error(g.red(`error: @directive-run/timeline not installed in this project.
295
+ Install it: npm install --save-dev @directive-run/timeline`)),e&&console.error(g.dim(t.message)),process.exit(1);}}function Jt(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 me(){console.error(`
296
+ Usage: directive bisect <timeline.json> --system <factory.ts> --assert <expr>
297
+
298
+ Binary-search a recorded timeline for the first frame that triggers a
299
+ failing assertion \u2014 git-bisect, but over ObservationEvent frames.
300
+
301
+ Arguments:
302
+ <timeline.json> Path to a timeline produced by serializeTimeline()
303
+
304
+ Options:
305
+ --system, -s <path> TypeScript file exporting a system factory
306
+ (createSystem / systemFactory / default).
307
+ The factory must return a started Directive
308
+ system; bisect calls it once per midpoint.
309
+ --assert, -a <expression> JS expression with 'facts' and 'system' in
310
+ scope. Truthy = good prefix, falsy = bad
311
+ prefix. Bisect finds the smallest bad prefix.
312
+ --max-frames <n> Per-replay frame cap (default 100,000)
313
+ --no-determinism-check Skip the "replay-twice and compare" gate
314
+ before bisecting. Use only on timelines you
315
+ know are deterministic.
316
+ --json Emit BisectResult as JSON
317
+ --verbose, -v Print every midpoint and its verdict
318
+ --help, -h Show this help
319
+
320
+ SECURITY: --assert is evaluated as JavaScript in this process. Only
321
+ pass expressions from sources you trust (your own scripts, your own
322
+ PRs). Don't paste expressions from issues, untrusted Slack messages,
323
+ or third-party sources without reading them first.
324
+
325
+ Examples:
326
+ directive bisect bug-1234.json --system test/bisect-sys.ts \\
327
+ --assert 'facts.count >= 0'
328
+
329
+ directive bisect crash.json -s factory.ts -a 'facts.status !== "error"' --json
330
+ `);}function Gt(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}
331
+ expression: ${e}`)}return r=>{let s=r?.facts;return !!t(s,r)}}async function Qe(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(me(),process.exit(e.length===0?1:0));let{jsonPath:t,opts:r}=Jt(e);t||(console.error(g.red("error: missing <timeline.json> argument")),me(),process.exit(1)),r.systemPath||(console.error(g.red("error: --system <path> is required"),g.dim(`
332
+ (bisect needs a factory to instantiate a fresh system per midpoint)`)),me(),process.exit(1)),r.assertExpr||(console.error(g.red("error: --assert <expression> is required"),g.dim(`
333
+ (assertion distinguishes 'good' from 'bad' system state)`)),me(),process.exit(1));let s=resolve(t);existsSync(s)||(console.error(g.red(`error: timeline file not found: ${s}`)),process.exit(1));let n;try{n=readFileSync(s,"utf8");}catch(x){console.error(g.red(`error: failed to read ${s}: ${x.message}`)),process.exit(1);}let o;try{o=JSON.parse(n);}catch(x){console.error(g.red(`error: ${s} is not valid JSON: ${x.message}`)),process.exit(1);}let{deserializeTimeline:i,bisectTimeline:a}=await X(r.verbose),l;try{l=i(o);}catch(x){console.error(g.red(`error: timeline JSON failed validation: ${x.message}`)),process.exit(1);}let c;try{c=Gt(r.assertExpr);}catch(x){console.error(g.red(`error: ${x.message}`)),process.exit(1);}let f;try{f=await Xe(r.systemPath);}catch(x){console.error(g.red(`error: failed to load system factory: ${x.message}`)),process.exit(1);}r.verbose&&console.error(g.dim(`bisecting ${l.frames.length} frames with assertion: ${r.assertExpr}`));let u=await a(l,f,c,{maxFrames:r.maxFrames,determinismCheck:!r.noDeterminismCheck});if(r.json){let x={firstFailingFrameIndex:u.firstFailingFrameIndex??null,iterations:u.iterations,noFailureFound:u.noFailureFound,failsOnEmptyReplay:u.failsOnEmptyReplay,nonDeterministic:u.nonDeterministic};console.log(JSON.stringify(x,null,2)),process.exit(0);}u.nonDeterministic&&(console.error(g.red("\u2717 bisect aborted: timeline is non-deterministic")),console.error(g.dim(` Two full-timeline replays produced different oracle verdicts.
334
+ Bisection is unreliable on non-deterministic timelines.
335
+ Either fix the timeline source (deterministic clocks/seeds)
336
+ or re-run with --no-determinism-check if you accept the risk.`)),process.exit(2)),u.noFailureFound&&(console.error(g.yellow("\u26A0 no failure to bisect: assertion passes on the full timeline")),console.error(g.dim(` The recorded timeline does not exhibit the bug your
337
+ --assert expression checks. Verify the assertion or
338
+ try a different bad.json.`)),process.exit(0)),u.failsOnEmptyReplay&&(console.error(g.yellow("\u26A0 assertion fails BEFORE any frame replays \u2014 bug is in initialization")),console.error(g.dim(` The freshly-started system already violates the assertion.
339
+ Bisect cannot narrow further. Inspect the system factory
340
+ or initial fact values.`)),process.exit(0));let p=u.firstFailingFrameIndex??-1,k=u.firstFailingFrame,j=k?.event.type??"<unknown>";console.log(`${g.green("\u2713")} bisect complete: ${g.bold(`first failing frame is #${p}`)} ${g.dim(`(${j})`)}`),console.log(g.dim(` \u2022 iterations: ${u.iterations} | timeline frames: ${l.frames.length}`)),r.verbose&&k&&(console.log(g.dim(" \u2022 frame:")),console.log(g.dim(` ${JSON.stringify(k,null,2).split(`
341
+ `).join(`
342
+ `)}`))),process.exit(2);}function Vt(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 Yt(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 Xt(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 Zt(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 Qt(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 er(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 et(e){let t=Vt(e);console.log(),console.log(g.bold(g.cyan("Directive Doctor"))),console.log(g.dim("\u2500".repeat(40))),console.log();let r=[Yt(t.dir),Xt(t.dir),Zt(t.dir),Qt(t.dir),er(t.dir)],s=0;for(let n of r){let o=n.passed?g.green("\u2713"):g.red("\u2717");console.log(`${o} ${g.bold(n.label)}`),console.log(` ${g.dim(n.message)}`),!n.passed&&n.fix&&(console.log(` ${g.yellow("Fix:")} ${n.fix}`),s++),console.log();}s>0?(console.log(g.yellow(`${s} issue(s) found. See suggested fixes above.`)),process.exit(1)):console.log(g.green("All checks passed!"));}var nt={"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 ir(e){for(let[t,r]of Object.entries(nt))if(r.includes(e))return t;return "Other"}function or(e){let t=e.split(`
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 st(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(g.bold(g.cyan("Directive Examples"))),console.log(g.dim("\u2500".repeat(50))),console.log();let s=new Map;for(let[i,a]of r){let l=ir(i);t&&!l.toLowerCase().includes(t)&&!i.includes(t)||(s.has(l)||s.set(l,[]),s.get(l).push({name:i,desc:or(a)}));}if(s.size===0){console.log(g.dim("No examples match the filter."));return}let n=Object.keys(nt),o=[...s.keys()].sort((i,a)=>(n.indexOf(i)??99)-(n.indexOf(a)??99));for(let i of o){let a=s.get(i);console.log(g.bold(i));for(let l of a){let c=l.desc?g.dim(` \u2014 ${l.desc}`):"";console.log(` ${g.cyan(l.name)}${c}`);}console.log();}console.log(g.dim(`${r.size} examples available. Run ${g.cyan("directive examples copy <name>")} to extract one.`));}async function it(e,t){let r=process.cwd();for(let l=0;l<t.length;l++)if(t[l]==="--dest"){let c=t[++l];c&&(r=c);}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 ${g.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 a=relative(process.cwd(),o);console.log(`${g.green("Copied")} ${g.cyan(e)} \u2192 ${g.dim(a)}`);}function ar(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 at(e){let{filePath:t,requirementId:r}=ar(e);t||(console.error("Usage: directive explain <file> [requirement-id]"),process.exit(1));let s=await P(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
+
345
+ Current requirements:`),n.unmet.length===0)console.log(g.dim(" (no unmet requirements)"));else for(let i of n.unmet)console.log(` ${g.cyan(i.id)} \u2014 ${i.requirement.type} (from ${i.fromConstraint})`);s.stop(),process.exit(1);}console.log(),console.log(g.bold(g.cyan("Requirement Explanation"))),console.log(g.dim("\u2500".repeat(40))),console.log(),console.log(o),console.log();}else if(console.log(),console.log(g.bold(g.cyan("All Requirements"))),console.log(g.dim("\u2500".repeat(40))),console.log(),n.unmet.length===0){console.log(g.green("All requirements are met.")),console.log();let o=Object.entries(n.resolvers);if(o.length>0){console.log(g.bold("Recent Resolver Activity:"));for(let[i,a]of o){let l=ot(a.state),c=a.duration!==void 0?` (${a.duration}ms)`:"";console.log(` ${g.cyan(i)} ${l}${c}`);}console.log();}}else {console.log(`${g.yellow(String(n.unmet.length))} unmet requirement(s):
346
+ `);for(let o of n.unmet){console.log(`${g.yellow("\u25CF")} ${g.bold(o.requirement.type)} (id: ${g.dim(o.id)})`),console.log(` From constraint: ${g.cyan(o.fromConstraint)}`);let i={...o.requirement};delete i.type,Object.keys(i).length>0&&console.log(` Payload: ${JSON.stringify(i)}`);let l=n.resolvers[o.id];l?console.log(` Resolver: ${ot(l.state)}${l.error?` \u2014 ${l.error}`:""}`):n.resolverDefs.some(f=>f.requirement===o.requirement.type||f.requirement==="(predicate)")||console.log(` ${g.red("No resolver registered for this type")}`),console.log();}console.log(g.dim(`Run ${g.cyan("directive explain <file> <requirement-id>")} for detailed explanation.`));}s.stop();}function ot(e){switch(e){case "resolved":return g.green("resolved");case "errored":return g.red("errored");case "inflight":return g.yellow("inflight");case "pending":return g.yellow("pending");case "cancelled":return g.dim("cancelled");default:return g.dim(e)}}function ur(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 fr(e){let t=[];t.push(g.bold("Dependency Graph")),t.push(g.dim("\u2550".repeat(50))),t.push("");let r=new Map;for(let a of e.constraints)r.set(a.id,{reqTypes:new Set,active:a.active,priority:a.priority});for(let a of e.unmet){let l=r.get(a.fromConstraint);l&&l.reqTypes.add(a.requirement.type);}let s=new Map;for(let a of e.resolverDefs)s.has(a.requirement)||s.set(a.requirement,[]),s.get(a.requirement).push(a.id);t.push(g.bold("Constraints \u2192 Requirements \u2192 Resolvers")),t.push("");for(let[a,l]of r){let c=l.active?g.green("\u25CF"):g.dim("\u25CB");if(t.push(`${c} ${g.cyan(a)} (priority: ${l.priority})`),l.reqTypes.size>0)for(let f of l.reqTypes){t.push(` \u2514\u2500\u25B6 ${g.yellow(f)}`);let u=s.get(f)||[];if(u.length>0)for(let p of u)t.push(` \u2514\u2500\u25B6 ${g.magenta(p)}`);else t.push(` \u2514\u2500\u25B6 ${g.red("(no resolver)")}`);}else t.push(` \u2514\u2500\u25B6 ${g.dim("(no active requirements)")}`);t.push("");}let n=new Set;for(let a of s.values())for(let l of a)n.add(l);if(e.resolverDefs.map(a=>a.id).filter(a=>!n.has(a)).length>0){t.push(g.bold("Standalone Resolvers:"));for(let a of e.resolverDefs)n.has(a.id)||t.push(` ${g.magenta(a.id)} handles ${g.yellow(a.requirement)}`);}return t.join(`
347
+ `)}function dr(e,t){let r=[],s=[],l=Object.keys(t);for(let d=0;d<l.length;d++){let $=l[d];r.push({id:`fact-${$}`,label:$,type:"fact",x:40,y:60+d*50,color:"#3b82f6"});}for(let d=0;d<e.constraints.length;d++){let $=e.constraints[d];r.push({id:`constraint-${$.id}`,label:$.id,type:"constraint",x:260,y:60+d*50,color:$.active?"#22c55e":"#6b7280"});}let c=new Set;for(let d of e.unmet)c.add(d.requirement.type);let f=0;for(let d of c)r.push({id:`req-${d}`,label:d,type:"requirement",x:480,y:60+f*50,color:"#eab308"}),f++;for(let d=0;d<e.resolverDefs.length;d++){let $=e.resolverDefs[d];r.push({id:`resolver-${$.id}`,label:$.id,type:"resolver",x:700,y:60+d*50,color:"#a855f7"});}for(let d of e.unmet)s.push({from:`constraint-${d.fromConstraint}`,to:`req-${d.requirement.type}`});for(let d of e.resolverDefs)c.has(d.requirement)&&s.push({from:`req-${d.requirement}`,to:`resolver-${d.id}`});let u=new Map(r.map(d=>[d.id,d])),p=960,k=Math.max(...r.map(d=>d.y))+50+20,j=s.map(d=>{let $=u.get(d.from),z=u.get(d.to);return !$||!z?"":`<line x1="${$.x+90}" y1="${$.y+15}" x2="${z.x}" y2="${z.y+15}" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#arrow)"/>`}).join(`
348
+ `),x=r.map(d=>`<g>
349
+ <rect x="${d.x}" y="${d.y}" width="180" height="30" rx="6" fill="${d.color}" opacity="0.15" stroke="${d.color}" stroke-width="1.5"/>
350
+ <text x="${d.x+90}" y="${d.y+19}" text-anchor="middle" font-size="12" font-family="monospace" fill="${d.color}">${pr(d.label)}</text>
351
+ </g>`).join(`
352
+ `),te=["Facts","Constraints","Requirements","Resolvers"].map((d,$)=>`<text x="${40+$*220+90}" y="35" text-anchor="middle" font-size="14" font-weight="bold" font-family="system-ui" fill="#e2e8f0">${d}</text>`).join(`
353
+ `);return `<!DOCTYPE html>
354
+ <html>
355
+ <head>
356
+ <title>Directive System Graph</title>
357
+ <style>
358
+ body { margin: 0; background: #0f172a; display: flex; justify-content: center; padding: 20px; }
359
+ svg { max-width: 100%; }
360
+ </style>
361
+ </head>
362
+ <body>
363
+ <svg width="${p}" height="${k}" xmlns="http://www.w3.org/2000/svg">
364
+ <defs>
365
+ <marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
366
+ <path d="M 0 0 L 10 5 L 0 10 z" fill="#94a3b8"/>
367
+ </marker>
368
+ </defs>
369
+ ${te}
370
+ ${j}
371
+ ${x}
372
+ </svg>
373
+ </body>
374
+ </html>`}function pr(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function lt(e){let{filePath:t,opts:r}=ur(e);t||(console.error("Usage: directive graph <file> [--ascii] [--no-open] [--output <path>]"),process.exit(1));let s=await P(t);s.isRunning||s.start();let n=s.inspect();if(r.ascii){console.log(fr(n)),s.stop();return}let o={};if(s.facts)for(let l of Object.keys(s.facts))try{o[l]=s.facts[l];}catch{o[l]=null;}let i=dr(n,o),a=r.output||join(process.cwd(),".directive-graph.html");if(writeFileSync(a,i,"utf-8"),console.log(`${g.green("Generated")} ${g.dim(a)}`),r.open)try{let{execFile:l}=await import('child_process'),c=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";l(c,[a]),console.log(g.dim("Opened in browser."));}catch{console.log(g.dim(`Open ${a} in your browser to view the graph.`));}s.stop();}function vr(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 br(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 wr(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 je(e){return {counter:{id:"counter",label:"Counter (minimal)",hint:"schema + init + derive + events \u2014 simplest starting point",files:[{path:`src/${e}.ts`,content:$r(e)},{path:"src/main.ts",content:Sr(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:kr(e)},{path:"src/main.ts",content:xr(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:Rr(e)},{path:"src/main.ts",content:Cr(e)}],deps:["@directive-run/core","@directive-run/ai"]}}}function $r(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
266
375
 
267
376
  const schema = {
268
377
  facts: {
@@ -281,7 +390,7 @@ const schema = {
281
390
  },
282
391
  } satisfies ModuleSchema;
283
392
 
284
- export const ${J(e)} = createModule("${e}", {
393
+ export const ${Q(e)} = createModule("${e}", {
285
394
  schema,
286
395
 
287
396
  init: (facts) => {
@@ -309,7 +418,7 @@ export const ${J(e)} = createModule("${e}", {
309
418
  },
310
419
  },
311
420
  });
312
- `}function bt(e){let t=J(e);return `import { createSystem } from "@directive-run/core";
421
+ `}function Sr(e){let t=Q(e);return `import { createSystem } from "@directive-run/core";
313
422
  import { ${t} } from "./${e}.js";
314
423
 
315
424
  const system = createSystem({
@@ -335,7 +444,7 @@ system.events.increment();
335
444
  system.events.increment();
336
445
 
337
446
  export default system;
338
- `}function wt(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
447
+ `}function kr(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
339
448
 
340
449
  type AuthStatus = "idle" | "authenticating" | "authenticated" | "expired";
341
450
 
@@ -362,7 +471,7 @@ const schema = {
362
471
  },
363
472
  } satisfies ModuleSchema;
364
473
 
365
- export const ${J(e)} = createModule("${e}", {
474
+ export const ${Q(e)} = createModule("${e}", {
366
475
  schema,
367
476
 
368
477
  init: (facts) => {
@@ -439,7 +548,7 @@ export const ${J(e)} = createModule("${e}", {
439
548
  },
440
549
  },
441
550
  });
442
- `}function xt(e){let t=J(e);return `import { createSystem } from "@directive-run/core";
551
+ `}function xr(e){let t=Q(e);return `import { createSystem } from "@directive-run/core";
443
552
  import { ${t} } from "./${e}.js";
444
553
 
445
554
  const system = createSystem({
@@ -460,7 +569,7 @@ console.log("authenticated:", system.read("isAuthenticated"));
460
569
  console.log("token:", system.facts.token);
461
570
 
462
571
  export default system;
463
- `}function $t(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
572
+ `}function Rr(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
464
573
  import {
465
574
  createAgentOrchestrator,
466
575
  createAgentMemory,
@@ -494,7 +603,7 @@ const schema = {
494
603
  },
495
604
  } satisfies ModuleSchema;
496
605
 
497
- export const ${J(e)} = createModule("${e}", {
606
+ export const ${Q(e)} = createModule("${e}", {
498
607
  schema,
499
608
 
500
609
  init: (facts) => {
@@ -568,7 +677,7 @@ export const memory = createAgentMemory({
568
677
  // maxTokenBudget: 50000,
569
678
  // memory,
570
679
  // });
571
- `}function kt(e){let t=J(e);return `import { createSystem } from "@directive-run/core";
680
+ `}function Cr(e){let t=Q(e);return `import { createSystem } from "@directive-run/core";
572
681
  import { ${t} } from "./${e}.js";
573
682
 
574
683
  const system = createSystem({
@@ -587,79 +696,89 @@ await system.settle();
587
696
  console.log("output:", system.facts.output);
588
697
 
589
698
  export default system;
590
- `}function J(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}function St(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}async function Ae(e){let t=gt(e);p.intro(f.bgCyan(f.black(" directive init ")));let r;if(t.noInteractive)r="my-module";else {let l=await p.text({message:"Module name:",placeholder:"my-module",defaultValue:"my-module",validate:h=>{if(!/^[a-z][a-z0-9-]*$/.test(h))return "Must start with a letter, use lowercase letters, numbers, and hyphens"}});p.isCancel(l)&&(p.cancel("Cancelled."),process.exit(0)),r=l;}let s;if(t.template){let l=me(r);t.template in l||(p.log.error(`Unknown template: ${t.template}. Available: ${Object.keys(l).join(", ")}`),process.exit(1)),s=t.template;}else if(t.noInteractive)s="counter";else {let l=me(r),h=await p.select({message:"Project template:",options:Object.values(l).map(T=>({value:T.id,label:T.label,hint:T.hint}))});p.isCancel(h)&&(p.cancel("Cancelled."),process.exit(0)),s=h;}let i=me(r)[s],n=ht(t.dir);p.log.info(`Package manager: ${f.cyan(n)}`);let a=p.spinner();a.start("Creating project files...");let m=0;for(let l of i.files){let h=join(t.dir,l.path);if(existsSync(h)){m++;continue}St(h,l.content);}a.stop("Project files created.");for(let l of i.files){let h=join(t.dir,l.path),T=relative(t.dir,h);existsSync(h)&&p.log.success(`${f.green("Created")} ${f.dim(T)}`);}m>0&&p.log.warn(`Skipped ${m} file(s) that already exist.`);let d=yt(n,i.deps.join(" "));p.outro(`Next steps:
591
- ${f.cyan(d)}
592
- ${f.cyan(`${x} ai-rules init`)}
593
- ${f.dim("Start building!")}`);}function Oe(e){let t={with:[],minimal:false,dir:process.cwd()};for(let r=0;r<e.length;r++)switch(e[r]){case "--with":{let o=e[++r];o&&(t.with=o.split(",").map(i=>i.trim()));break}case "--minimal":t.minimal=true;break;case "--dir":{let o=e[++r];o&&(t.dir=o);break}}return t}var Te=["derive","events","constraints","resolvers","effects"];function Tt(e,t){let r=De(e),s=t.includes("constraints"),o=t.includes("resolvers"),n=`import { ${["type ModuleSchema","createModule","t"].join(", ")} } from "@directive-run/core";
594
-
595
- `;return n+=`const schema = {
596
- `,n+=` facts: {
597
- `,n+=` // Add your facts here
598
- `,n+=` status: t.string(),
599
- `,n+=` },
600
- `,t.includes("derive")&&(n+=` derivations: {
601
- `,n+=` // Add derivation types here
602
- `,n+=` isReady: t.boolean(),
603
- `,n+=` },
604
- `),t.includes("events")&&(n+=` events: {
605
- `,n+=` // Add event shapes here
606
- `,n+=` setStatus: { value: t.string() },
607
- `,n+=` },
608
- `),(s||o)&&(n+=` requirements: {
609
- `,n+=` // Add requirement shapes here
610
- `,n+=` PROCESS: { input: t.string() },
611
- `,n+=` },
612
- `),n+=`} satisfies ModuleSchema;
613
-
614
- `,n+=`export const ${r} = createModule("${e}", {
615
- `,n+=` schema,
616
-
617
- `,n+=` init: (facts) => {
618
- `,n+=` facts.status = "idle";
619
- `,n+=` },
620
- `,t.includes("derive")&&(n+=`
699
+ `}function Q(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}function Er(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}async function ct(e){let t=vr(e);m.intro(g.bgCyan(g.black(" directive init ")));let r;if(t.noInteractive)r="my-module";else {let u=await m.text({message:"Module name:",placeholder:"my-module",defaultValue:"my-module",validate:p=>{if(!/^[a-z][a-z0-9-]*$/.test(p))return "Must start with a letter, use lowercase letters, numbers, and hyphens"}});m.isCancel(u)&&(m.cancel("Cancelled."),process.exit(0)),r=u;}let s;if(t.template){let u=je(r);t.template in u||(m.log.error(`Unknown template: ${t.template}. Available: ${Object.keys(u).join(", ")}`),process.exit(1)),s=t.template;}else if(t.noInteractive)s="counter";else {let u=je(r),p=await m.select({message:"Project template:",options:Object.values(u).map(k=>({value:k.id,label:k.label,hint:k.hint}))});m.isCancel(p)&&(m.cancel("Cancelled."),process.exit(0)),s=p;}let o=je(r)[s],i=br(t.dir);m.log.info(`Package manager: ${g.cyan(i)}`);let a=m.spinner();a.start("Creating project files...");let c=0;for(let u of o.files){let p=join(t.dir,u.path);if(existsSync(p)){c++;continue}Er(p,u.content);}a.stop("Project files created.");for(let u of o.files){let p=join(t.dir,u.path),k=relative(t.dir,p);existsSync(p)&&m.log.success(`${g.green("Created")} ${g.dim(k)}`);}c>0&&m.log.warn(`Skipped ${c} file(s) that already exist.`);let f=wr(i,o.deps.join(" "));m.outro(`Next steps:
700
+ ${g.cyan(f)}
701
+ ${g.cyan(`${R} ai-rules init`)}
702
+ ${g.dim("Start building!")}`);}function Dr(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 jr(e){let t=[];t.push(g.bold("Facts:"));let r=Object.entries(e);if(r.length===0)return t.push(" (none)"),t.join(`
703
+ `);for(let[s,n]of r){let o=Tr(n);t.push(` ${g.cyan(s)} = ${o}`);}return t.join(`
704
+ `)}function Or(e){let t=[];if(t.push(g.bold("Constraints:")),e.length===0)return t.push(" (none)"),t.join(`
705
+ `);for(let r of e){let s=r.disabled?g.dim("disabled"):r.active?g.green("active"):g.dim("inactive"),n=r.hitCount>0?g.yellow(` (${r.hitCount} hits)`):"";t.push(` ${g.cyan(r.id)} ${s} priority=${r.priority}${n}`);}return t.join(`
706
+ `)}function Ar(e,t){let r=[];if(r.push(g.bold("Resolvers:")),e.length===0)return r.push(" (none)"),r.join(`
707
+ `);for(let s of e){let n=t[s.id],o=n?Ir(n.state,n.error,n.duration):g.dim("idle");r.push(` ${g.cyan(s.id)} \u2192 ${s.requirement} ${o}`);}return r.join(`
708
+ `)}function Mr(e){let t=[];if(t.push(g.bold("Unmet Requirements:")),e.length===0)return t.push(` ${g.green("(all requirements met)")}`),t.join(`
709
+ `);for(let r of e)t.push(` ${g.yellow(r.requirement.type)} (id: ${g.dim(r.id)}) from ${g.dim(r.fromConstraint)}`);return t.join(`
710
+ `)}function qr(e){let t=[];if(t.push(g.bold("Inflight:")),e.length===0)return t.push(` ${g.green("(none)")}`),t.join(`
711
+ `);let r=Date.now();for(let s of e){let n=r-s.startedAt;t.push(` ${g.cyan(s.resolverId)} \u2192 req ${g.dim(s.id)} ${g.yellow(`${n}ms`)}`);}return t.join(`
712
+ `)}function Ir(e,t,r){let s=r!==void 0?` ${r}ms`:"";switch(e){case "resolved":return g.green(`resolved${s}`);case "errored":return g.red(`errored${s}${t?` \u2014 ${t}`:""}`);case "inflight":return g.yellow("inflight");case "cancelled":return g.dim("cancelled");default:return g.dim(e)}}function Tr(e){return e===null?g.dim("null"):e===void 0?g.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 Pr(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(a=>a.requirement===o.requirement.type||a.requirement==="(predicate)")||t.push(`No resolver for requirement type "${o.requirement.type}"`);return t}async function ut(e){let{filePath:t,opts:r}=Dr(e);t||(console.error("Usage: directive inspect <file> [--json] [--module <name>]"),process.exit(1));let s=await P(t);s.isRunning||s.start();let n=s.inspect();if(r.json){let a={};if(s.facts)for(let l of Object.keys(s.facts))try{a[l]=s.facts[l];}catch{a[l]="(error reading)";}console.log(JSON.stringify({facts:a,...n},null,2)),s.stop();return}console.log(),console.log(g.bold(g.cyan("Directive System Inspection"))),console.log(g.dim("\u2500".repeat(40))),console.log();let o={};if(s.facts)for(let a of Object.keys(s.facts))try{o[a]=s.facts[a];}catch{o[a]="(error reading)";}console.log(jr(o)),console.log(),console.log(Or(n.constraints)),console.log(),console.log(Ar(n.resolverDefs,n.resolvers)),console.log(),console.log(Mr(n.unmet)),console.log(),n.inflight.length>0&&(console.log(qr(n.inflight)),console.log());let i=Pr(n);if(i.length>0){console.log(g.bold(g.yellow("Warnings:")));for(let a of i)console.log(` ${g.yellow("\u26A0")} ${a}`);console.log();}s.stop();}function dt(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 ft=["derive","events","constraints","resolvers","effects"];function _r(e,t){let r=pt(e),s=t.includes("constraints"),n=t.includes("resolvers"),i=`import { ${["type ModuleSchema","createModule","t"].join(", ")} } from "@directive-run/core";
713
+
714
+ `;return i+=`const schema = {
715
+ `,i+=` facts: {
716
+ `,i+=` // Add your facts here
717
+ `,i+=` status: t.string(),
718
+ `,i+=` },
719
+ `,t.includes("derive")&&(i+=` derivations: {
720
+ `,i+=` // Add derivation types here
721
+ `,i+=` isReady: t.boolean(),
722
+ `,i+=` },
723
+ `),t.includes("events")&&(i+=` events: {
724
+ `,i+=` // Add event shapes here
725
+ `,i+=` setStatus: { value: t.string() },
726
+ `,i+=` },
727
+ `),(s||n)&&(i+=` requirements: {
728
+ `,i+=` // Add requirement shapes here
729
+ `,i+=` PROCESS: { input: t.string() },
730
+ `,i+=` },
731
+ `),i+=`} satisfies ModuleSchema;
732
+
733
+ `,i+=`export const ${r} = createModule("${e}", {
734
+ `,i+=` schema,
735
+
736
+ `,i+=` init: (facts) => {
737
+ `,i+=` facts.status = "idle";
738
+ `,i+=` },
739
+ `,t.includes("derive")&&(i+=`
621
740
  derive: {
622
- `,n+=` isReady: (facts) => facts.status === "ready",
623
- `,n+=` },
624
- `),t.includes("events")&&(n+=`
741
+ `,i+=` isReady: (facts) => facts.status === "ready",
742
+ `,i+=` },
743
+ `),t.includes("events")&&(i+=`
625
744
  events: {
626
- `,n+=` setStatus: (facts, { value }) => {
627
- `,n+=` facts.status = value;
628
- `,n+=` },
629
- `,n+=` },
630
- `),s&&(n+=`
745
+ `,i+=` setStatus: (facts, { value }) => {
746
+ `,i+=` facts.status = value;
747
+ `,i+=` },
748
+ `,i+=` },
749
+ `),s&&(i+=`
631
750
  constraints: {
632
- `,n+=` needsProcessing: {
633
- `,n+=` priority: 100,
634
- `,n+=` when: (facts) => facts.status === "pending",
635
- `,n+=` require: (facts) => ({
636
- `,n+=` type: "PROCESS",
637
- `,n+=` input: facts.status,
638
- `,n+=` }),
639
- `,n+=` },
640
- `,n+=` },
641
- `),o&&(n+=`
751
+ `,i+=` needsProcessing: {
752
+ `,i+=` priority: 100,
753
+ `,i+=` when: (facts) => facts.status === "pending",
754
+ `,i+=` require: (facts) => ({
755
+ `,i+=` type: "PROCESS",
756
+ `,i+=` input: facts.status,
757
+ `,i+=` }),
758
+ `,i+=` },
759
+ `,i+=` },
760
+ `),n&&(i+=`
642
761
  resolvers: {
643
- `,n+=` process: {
644
- `,n+=` requirement: "PROCESS",
645
- `,n+=` resolve: async (req, context) => {
646
- `,n+=` // Implement resolution logic here
647
- `,n+=` context.facts.status = "done";
648
- `,n+=` },
649
- `,n+=` },
650
- `,n+=` },
651
- `),t.includes("effects")&&(n+=`
762
+ `,i+=` process: {
763
+ `,i+=` requirement: "PROCESS",
764
+ `,i+=` resolve: async (req, context) => {
765
+ `,i+=` // Implement resolution logic here
766
+ `,i+=` context.facts.status = "done";
767
+ `,i+=` },
768
+ `,i+=` },
769
+ `,i+=` },
770
+ `),t.includes("effects")&&(i+=`
652
771
  effects: {
653
- `,n+=` logChange: {
654
- `,n+=` deps: ["status"],
655
- `,n+=` run: (facts, prev) => {
656
- `,n+=` if (prev && prev.status !== facts.status) {
657
- `,n+=" console.log(`Status: ${prev.status} \u2192 ${facts.status}`);\n",n+=` }
658
- `,n+=` },
659
- `,n+=` },
660
- `,n+=` },
661
- `),n+=`});
662
- `,n}function Ot(e){let t=De(e);return `import { type ModuleSchema, createModule, createSystem, t } from "@directive-run/core";
772
+ `,i+=` logChange: {
773
+ `,i+=` deps: ["status"],
774
+ `,i+=` run: (facts, prev) => {
775
+ `,i+=` if (prev && prev.status !== facts.status) {
776
+ `,i+=" console.log(`Status: ${prev.status} \u2192 ${facts.status}`);\n",i+=` }
777
+ `,i+=` },
778
+ `,i+=` },
779
+ `,i+=` },
780
+ `),i+=`});
781
+ `,i}function Ur(e){let t=pt(e);return `import { type ModuleSchema, createModule, createSystem, t } from "@directive-run/core";
663
782
  import {
664
783
  createAgentOrchestrator,
665
784
  createAgentMemory,
@@ -790,81 +909,39 @@ export const memory = createAgentMemory({
790
909
  export const system = createSystem({
791
910
  module: ${t},
792
911
  });
793
- `}function De(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}function Ee(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}function je(e){return join(e,"src")}async function Me(e,t){let r=Oe(t);(!e||!/^[a-z][a-z0-9-]*$/.test(e))&&(console.error(`Invalid module name: ${e||"(none)"}
794
- 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(c=>Te.includes(c)):s=Te;let o=je(r.dir),i=join(o,`${e}.ts`);existsSync(i)&&(console.error(`File already exists: ${relative(r.dir,i)}`),process.exit(1));let n=Tt(e,s);Ee(i,n);let a=relative(r.dir,i);console.log(`${f.green("Created")} ${f.dim(a)}`),s.length===0?console.log(f.dim(" Minimal module (schema + init only)")):console.log(f.dim(` Sections: ${s.join(", ")}`));}async function Pe(e,t){let r=Oe(t);(!e||!/^[a-z][a-z0-9-]*$/.test(e))&&(console.error(`Invalid orchestrator name: ${e||"(none)"}
795
- Must start with a letter, use lowercase letters, numbers, and hyphens.`),process.exit(1));let s=je(r.dir),o=join(s,`${e}.ts`);existsSync(o)&&(console.error(`File already exists: ${relative(r.dir,o)}`),process.exit(1));let i=Ot(e);Ee(o,i);let n=relative(r.dir,o);console.log(`${f.green("Created")} ${f.dim(n)}`),console.log(f.dim(" AI orchestrator with memory, guardrails, and streaming"));}async function P(e){let t=resolve(e);if(!existsSync(t))throw new Error(`File not found: ${t}`);try{let r=await import(t);if(r.default&&F(r.default))return r.default;if(r.system&&F(r.system))return r.system;for(let s of Object.keys(r))if(F(r[s]))return r[s];throw new Error(`No Directive system found in ${f.dim(e)}
796
- Export a system as default or named "system":
797
-
798
- ${f.cyan("export default")} createSystem({ module: myModule });
799
- ${f.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 ${f.dim(e)}: ${r instanceof Error?r.message:String(r)}
800
-
801
- Make sure the file is valid TypeScript and tsx is installed:
802
- ${f.cyan("npm install -D tsx")}`)}}function F(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 Ne(e){let t=resolve(e);if(!existsSync(t))throw new Error(`File not found: ${t}`);let r;try{r=await import(t);}catch(i){throw new Error(`Failed to load ${f.dim(e)}: ${i instanceof Error?i.message:String(i)}
803
-
804
- Make sure the file is valid TypeScript and tsx is installed:
805
- ${f.cyan("npm install -D tsx")}`)}let s=[["createSystem",r.createSystem],["systemFactory",r.systemFactory],["default",r.default]];for(let[i,n]of s)if(typeof n=="function")return async()=>{let a=await Promise.resolve(n());if(!F(a))throw new Error(`Factory '${i}' from ${f.dim(e)} returned a value that is not a started Directive system.
806
- Expected an object with inspect/start/stop/facts. The factory must call sys.start() before returning.`);return a};throw F(r.default)||F(r.system)||Object.values(r).some(F)?new Error(`Found a started Directive system in ${f.dim(e)}, but bisect needs a factory.
807
- Bisect instantiates a fresh system for every midpoint replay (so each attempt is hermetic),
808
- which means it can't reuse a singleton instance the way ${f.cyan("directive replay")} does.
912
+ `}function pt(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}function mt(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}function gt(e){return join(e,"src")}async function ht(e,t){let r=dt(t);(!e||!/^[a-z][a-z0-9-]*$/.test(e))&&(console.error(`Invalid module name: ${e||"(none)"}
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(l=>ft.includes(l)):s=ft;let n=gt(r.dir),o=join(n,`${e}.ts`);existsSync(o)&&(console.error(`File already exists: ${relative(r.dir,o)}`),process.exit(1));let i=_r(e,s);mt(o,i);let a=relative(r.dir,o);console.log(`${g.green("Created")} ${g.dim(a)}`),s.length===0?console.log(g.dim(" Minimal module (schema + init only)")):console.log(g.dim(` Sections: ${s.join(", ")}`));}async function yt(e,t){let r=dt(t);(!e||!/^[a-z][a-z0-9-]*$/.test(e))&&(console.error(`Invalid orchestrator name: ${e||"(none)"}
914
+ Must start with a letter, use lowercase letters, numbers, and hyphens.`),process.exit(1));let s=gt(r.dir),n=join(s,`${e}.ts`);existsSync(n)&&(console.error(`File already exists: ${relative(r.dir,n)}`),process.exit(1));let o=Ur(e);mt(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"));}Object.freeze(new Set(["__proto__","constructor","prototype"]));var F=new Set(["$eq","$ne","$in","$nin","$exists","$gt","$gte","$lt","$lte","$between","$matches","$startsWith","$endsWith","$contains","$changed"]),bt=new Set(["$all","$any","$not"]),ie=64;function I(e){return typeof e!="object"||e===null||Array.isArray(e)?false:!(e instanceof Date)&&!(e instanceof RegExp)}function ve(e){if(typeof e!="object"||e===null||Array.isArray(e))return false;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function qe(e){if(!I(e))return false;let t=0,r=false;for(let s of Object.keys(e)){if(s.startsWith("$"))r=true,F.has(s)||ae(`predicate: unknown operator "${s}" \u2014 looks like a typo. Known operators: ${[...F].join(", ")}`);else if(r||t===0)return false;t++;}return r?t>0:false}function wt(e){return e===null?false:Array.isArray(e)?e.every(t=>ve(t)&&"fact"in t&&"op"in t):ve(e)}function oe(e,t,r="",s=new WeakSet,n=0){if(n>ie){console.warn(`[Directive] predicate depth limit (${ie}) 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,a)=>{if(!I(i))return;let l=i;if(typeof l.fact=="string"&&typeof l.op=="string"){let c=r?`${r}[${a}]`:`[${a}]`;t.operator?.(r?`${r}.${l.fact}`:l.fact,l.op,l.value,`${c}.value`);}});return}if(!I(e))return;if(s.has(e)){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 a=i==="$not"?[o.$not]:o[i]??[];for(let l of a)oe(l,t,r,s,n+1);return}for(let i of Object.keys(o)){let a=r?`${r}.${i}`:i;if(i.startsWith("$")){t.strayOperatorKey?.(i,a);continue}let l=o[i];if(qe(l)){let c=l;for(let f of Object.keys(c))t.operator?.(a,f,c[f],`${a}.${f}`);continue}if(ve(l)){if(t.nested?.(i)===false)continue;oe(l,t,a,s,n+1);continue}t.literal?.(a,l);}}function $t(e,t=""){function r(n,o,i,a){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")&&!(a>ie)&&!i.has(n)){if(i.add(n),Array.isArray(n)){n.forEach((l,c)=>{r(l,`${o}[${c}]`,i,a+1);});return}for(let l of Object.keys(n))r(n[l],o?`${o}.${l}`:l,i,a+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((a,l)=>{r(a,`${i}[${l}]`,new WeakSet,1);});else if(ve(n))for(let a of Object.keys(n))r(n[a],`${i}.${a}`,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).`);oe(e,{operator(n,o,i,a){s(i,o,t?`${t}.${a}`:a);},literal(n,o){s(o,"",t?`${t}.${n}`:n);}});}function Br(){return {ids:new WeakMap,next:{v:1},pairs:new Set}}function vt(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??Br(),n=`${vt(s,e)}:${vt(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((a,l)=>q(a,t[l],s));if(e instanceof Set||t instanceof Set){if(!(e instanceof Set)||!(t instanceof Set)||e.size!==t.size)return false;let a=[...t];return [...e].every(l=>a.some(c=>q(l,c,s)))}if(e instanceof Map||t instanceof Map){if(!(e instanceof Map)||!(t instanceof Map)||e.size!==t.size)return false;let a=[...t.entries()],l=new Array(a.length).fill(false);for(let[c,f]of e){let u=false;for(let p=0;p<a.length;p++){if(l[p])continue;let[k,j]=a[p];if(q(c,k,s)&&q(f,j,s)){l[p]=true,u=true;break}}if(!u)return false}return true}let o=Object.keys(e),i=Object.keys(t);return o.length!==i.length?false:o.every(a=>Object.hasOwn(t,a)&&q(e[a],t[a],s))}function be(e){if(e instanceof Date)return e.getTime();if(typeof e=="number"||typeof e=="bigint"||typeof e=="string")return e}function Me(e,t,r){let s=be(t),n=be(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 we(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 Me(e,t,r);case "$between":{if(!Array.isArray(r)||r.length!==2)return false;let n=be(r[0]),o=be(r[1]);return n!==void 0&&o!==void 0&&typeof n==typeof o&&n>o?(ae("$between: reversed pair \u2014 [min, max] required"),false):Me("$gte",t,r[0])&&Me("$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 ae(e){console.warn(`[Directive] ${e}`);}function Lr(e,t,r,s){if(qe(e)){let n=Object.keys(e);n.length>1&&ae(`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(!we(o,t,e[o],r))return false;return true}return I(e)?J(e,I(t)?t:Object.create(null),I(r)?r:void 0,s+1):q(t,e)}function J(e,t,r,s=0){if(s>ie)return ae(`predicate depth limit (${ie}) 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:a}=n;return we(i,t?.[o],a,r?.[o])});if(!I(e))return !!e;if("$all"in e)return e.$all.every(n=>J(n,t,r,s+1));if("$any"in e)return e.$any.some(n=>J(n,t,r,s+1));if("$not"in e)return !J(e.$not,t,r,s+1);for(let n of Object.keys(e)){if(F.has(n))return ae(`predicate: operator "${n}" mixed with fact keys \u2014 wrap operators in a per-fact object`),false;if(!Lr(e[n],t?.[n],r?.[n],s))return false}return true}function le(e,t,r,s=""){let n=[];if(Array.isArray(e)){for(let o of e){if(!I(o))continue;let{fact:i,op:a,value:l}=o,c=t?.[i];n.push({path:s+i,op:a,expected:l,actual:c,pass:we(a,c,l,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],a=[];for(let f of i)a.push(...le(f,t,r,s));let l=a.filter(f=>f.pass).length,c;return o==="$all"?c=a.length===0||l===a.length:o==="$any"?c=a.length>0&&l>0:c=!a.every(f=>f.pass),n.push({path:s||o,op:o,expected:i.length,actual:l,pass:c,children:a}),n}for(let o of Object.keys(e)){if(F.has(o))continue;let i=e[o],a=t?.[o],l=s+o;if(qe(i))for(let c of Object.keys(i))n.push({path:l,op:c,expected:i[c],actual:a,pass:we(c,a,i[c],r?.[o])});else I(i)?n.push(...le(i,I(a)?a:Object.create(null),I(r?.[o])?r?.[o]:void 0,`${l}.`)):n.push({path:l,op:"$eq",expected:i,actual:a,pass:q(a,i)});}return n}var ee=1e6;function St(e,t){try{$t(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(!wt(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(oe(e,{operator(s,n){r===void 0&&n.startsWith("$")&&!F.has(n)&&(r=n);},strayOperatorKey(s){r===void 0&&!F.has(s)&&!bt.has(s)&&(r=s);}}),r!==void 0)throw new Error(`[Directive] replayUnder: the ${t} predicate uses an unknown operator "${r}" \u2014 known operators: ${[...F].join(", ")}`)}function Ie(e){if(e&&typeof e=="object"&&!Array.isArray(e)&&Array.isArray(e.snapshots))return Kr(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>ee)throw new Error(`[Directive] toReplayFrames: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${ee}) \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 Kr(e){let t=typeof e=="string"?JSON.parse(e):e;if(Array.isArray(t))return kt(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 kt(r.snapshots)}function kt(e){if(!Array.isArray(e))throw new Error("[Directive] framesFromSnapshots: expected an array of fact-state snapshots");if(e.length>ee)throw new Error(`[Directive] framesFromSnapshots: history has ${e.length} snapshots, exceeds the MAX_REPLAY_FRAMES limit (${ee}) \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 Ie(e)}function Rt(e){let{frames:t,original:r,proposed:s,entityKey:n}=e,o=e.maxSamples??20,i=o>0?o:0;if(t.length>ee)throw new Error(`[Directive] replayUnder: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${ee}) \u2014 split or down-sample the history`);St(r,"original"),St(s,"proposed");let a=0,l=0,c=0,f=0,u=0,p=[],k=[],j=n?new Set:void 0,x=n?new Set:void 0,G;for(let d of t){let $=d.facts,z=J(r,$,G),Se=J(s,$,G);z&&(a++,j?.add($[n])),Se&&(l++,x?.add($[n])),z===Se?u++:!z&&Se?(c++,p.length<i&&p.push(xt(d,r,s,G))):(f++,k.length<i&&k.push(xt(d,r,s,G))),G=$;}let te={framesEvaluated:t.length,original:{matched:a},proposed:{matched:l},delta:l-a,newMatchCount:c,lostMatchCount:f,unchanged:u,newMatches:p,lostMatches:k};return j&&x&&(te.original.matchedEntities=j.size,te.proposed.matchedEntities=x.size),te}function xt(e,t,r,s){let n=e.facts,o={frameId:e.id,facts:n,originalExplain:le(t,n,s),proposedExplain:le(r,n,s)};return e.timestamp!==void 0&&(o.timestamp=e.timestamp),o}function Vr(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 $e(){console.error(`
915
+ Usage: directive replay-under --history <frames.json> --proposed <spec.json>
809
916
 
810
- Wrap the existing export in a function:
917
+ Replay a recorded fact-frame history through a proposed constraint
918
+ predicate and report how its match set differs from the original.
919
+ This is a static predicate backtest \u2014 the engine is not re-run.
811
920
 
812
- ${f.cyan("export function createSystem()")} {
813
- const sys = createSystem({ module: yourModule });
814
- sys.start();
815
- return sys;
816
- }`):new Error(`No system factory found in ${f.dim(e)}
817
- Bisect needs to instantiate a fresh system per midpoint replay. Export one of:
818
-
819
- ${f.cyan("export function createSystem()")} { ... return sys; }
820
- ${f.cyan("export const systemFactory")} = () => { ... return sys; };
821
- ${f.cyan("export default")} () => { ... return sys; };
921
+ Options:
922
+ --history <path> Recorded frames JSON (required) \u2014 a frame array,
923
+ a { frames } object, a bare fact-object array, or
924
+ a system.history.export() file
925
+ --proposed <path> Proposed predicate JSON (required)
926
+ --original <path> Original predicate JSON (required in v1)
927
+ --max-samples <n> Diff frames sampled per bucket (default 20)
928
+ --entity-key <fact> Fact key identifying an entity \u2014 also reports
929
+ distinct-entity counts (e.g. userId, sessionId)
930
+ --json Emit the PredicateBacktestReport as JSON
931
+ --help Show this help
822
932
 
823
- The factory MUST call sys.start() and return the started system.
824
- (Did you forget ${f.cyan("sys.start()")} before returning?)`)}function Dt(e){let t={json:false},r="";for(let s=0;s<e.length;s++){let o=e[s];switch(o){case "--json":t.json=true;break;case "--module":{let i=e[++s];i&&(t.module=i);break}default:o&&!o.startsWith("-")&&!r&&(r=o);}}return {filePath:r,opts:t}}function Et(e){let t=[];t.push(f.bold("Facts:"));let r=Object.entries(e);if(r.length===0)return t.push(" (none)"),t.join(`
825
- `);for(let[s,o]of r){let i=Nt(o);t.push(` ${f.cyan(s)} = ${i}`);}return t.join(`
826
- `)}function jt(e){let t=[];if(t.push(f.bold("Constraints:")),e.length===0)return t.push(" (none)"),t.join(`
827
- `);for(let r of e){let s=r.disabled?f.dim("disabled"):r.active?f.green("active"):f.dim("inactive"),o=r.hitCount>0?f.yellow(` (${r.hitCount} hits)`):"";t.push(` ${f.cyan(r.id)} ${s} priority=${r.priority}${o}`);}return t.join(`
828
- `)}function Mt(e,t){let r=[];if(r.push(f.bold("Resolvers:")),e.length===0)return r.push(" (none)"),r.join(`
829
- `);for(let s of e){let o=t[s.id],i=o?It(o.state,o.error,o.duration):f.dim("idle");r.push(` ${f.cyan(s.id)} \u2192 ${s.requirement} ${i}`);}return r.join(`
830
- `)}function Pt(e){let t=[];if(t.push(f.bold("Unmet Requirements:")),e.length===0)return t.push(` ${f.green("(all requirements met)")}`),t.join(`
831
- `);for(let r of e)t.push(` ${f.yellow(r.requirement.type)} (id: ${f.dim(r.id)}) from ${f.dim(r.fromConstraint)}`);return t.join(`
832
- `)}function qt(e){let t=[];if(t.push(f.bold("Inflight:")),e.length===0)return t.push(` ${f.green("(none)")}`),t.join(`
833
- `);let r=Date.now();for(let s of e){let o=r-s.startedAt;t.push(` ${f.cyan(s.resolverId)} \u2192 req ${f.dim(s.id)} ${f.yellow(`${o}ms`)}`);}return t.join(`
834
- `)}function It(e,t,r){let s=r!==void 0?` ${r}ms`:"";switch(e){case "resolved":return f.green(`resolved${s}`);case "errored":return f.red(`errored${s}${t?` \u2014 ${t}`:""}`);case "inflight":return f.yellow("inflight");case "cancelled":return f.dim("cancelled");default:return f.dim(e)}}function Nt(e){return e===null?f.dim("null"):e===void 0?f.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 Ft(e){let t=[];new Set(e.unmet.map(i=>i.requirement.type));new Set(e.resolverDefs.map(i=>i.requirement));for(let i of e.resolverDefs)i.requirement;for(let i of e.unmet)e.resolverDefs.some(a=>a.requirement===i.requirement.type||a.requirement==="(predicate)")||t.push(`No resolver for requirement type "${i.requirement.type}"`);return t}async function Fe(e){let{filePath:t,opts:r}=Dt(e);t||(console.error("Usage: directive inspect <file> [--json] [--module <name>]"),process.exit(1));let s=await P(t);s.isRunning||s.start();let o=s.inspect();if(r.json){let a={};if(s.facts)for(let c of Object.keys(s.facts))try{a[c]=s.facts[c];}catch{a[c]="(error reading)";}console.log(JSON.stringify({facts:a,...o},null,2)),s.stop();return}console.log(),console.log(f.bold(f.cyan("Directive System Inspection"))),console.log(f.dim("\u2500".repeat(40))),console.log();let i={};if(s.facts)for(let a of Object.keys(s.facts))try{i[a]=s.facts[a];}catch{i[a]="(error reading)";}console.log(Et(i)),console.log(),console.log(jt(o.constraints)),console.log(),console.log(Mt(o.resolverDefs,o.resolvers)),console.log(),console.log(Pt(o.unmet)),console.log(),o.inflight.length>0&&(console.log(qt(o.inflight)),console.log());let n=Ft(o);if(n.length>0){console.log(f.bold(f.yellow("Warnings:")));for(let a of n)console.log(` ${f.yellow("\u26A0")} ${a}`);console.log();}s.stop();}function Ut(e){let t={},r="",s;for(let o=0;o<e.length;o++){let i=e[o];if(i==="--module"){let n=e[++o];n&&(t.module=n);}else i&&!i.startsWith("-")&&(r?s||(s=i):r=i);}return {filePath:r,requirementId:s,opts:t}}async function We(e){let{filePath:t,requirementId:r}=Ut(e);t||(console.error("Usage: directive explain <file> [requirement-id]"),process.exit(1));let s=await P(t);s.isRunning||s.start();let o=s.inspect();if(r){let i=s.explain(r);if(!i){if(console.error(`Requirement "${r}" not found.
835
-
836
- Current requirements:`),o.unmet.length===0)console.log(f.dim(" (no unmet requirements)"));else for(let n of o.unmet)console.log(` ${f.cyan(n.id)} \u2014 ${n.requirement.type} (from ${n.fromConstraint})`);s.stop(),process.exit(1);}console.log(),console.log(f.bold(f.cyan("Requirement Explanation"))),console.log(f.dim("\u2500".repeat(40))),console.log(),console.log(i),console.log();}else if(console.log(),console.log(f.bold(f.cyan("All Requirements"))),console.log(f.dim("\u2500".repeat(40))),console.log(),o.unmet.length===0){console.log(f.green("All requirements are met.")),console.log();let i=Object.entries(o.resolvers);if(i.length>0){console.log(f.bold("Recent Resolver Activity:"));for(let[n,a]of i){let c=Ue(a.state),m=a.duration!==void 0?` (${a.duration}ms)`:"";console.log(` ${f.cyan(n)} ${c}${m}`);}console.log();}}else {console.log(`${f.yellow(String(o.unmet.length))} unmet requirement(s):
837
- `);for(let i of o.unmet){console.log(`${f.yellow("\u25CF")} ${f.bold(i.requirement.type)} (id: ${f.dim(i.id)})`),console.log(` From constraint: ${f.cyan(i.fromConstraint)}`);let n={...i.requirement};delete n.type,Object.keys(n).length>0&&console.log(` Payload: ${JSON.stringify(n)}`);let c=o.resolvers[i.id];c?console.log(` Resolver: ${Ue(c.state)}${c.error?` \u2014 ${c.error}`:""}`):o.resolverDefs.some(d=>d.requirement===i.requirement.type||d.requirement==="(predicate)")||console.log(` ${f.red("No resolver registered for this type")}`),console.log();}console.log(f.dim(`Run ${f.cyan("directive explain <file> <requirement-id>")} for detailed explanation.`));}s.stop();}function Ue(e){switch(e){case "resolved":return f.green("resolved");case "errored":return f.red("errored");case "inflight":return f.yellow("inflight");case "pending":return f.yellow("pending");case "cancelled":return f.dim("cancelled");default:return f.dim(e)}}function Gt(e){let t={ascii:false,open:true},r="";for(let s=0;s<e.length;s++){let o=e[s];switch(o){case "--ascii":t.ascii=true;break;case "--no-open":t.open=false;break;case "--output":{let i=e[++s];i&&(t.output=i);break}default:o&&!o.startsWith("-")&&!r&&(r=o);}}return {filePath:r,opts:t}}function zt(e){let t=[];t.push(f.bold("Dependency Graph")),t.push(f.dim("\u2550".repeat(50))),t.push("");let r=new Map;for(let a of e.constraints)r.set(a.id,{reqTypes:new Set,active:a.active,priority:a.priority});for(let a of e.unmet){let c=r.get(a.fromConstraint);c&&c.reqTypes.add(a.requirement.type);}let s=new Map;for(let a of e.resolverDefs)s.has(a.requirement)||s.set(a.requirement,[]),s.get(a.requirement).push(a.id);t.push(f.bold("Constraints \u2192 Requirements \u2192 Resolvers")),t.push("");for(let[a,c]of r){let m=c.active?f.green("\u25CF"):f.dim("\u25CB");if(t.push(`${m} ${f.cyan(a)} (priority: ${c.priority})`),c.reqTypes.size>0)for(let d of c.reqTypes){t.push(` \u2514\u2500\u25B6 ${f.yellow(d)}`);let l=s.get(d)||[];if(l.length>0)for(let h of l)t.push(` \u2514\u2500\u25B6 ${f.magenta(h)}`);else t.push(` \u2514\u2500\u25B6 ${f.red("(no resolver)")}`);}else t.push(` \u2514\u2500\u25B6 ${f.dim("(no active requirements)")}`);t.push("");}let o=new Set;for(let a of s.values())for(let c of a)o.add(c);if(e.resolverDefs.map(a=>a.id).filter(a=>!o.has(a)).length>0){t.push(f.bold("Standalone Resolvers:"));for(let a of e.resolverDefs)o.has(a.id)||t.push(` ${f.magenta(a.id)} handles ${f.yellow(a.requirement)}`);}return t.join(`
838
- `)}function _t(e,t){let r=[],s=[],c=Object.keys(t);for(let u=0;u<c.length;u++){let R=c[u];r.push({id:`fact-${R}`,label:R,type:"fact",x:40,y:60+u*50,color:"#3b82f6"});}for(let u=0;u<e.constraints.length;u++){let R=e.constraints[u];r.push({id:`constraint-${R.id}`,label:R.id,type:"constraint",x:260,y:60+u*50,color:R.active?"#22c55e":"#6b7280"});}let m=new Set;for(let u of e.unmet)m.add(u.requirement.type);let d=0;for(let u of m)r.push({id:`req-${u}`,label:u,type:"requirement",x:480,y:60+d*50,color:"#eab308"}),d++;for(let u=0;u<e.resolverDefs.length;u++){let R=e.resolverDefs[u];r.push({id:`resolver-${R.id}`,label:R.id,type:"resolver",x:700,y:60+u*50,color:"#a855f7"});}for(let u of e.unmet)s.push({from:`constraint-${u.fromConstraint}`,to:`req-${u.requirement.type}`});for(let u of e.resolverDefs)m.has(u.requirement)&&s.push({from:`req-${u.requirement}`,to:`resolver-${u.id}`});let l=new Map(r.map(u=>[u.id,u])),h=960,T=Math.max(...r.map(u=>u.y))+50+20,j=s.map(u=>{let R=l.get(u.from),ne=l.get(u.to);return !R||!ne?"":`<line x1="${R.x+90}" y1="${R.y+15}" x2="${ne.x}" y2="${ne.y+15}" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#arrow)"/>`}).join(`
839
- `),C=r.map(u=>`<g>
840
- <rect x="${u.x}" y="${u.y}" width="180" height="30" rx="6" fill="${u.color}" opacity="0.15" stroke="${u.color}" stroke-width="1.5"/>
841
- <text x="${u.x+90}" y="${u.y+19}" text-anchor="middle" font-size="12" font-family="monospace" fill="${u.color}">${Jt(u.label)}</text>
842
- </g>`).join(`
843
- `),tt=["Facts","Constraints","Requirements","Resolvers"].map((u,R)=>`<text x="${40+R*220+90}" y="35" text-anchor="middle" font-size="14" font-weight="bold" font-family="system-ui" fill="#e2e8f0">${u}</text>`).join(`
844
- `);return `<!DOCTYPE html>
845
- <html>
846
- <head>
847
- <title>Directive System Graph</title>
848
- <style>
849
- body { margin: 0; background: #0f172a; display: flex; justify-content: center; padding: 20px; }
850
- svg { max-width: 100%; }
851
- </style>
852
- </head>
853
- <body>
854
- <svg width="${h}" height="${T}" xmlns="http://www.w3.org/2000/svg">
855
- <defs>
856
- <marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
857
- <path d="M 0 0 L 10 5 L 0 10 z" fill="#94a3b8"/>
858
- </marker>
859
- </defs>
860
- ${tt}
861
- ${j}
862
- ${C}
863
- </svg>
864
- </body>
865
- </html>`}function Jt(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function Le(e){let{filePath:t,opts:r}=Gt(e);t||(console.error("Usage: directive graph <file> [--ascii] [--no-open] [--output <path>]"),process.exit(1));let s=await P(t);s.isRunning||s.start();let o=s.inspect();if(r.ascii){console.log(zt(o)),s.stop();return}let i={};if(s.facts)for(let c of Object.keys(s.facts))try{i[c]=s.facts[c];}catch{i[c]=null;}let n=_t(o,i),a=r.output||join(process.cwd(),".directive-graph.html");if(writeFileSync(a,n,"utf-8"),console.log(`${f.green("Generated")} ${f.dim(a)}`),r.open)try{let{execFile:c}=await import('child_process'),m=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";c(m,[a]),console.log(f.dim("Opened in browser."));}catch{console.log(f.dim(`Open ${a} in your browser to view the graph.`));}s.stop();}function Ht(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 Kt(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 Yt(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},o=Object.keys(s).filter(i=>i.startsWith("@directive-run/"));return o.length<=1?{label:"Package version compatibility",passed:true,message:o.length===0?"No packages found":"Single package"}:{label:"Package version compatibility",passed:true,message:`${o.length} packages: ${o.join(", ")}`}}function Xt(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,""),i=JSON.parse(s).compilerOptions||{},n=[];return i.strict!==!0&&n.push("strict mode not enabled"),i.moduleResolution&&!["bundler","nodenext","node16"].includes(i.moduleResolution.toLowerCase())&&n.push(`moduleResolution is "${i.moduleResolution}"`),n.length>0?{label:"TypeScript configuration",passed:!1,message:n.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 Vt(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 o=readdirSync(s);for(let i of o){let n=join(s,i,"node_modules","@directive-run","core");existsSync(n)&&r.push(`@directive-run/${i}/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 Qt(e){let t=[".cursorrules",".claude/CLAUDE.md",".github/copilot-instructions.md",".windsurfrules",".clinerules"],r=[];for(let s of t){let o=join(e,s);if(existsSync(o)){let i=readFileSync(o,"utf-8");G(i)&&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 Ge(e){let t=Ht(e);console.log(),console.log(f.bold(f.cyan("Directive Doctor"))),console.log(f.dim("\u2500".repeat(40))),console.log();let r=[Kt(t.dir),Yt(t.dir),Xt(t.dir),Vt(t.dir),Qt(t.dir)],s=0;for(let o of r){let i=o.passed?f.green("\u2713"):f.red("\u2717");console.log(`${i} ${f.bold(o.label)}`),console.log(` ${f.dim(o.message)}`),!o.passed&&o.fix&&(console.log(` ${f.yellow("Fix:")} ${o.fix}`),s++),console.log();}s>0?(console.log(f.yellow(`${s} issue(s) found. See suggested fixes above.`)),process.exit(1)):console.log(f.green("All checks passed!"));}var Je={"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 sr(e){for(let[t,r]of Object.entries(Je))if(r.includes(e))return t;return "Other"}function nr(e){let t=e.split(`
866
- `);for(let r of t){let s=r.trim();if(s.startsWith("// Example:")||s.startsWith("// Source:")||s.startsWith("// Extracted"))continue;let o=s.match(/^\*\s+(.+?)(?:\s*\*\/)?$/);if(o?.[1]&&!o[1].startsWith("@"))return o[1];if(s.startsWith("//")&&s.length>3)return s.slice(2).trim();if(s!==""&&!s.startsWith("//")&&!s.startsWith("/*")&&!s.startsWith("*"))break}return ""}async function Be(e){let t;for(let n=0;n<e.length;n++)e[n]==="--filter"&&(t=e[++n]?.toLowerCase());let r=getAllExamples();console.log(),console.log(f.bold(f.cyan("Directive Examples"))),console.log(f.dim("\u2500".repeat(50))),console.log();let s=new Map;for(let[n,a]of r){let c=sr(n);t&&!c.toLowerCase().includes(t)&&!n.includes(t)||(s.has(c)||s.set(c,[]),s.get(c).push({name:n,desc:nr(a)}));}if(s.size===0){console.log(f.dim("No examples match the filter."));return}let o=Object.keys(Je),i=[...s.keys()].sort((n,a)=>(o.indexOf(n)??99)-(o.indexOf(a)??99));for(let n of i){let a=s.get(n);console.log(f.bold(n));for(let c of a){let m=c.desc?f.dim(` \u2014 ${c.desc}`):"";console.log(` ${f.cyan(c.name)}${m}`);}console.log();}console.log(f.dim(`${r.size} examples available. Run ${f.cyan("directive examples copy <name>")} to extract one.`));}async function He(e,t){let r=process.cwd();for(let c=0;c<t.length;c++)if(t[c]==="--dest"){let m=t[++c];m&&(r=m);}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 ${f.cyan("directive examples list")} to see available examples.`),process.exit(1));let o=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"'),i=join(r,`${e}.ts`);existsSync(i)&&(console.error(`File already exists: ${relative(process.cwd(),i)}`),process.exit(1));let n=dirname(i);existsSync(n)||mkdirSync(n,{recursive:true}),writeFileSync(i,o,"utf-8");let a=relative(process.cwd(),i);console.log(`${f.green("Copied")} ${f.cyan(e)} \u2192 ${f.dim(a)}`);}async function B(e=false){try{return await import('@directive-run/timeline')}catch(t){console.error(f.red(`error: @directive-run/timeline not installed in this project.
867
- Install it: npm install --save-dev @directive-run/timeline`)),e&&console.error(f.dim(t.message)),process.exit(1);}}function cr(e){let t={json:false,dispatchableOnly:true,verbose:false},r="";for(let s=0;s<e.length;s++){let o=e[s];switch(o){case "--system":case "-s":{let i=e[++s];i&&(t.systemPath=i);break}case "--max-frames":{let i=e[++s],n=i?Number.parseInt(i,10):Number.NaN;Number.isFinite(n)&&n>0&&(t.maxFrames=n);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:o&&!o.startsWith("-")&&!r&&(r=o);}}return {jsonPath:r,opts:t}}function fe(){console.error(`
933
+ Examples:
934
+ directive replay-under --history sessions.json \\
935
+ --original current-rule.json --proposed tightened-rule.json
936
+ directive replay-under --history sessions.json \\
937
+ --original a.json --proposed b.json --entity-key userId --json
938
+ `);}function Te(e,t){let r=resolve(e);existsSync(r)||(console.error(g.red(`error: ${t} file not found: ${r}`)),process.exit(1));try{return JSON.parse(readFileSync(r,"utf8"))}catch(s){console.error(g.red(`error: failed to parse ${t} (${r}): `)+s.message),process.exit(1);}}function Yr(e){try{return Ie(e)}catch(t){console.error(g.red(`error: ${t.message}`)),process.exit(1);}}function Ct(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===0}function Et(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?g.dim(` +${r} more`):"")}function Xr(e,t){let{original:r,proposed:s,delta:n}=e,o=n>0?g.green(`+${n}`):n<0?g.red(`${n}`):g.dim("\xB10");if(console.log(`
939
+ ${g.bold("replay-under")} \u2014 predicate backtest
940
+ `),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(` ${g.green(`+${e.newMatchCount}`)} new matches ${g.dim("frames that now match the rule")}`),console.log(` ${g.red(`-${e.lostMatchCount}`)} lost matches ${g.dim("frames that no longer match")}`),e.newMatches.length>0){console.log(`
942
+ ${g.green("sample new matches:")}`);for(let l of e.newMatches.slice(0,8))console.log(` frame ${l.frameId} ${g.dim(Et(l.facts))}`);}if(e.lostMatches.length>0){console.log(`
943
+ ${g.red("sample lost matches:")}`);for(let l of e.lostMatches.slice(0,8))console.log(` frame ${l.frameId} ${g.dim(Et(l.facts))}`);}let i=e.newMatches.length+e.lostMatches.length,a=e.newMatchCount+e.lostMatchCount;i<a&&console.log(g.dim(`
944
+ ${i} of ${a} diff frames sampled \u2014 --json for the full report`)),console.log("");}async function Dt(e){(e.includes("--help")||e.length===0)&&($e(),process.exit(e.length===0?1:0));let t=Vr(e);t.historyPath||(console.error(g.red("error: --history <frames.json> is required")),$e(),process.exit(1)),t.proposedPath||(console.error(g.red("error: --proposed <spec.json> is required")),$e(),process.exit(1)),t.originalPath||(console.error(g.red("error: --original <spec.json> is required")+g.dim("\n (v1 cannot recover the constraint's current `when` from a live system)")),$e(),process.exit(1));let r=Yr(Te(t.historyPath,"--history")),s=Te(t.originalPath,"--original"),n=Te(t.proposedPath,"--proposed");Ct(s)&&console.error(g.yellow("warning: --original is an empty predicate {} \u2014 it matches every frame")),Ct(n)&&console.error(g.yellow("warning: --proposed is an empty predicate {} \u2014 it matches every frame"));let o;try{o=Rt({frames:r,original:s,proposed:n,maxSamples:t.maxSamples,entityKey:t.entityKey});}catch(i){console.error(g.red(`error: ${i.message}`)),process.exit(1);}if(t.json){console.log(JSON.stringify(o,null,2));return}Xr(o,t.entityKey);}function tn(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 Pe(){console.error(`
868
945
  Usage: directive replay <timeline.json> [options]
869
946
 
870
947
  Replay a serialized Directive timeline against a fresh system.
@@ -886,55 +963,8 @@ Examples:
886
963
  directive replay bug-1234.json --system src/app/system.ts
887
964
  directive replay error.json --system src/system.ts --json
888
965
  directive replay error.json --system src/system.ts --verbose
889
- `);}async function Ye(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(fe(),process.exit(e.length===0?1:0));let{jsonPath:t,opts:r}=cr(e);t||(console.error(f.red("error: missing <timeline.json> argument")),fe(),process.exit(1)),r.systemPath||(console.error(f.red("error: --system <path> is required"),f.dim(`
890
- (replay needs a fresh system to dispatch against)`)),fe(),process.exit(1));let s=resolve(t);existsSync(s)||(console.error(f.red(`error: timeline file not found: ${s}`)),process.exit(1));let o;try{o=readFileSync(s,"utf8");}catch(h){console.error(f.red(`error: failed to read ${s}: ${h.message}`)),process.exit(1);}let i;try{i=JSON.parse(o);}catch(h){console.error(f.red(`error: ${s} is not valid JSON: ${h.message}`)),process.exit(1);}let{deserializeTimeline:n,replayTimeline:a}=await B(r.verbose),c;try{c=n(i);}catch(h){console.error(f.red(`error: timeline JSON failed validation: ${h.message}`)),process.exit(1);}let m;try{m=await P(r.systemPath);}catch(h){console.error(f.red(`error: failed to load system file: ${h.message}`)),process.exit(1);}let d=m;if(typeof d.dispatch!="function"&&(console.error(f.red("error: loaded system has no dispatch() method. The --system file must export a started Directive system or a factory.")),process.exit(1)),typeof d.start=="function")try{d.start();}catch{}let l=await a(c,d,{dispatchableOnly:r.dispatchableOnly,maxFrames:r.maxFrames});if(r.json)console.log(JSON.stringify(l,null,2));else {let{dispatched:h,skipped:T,truncated:j}=l,C=h>0;console.log(`${C?f.green("\u2713"):f.yellow("\u26A0")} replay complete:`,f.bold(`${h} dispatched`),f.dim(`/ ${T} skipped`),j>0?f.yellow(`/ ${j} TRUNCATED`):""),h===0&&console.error(f.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.")),j>0&&console.error(f.yellow(`warning: ${j} frames truncated by --max-frames cap. Raise it with --max-frames <n> if you need them.`));}process.exit(0);}function dr(e){let t={json:false,noDeterminismCheck:false,verbose:false},r="";for(let s=0;s<e.length;s++){let o=e[s];switch(o){case "--system":case "-s":{let i=e[++s];i&&(t.systemPath=i);break}case "--assert":case "-a":{let i=e[++s];i&&(t.assertExpr=i);break}case "--max-frames":{let i=e[++s],n=i?Number.parseInt(i,10):Number.NaN;Number.isFinite(n)&&n>0&&(t.maxFrames=n);break}case "--no-determinism-check":t.noDeterminismCheck=true;break;case "--json":t.json=true;break;case "--verbose":case "-v":t.verbose=true;break;default:o&&!o.startsWith("-")&&!r&&(r=o);}}return {jsonPath:r,opts:t}}function se(){console.error(`
891
- Usage: directive bisect <timeline.json> --system <factory.ts> --assert <expr>
892
-
893
- Binary-search a recorded timeline for the first frame that triggers a
894
- failing assertion \u2014 git-bisect, but over ObservationEvent frames.
895
-
896
- Arguments:
897
- <timeline.json> Path to a timeline produced by serializeTimeline()
898
-
899
- Options:
900
- --system, -s <path> TypeScript file exporting a system factory
901
- (createSystem / systemFactory / default).
902
- The factory must return a started Directive
903
- system; bisect calls it once per midpoint.
904
- --assert, -a <expression> JS expression with 'facts' and 'system' in
905
- scope. Truthy = good prefix, falsy = bad
906
- prefix. Bisect finds the smallest bad prefix.
907
- --max-frames <n> Per-replay frame cap (default 100,000)
908
- --no-determinism-check Skip the "replay-twice and compare" gate
909
- before bisecting. Use only on timelines you
910
- know are deterministic.
911
- --json Emit BisectResult as JSON
912
- --verbose, -v Print every midpoint and its verdict
913
- --help, -h Show this help
914
-
915
- SECURITY: --assert is evaluated as JavaScript in this process. Only
916
- pass expressions from sources you trust (your own scripts, your own
917
- PRs). Don't paste expressions from issues, untrusted Slack messages,
918
- or third-party sources without reading them first.
919
-
920
- Examples:
921
- directive bisect bug-1234.json --system test/bisect-sys.ts \\
922
- --assert 'facts.count >= 0'
923
-
924
- directive bisect crash.json -s factory.ts -a 'facts.status !== "error"' --json
925
- `);}function pr(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}
926
- expression: ${e}`)}return r=>{let s=r?.facts;return !!t(s,r)}}async function Xe(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(se(),process.exit(e.length===0?1:0));let{jsonPath:t,opts:r}=dr(e);t||(console.error(f.red("error: missing <timeline.json> argument")),se(),process.exit(1)),r.systemPath||(console.error(f.red("error: --system <path> is required"),f.dim(`
927
- (bisect needs a factory to instantiate a fresh system per midpoint)`)),se(),process.exit(1)),r.assertExpr||(console.error(f.red("error: --assert <expression> is required"),f.dim(`
928
- (assertion distinguishes 'good' from 'bad' system state)`)),se(),process.exit(1));let s=resolve(t);existsSync(s)||(console.error(f.red(`error: timeline file not found: ${s}`)),process.exit(1));let o;try{o=readFileSync(s,"utf8");}catch(C){console.error(f.red(`error: failed to read ${s}: ${C.message}`)),process.exit(1);}let i;try{i=JSON.parse(o);}catch(C){console.error(f.red(`error: ${s} is not valid JSON: ${C.message}`)),process.exit(1);}let{deserializeTimeline:n,bisectTimeline:a}=await B(r.verbose),c;try{c=n(i);}catch(C){console.error(f.red(`error: timeline JSON failed validation: ${C.message}`)),process.exit(1);}let m;try{m=pr(r.assertExpr);}catch(C){console.error(f.red(`error: ${C.message}`)),process.exit(1);}let d;try{d=await Ne(r.systemPath);}catch(C){console.error(f.red(`error: failed to load system factory: ${C.message}`)),process.exit(1);}r.verbose&&console.error(f.dim(`bisecting ${c.frames.length} frames with assertion: ${r.assertExpr}`));let l=await a(c,d,m,{maxFrames:r.maxFrames,determinismCheck:!r.noDeterminismCheck});if(r.json){let C={firstFailingFrameIndex:l.firstFailingFrameIndex??null,iterations:l.iterations,noFailureFound:l.noFailureFound,failsOnEmptyReplay:l.failsOnEmptyReplay,nonDeterministic:l.nonDeterministic};console.log(JSON.stringify(C,null,2)),process.exit(0);}l.nonDeterministic&&(console.error(f.red("\u2717 bisect aborted: timeline is non-deterministic")),console.error(f.dim(` Two full-timeline replays produced different oracle verdicts.
929
- Bisection is unreliable on non-deterministic timelines.
930
- Either fix the timeline source (deterministic clocks/seeds)
931
- or re-run with --no-determinism-check if you accept the risk.`)),process.exit(2)),l.noFailureFound&&(console.error(f.yellow("\u26A0 no failure to bisect: assertion passes on the full timeline")),console.error(f.dim(` The recorded timeline does not exhibit the bug your
932
- --assert expression checks. Verify the assertion or
933
- try a different bad.json.`)),process.exit(0)),l.failsOnEmptyReplay&&(console.error(f.yellow("\u26A0 assertion fails BEFORE any frame replays \u2014 bug is in initialization")),console.error(f.dim(` The freshly-started system already violates the assertion.
934
- Bisect cannot narrow further. Inspect the system factory
935
- or initial fact values.`)),process.exit(0));let h=l.firstFailingFrameIndex??-1,T=l.firstFailingFrame,j=T?.event.type??"<unknown>";console.log(`${f.green("\u2713")} bisect complete: ${f.bold(`first failing frame is #${h}`)} ${f.dim(`(${j})`)}`),console.log(f.dim(` \u2022 iterations: ${l.iterations} | timeline frames: ${c.frames.length}`)),r.verbose&&T&&(console.log(f.dim(" \u2022 frame:")),console.log(f.dim(` ${JSON.stringify(T,null,2).split(`
936
- `).join(`
937
- `)}`))),process.exit(2);}function yr(e){let t={json:false,verbose:false},r=[];for(let s=0;s<e.length;s++){let o=e[s];switch(o){case "--json":t.json=true;break;case "--verbose":case "-v":t.verbose=true;break;default:o&&!o.startsWith("-")&&r.push(o);}}return {aPath:r[0]??"",bPath:r[1]??"",opts:t}}function Ve(){console.error(`
966
+ `);}async function jt(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(Pe(),process.exit(e.length===0?1:0));let{jsonPath:t,opts:r}=tn(e);t||(console.error(g.red("error: missing <timeline.json> argument")),Pe(),process.exit(1)),r.systemPath||(console.error(g.red("error: --system <path> is required"),g.dim(`
967
+ (replay needs a fresh system to dispatch against)`)),Pe(),process.exit(1));let s=resolve(t);existsSync(s)||(console.error(g.red(`error: timeline file not found: ${s}`)),process.exit(1));let n;try{n=readFileSync(s,"utf8");}catch(p){console.error(g.red(`error: failed to read ${s}: ${p.message}`)),process.exit(1);}let o;try{o=JSON.parse(n);}catch(p){console.error(g.red(`error: ${s} is not valid JSON: ${p.message}`)),process.exit(1);}let{deserializeTimeline:i,replayTimeline:a}=await X(r.verbose),l;try{l=i(o);}catch(p){console.error(g.red(`error: timeline JSON failed validation: ${p.message}`)),process.exit(1);}let c;try{c=await P(r.systemPath);}catch(p){console.error(g.red(`error: failed to load system file: ${p.message}`)),process.exit(1);}let f=c;if(typeof f.dispatch!="function"&&(console.error(g.red("error: loaded system has no dispatch() method. The --system file must export a started Directive system or a factory.")),process.exit(1)),typeof f.start=="function")try{f.start();}catch{}let u=await a(l,f,{dispatchableOnly:r.dispatchableOnly,maxFrames:r.maxFrames});if(r.json)console.log(JSON.stringify(u,null,2));else {let{dispatched:p,skipped:k,truncated:j}=u,x=p>0;console.log(`${x?g.green("\u2713"):g.yellow("\u26A0")} replay complete:`,g.bold(`${p} dispatched`),g.dim(`/ ${k} skipped`),j>0?g.yellow(`/ ${j} TRUNCATED`):""),p===0&&console.error(g.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.")),j>0&&console.error(g.yellow(`warning: ${j} frames truncated by --max-frames cap. Raise it with --max-frames <n> if you need them.`));}process.exit(0);}function on(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 Ot(){console.error(`
938
968
  Usage: directive timeline diff <a.json> <b.json>
939
969
 
940
970
  Compare two serialized Directive timelines as a structured causal-graph
@@ -958,10 +988,10 @@ Exit codes:
958
988
  Examples:
959
989
  directive timeline diff baseline.json regression.json
960
990
  directive timeline diff a.json b.json --json | jq .constraintFires
961
- `);}function X(e){return e>0?f.green(`+${e}`):e<0?f.red(`${e}`):f.dim(" 0")}function Qe(e){return e.length===0?[f.dim(" (no differences)")]:e.map(t=>` ${f.bold(t.id.padEnd(28))} ${String(t.aCount).padStart(4)} \u2192 ${String(t.bCount).padStart(4)} (${X(t.delta)})`)}function vr(e){return e.length===0?[f.dim(" (no differences)")]:e.map(t=>` ${f.bold(t.resolver.padEnd(28))} starts ${t.aStarts}\u2192${t.bStarts} (${X(t.bStarts-t.aStarts)}) completes ${t.aCompletes}\u2192${t.bCompletes} (${X(t.bCompletes-t.aCompletes)}) errors ${t.aErrors}\u2192${t.bErrors} (${X(t.bErrors-t.aErrors)})`)}function br(e){return e.length===0?[f.dim(" (no new errors)")]:e.map(t=>{let r=t.side==="a"?f.cyan("a-only"):f.yellow("b-only"),s=(()=>{try{return JSON.stringify(t.error)}catch{return `[${typeof t.error}]`}})();return ` ${r} frame #${t.frameIndex} ${f.bold(t.kind)} '${t.id}' ${f.dim(s)}`})}function Ze(e){let t=resolve(e);existsSync(t)||(console.error(f.red(`error: timeline file not found: ${t}`)),process.exit(1));let r;try{r=readFileSync(t,"utf8");}catch(s){console.error(f.red(`error: failed to read ${t}: ${s.message}`)),process.exit(1);}try{return JSON.parse(r)}catch(s){console.error(f.red(`error: ${t} is not valid JSON: ${s.message}`)),process.exit(1);}}async function et(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(Ve(),process.exit(e.length===0?1:0));let{aPath:t,bPath:r,opts:s}=yr(e);(!t||!r)&&(console.error(f.red("error: both <a.json> and <b.json> are required")),Ve(),process.exit(1));let{deserializeTimeline:o,diffTimelines:i}=await B(s.verbose),n=Ze(t),a=Ze(r),c,m;try{c=o(n),m=o(a);}catch(l){console.error(f.red(`error: timeline JSON failed validation: ${l.message}`)),process.exit(1);}let d=i(c,m);s.json&&(console.log(JSON.stringify(d,null,2)),process.exit(d.identical?0:2)),d.identical&&(console.log(f.green("\u2713 identical:"),`both timelines have ${d.aFrameCount} frames and the same causal shape.`),process.exit(0)),console.log(f.bold("Timeline diff"),f.dim(`(${t} vs ${r})`)),console.log(""),console.log(`Frames: ${d.aFrameCount} \u2192 ${d.bFrameCount} (${X(d.frameCountDelta)})`),console.log(""),console.log(f.bold("Constraint fires:"));for(let l of Qe(d.constraintFires))console.log(l);console.log(""),console.log(f.bold("Mutations:"));for(let l of Qe(d.mutations))console.log(l);console.log(""),console.log(f.bold("Resolver runs:"));for(let l of vr(d.resolverRuns))console.log(l);console.log(""),console.log(f.bold("New errors:"));for(let l of br(d.newErrors))console.log(l);console.log(""),process.exit(2);}var wr=`
962
- ${x} \u2014 CLI tools for Directive
991
+ `);}function ce(e){return e>0?g.green(`+${e}`):e<0?g.red(`${e}`):g.dim(" 0")}function At(e){return e.length===0?[g.dim(" (no differences)")]:e.map(t=>` ${g.bold(t.id.padEnd(28))} ${String(t.aCount).padStart(4)} \u2192 ${String(t.bCount).padStart(4)} (${ce(t.delta)})`)}function an(e){return e.length===0?[g.dim(" (no differences)")]:e.map(t=>` ${g.bold(t.resolver.padEnd(28))} starts ${t.aStarts}\u2192${t.bStarts} (${ce(t.bStarts-t.aStarts)}) completes ${t.aCompletes}\u2192${t.bCompletes} (${ce(t.bCompletes-t.aCompletes)}) errors ${t.aErrors}\u2192${t.bErrors} (${ce(t.bErrors-t.aErrors)})`)}function ln(e){return e.length===0?[g.dim(" (no new errors)")]:e.map(t=>{let r=t.side==="a"?g.cyan("a-only"):g.yellow("b-only"),s=(()=>{try{return JSON.stringify(t.error)}catch{return `[${typeof t.error}]`}})();return ` ${r} frame #${t.frameIndex} ${g.bold(t.kind)} '${t.id}' ${g.dim(s)}`})}function Mt(e){let t=resolve(e);existsSync(t)||(console.error(g.red(`error: timeline file not found: ${t}`)),process.exit(1));let r;try{r=readFileSync(t,"utf8");}catch(s){console.error(g.red(`error: failed to read ${t}: ${s.message}`)),process.exit(1);}try{return JSON.parse(r)}catch(s){console.error(g.red(`error: ${t} is not valid JSON: ${s.message}`)),process.exit(1);}}async function qt(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(Ot(),process.exit(e.length===0?1:0));let{aPath:t,bPath:r,opts:s}=on(e);(!t||!r)&&(console.error(g.red("error: both <a.json> and <b.json> are required")),Ot(),process.exit(1));let{deserializeTimeline:n,diffTimelines:o}=await X(s.verbose),i=Mt(t),a=Mt(r),l,c;try{l=n(i),c=n(a);}catch(u){console.error(g.red(`error: timeline JSON failed validation: ${u.message}`)),process.exit(1);}let f=o(l,c);s.json&&(console.log(JSON.stringify(f,null,2)),process.exit(f.identical?0:2)),f.identical&&(console.log(g.green("\u2713 identical:"),`both timelines have ${f.aFrameCount} frames and the same causal shape.`),process.exit(0)),console.log(g.bold("Timeline diff"),g.dim(`(${t} vs ${r})`)),console.log(""),console.log(`Frames: ${f.aFrameCount} \u2192 ${f.bFrameCount} (${ce(f.frameCountDelta)})`),console.log(""),console.log(g.bold("Constraint fires:"));for(let u of At(f.constraintFires))console.log(u);console.log(""),console.log(g.bold("Mutations:"));for(let u of At(f.mutations))console.log(u);console.log(""),console.log(g.bold("Resolver runs:"));for(let u of an(f.resolverRuns))console.log(u);console.log(""),console.log(g.bold("New errors:"));for(let u of ln(f.newErrors))console.log(u);console.log(""),process.exit(2);}var cn=`
992
+ ${R} \u2014 CLI tools for Directive
963
993
 
964
- Usage: ${x} <command> [options]
994
+ Usage: ${R} <command> [options]
965
995
 
966
996
  Commands:
967
997
  init Project scaffolding wizard
@@ -978,6 +1008,8 @@ Commands:
978
1008
  examples copy <name> Extract example to project
979
1009
  replay <timeline.json> Replay a serialized Directive timeline
980
1010
  (paired with @directive-run/timeline)
1011
+ replay-under --history ... Predicate backtest \u2014 diff a proposed
1012
+ predicate against recorded history
981
1013
  bisect <timeline.json> Binary-search a timeline for the first
982
1014
  frame that triggers a failing assertion
983
1015
  timeline diff <a> <b> Semantic causal-graph diff between two
@@ -1015,14 +1047,14 @@ ai-rules init options:
1015
1047
  examples options:
1016
1048
  --filter <category> Filter by category or name
1017
1049
  --dest <dir> Destination directory for copy
1018
- `.trim();async function xr(){let e=process.argv.slice(2);if((e.length===0||e.includes("--help")||e.includes("-h"))&&(console.log(wr),process.exit(0)),e.includes("--version")||e.includes("-v")){let{readFileSync:r}=await import('fs'),{fileURLToPath:s}=await import('url'),{dirname:o,join:i}=await import('path'),n=o(s(import.meta.url)),a=JSON.parse(r(i(n,"..","package.json"),"utf-8"));console.log(a.version),process.exit(0);}let t=e[0];switch(t){case "init":{await Ae(e.slice(1));break}case "new":{let r=e[1],s=e[2];r==="module"?(s||(console.error("Usage: directive new module <name>"),process.exit(1)),await Me(s,e.slice(3))):r==="orchestrator"?(s||(console.error("Usage: directive new orchestrator <name>"),process.exit(1)),await Pe(s,e.slice(3))):(console.error(`Unknown subcommand: ${r??"(none)"}
1019
- Usage: ${x} new module <name>
1020
- ${x} new orchestrator <name>`),process.exit(1));break}case "inspect":{await Fe(e.slice(1));break}case "explain":{await We(e.slice(1));break}case "graph":{await Le(e.slice(1));break}case "doctor":{await Ge(e.slice(1));break}case "ai-rules":{let r=e[1];r==="init"?await Se(e.slice(2)):r==="update"?await Ce(e.slice(2)):r==="check"?await Re(e.slice(2)):(console.error(`Unknown subcommand: ${r??"(none)"}
1021
- Usage: ${x} ai-rules init
1022
- ${x} ai-rules update
1023
- ${x} ai-rules check`),process.exit(1));break}case "examples":{let r=e[1];if(r==="list")await Be(e.slice(2));else if(r==="copy"){let s=e[2];s||(console.error("Usage: directive examples copy <name>"),process.exit(1)),await He(s,e.slice(3));}else console.error(`Unknown subcommand: ${r??"(none)"}
1024
- Usage: ${x} examples list [--filter <category>]
1025
- ${x} examples copy <name> [--dest <dir>]`),process.exit(1);break}case "replay":{await Ye(e.slice(1));break}case "bisect":{await Xe(e.slice(1));break}case "timeline":{let r=e[1];r==="diff"?await et(e.slice(2)):(console.error(`Unknown subcommand: ${r??"(none)"}
1026
- Usage: ${x} timeline diff <a.json> <b.json>`),process.exit(1));break}default:console.error(`Unknown command: ${t}
1027
- Run '${x} --help' for usage.`),process.exit(1);}}xr().catch(e=>{console.error(e.message||e),process.exit(1);});//# sourceMappingURL=cli.js.map
1050
+ `.trim();async function un(){let e=process.argv.slice(2),t=e[0];if((e.length===0||t==="--help"||t==="-h")&&(console.log(cn),process.exit(0)),t==="--version"||t==="-v"){let{readFileSync:n}=await import('fs'),{fileURLToPath:o}=await import('url'),{dirname:i,join:a}=await import('path'),l=i(o(import.meta.url)),c=JSON.parse(n(a(l,"..","package.json"),"utf-8"));console.log(c.version),process.exit(0);}let s=e[0];switch(s){case "init":{await ct(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 ht(o,e.slice(3))):n==="orchestrator"?(o||(console.error("Usage: directive new orchestrator <name>"),process.exit(1)),await yt(o,e.slice(3))):(console.error(`Unknown subcommand: ${n??"(none)"}
1051
+ Usage: ${R} new module <name>
1052
+ ${R} new orchestrator <name>`),process.exit(1));break}case "inspect":{await ut(e.slice(1));break}case "explain":{await at(e.slice(1));break}case "graph":{await lt(e.slice(1));break}case "doctor":{await et(e.slice(1));break}case "ai-rules":{let n=e[1];n==="init"?await Je(e.slice(2)):n==="update"?await Ge(e.slice(2)):n==="check"?await He(e.slice(2)):(console.error(`Unknown subcommand: ${n??"(none)"}
1053
+ Usage: ${R} ai-rules init
1054
+ ${R} ai-rules update
1055
+ ${R} ai-rules check`),process.exit(1));break}case "examples":{let n=e[1];if(n==="list")await st(e.slice(2));else if(n==="copy"){let o=e[2];o||(console.error("Usage: directive examples copy <name>"),process.exit(1)),await it(o,e.slice(3));}else console.error(`Unknown subcommand: ${n??"(none)"}
1056
+ Usage: ${R} examples list [--filter <category>]
1057
+ ${R} examples copy <name> [--dest <dir>]`),process.exit(1);break}case "replay":{await jt(e.slice(1));break}case "replay-under":{await Dt(e.slice(1));break}case "bisect":{await Qe(e.slice(1));break}case "timeline":{let n=e[1];n==="diff"?await qt(e.slice(2)):(console.error(`Unknown subcommand: ${n??"(none)"}
1058
+ Usage: ${R} timeline diff <a.json> <b.json>`),process.exit(1));break}default:console.error(`Unknown command: ${s}
1059
+ Run '${R} --help' for usage.`),process.exit(1);}}un().catch(e=>{console.error(e.message||e),process.exit(1);});//# sourceMappingURL=cli.js.map
1028
1060
  //# sourceMappingURL=cli.js.map