@directive-run/cli 1.3.0 → 1.5.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 u from'@clack/prompts';import {existsSync,mkdirSync,writeFileSync,readFileSync,readdirSync}from'fs';import {join,relative,dirname,resolve}from'path';import d from'picocolors';import {getAllExamples,getExample,getKnowledge}from'@directive-run/knowledge';var y="directive";var _="<!-- directive:start -->",W="<!-- directive:end -->";var J=[{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 ae(e){let t=[];for(let r of J)r.signals.some(o=>existsSync(join(e,o)))&&t.push({name:r.name,id:r.id,outputPath:join(e,r.outputPath)});return t}function L(e){let t=J.find(r=>r.id===e);if(!t)throw new Error(`Unknown tool: ${e}`);return t}function ce(){return J.map(e=>e.id)}function I(e,t){let r=e.indexOf(_),s=e.indexOf(W),o=`${_}
2
+ import {existsSync,readFileSync,mkdirSync,writeFileSync,readdirSync}from'fs';import {resolve,join,relative,dirname}from'path';import*as p from'@clack/prompts';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}
3
3
  ${t}
4
- ${W}`;if(r!==-1&&s!==-1&&s>r)return e.slice(0,r)+o+e.slice(s+W.length);let i=e.endsWith(`
4
+ ${H}`;if(r!==-1&&s!==-1&&s>r)return e.slice(0,r)+o+e.slice(s+H.length);let i=e.endsWith(`
5
5
  `)?`
6
6
  `:`
7
7
 
8
8
  `;return e+i+o+`
9
- `}function P(e){return e.includes(_)&&e.includes(W)}var Fe=[{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 Fe)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 me(){let e=getKnowledge("core-patterns"),t=getKnowledge("anti-patterns"),r=getKnowledge("naming"),s=getKnowledge("schema-types");return `# Directive \u2014 Complete AI Coding Rules
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
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 z(){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 E(){return z()+"\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 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"+`
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 pe(){return E()}function fe(){return E()}var ze={cursor:z,claude:me,copilot:E,windsurf:fe,cline:pe};function H(e){let t=ze[e];if(!t)throw new Error(`No template for tool: ${e}`);return t()}function te(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 ge(e){let t=te(e);u.intro(d.bgCyan(d.black(" directive ai-rules ")));let r=ue(t.dir),s=t.dir;if(r.isMonorepo&&r.rootDir!==t.dir){let n=await u.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)})`}]});u.isCancel(n)&&(u.cancel("Cancelled."),process.exit(0)),n==="root"&&(s=r.rootDir);}let o;if(t.tools.length>0)o=t.tools.map(n=>{let a=L(n);return {name:a.name,id:a.id,outputPath:join(s,a.outputPath)}});else {let n=ae(s);if(n.length>0){let a=await u.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});u.isCancel(a)&&(u.cancel("Cancelled."),process.exit(0)),o=a.map(c=>{let m=L(c);return {name:m.name,id:m.id,outputPath:join(s,m.outputPath)}});}else {let a=await u.multiselect({message:"No AI tools detected. Which tools do you use?",options:ce().map(c=>{let m=L(c);return {value:c,label:m.name}}),required:true});u.isCancel(a)&&(u.cancel("Cancelled."),process.exit(0)),o=a.map(c=>{let m=L(c);return {name:m.name,id:m.id,outputPath:join(s,m.outputPath)}});}}o.length===0&&(u.cancel("No tools selected."),process.exit(0));let i=u.spinner();for(let n of o){i.start(`Generating ${n.name} rules...`);let a=H(n.id),c=n.outputPath,m=existsSync(c);if(i.stop(`Generated ${n.name} rules.`),m&&!t.force){let w=readFileSync(c,"utf-8");if(t.merge){T(c,I(w,a)),u.log.success(`${d.green("Merged")} Directive section into ${d.dim(relative(s,c))}`);continue}if(P(w)){let f=await u.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"}]});u.isCancel(f)&&(u.cancel("Cancelled."),process.exit(0)),f==="merge"?(T(c,I(w,a)),u.log.success(`${d.green("Updated")} ${d.dim(relative(s,c))}`)):f==="overwrite"?(T(c,a),u.log.success(`${d.green("Wrote")} ${d.dim(relative(s,c))}`)):u.log.info(`Skipped ${d.dim(relative(s,c))}`);}else {let f=await u.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"}]});u.isCancel(f)&&(u.cancel("Cancelled."),process.exit(0)),f==="append"?(T(c,I(w,a)),u.log.success(`${d.green("Appended")} to ${d.dim(relative(s,c))}`)):f==="overwrite"?(T(c,a),u.log.success(`${d.green("Wrote")} ${d.dim(relative(s,c))}`)):u.log.info(`Skipped ${d.dim(relative(s,c))}`);}}else T(c,a),u.log.success(`${d.green("Created")} ${d.dim(relative(s,c))}`);}u.outro(`Done! Run ${d.cyan(`${y} ai-rules init --merge`)} anytime to update.`);}function T(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}async function he(e){let r=te(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(!P(n))continue;let a=H(i.id),c=I(n,a);T(i.path,c),console.log(`${d.green("Updated")} ${d.dim(relative(r,i.path))}`),o++;}console.log(o===0?d.dim(`No existing rule files found. Run ${d.cyan(`${y} ai-rules init`)} first.`):d.green(`
263
- Updated ${o} file(s) to latest knowledge version.`));}async function ye(e){let r=te(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(!P(a))continue;o++;let c=H(n.id);I(a,c)!==a?(console.log(`${d.red("\u2717")} ${n.name} rules are ${d.yellow("stale")}`),i++):console.log(`${d.green("\u2713")} ${n.name} rules are ${d.green("current")}`);}if(o===0){console.log(d.dim("No rule files found to check."));return}i>0?(console.log(`
264
- ${d.yellow(`${i} file(s) are stale.`)} Run ${d.cyan(`${y} ai-rules update`)} to refresh.`),process.exit(1)):console.log(d.green(`
265
- All rule files are current.`));}function Qe(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 Ze(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 et(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 re(e){return {counter:{id:"counter",label:"Counter (minimal)",hint:"schema + init + derive + events \u2014 simplest starting point",files:[{path:`src/${e}.ts`,content:tt(e)},{path:"src/main.ts",content:rt(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:st(e)},{path:"src/main.ts",content:nt(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:ot(e)},{path:"src/main.ts",content:it(e)}],deps:["@directive-run/core","@directive-run/ai"]}}}function tt(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
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.`));}async function M(e){let t=resolve(e);if(!existsSync(t))throw new Error(`File not found: ${t}`);try{let r=await import(t);if(r.default&&I(r.default))return r.default;if(r.system&&I(r.system))return r.system;for(let s of Object.keys(r))if(I(r[s]))return r[s];throw new Error(`No Directive system found in ${f.dim(e)}
266
+ Export a system as default or named "system":
267
+
268
+ ${f.cyan("export default")} createSystem({ module: myModule });
269
+ ${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)}
270
+
271
+ Make sure the file is valid TypeScript and tsx is installed:
272
+ ${f.cyan("npm install -D tsx")}`)}}function I(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 Oe(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)}
273
+
274
+ Make sure the file is valid TypeScript and tsx is installed:
275
+ ${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(!I(a))throw new Error(`Factory '${i}' from ${f.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 I(r.default)||I(r.system)||Object.values(r).some(I)?new Error(`Found a started Directive system in ${f.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 ${f.cyan("directive replay")} does.
279
+
280
+ Wrap the existing export in a function:
281
+
282
+ ${f.cyan("export function createSystem()")} {
283
+ const sys = createSystem({ module: yourModule });
284
+ sys.start();
285
+ return sys;
286
+ }`):new Error(`No system factory found in ${f.dim(e)}
287
+ Bisect needs to instantiate a fresh system per midpoint replay. Export one of:
288
+
289
+ ${f.cyan("export function createSystem()")} { ... return sys; }
290
+ ${f.cyan("export const systemFactory")} = () => { ... return sys; };
291
+ ${f.cyan("export default")} () => { ... return sys; };
292
+
293
+ The factory MUST call sys.start() and return the started system.
294
+ (Did you forget ${f.cyan("sys.start()")} before returning?)`)}async function _(e=false){try{return await import('@directive-run/timeline')}catch(t){console.error(f.red(`error: @directive-run/timeline not installed in this project.
295
+ Install it: npm install --save-dev @directive-run/timeline`)),e&&console.error(f.dim(t.message)),process.exit(1);}}function ft(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 te(){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 Ee(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(te(),process.exit(e.length===0?1:0));let{jsonPath:t,opts:r}=ft(e);t||(console.error(f.red("error: missing <timeline.json> argument")),te(),process.exit(1)),r.systemPath||(console.error(f.red("error: --system <path> is required"),f.dim(`
332
+ (bisect needs a factory to instantiate a fresh system per midpoint)`)),te(),process.exit(1)),r.assertExpr||(console.error(f.red("error: --assert <expression> is required"),f.dim(`
333
+ (assertion distinguishes 'good' from 'bad' system state)`)),te(),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 _(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=gt(r.assertExpr);}catch(C){console.error(f.red(`error: ${C.message}`)),process.exit(1);}let d;try{d=await Oe(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.
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)),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
337
+ --assert expression checks. Verify the assertion or
338
+ 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.
339
+ Bisect cannot narrow further. Inspect the system factory
340
+ 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(`
341
+ `).join(`
342
+ `)}`))),process.exit(2);}function yt(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 vt(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 bt(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 wt(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 xt(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 $t(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 je(e){let t=yt(e);console.log(),console.log(f.bold(f.cyan("Directive Doctor"))),console.log(f.dim("\u2500".repeat(40))),console.log();let r=[vt(t.dir),bt(t.dir),wt(t.dir),xt(t.dir),$t(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 qe={"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 At(e){for(let[t,r]of Object.entries(qe))if(r.includes(e))return t;return "Other"}function Tt(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 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 Ie(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=At(n);t&&!c.toLowerCase().includes(t)&&!n.includes(t)||(s.has(c)||s.set(c,[]),s.get(c).push({name:n,desc:Tt(a)}));}if(s.size===0){console.log(f.dim("No examples match the filter."));return}let o=Object.keys(qe),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 Ne(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)}`);}function Ot(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 Ue(e){let{filePath:t,requirementId:r}=Ot(e);t||(console.error("Usage: directive explain <file> [requirement-id]"),process.exit(1));let s=await M(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.
344
+
345
+ 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=Fe(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):
346
+ `);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: ${Fe(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 Fe(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 jt(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 Mt(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(`
347
+ `)}function Pt(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(`
348
+ `),C=r.map(u=>`<g>
349
+ <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"/>
350
+ <text x="${u.x+90}" y="${u.y+19}" text-anchor="middle" font-size="12" font-family="monospace" fill="${u.color}">${qt(u.label)}</text>
351
+ </g>`).join(`
352
+ `),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(`
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="${h}" height="${T}" 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
+ ${tt}
370
+ ${j}
371
+ ${C}
372
+ </svg>
373
+ </body>
374
+ </html>`}function qt(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function We(e){let{filePath:t,opts:r}=jt(e);t||(console.error("Usage: directive graph <file> [--ascii] [--no-open] [--output <path>]"),process.exit(1));let s=await M(t);s.isRunning||s.start();let o=s.inspect();if(r.ascii){console.log(Mt(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=Pt(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 Wt(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 Lt(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 Gt(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:zt(e)},{path:"src/main.ts",content:_t(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:Jt(e)},{path:"src/main.ts",content:Bt(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:Ht(e)},{path:"src/main.ts",content:Kt(e)}],deps:["@directive-run/core","@directive-run/ai"]}}}function zt(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 ${B(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 rt(e){let t=j(e);return `import { createSystem } from "@directive-run/core";
421
+ `}function _t(e){let t=B(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 st(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
447
+ `}function Jt(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 ${B(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 nt(e){let t=j(e);return `import { createSystem } from "@directive-run/core";
551
+ `}function Bt(e){let t=B(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 ot(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
572
+ `}function Ht(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 ${B(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 it(e){let t=j(e);return `import { createSystem } from "@directive-run/core";
680
+ `}function Kt(e){let t=B(e);return `import { createSystem } from "@directive-run/core";
572
681
  import { ${t} } from "./${e}.js";
573
682
 
574
683
  const system = createSystem({
@@ -587,10 +696,20 @@ 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 at(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}async function ve(e){let t=Qe(e);u.intro(d.bgCyan(d.black(" directive init ")));let r;if(t.noInteractive)r="my-module";else {let f=await u.text({message:"Module name:",placeholder:"my-module",defaultValue:"my-module",validate:x=>{if(!/^[a-z][a-z0-9-]*$/.test(x))return "Must start with a letter, use lowercase letters, numbers, and hyphens"}});u.isCancel(f)&&(u.cancel("Cancelled."),process.exit(0)),r=f;}let s;if(t.template){let f=re(r);t.template in f||(u.log.error(`Unknown template: ${t.template}. Available: ${Object.keys(f).join(", ")}`),process.exit(1)),s=t.template;}else if(t.noInteractive)s="counter";else {let f=re(r),x=await u.select({message:"Project template:",options:Object.values(f).map(R=>({value:R.id,label:R.label,hint:R.hint}))});u.isCancel(x)&&(u.cancel("Cancelled."),process.exit(0)),s=x;}let i=re(r)[s],n=Ze(t.dir);u.log.info(`Package manager: ${d.cyan(n)}`);let a=u.spinner();a.start("Creating project files...");let m=0;for(let f of i.files){let x=join(t.dir,f.path);if(existsSync(x)){m++;continue}at(x,f.content);}a.stop("Project files created.");for(let f of i.files){let x=join(t.dir,f.path),R=relative(t.dir,x);existsSync(x)&&u.log.success(`${d.green("Created")} ${d.dim(R)}`);}m>0&&u.log.warn(`Skipped ${m} file(s) that already exist.`);let w=et(n,i.deps.join(" "));u.outro(`Next steps:
591
- ${d.cyan(w)}
592
- ${d.cyan(`${y} ai-rules init`)}
593
- ${d.dim("Start building!")}`);}function be(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 we=["derive","events","constraints","resolvers","effects"];function dt(e,t){let r=xe(e),s=t.includes("constraints"),o=t.includes("resolvers"),n=`import { ${["type ModuleSchema","createModule","t"].join(", ")} } from "@directive-run/core";
699
+ `}function B(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}function Yt(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}async function Le(e){let t=Wt(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=Lt(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}Yt(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=Gt(n,i.deps.join(" "));p.outro(`Next steps:
700
+ ${f.cyan(d)}
701
+ ${f.cyan(`${x} ai-rules init`)}
702
+ ${f.dim("Start building!")}`);}function Xt(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 Vt(e){let t=[];t.push(f.bold("Facts:"));let r=Object.entries(e);if(r.length===0)return t.push(" (none)"),t.join(`
703
+ `);for(let[s,o]of r){let i=sr(o);t.push(` ${f.cyan(s)} = ${i}`);}return t.join(`
704
+ `)}function Qt(e){let t=[];if(t.push(f.bold("Constraints:")),e.length===0)return t.push(" (none)"),t.join(`
705
+ `);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(`
706
+ `)}function Zt(e,t){let r=[];if(r.push(f.bold("Resolvers:")),e.length===0)return r.push(" (none)"),r.join(`
707
+ `);for(let s of e){let o=t[s.id],i=o?rr(o.state,o.error,o.duration):f.dim("idle");r.push(` ${f.cyan(s.id)} \u2192 ${s.requirement} ${i}`);}return r.join(`
708
+ `)}function er(e){let t=[];if(t.push(f.bold("Unmet Requirements:")),e.length===0)return t.push(` ${f.green("(all requirements met)")}`),t.join(`
709
+ `);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(`
710
+ `)}function tr(e){let t=[];if(t.push(f.bold("Inflight:")),e.length===0)return t.push(` ${f.green("(none)")}`),t.join(`
711
+ `);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(`
712
+ `)}function rr(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 sr(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 nr(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 Ge(e){let{filePath:t,opts:r}=Xt(e);t||(console.error("Usage: directive inspect <file> [--json] [--module <name>]"),process.exit(1));let s=await M(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(Vt(i)),console.log(),console.log(Qt(o.constraints)),console.log(),console.log(Zt(o.resolverDefs,o.resolvers)),console.log(),console.log(er(o.unmet)),console.log(),o.inflight.length>0&&(console.log(tr(o.inflight)),console.log());let n=nr(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 _e(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 ze=["derive","events","constraints","resolvers","effects"];function cr(e,t){let r=Je(e),s=t.includes("constraints"),o=t.includes("resolvers"),n=`import { ${["type ModuleSchema","createModule","t"].join(", ")} } from "@directive-run/core";
594
713
 
595
714
  `;return n+=`const schema = {
596
715
  `,n+=` facts: {
@@ -659,7 +778,7 @@ export default system;
659
778
  `,n+=` },
660
779
  `,n+=` },
661
780
  `),n+=`});
662
- `,n}function mt(e){let t=xe(e);return `import { type ModuleSchema, createModule, createSystem, t } from "@directive-run/core";
781
+ `,n}function lr(e){let t=Je(e);return `import { type ModuleSchema, createModule, createSystem, t } from "@directive-run/core";
663
782
  import {
664
783
  createAgentOrchestrator,
665
784
  createAgentMemory,
@@ -790,61 +909,59 @@ export const memory = createAgentMemory({
790
909
  export const system = createSystem({
791
910
  module: ${t},
792
911
  });
793
- `}function xe(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}function $e(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}function ke(e){return join(e,"src")}async function Se(e,t){let r=be(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=>we.includes(c)):s=we;let o=ke(r.dir),i=join(o,`${e}.ts`);existsSync(i)&&(console.error(`File already exists: ${relative(r.dir,i)}`),process.exit(1));let n=dt(e,s);$e(i,n);let a=relative(r.dir,i);console.log(`${d.green("Created")} ${d.dim(a)}`),s.length===0?console.log(d.dim(" Minimal module (schema + init only)")):console.log(d.dim(` Sections: ${s.join(", ")}`));}async function Ce(e,t){let r=be(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=ke(r.dir),o=join(s,`${e}.ts`);existsSync(o)&&(console.error(`File already exists: ${relative(r.dir,o)}`),process.exit(1));let i=mt(e);$e(o,i);let n=relative(r.dir,o);console.log(`${d.green("Created")} ${d.dim(n)}`),console.log(d.dim(" AI orchestrator with memory, guardrails, and streaming"));}async function U(e){let t=resolve(e);if(!existsSync(t))throw new Error(`File not found: ${t}`);try{let r=await import(t);if(r.default&&oe(r.default))return r.default;if(r.system&&oe(r.system))return r.system;for(let s of Object.keys(r))if(oe(r[s]))return r[s];throw new Error(`No Directive system found in ${d.dim(e)}
796
- Export a system as default or named "system":
912
+ `}function Je(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}function Be(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}function He(e){return join(e,"src")}async function Ke(e,t){let r=_e(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(c=>ze.includes(c)):s=ze;let o=He(r.dir),i=join(o,`${e}.ts`);existsSync(i)&&(console.error(`File already exists: ${relative(r.dir,i)}`),process.exit(1));let n=cr(e,s);Be(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 Ye(e,t){let r=_e(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=He(r.dir),o=join(s,`${e}.ts`);existsSync(o)&&(console.error(`File already exists: ${relative(r.dir,o)}`),process.exit(1));let i=lr(e);Be(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"));}function pr(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(`
915
+ Usage: directive replay <timeline.json> [options]
797
916
 
798
- ${d.cyan("export default")} createSystem({ module: myModule });
799
- ${d.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 ${d.dim(e)}: ${r instanceof Error?r.message:String(r)}
917
+ Replay a serialized Directive timeline against a fresh system.
800
918
 
801
- Make sure the file is valid TypeScript and tsx is installed:
802
- ${d.cyan("npm install -D tsx")}`)}}function oe(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}function gt(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 ht(e){let t=[];t.push(d.bold("Facts:"));let r=Object.entries(e);if(r.length===0)return t.push(" (none)"),t.join(`
803
- `);for(let[s,o]of r){let i=$t(o);t.push(` ${d.cyan(s)} = ${i}`);}return t.join(`
804
- `)}function yt(e){let t=[];if(t.push(d.bold("Constraints:")),e.length===0)return t.push(" (none)"),t.join(`
805
- `);for(let r of e){let s=r.disabled?d.dim("disabled"):r.active?d.green("active"):d.dim("inactive"),o=r.hitCount>0?d.yellow(` (${r.hitCount} hits)`):"";t.push(` ${d.cyan(r.id)} ${s} priority=${r.priority}${o}`);}return t.join(`
806
- `)}function vt(e,t){let r=[];if(r.push(d.bold("Resolvers:")),e.length===0)return r.push(" (none)"),r.join(`
807
- `);for(let s of e){let o=t[s.id],i=o?xt(o.state,o.error,o.duration):d.dim("idle");r.push(` ${d.cyan(s.id)} \u2192 ${s.requirement} ${i}`);}return r.join(`
808
- `)}function wt(e){let t=[];if(t.push(d.bold("Unmet Requirements:")),e.length===0)return t.push(` ${d.green("(all requirements met)")}`),t.join(`
809
- `);for(let r of e)t.push(` ${d.yellow(r.requirement.type)} (id: ${d.dim(r.id)}) from ${d.dim(r.fromConstraint)}`);return t.join(`
810
- `)}function bt(e){let t=[];if(t.push(d.bold("Inflight:")),e.length===0)return t.push(` ${d.green("(none)")}`),t.join(`
811
- `);let r=Date.now();for(let s of e){let o=r-s.startedAt;t.push(` ${d.cyan(s.resolverId)} \u2192 req ${d.dim(s.id)} ${d.yellow(`${o}ms`)}`);}return t.join(`
812
- `)}function xt(e,t,r){let s=r!==void 0?` ${r}ms`:"";switch(e){case "resolved":return d.green(`resolved${s}`);case "errored":return d.red(`errored${s}${t?` \u2014 ${t}`:""}`);case "inflight":return d.yellow("inflight");case "cancelled":return d.dim("cancelled");default:return d.dim(e)}}function $t(e){return e===null?d.dim("null"):e===void 0?d.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 kt(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 Ae(e){let{filePath:t,opts:r}=gt(e);t||(console.error("Usage: directive inspect <file> [--json] [--module <name>]"),process.exit(1));let s=await U(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(d.bold(d.cyan("Directive System Inspection"))),console.log(d.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(ht(i)),console.log(),console.log(yt(o.constraints)),console.log(),console.log(vt(o.resolverDefs,o.resolvers)),console.log(),console.log(wt(o.unmet)),console.log(),o.inflight.length>0&&(console.log(bt(o.inflight)),console.log());let n=kt(o);if(n.length>0){console.log(d.bold(d.yellow("Warnings:")));for(let a of n)console.log(` ${d.yellow("\u26A0")} ${a}`);console.log();}s.stop();}function St(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 Te(e){let{filePath:t,requirementId:r}=St(e);t||(console.error("Usage: directive explain <file> [requirement-id]"),process.exit(1));let s=await U(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.
813
-
814
- Current requirements:`),o.unmet.length===0)console.log(d.dim(" (no unmet requirements)"));else for(let n of o.unmet)console.log(` ${d.cyan(n.id)} \u2014 ${n.requirement.type} (from ${n.fromConstraint})`);s.stop(),process.exit(1);}console.log(),console.log(d.bold(d.cyan("Requirement Explanation"))),console.log(d.dim("\u2500".repeat(40))),console.log(),console.log(i),console.log();}else if(console.log(),console.log(d.bold(d.cyan("All Requirements"))),console.log(d.dim("\u2500".repeat(40))),console.log(),o.unmet.length===0){console.log(d.green("All requirements are met.")),console.log();let i=Object.entries(o.resolvers);if(i.length>0){console.log(d.bold("Recent Resolver Activity:"));for(let[n,a]of i){let c=Re(a.state),m=a.duration!==void 0?` (${a.duration}ms)`:"";console.log(` ${d.cyan(n)} ${c}${m}`);}console.log();}}else {console.log(`${d.yellow(String(o.unmet.length))} unmet requirement(s):
815
- `);for(let i of o.unmet){console.log(`${d.yellow("\u25CF")} ${d.bold(i.requirement.type)} (id: ${d.dim(i.id)})`),console.log(` From constraint: ${d.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: ${Re(c.state)}${c.error?` \u2014 ${c.error}`:""}`):o.resolverDefs.some(w=>w.requirement===i.requirement.type||w.requirement==="(predicate)")||console.log(` ${d.red("No resolver registered for this type")}`),console.log();}console.log(d.dim(`Run ${d.cyan("directive explain <file> <requirement-id>")} for detailed explanation.`));}s.stop();}function Re(e){switch(e){case "resolved":return d.green("resolved");case "errored":return d.red("errored");case "inflight":return d.yellow("inflight");case "pending":return d.yellow("pending");case "cancelled":return d.dim("cancelled");default:return d.dim(e)}}function Rt(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 Tt(e){let t=[];t.push(d.bold("Dependency Graph")),t.push(d.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(d.bold("Constraints \u2192 Requirements \u2192 Resolvers")),t.push("");for(let[a,c]of r){let m=c.active?d.green("\u25CF"):d.dim("\u25CB");if(t.push(`${m} ${d.cyan(a)} (priority: ${c.priority})`),c.reqTypes.size>0)for(let w of c.reqTypes){t.push(` \u2514\u2500\u25B6 ${d.yellow(w)}`);let f=s.get(w)||[];if(f.length>0)for(let x of f)t.push(` \u2514\u2500\u25B6 ${d.magenta(x)}`);else t.push(` \u2514\u2500\u25B6 ${d.red("(no resolver)")}`);}else t.push(` \u2514\u2500\u25B6 ${d.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(d.bold("Standalone Resolvers:"));for(let a of e.resolverDefs)o.has(a.id)||t.push(` ${d.magenta(a.id)} handles ${d.yellow(a.requirement)}`);}return t.join(`
816
- `)}function Mt(e,t){let r=[],s=[],c=Object.keys(t);for(let l=0;l<c.length;l++){let b=c[l];r.push({id:`fact-${b}`,label:b,type:"fact",x:40,y:60+l*50,color:"#3b82f6"});}for(let l=0;l<e.constraints.length;l++){let b=e.constraints[l];r.push({id:`constraint-${b.id}`,label:b.id,type:"constraint",x:260,y:60+l*50,color:b.active?"#22c55e":"#6b7280"});}let m=new Set;for(let l of e.unmet)m.add(l.requirement.type);let w=0;for(let l of m)r.push({id:`req-${l}`,label:l,type:"requirement",x:480,y:60+w*50,color:"#eab308"}),w++;for(let l=0;l<e.resolverDefs.length;l++){let b=e.resolverDefs[l];r.push({id:`resolver-${b.id}`,label:b.id,type:"resolver",x:700,y:60+l*50,color:"#a855f7"});}for(let l of e.unmet)s.push({from:`constraint-${l.fromConstraint}`,to:`req-${l.requirement.type}`});for(let l of e.resolverDefs)m.has(l.requirement)&&s.push({from:`req-${l.requirement}`,to:`resolver-${l.id}`});let f=new Map(r.map(l=>[l.id,l])),x=960,R=Math.max(...r.map(l=>l.y))+50+20,Ne=s.map(l=>{let b=f.get(l.from),X=f.get(l.to);return !b||!X?"":`<line x1="${b.x+90}" y1="${b.y+15}" x2="${X.x}" y2="${X.y+15}" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#arrow)"/>`}).join(`
817
- `),je=r.map(l=>`<g>
818
- <rect x="${l.x}" y="${l.y}" width="180" height="30" rx="6" fill="${l.color}" opacity="0.15" stroke="${l.color}" stroke-width="1.5"/>
819
- <text x="${l.x+90}" y="${l.y+19}" text-anchor="middle" font-size="12" font-family="monospace" fill="${l.color}">${qt(l.label)}</text>
820
- </g>`).join(`
821
- `),Ue=["Facts","Constraints","Requirements","Resolvers"].map((l,b)=>`<text x="${40+b*220+90}" y="35" text-anchor="middle" font-size="14" font-weight="bold" font-family="system-ui" fill="#e2e8f0">${l}</text>`).join(`
822
- `);return `<!DOCTYPE html>
823
- <html>
824
- <head>
825
- <title>Directive System Graph</title>
826
- <style>
827
- body { margin: 0; background: #0f172a; display: flex; justify-content: center; padding: 20px; }
828
- svg { max-width: 100%; }
829
- </style>
830
- </head>
831
- <body>
832
- <svg width="${x}" height="${R}" xmlns="http://www.w3.org/2000/svg">
833
- <defs>
834
- <marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
835
- <path d="M 0 0 L 10 5 L 0 10 z" fill="#94a3b8"/>
836
- </marker>
837
- </defs>
838
- ${Ue}
839
- ${Ne}
840
- ${je}
841
- </svg>
842
- </body>
843
- </html>`}function qt(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function Me(e){let{filePath:t,opts:r}=Rt(e);t||(console.error("Usage: directive graph <file> [--ascii] [--no-open] [--output <path>]"),process.exit(1));let s=await U(t);s.isRunning||s.start();let o=s.inspect();if(r.ascii){console.log(Tt(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=Mt(o,i),a=r.output||join(process.cwd(),".directive-graph.html");if(writeFileSync(a,n,"utf-8"),console.log(`${d.green("Generated")} ${d.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(d.dim("Opened in browser."));}catch{console.log(d.dim(`Open ${a} in your browser to view the graph.`));}s.stop();}function Dt(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 It(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 Pt(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 Et(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 Nt(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 jt(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");P(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 qe(e){let t=Dt(e);console.log(),console.log(d.bold(d.cyan("Directive Doctor"))),console.log(d.dim("\u2500".repeat(40))),console.log();let r=[It(t.dir),Pt(t.dir),Et(t.dir),Nt(t.dir),jt(t.dir)],s=0;for(let o of r){let i=o.passed?d.green("\u2713"):d.red("\u2717");console.log(`${i} ${d.bold(o.label)}`),console.log(` ${d.dim(o.message)}`),!o.passed&&o.fix&&(console.log(` ${d.yellow("Fix:")} ${o.fix}`),s++),console.log();}s>0?(console.log(d.yellow(`${s} issue(s) found. See suggested fixes above.`)),process.exit(1)):console.log(d.green("All checks passed!"));}var Ie={"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 Ft(e){for(let[t,r]of Object.entries(Ie))if(r.includes(e))return t;return "Other"}function _t(e){let t=e.split(`
844
- `);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 Pe(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(d.bold(d.cyan("Directive Examples"))),console.log(d.dim("\u2500".repeat(50))),console.log();let s=new Map;for(let[n,a]of r){let c=Ft(n);t&&!c.toLowerCase().includes(t)&&!n.includes(t)||(s.has(c)||s.set(c,[]),s.get(c).push({name:n,desc:_t(a)}));}if(s.size===0){console.log(d.dim("No examples match the filter."));return}let o=Object.keys(Ie),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(d.bold(n));for(let c of a){let m=c.desc?d.dim(` \u2014 ${c.desc}`):"";console.log(` ${d.cyan(c.name)}${m}`);}console.log();}console.log(d.dim(`${r.size} examples available. Run ${d.cyan("directive examples copy <name>")} to extract one.`));}async function Ee(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 ${d.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(`${d.green("Copied")} ${d.cyan(e)} \u2192 ${d.dim(a)}`);}var zt=`
845
- ${y} \u2014 CLI tools for Directive
919
+ Arguments:
920
+ <timeline.json> Path to a timeline produced by serializeTimeline()
921
+
922
+ Options:
923
+ --system, -s <path> Path to a TypeScript file exporting a Directive
924
+ system (default export or 'system' named export)
925
+ --max-frames <n> Cap on frames replayed (default 100,000)
926
+ --all-frames Walk every frame, not just dispatchable ones
927
+ (diagnostic mode \u2014 most frames will skip silently)
928
+ --json Emit ReplayResult as JSON
929
+ --verbose, -v Print per-frame trace
930
+ --help, -h Show this help
931
+
932
+ Examples:
933
+ directive replay bug-1234.json --system src/app/system.ts
934
+ directive replay error.json --system src/system.ts --json
935
+ directive replay error.json --system src/system.ts --verbose
936
+ `);}async function Xe(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(fe(),process.exit(e.length===0?1:0));let{jsonPath:t,opts:r}=pr(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(`
937
+ (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 _(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 M(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 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(`
938
+ Usage: directive timeline diff <a.json> <b.json>
939
+
940
+ Compare two serialized Directive timelines as a structured causal-graph
941
+ diff. Reports frame counts, constraint-fire deltas, mutation deltas,
942
+ resolver runs, and new errors.
943
+
944
+ Arguments:
945
+ <a.json> First timeline (typically the "good" / baseline run)
946
+ <b.json> Second timeline (typically the "bad" / regression run)
947
+
948
+ Options:
949
+ --json Emit TimelineDiff as JSON
950
+ -v, --verbose Include unchanged categories in the human output
951
+ --help, -h Show this help
952
+
953
+ Exit codes:
954
+ 0 identical timelines
955
+ 1 CLI argument error
956
+ 2 diff found differences
957
+
958
+ Examples:
959
+ directive timeline diff baseline.json regression.json
960
+ 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 _(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
846
963
 
847
- Usage: ${y} <command> [options]
964
+ Usage: ${x} <command> [options]
848
965
 
849
966
  Commands:
850
967
  init Project scaffolding wizard
@@ -859,6 +976,12 @@ Commands:
859
976
  ai-rules check Validate rules are current (CI)
860
977
  examples list Browse available examples
861
978
  examples copy <name> Extract example to project
979
+ replay <timeline.json> Replay a serialized Directive timeline
980
+ (paired with @directive-run/timeline)
981
+ bisect <timeline.json> Binary-search a timeline for the first
982
+ frame that triggers a failing assertion
983
+ timeline diff <a> <b> Semantic causal-graph diff between two
984
+ serialized timelines
862
985
 
863
986
  Options:
864
987
  --help, -h Show this help message
@@ -892,13 +1015,14 @@ ai-rules init options:
892
1015
  examples options:
893
1016
  --filter <category> Filter by category or name
894
1017
  --dest <dir> Destination directory for copy
895
- `.trim();async function Ht(){let e=process.argv.slice(2);if((e.length===0||e.includes("--help")||e.includes("-h"))&&(console.log(zt),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 ve(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 Se(s,e.slice(3))):r==="orchestrator"?(s||(console.error("Usage: directive new orchestrator <name>"),process.exit(1)),await Ce(s,e.slice(3))):(console.error(`Unknown subcommand: ${r??"(none)"}
896
- Usage: ${y} new module <name>
897
- ${y} new orchestrator <name>`),process.exit(1));break}case "inspect":{await Ae(e.slice(1));break}case "explain":{await Te(e.slice(1));break}case "graph":{await Me(e.slice(1));break}case "doctor":{await qe(e.slice(1));break}case "ai-rules":{let r=e[1];r==="init"?await ge(e.slice(2)):r==="update"?await he(e.slice(2)):r==="check"?await ye(e.slice(2)):(console.error(`Unknown subcommand: ${r??"(none)"}
898
- Usage: ${y} ai-rules init
899
- ${y} ai-rules update
900
- ${y} ai-rules check`),process.exit(1));break}case "examples":{let r=e[1];if(r==="list")await Pe(e.slice(2));else if(r==="copy"){let s=e[2];s||(console.error("Usage: directive examples copy <name>"),process.exit(1)),await Ee(s,e.slice(3));}else console.error(`Unknown subcommand: ${r??"(none)"}
901
- Usage: ${y} examples list [--filter <category>]
902
- ${y} examples copy <name> [--dest <dir>]`),process.exit(1);break}default:console.error(`Unknown command: ${t}
903
- Run '${y} --help' for usage.`),process.exit(1);}}Ht().catch(e=>{console.error(e.message||e),process.exit(1);});//# sourceMappingURL=cli.js.map
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 Le(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 Ke(s,e.slice(3))):r==="orchestrator"?(s||(console.error("Usage: directive new orchestrator <name>"),process.exit(1)),await Ye(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 Ge(e.slice(1));break}case "explain":{await Ue(e.slice(1));break}case "graph":{await We(e.slice(1));break}case "doctor":{await je(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 Ie(e.slice(2));else if(r==="copy"){let s=e[2];s||(console.error("Usage: directive examples copy <name>"),process.exit(1)),await Ne(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 Xe(e.slice(1));break}case "bisect":{await Ee(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
904
1028
  //# sourceMappingURL=cli.js.map