@directive-run/cli 1.1.2 → 1.4.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*as p from'@clack/prompts';import {existsSync,readFileSync,mkdirSync,writeFileSync,readdirSync}from'fs';import {resolve,join,relative,dirname}from'path';import f from'picocolors';import {getAllExamples,getExample,getKnowledge}from'@directive-run/knowledge';var x="directive";var V="<!-- directive:start -->",H="<!-- directive:end -->";var oe=[{id:"cursor",name:"Cursor",signals:[".cursor",".cursorrules"],outputPath:".cursorrules"},{id:"claude",name:"Claude Code",signals:[".claude"],outputPath:".claude/CLAUDE.md"},{id:"copilot",name:"GitHub Copilot",signals:[".github"],outputPath:".github/copilot-instructions.md"},{id:"windsurf",name:"Windsurf",signals:[".windsurfrules"],outputPath:".windsurfrules"},{id:"cline",name:"Cline",signals:[".clinerules"],outputPath:".clinerules"}];function he(e){let t=[];for(let r of oe)r.signals.some(o=>existsSync(join(e,o)))&&t.push({name:r.name,id:r.id,outputPath:join(e,r.outputPath)});return t}function K(e){let t=oe.find(r=>r.id===e);if(!t)throw new Error(`Unknown tool: ${e}`);return t}function ye(){return oe.map(e=>e.id)}function L(e,t){let r=e.indexOf(V),s=e.indexOf(H),o=`${V}
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,10 @@ 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.`));}function gt(e){let t={dir:process.cwd(),noInteractive:false};for(let r=0;r<e.length;r++)switch(e[r]){case "--template":{let o=e[++r];o&&(t.template=o);break}case "--dir":{let o=e[++r];o&&(t.dir=o);break}case "--no-interactive":t.noInteractive=true;break}return t}function ht(e){return existsSync(join(e,"pnpm-lock.yaml"))?"pnpm":existsSync(join(e,"bun.lockb"))||existsSync(join(e,"bun.lock"))?"bun":existsSync(join(e,"yarn.lock"))?"yarn":"npm"}function yt(e,t){switch(e){case "pnpm":return `pnpm add ${t}`;case "yarn":return `yarn add ${t}`;case "bun":return `bun add ${t}`;default:return `npm install ${t}`}}function me(e){return {counter:{id:"counter",label:"Counter (minimal)",hint:"schema + init + derive + events \u2014 simplest starting point",files:[{path:`src/${e}.ts`,content:vt(e)},{path:"src/main.ts",content:bt(e)}],deps:["@directive-run/core"]},"auth-flow":{id:"auth-flow",label:"Auth flow (constraints + resolvers)",hint:"login flow with constraints, resolvers, retry, and effects",files:[{path:`src/${e}.ts`,content:wt(e)},{path:"src/main.ts",content:xt(e)}],deps:["@directive-run/core"]},"ai-orchestrator":{id:"ai-orchestrator",label:"AI orchestrator",hint:"agent orchestrator with guardrails and streaming",files:[{path:`src/${e}.ts`,content:$t(e)},{path:"src/main.ts",content:kt(e)}],deps:["@directive-run/core","@directive-run/ai"]}}}function vt(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
266
266
 
267
267
  const schema = {
268
268
  facts: {
@@ -281,7 +281,7 @@ const schema = {
281
281
  },
282
282
  } satisfies ModuleSchema;
283
283
 
284
- export const ${j(e)} = createModule("${e}", {
284
+ export const ${J(e)} = createModule("${e}", {
285
285
  schema,
286
286
 
287
287
  init: (facts) => {
@@ -309,7 +309,7 @@ export const ${j(e)} = createModule("${e}", {
309
309
  },
310
310
  },
311
311
  });
312
- `}function rt(e){let t=j(e);return `import { createSystem } from "@directive-run/core";
312
+ `}function bt(e){let t=J(e);return `import { createSystem } from "@directive-run/core";
313
313
  import { ${t} } from "./${e}.js";
314
314
 
315
315
  const system = createSystem({
@@ -335,7 +335,7 @@ system.events.increment();
335
335
  system.events.increment();
336
336
 
337
337
  export default system;
338
- `}function st(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
338
+ `}function wt(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
339
339
 
340
340
  type AuthStatus = "idle" | "authenticating" | "authenticated" | "expired";
341
341
 
@@ -362,7 +362,7 @@ const schema = {
362
362
  },
363
363
  } satisfies ModuleSchema;
364
364
 
365
- export const ${j(e)} = createModule("${e}", {
365
+ export const ${J(e)} = createModule("${e}", {
366
366
  schema,
367
367
 
368
368
  init: (facts) => {
@@ -439,7 +439,7 @@ export const ${j(e)} = createModule("${e}", {
439
439
  },
440
440
  },
441
441
  });
442
- `}function nt(e){let t=j(e);return `import { createSystem } from "@directive-run/core";
442
+ `}function xt(e){let t=J(e);return `import { createSystem } from "@directive-run/core";
443
443
  import { ${t} } from "./${e}.js";
444
444
 
445
445
  const system = createSystem({
@@ -460,7 +460,7 @@ console.log("authenticated:", system.read("isAuthenticated"));
460
460
  console.log("token:", system.facts.token);
461
461
 
462
462
  export default system;
463
- `}function ot(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
463
+ `}function $t(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
464
464
  import {
465
465
  createAgentOrchestrator,
466
466
  createAgentMemory,
@@ -494,7 +494,7 @@ const schema = {
494
494
  },
495
495
  } satisfies ModuleSchema;
496
496
 
497
- export const ${j(e)} = createModule("${e}", {
497
+ export const ${J(e)} = createModule("${e}", {
498
498
  schema,
499
499
 
500
500
  init: (facts) => {
@@ -568,7 +568,7 @@ export const memory = createAgentMemory({
568
568
  // maxTokenBudget: 50000,
569
569
  // memory,
570
570
  // });
571
- `}function it(e){let t=j(e);return `import { createSystem } from "@directive-run/core";
571
+ `}function kt(e){let t=J(e);return `import { createSystem } from "@directive-run/core";
572
572
  import { ${t} } from "./${e}.js";
573
573
 
574
574
  const system = createSystem({
@@ -587,10 +587,10 @@ await system.settle();
587
587
  console.log("output:", system.facts.output);
588
588
 
589
589
  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";
590
+ `}function J(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}function St(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}async function Ae(e){let t=gt(e);p.intro(f.bgCyan(f.black(" directive init ")));let r;if(t.noInteractive)r="my-module";else {let l=await p.text({message:"Module name:",placeholder:"my-module",defaultValue:"my-module",validate:h=>{if(!/^[a-z][a-z0-9-]*$/.test(h))return "Must start with a letter, use lowercase letters, numbers, and hyphens"}});p.isCancel(l)&&(p.cancel("Cancelled."),process.exit(0)),r=l;}let s;if(t.template){let l=me(r);t.template in l||(p.log.error(`Unknown template: ${t.template}. Available: ${Object.keys(l).join(", ")}`),process.exit(1)),s=t.template;}else if(t.noInteractive)s="counter";else {let l=me(r),h=await p.select({message:"Project template:",options:Object.values(l).map(T=>({value:T.id,label:T.label,hint:T.hint}))});p.isCancel(h)&&(p.cancel("Cancelled."),process.exit(0)),s=h;}let i=me(r)[s],n=ht(t.dir);p.log.info(`Package manager: ${f.cyan(n)}`);let a=p.spinner();a.start("Creating project files...");let m=0;for(let l of i.files){let h=join(t.dir,l.path);if(existsSync(h)){m++;continue}St(h,l.content);}a.stop("Project files created.");for(let l of i.files){let h=join(t.dir,l.path),T=relative(t.dir,h);existsSync(h)&&p.log.success(`${f.green("Created")} ${f.dim(T)}`);}m>0&&p.log.warn(`Skipped ${m} file(s) that already exist.`);let d=yt(n,i.deps.join(" "));p.outro(`Next steps:
591
+ ${f.cyan(d)}
592
+ ${f.cyan(`${x} ai-rules init`)}
593
+ ${f.dim("Start building!")}`);}function Oe(e){let t={with:[],minimal:false,dir:process.cwd()};for(let r=0;r<e.length;r++)switch(e[r]){case "--with":{let o=e[++r];o&&(t.with=o.split(",").map(i=>i.trim()));break}case "--minimal":t.minimal=true;break;case "--dir":{let o=e[++r];o&&(t.dir=o);break}}return t}var Te=["derive","events","constraints","resolvers","effects"];function Tt(e,t){let r=De(e),s=t.includes("constraints"),o=t.includes("resolvers"),n=`import { ${["type ModuleSchema","createModule","t"].join(", ")} } from "@directive-run/core";
594
594
 
595
595
  `;return n+=`const schema = {
596
596
  `,n+=` facts: {
@@ -659,7 +659,7 @@ export default system;
659
659
  `,n+=` },
660
660
  `,n+=` },
661
661
  `),n+=`});
662
- `,n}function mt(e){let t=xe(e);return `import { type ModuleSchema, createModule, createSystem, t } from "@directive-run/core";
662
+ `,n}function Ot(e){let t=De(e);return `import { type ModuleSchema, createModule, createSystem, t } from "@directive-run/core";
663
663
  import {
664
664
  createAgentOrchestrator,
665
665
  createAgentMemory,
@@ -790,35 +790,57 @@ export const memory = createAgentMemory({
790
790
  export const system = createSystem({
791
791
  module: ${t},
792
792
  });
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)}
793
+ `}function De(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}function Ee(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}function je(e){return join(e,"src")}async function Me(e,t){let r=Oe(t);(!e||!/^[a-z][a-z0-9-]*$/.test(e))&&(console.error(`Invalid module name: ${e||"(none)"}
794
+ Must start with a letter, use lowercase letters, numbers, and hyphens.`),process.exit(1));let s;r.minimal?s=[]:r.with.length>0?s=r.with.filter(c=>Te.includes(c)):s=Te;let o=je(r.dir),i=join(o,`${e}.ts`);existsSync(i)&&(console.error(`File already exists: ${relative(r.dir,i)}`),process.exit(1));let n=Tt(e,s);Ee(i,n);let a=relative(r.dir,i);console.log(`${f.green("Created")} ${f.dim(a)}`),s.length===0?console.log(f.dim(" Minimal module (schema + init only)")):console.log(f.dim(` Sections: ${s.join(", ")}`));}async function Pe(e,t){let r=Oe(t);(!e||!/^[a-z][a-z0-9-]*$/.test(e))&&(console.error(`Invalid orchestrator name: ${e||"(none)"}
795
+ Must start with a letter, use lowercase letters, numbers, and hyphens.`),process.exit(1));let s=je(r.dir),o=join(s,`${e}.ts`);existsSync(o)&&(console.error(`File already exists: ${relative(r.dir,o)}`),process.exit(1));let i=Ot(e);Ee(o,i);let n=relative(r.dir,o);console.log(`${f.green("Created")} ${f.dim(n)}`),console.log(f.dim(" AI orchestrator with memory, guardrails, and streaming"));}async function P(e){let t=resolve(e);if(!existsSync(t))throw new Error(`File not found: ${t}`);try{let r=await import(t);if(r.default&&F(r.default))return r.default;if(r.system&&F(r.system))return r.system;for(let s of Object.keys(r))if(F(r[s]))return r[s];throw new Error(`No Directive system found in ${f.dim(e)}
796
796
  Export a system as default or named "system":
797
797
 
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)}
798
+ ${f.cyan("export default")} createSystem({ module: myModule });
799
+ ${f.cyan("export const system")} = createSystem({ module: myModule });`)}catch(r){throw r instanceof Error&&r.message.includes("No Directive system")?r:new Error(`Failed to load ${f.dim(e)}: ${r instanceof Error?r.message:String(r)}
800
800
 
801
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>
802
+ ${f.cyan("npm install -D tsx")}`)}}function F(e){if(typeof e!="object"||e===null)return false;let t=e;return typeof t.inspect=="function"&&typeof t.start=="function"&&typeof t.stop=="function"&&"facts"in t}async function Ne(e){let t=resolve(e);if(!existsSync(t))throw new Error(`File not found: ${t}`);let r;try{r=await import(t);}catch(i){throw new Error(`Failed to load ${f.dim(e)}: ${i instanceof Error?i.message:String(i)}
803
+
804
+ Make sure the file is valid TypeScript and tsx is installed:
805
+ ${f.cyan("npm install -D tsx")}`)}let s=[["createSystem",r.createSystem],["systemFactory",r.systemFactory],["default",r.default]];for(let[i,n]of s)if(typeof n=="function")return async()=>{let a=await Promise.resolve(n());if(!F(a))throw new Error(`Factory '${i}' from ${f.dim(e)} returned a value that is not a started Directive system.
806
+ Expected an object with inspect/start/stop/facts. The factory must call sys.start() before returning.`);return a};throw F(r.default)||F(r.system)||Object.values(r).some(F)?new Error(`Found a started Directive system in ${f.dim(e)}, but bisect needs a factory.
807
+ Bisect instantiates a fresh system for every midpoint replay (so each attempt is hermetic),
808
+ which means it can't reuse a singleton instance the way ${f.cyan("directive replay")} does.
809
+
810
+ Wrap the existing export in a function:
811
+
812
+ ${f.cyan("export function createSystem()")} {
813
+ const sys = createSystem({ module: yourModule });
814
+ sys.start();
815
+ return sys;
816
+ }`):new Error(`No system factory found in ${f.dim(e)}
817
+ Bisect needs to instantiate a fresh system per midpoint replay. Export one of:
818
+
819
+ ${f.cyan("export function createSystem()")} { ... return sys; }
820
+ ${f.cyan("export const systemFactory")} = () => { ... return sys; };
821
+ ${f.cyan("export default")} () => { ... return sys; };
822
+
823
+ The factory MUST call sys.start() and return the started system.
824
+ (Did you forget ${f.cyan("sys.start()")} before returning?)`)}function Dt(e){let t={json:false},r="";for(let s=0;s<e.length;s++){let o=e[s];switch(o){case "--json":t.json=true;break;case "--module":{let i=e[++s];i&&(t.module=i);break}default:o&&!o.startsWith("-")&&!r&&(r=o);}}return {filePath:r,opts:t}}function Et(e){let t=[];t.push(f.bold("Facts:"));let r=Object.entries(e);if(r.length===0)return t.push(" (none)"),t.join(`
825
+ `);for(let[s,o]of r){let i=Nt(o);t.push(` ${f.cyan(s)} = ${i}`);}return t.join(`
826
+ `)}function jt(e){let t=[];if(t.push(f.bold("Constraints:")),e.length===0)return t.push(" (none)"),t.join(`
827
+ `);for(let r of e){let s=r.disabled?f.dim("disabled"):r.active?f.green("active"):f.dim("inactive"),o=r.hitCount>0?f.yellow(` (${r.hitCount} hits)`):"";t.push(` ${f.cyan(r.id)} ${s} priority=${r.priority}${o}`);}return t.join(`
828
+ `)}function Mt(e,t){let r=[];if(r.push(f.bold("Resolvers:")),e.length===0)return r.push(" (none)"),r.join(`
829
+ `);for(let s of e){let o=t[s.id],i=o?It(o.state,o.error,o.duration):f.dim("idle");r.push(` ${f.cyan(s.id)} \u2192 ${s.requirement} ${i}`);}return r.join(`
830
+ `)}function Pt(e){let t=[];if(t.push(f.bold("Unmet Requirements:")),e.length===0)return t.push(` ${f.green("(all requirements met)")}`),t.join(`
831
+ `);for(let r of e)t.push(` ${f.yellow(r.requirement.type)} (id: ${f.dim(r.id)}) from ${f.dim(r.fromConstraint)}`);return t.join(`
832
+ `)}function qt(e){let t=[];if(t.push(f.bold("Inflight:")),e.length===0)return t.push(` ${f.green("(none)")}`),t.join(`
833
+ `);let r=Date.now();for(let s of e){let o=r-s.startedAt;t.push(` ${f.cyan(s.resolverId)} \u2192 req ${f.dim(s.id)} ${f.yellow(`${o}ms`)}`);}return t.join(`
834
+ `)}function It(e,t,r){let s=r!==void 0?` ${r}ms`:"";switch(e){case "resolved":return f.green(`resolved${s}`);case "errored":return f.red(`errored${s}${t?` \u2014 ${t}`:""}`);case "inflight":return f.yellow("inflight");case "cancelled":return f.dim("cancelled");default:return f.dim(e)}}function Nt(e){return e===null?f.dim("null"):e===void 0?f.dim("undefined"):typeof e=="string"?e.length>60?`"${e.slice(0,57)}..."`:`"${e}"`:typeof e=="number"||typeof e=="boolean"?String(e):Array.isArray(e)?`[${e.length} items]`:JSON.stringify(e).slice(0,60)}function Ft(e){let t=[];new Set(e.unmet.map(i=>i.requirement.type));new Set(e.resolverDefs.map(i=>i.requirement));for(let i of e.resolverDefs)i.requirement;for(let i of e.unmet)e.resolverDefs.some(a=>a.requirement===i.requirement.type||a.requirement==="(predicate)")||t.push(`No resolver for requirement type "${i.requirement.type}"`);return t}async function Fe(e){let{filePath:t,opts:r}=Dt(e);t||(console.error("Usage: directive inspect <file> [--json] [--module <name>]"),process.exit(1));let s=await P(t);s.isRunning||s.start();let o=s.inspect();if(r.json){let a={};if(s.facts)for(let c of Object.keys(s.facts))try{a[c]=s.facts[c];}catch{a[c]="(error reading)";}console.log(JSON.stringify({facts:a,...o},null,2)),s.stop();return}console.log(),console.log(f.bold(f.cyan("Directive System Inspection"))),console.log(f.dim("\u2500".repeat(40))),console.log();let i={};if(s.facts)for(let a of Object.keys(s.facts))try{i[a]=s.facts[a];}catch{i[a]="(error reading)";}console.log(Et(i)),console.log(),console.log(jt(o.constraints)),console.log(),console.log(Mt(o.resolverDefs,o.resolvers)),console.log(),console.log(Pt(o.unmet)),console.log(),o.inflight.length>0&&(console.log(qt(o.inflight)),console.log());let n=Ft(o);if(n.length>0){console.log(f.bold(f.yellow("Warnings:")));for(let a of n)console.log(` ${f.yellow("\u26A0")} ${a}`);console.log();}s.stop();}function Ut(e){let t={},r="",s;for(let o=0;o<e.length;o++){let i=e[o];if(i==="--module"){let n=e[++o];n&&(t.module=n);}else i&&!i.startsWith("-")&&(r?s||(s=i):r=i);}return {filePath:r,requirementId:s,opts:t}}async function We(e){let{filePath:t,requirementId:r}=Ut(e);t||(console.error("Usage: directive explain <file> [requirement-id]"),process.exit(1));let s=await P(t);s.isRunning||s.start();let o=s.inspect();if(r){let i=s.explain(r);if(!i){if(console.error(`Requirement "${r}" not found.
835
+
836
+ Current requirements:`),o.unmet.length===0)console.log(f.dim(" (no unmet requirements)"));else for(let n of o.unmet)console.log(` ${f.cyan(n.id)} \u2014 ${n.requirement.type} (from ${n.fromConstraint})`);s.stop(),process.exit(1);}console.log(),console.log(f.bold(f.cyan("Requirement Explanation"))),console.log(f.dim("\u2500".repeat(40))),console.log(),console.log(i),console.log();}else if(console.log(),console.log(f.bold(f.cyan("All Requirements"))),console.log(f.dim("\u2500".repeat(40))),console.log(),o.unmet.length===0){console.log(f.green("All requirements are met.")),console.log();let i=Object.entries(o.resolvers);if(i.length>0){console.log(f.bold("Recent Resolver Activity:"));for(let[n,a]of i){let c=Ue(a.state),m=a.duration!==void 0?` (${a.duration}ms)`:"";console.log(` ${f.cyan(n)} ${c}${m}`);}console.log();}}else {console.log(`${f.yellow(String(o.unmet.length))} unmet requirement(s):
837
+ `);for(let i of o.unmet){console.log(`${f.yellow("\u25CF")} ${f.bold(i.requirement.type)} (id: ${f.dim(i.id)})`),console.log(` From constraint: ${f.cyan(i.fromConstraint)}`);let n={...i.requirement};delete n.type,Object.keys(n).length>0&&console.log(` Payload: ${JSON.stringify(n)}`);let c=o.resolvers[i.id];c?console.log(` Resolver: ${Ue(c.state)}${c.error?` \u2014 ${c.error}`:""}`):o.resolverDefs.some(d=>d.requirement===i.requirement.type||d.requirement==="(predicate)")||console.log(` ${f.red("No resolver registered for this type")}`),console.log();}console.log(f.dim(`Run ${f.cyan("directive explain <file> <requirement-id>")} for detailed explanation.`));}s.stop();}function Ue(e){switch(e){case "resolved":return f.green("resolved");case "errored":return f.red("errored");case "inflight":return f.yellow("inflight");case "pending":return f.yellow("pending");case "cancelled":return f.dim("cancelled");default:return f.dim(e)}}function Gt(e){let t={ascii:false,open:true},r="";for(let s=0;s<e.length;s++){let o=e[s];switch(o){case "--ascii":t.ascii=true;break;case "--no-open":t.open=false;break;case "--output":{let i=e[++s];i&&(t.output=i);break}default:o&&!o.startsWith("-")&&!r&&(r=o);}}return {filePath:r,opts:t}}function zt(e){let t=[];t.push(f.bold("Dependency Graph")),t.push(f.dim("\u2550".repeat(50))),t.push("");let r=new Map;for(let a of e.constraints)r.set(a.id,{reqTypes:new Set,active:a.active,priority:a.priority});for(let a of e.unmet){let c=r.get(a.fromConstraint);c&&c.reqTypes.add(a.requirement.type);}let s=new Map;for(let a of e.resolverDefs)s.has(a.requirement)||s.set(a.requirement,[]),s.get(a.requirement).push(a.id);t.push(f.bold("Constraints \u2192 Requirements \u2192 Resolvers")),t.push("");for(let[a,c]of r){let m=c.active?f.green("\u25CF"):f.dim("\u25CB");if(t.push(`${m} ${f.cyan(a)} (priority: ${c.priority})`),c.reqTypes.size>0)for(let d of c.reqTypes){t.push(` \u2514\u2500\u25B6 ${f.yellow(d)}`);let l=s.get(d)||[];if(l.length>0)for(let h of l)t.push(` \u2514\u2500\u25B6 ${f.magenta(h)}`);else t.push(` \u2514\u2500\u25B6 ${f.red("(no resolver)")}`);}else t.push(` \u2514\u2500\u25B6 ${f.dim("(no active requirements)")}`);t.push("");}let o=new Set;for(let a of s.values())for(let c of a)o.add(c);if(e.resolverDefs.map(a=>a.id).filter(a=>!o.has(a)).length>0){t.push(f.bold("Standalone Resolvers:"));for(let a of e.resolverDefs)o.has(a.id)||t.push(` ${f.magenta(a.id)} handles ${f.yellow(a.requirement)}`);}return t.join(`
838
+ `)}function _t(e,t){let r=[],s=[],c=Object.keys(t);for(let u=0;u<c.length;u++){let R=c[u];r.push({id:`fact-${R}`,label:R,type:"fact",x:40,y:60+u*50,color:"#3b82f6"});}for(let u=0;u<e.constraints.length;u++){let R=e.constraints[u];r.push({id:`constraint-${R.id}`,label:R.id,type:"constraint",x:260,y:60+u*50,color:R.active?"#22c55e":"#6b7280"});}let m=new Set;for(let u of e.unmet)m.add(u.requirement.type);let d=0;for(let u of m)r.push({id:`req-${u}`,label:u,type:"requirement",x:480,y:60+d*50,color:"#eab308"}),d++;for(let u=0;u<e.resolverDefs.length;u++){let R=e.resolverDefs[u];r.push({id:`resolver-${R.id}`,label:R.id,type:"resolver",x:700,y:60+u*50,color:"#a855f7"});}for(let u of e.unmet)s.push({from:`constraint-${u.fromConstraint}`,to:`req-${u.requirement.type}`});for(let u of e.resolverDefs)m.has(u.requirement)&&s.push({from:`req-${u.requirement}`,to:`resolver-${u.id}`});let l=new Map(r.map(u=>[u.id,u])),h=960,T=Math.max(...r.map(u=>u.y))+50+20,j=s.map(u=>{let R=l.get(u.from),ne=l.get(u.to);return !R||!ne?"":`<line x1="${R.x+90}" y1="${R.y+15}" x2="${ne.x}" y2="${ne.y+15}" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#arrow)"/>`}).join(`
839
+ `),C=r.map(u=>`<g>
840
+ <rect x="${u.x}" y="${u.y}" width="180" height="30" rx="6" fill="${u.color}" opacity="0.15" stroke="${u.color}" stroke-width="1.5"/>
841
+ <text x="${u.x+90}" y="${u.y+19}" text-anchor="middle" font-size="12" font-family="monospace" fill="${u.color}">${Jt(u.label)}</text>
820
842
  </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(`
843
+ `),tt=["Facts","Constraints","Requirements","Resolvers"].map((u,R)=>`<text x="${40+R*220+90}" y="35" text-anchor="middle" font-size="14" font-weight="bold" font-family="system-ui" fill="#e2e8f0">${u}</text>`).join(`
822
844
  `);return `<!DOCTYPE html>
823
845
  <html>
824
846
  <head>
@@ -829,22 +851,117 @@ Current requirements:`),o.unmet.length===0)console.log(d.dim(" (no unmet requir
829
851
  </style>
830
852
  </head>
831
853
  <body>
832
- <svg width="${x}" height="${R}" xmlns="http://www.w3.org/2000/svg">
854
+ <svg width="${h}" height="${T}" xmlns="http://www.w3.org/2000/svg">
833
855
  <defs>
834
856
  <marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
835
857
  <path d="M 0 0 L 10 5 L 0 10 z" fill="#94a3b8"/>
836
858
  </marker>
837
859
  </defs>
838
- ${Ue}
839
- ${Ne}
840
- ${je}
860
+ ${tt}
861
+ ${j}
862
+ ${C}
841
863
  </svg>
842
864
  </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
865
+ </html>`}function Jt(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function Le(e){let{filePath:t,opts:r}=Gt(e);t||(console.error("Usage: directive graph <file> [--ascii] [--no-open] [--output <path>]"),process.exit(1));let s=await P(t);s.isRunning||s.start();let o=s.inspect();if(r.ascii){console.log(zt(o)),s.stop();return}let i={};if(s.facts)for(let c of Object.keys(s.facts))try{i[c]=s.facts[c];}catch{i[c]=null;}let n=_t(o,i),a=r.output||join(process.cwd(),".directive-graph.html");if(writeFileSync(a,n,"utf-8"),console.log(`${f.green("Generated")} ${f.dim(a)}`),r.open)try{let{execFile:c}=await import('child_process'),m=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";c(m,[a]),console.log(f.dim("Opened in browser."));}catch{console.log(f.dim(`Open ${a} in your browser to view the graph.`));}s.stop();}function Ht(e){let t={dir:process.cwd()};for(let r=0;r<e.length;r++)if(e[r]==="--dir"){let s=e[++r];s&&(t.dir=s);}return t}function Kt(e){let t=join(e,"package.json");if(!existsSync(t))return {label:"@directive-run/core installed",passed:false,message:"No package.json found",fix:"Run `npm init` to create a package.json"};let r=JSON.parse(readFileSync(t,"utf-8")),s={...r.dependencies,...r.devDependencies};return s["@directive-run/core"]?{label:"@directive-run/core installed",passed:true,message:`v${s["@directive-run/core"]}`}:{label:"@directive-run/core installed",passed:false,message:"Not found in dependencies",fix:"Run `npm install @directive-run/core`"}}function Yt(e){let t=join(e,"package.json");if(!existsSync(t))return {label:"Package version compatibility",passed:true,message:"Skipped (no package.json)"};let r=JSON.parse(readFileSync(t,"utf-8")),s={...r.dependencies,...r.devDependencies},o=Object.keys(s).filter(i=>i.startsWith("@directive-run/"));return o.length<=1?{label:"Package version compatibility",passed:true,message:o.length===0?"No packages found":"Single package"}:{label:"Package version compatibility",passed:true,message:`${o.length} packages: ${o.join(", ")}`}}function Xt(e){let t=join(e,"tsconfig.json");if(!existsSync(t))return {label:"TypeScript configuration",passed:false,message:"No tsconfig.json found",fix:"Run `tsc --init` to create a TypeScript configuration"};try{let s=readFileSync(t,"utf-8").replace(/\/\/.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,""),i=JSON.parse(s).compilerOptions||{},n=[];return i.strict!==!0&&n.push("strict mode not enabled"),i.moduleResolution&&!["bundler","nodenext","node16"].includes(i.moduleResolution.toLowerCase())&&n.push(`moduleResolution is "${i.moduleResolution}"`),n.length>0?{label:"TypeScript configuration",passed:!1,message:n.join(", "),fix:'Set "strict": true and "moduleResolution": "bundler" in tsconfig.json'}:{label:"TypeScript configuration",passed:!0,message:"strict mode, correct module resolution"}}catch{return {label:"TypeScript configuration",passed:true,message:"Found (could not parse for detailed checks)"}}}function Vt(e){let t=join(e,"node_modules");if(!existsSync(t))return {label:"No duplicate Directive instances",passed:true,message:"No node_modules found"};let r=[];try{let s=join(t,"@directive-run");if(existsSync(s)){let o=readdirSync(s);for(let i of o){let n=join(s,i,"node_modules","@directive-run","core");existsSync(n)&&r.push(`@directive-run/${i}/node_modules/@directive-run/core`);}}}catch{}return r.length>0?{label:"No duplicate Directive instances",passed:false,message:`Found ${r.length} duplicate(s): ${r.join(", ")}`,fix:"Run `npm dedupe` or check for version mismatches"}:{label:"No duplicate Directive instances",passed:true,message:"No duplicates detected"}}function Qt(e){let t=[".cursorrules",".claude/CLAUDE.md",".github/copilot-instructions.md",".windsurfrules",".clinerules"],r=[];for(let s of t){let o=join(e,s);if(existsSync(o)){let i=readFileSync(o,"utf-8");G(i)&&r.push(s);}}return r.length===0?{label:"AI coding rules",passed:true,message:"Not installed (optional)"}:{label:"AI coding rules",passed:true,message:`Installed for: ${r.join(", ")}`}}async function Ge(e){let t=Ht(e);console.log(),console.log(f.bold(f.cyan("Directive Doctor"))),console.log(f.dim("\u2500".repeat(40))),console.log();let r=[Kt(t.dir),Yt(t.dir),Xt(t.dir),Vt(t.dir),Qt(t.dir)],s=0;for(let o of r){let i=o.passed?f.green("\u2713"):f.red("\u2717");console.log(`${i} ${f.bold(o.label)}`),console.log(` ${f.dim(o.message)}`),!o.passed&&o.fix&&(console.log(` ${f.yellow("Fix:")} ${o.fix}`),s++),console.log();}s>0?(console.log(f.yellow(`${s} issue(s) found. See suggested fixes above.`)),process.exit(1)):console.log(f.green("All checks passed!"));}var Je={"Getting Started":["counter","contact-form","auth-flow"],"Core Patterns":["async-chains","batch-resolver","debounce-constraints","error-boundaries","feature-flags","multi-module","optimistic-updates","pagination","permissions"],"Real-World":["dashboard-loader","form-wizard","newsletter","notifications","shopping-cart","theme-locale","url-sync","websocket","server"],Games:["checkers","sudoku","goal-heist","ab-testing"],AI:["ai-orchestrator","ai-checkpoint","ai-guardrails","fraud-analysis","provider-routing","topic-guard","dynamic-modules","time-machine"]};function sr(e){for(let[t,r]of Object.entries(Je))if(r.includes(e))return t;return "Other"}function nr(e){let t=e.split(`
866
+ `);for(let r of t){let s=r.trim();if(s.startsWith("// Example:")||s.startsWith("// Source:")||s.startsWith("// Extracted"))continue;let o=s.match(/^\*\s+(.+?)(?:\s*\*\/)?$/);if(o?.[1]&&!o[1].startsWith("@"))return o[1];if(s.startsWith("//")&&s.length>3)return s.slice(2).trim();if(s!==""&&!s.startsWith("//")&&!s.startsWith("/*")&&!s.startsWith("*"))break}return ""}async function Be(e){let t;for(let n=0;n<e.length;n++)e[n]==="--filter"&&(t=e[++n]?.toLowerCase());let r=getAllExamples();console.log(),console.log(f.bold(f.cyan("Directive Examples"))),console.log(f.dim("\u2500".repeat(50))),console.log();let s=new Map;for(let[n,a]of r){let c=sr(n);t&&!c.toLowerCase().includes(t)&&!n.includes(t)||(s.has(c)||s.set(c,[]),s.get(c).push({name:n,desc:nr(a)}));}if(s.size===0){console.log(f.dim("No examples match the filter."));return}let o=Object.keys(Je),i=[...s.keys()].sort((n,a)=>(o.indexOf(n)??99)-(o.indexOf(a)??99));for(let n of i){let a=s.get(n);console.log(f.bold(n));for(let c of a){let m=c.desc?f.dim(` \u2014 ${c.desc}`):"";console.log(` ${f.cyan(c.name)}${m}`);}console.log();}console.log(f.dim(`${r.size} examples available. Run ${f.cyan("directive examples copy <name>")} to extract one.`));}async function He(e,t){let r=process.cwd();for(let c=0;c<t.length;c++)if(t[c]==="--dest"){let m=t[++c];m&&(r=m);}e||(console.error("Usage: directive examples copy <name> [--dest <dir>]"),process.exit(1));let s=getExample(e);s||(console.error(`Example "${e}" not found.`),console.error(`Run ${f.cyan("directive examples list")} to see available examples.`),process.exit(1));let o=s.replace(/from\s+["']@directive-run\/core\/plugins["']/g,'from "@directive-run/core/plugins"').replace(/from\s+["']@directive-run\/core["']/g,'from "@directive-run/core"').replace(/from\s+["']@directive-run\/ai["']/g,'from "@directive-run/ai"'),i=join(r,`${e}.ts`);existsSync(i)&&(console.error(`File already exists: ${relative(process.cwd(),i)}`),process.exit(1));let n=dirname(i);existsSync(n)||mkdirSync(n,{recursive:true}),writeFileSync(i,o,"utf-8");let a=relative(process.cwd(),i);console.log(`${f.green("Copied")} ${f.cyan(e)} \u2192 ${f.dim(a)}`);}async function B(e=false){try{return await import('@directive-run/timeline')}catch(t){console.error(f.red(`error: @directive-run/timeline not installed in this project.
867
+ Install it: npm install --save-dev @directive-run/timeline`)),e&&console.error(f.dim(t.message)),process.exit(1);}}function cr(e){let t={json:false,dispatchableOnly:true,verbose:false},r="";for(let s=0;s<e.length;s++){let o=e[s];switch(o){case "--system":case "-s":{let i=e[++s];i&&(t.systemPath=i);break}case "--max-frames":{let i=e[++s],n=i?Number.parseInt(i,10):Number.NaN;Number.isFinite(n)&&n>0&&(t.maxFrames=n);break}case "--all-frames":case "--no-dispatchable-only":t.dispatchableOnly=false;break;case "--json":t.json=true;break;case "--verbose":case "-v":t.verbose=true;break;default:o&&!o.startsWith("-")&&!r&&(r=o);}}return {jsonPath:r,opts:t}}function fe(){console.error(`
868
+ Usage: directive replay <timeline.json> [options]
869
+
870
+ Replay a serialized Directive timeline against a fresh system.
871
+
872
+ Arguments:
873
+ <timeline.json> Path to a timeline produced by serializeTimeline()
874
+
875
+ Options:
876
+ --system, -s <path> Path to a TypeScript file exporting a Directive
877
+ system (default export or 'system' named export)
878
+ --max-frames <n> Cap on frames replayed (default 100,000)
879
+ --all-frames Walk every frame, not just dispatchable ones
880
+ (diagnostic mode \u2014 most frames will skip silently)
881
+ --json Emit ReplayResult as JSON
882
+ --verbose, -v Print per-frame trace
883
+ --help, -h Show this help
884
+
885
+ Examples:
886
+ directive replay bug-1234.json --system src/app/system.ts
887
+ directive replay error.json --system src/system.ts --json
888
+ directive replay error.json --system src/system.ts --verbose
889
+ `);}async function Ye(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(fe(),process.exit(e.length===0?1:0));let{jsonPath:t,opts:r}=cr(e);t||(console.error(f.red("error: missing <timeline.json> argument")),fe(),process.exit(1)),r.systemPath||(console.error(f.red("error: --system <path> is required"),f.dim(`
890
+ (replay needs a fresh system to dispatch against)`)),fe(),process.exit(1));let s=resolve(t);existsSync(s)||(console.error(f.red(`error: timeline file not found: ${s}`)),process.exit(1));let o;try{o=readFileSync(s,"utf8");}catch(h){console.error(f.red(`error: failed to read ${s}: ${h.message}`)),process.exit(1);}let i;try{i=JSON.parse(o);}catch(h){console.error(f.red(`error: ${s} is not valid JSON: ${h.message}`)),process.exit(1);}let{deserializeTimeline:n,replayTimeline:a}=await B(r.verbose),c;try{c=n(i);}catch(h){console.error(f.red(`error: timeline JSON failed validation: ${h.message}`)),process.exit(1);}let m;try{m=await P(r.systemPath);}catch(h){console.error(f.red(`error: failed to load system file: ${h.message}`)),process.exit(1);}let d=m;if(typeof d.dispatch!="function"&&(console.error(f.red("error: loaded system has no dispatch() method. The --system file must export a started Directive system or a factory.")),process.exit(1)),typeof d.start=="function")try{d.start();}catch{}let l=await a(c,d,{dispatchableOnly:r.dispatchableOnly,maxFrames:r.maxFrames});if(r.json)console.log(JSON.stringify(l,null,2));else {let{dispatched:h,skipped:T,truncated:j}=l,C=h>0;console.log(`${C?f.green("\u2713"):f.yellow("\u26A0")} replay complete:`,f.bold(`${h} dispatched`),f.dim(`/ ${T} skipped`),j>0?f.yellow(`/ ${j} TRUNCATED`):""),h===0&&console.error(f.yellow("warning: 0 frames dispatched. Either the timeline contains only non-dispatchable frames (system lifecycle, derivations, etc.) or the system shape doesn't match what the timeline recorded.")),j>0&&console.error(f.yellow(`warning: ${j} frames truncated by --max-frames cap. Raise it with --max-frames <n> if you need them.`));}process.exit(0);}function dr(e){let t={json:false,noDeterminismCheck:false,verbose:false},r="";for(let s=0;s<e.length;s++){let o=e[s];switch(o){case "--system":case "-s":{let i=e[++s];i&&(t.systemPath=i);break}case "--assert":case "-a":{let i=e[++s];i&&(t.assertExpr=i);break}case "--max-frames":{let i=e[++s],n=i?Number.parseInt(i,10):Number.NaN;Number.isFinite(n)&&n>0&&(t.maxFrames=n);break}case "--no-determinism-check":t.noDeterminismCheck=true;break;case "--json":t.json=true;break;case "--verbose":case "-v":t.verbose=true;break;default:o&&!o.startsWith("-")&&!r&&(r=o);}}return {jsonPath:r,opts:t}}function se(){console.error(`
891
+ Usage: directive bisect <timeline.json> --system <factory.ts> --assert <expr>
892
+
893
+ Binary-search a recorded timeline for the first frame that triggers a
894
+ failing assertion \u2014 git-bisect, but over ObservationEvent frames.
895
+
896
+ Arguments:
897
+ <timeline.json> Path to a timeline produced by serializeTimeline()
898
+
899
+ Options:
900
+ --system, -s <path> TypeScript file exporting a system factory
901
+ (createSystem / systemFactory / default).
902
+ The factory must return a started Directive
903
+ system; bisect calls it once per midpoint.
904
+ --assert, -a <expression> JS expression with 'facts' and 'system' in
905
+ scope. Truthy = good prefix, falsy = bad
906
+ prefix. Bisect finds the smallest bad prefix.
907
+ --max-frames <n> Per-replay frame cap (default 100,000)
908
+ --no-determinism-check Skip the "replay-twice and compare" gate
909
+ before bisecting. Use only on timelines you
910
+ know are deterministic.
911
+ --json Emit BisectResult as JSON
912
+ --verbose, -v Print every midpoint and its verdict
913
+ --help, -h Show this help
914
+
915
+ SECURITY: --assert is evaluated as JavaScript in this process. Only
916
+ pass expressions from sources you trust (your own scripts, your own
917
+ PRs). Don't paste expressions from issues, untrusted Slack messages,
918
+ or third-party sources without reading them first.
919
+
920
+ Examples:
921
+ directive bisect bug-1234.json --system test/bisect-sys.ts \\
922
+ --assert 'facts.count >= 0'
923
+
924
+ directive bisect crash.json -s factory.ts -a 'facts.status !== "error"' --json
925
+ `);}function pr(e){let t;try{t=new Function("facts","system",`"use strict"; return (${e});`);}catch(r){throw new Error(`Failed to compile --assert expression: ${r.message}
926
+ expression: ${e}`)}return r=>{let s=r?.facts;return !!t(s,r)}}async function Xe(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(se(),process.exit(e.length===0?1:0));let{jsonPath:t,opts:r}=dr(e);t||(console.error(f.red("error: missing <timeline.json> argument")),se(),process.exit(1)),r.systemPath||(console.error(f.red("error: --system <path> is required"),f.dim(`
927
+ (bisect needs a factory to instantiate a fresh system per midpoint)`)),se(),process.exit(1)),r.assertExpr||(console.error(f.red("error: --assert <expression> is required"),f.dim(`
928
+ (assertion distinguishes 'good' from 'bad' system state)`)),se(),process.exit(1));let s=resolve(t);existsSync(s)||(console.error(f.red(`error: timeline file not found: ${s}`)),process.exit(1));let o;try{o=readFileSync(s,"utf8");}catch(C){console.error(f.red(`error: failed to read ${s}: ${C.message}`)),process.exit(1);}let i;try{i=JSON.parse(o);}catch(C){console.error(f.red(`error: ${s} is not valid JSON: ${C.message}`)),process.exit(1);}let{deserializeTimeline:n,bisectTimeline:a}=await B(r.verbose),c;try{c=n(i);}catch(C){console.error(f.red(`error: timeline JSON failed validation: ${C.message}`)),process.exit(1);}let m;try{m=pr(r.assertExpr);}catch(C){console.error(f.red(`error: ${C.message}`)),process.exit(1);}let d;try{d=await Ne(r.systemPath);}catch(C){console.error(f.red(`error: failed to load system factory: ${C.message}`)),process.exit(1);}r.verbose&&console.error(f.dim(`bisecting ${c.frames.length} frames with assertion: ${r.assertExpr}`));let l=await a(c,d,m,{maxFrames:r.maxFrames,determinismCheck:!r.noDeterminismCheck});if(r.json){let C={firstFailingFrameIndex:l.firstFailingFrameIndex??null,iterations:l.iterations,noFailureFound:l.noFailureFound,failsOnEmptyReplay:l.failsOnEmptyReplay,nonDeterministic:l.nonDeterministic};console.log(JSON.stringify(C,null,2)),process.exit(0);}l.nonDeterministic&&(console.error(f.red("\u2717 bisect aborted: timeline is non-deterministic")),console.error(f.dim(` Two full-timeline replays produced different oracle verdicts.
929
+ Bisection is unreliable on non-deterministic timelines.
930
+ Either fix the timeline source (deterministic clocks/seeds)
931
+ or re-run with --no-determinism-check if you accept the risk.`)),process.exit(2)),l.noFailureFound&&(console.error(f.yellow("\u26A0 no failure to bisect: assertion passes on the full timeline")),console.error(f.dim(` The recorded timeline does not exhibit the bug your
932
+ --assert expression checks. Verify the assertion or
933
+ try a different bad.json.`)),process.exit(0)),l.failsOnEmptyReplay&&(console.error(f.yellow("\u26A0 assertion fails BEFORE any frame replays \u2014 bug is in initialization")),console.error(f.dim(` The freshly-started system already violates the assertion.
934
+ Bisect cannot narrow further. Inspect the system factory
935
+ or initial fact values.`)),process.exit(0));let h=l.firstFailingFrameIndex??-1,T=l.firstFailingFrame,j=T?.event.type??"<unknown>";console.log(`${f.green("\u2713")} bisect complete: ${f.bold(`first failing frame is #${h}`)} ${f.dim(`(${j})`)}`),console.log(f.dim(` \u2022 iterations: ${l.iterations} | timeline frames: ${c.frames.length}`)),r.verbose&&T&&(console.log(f.dim(" \u2022 frame:")),console.log(f.dim(` ${JSON.stringify(T,null,2).split(`
936
+ `).join(`
937
+ `)}`))),process.exit(2);}function yr(e){let t={json:false,verbose:false},r=[];for(let s=0;s<e.length;s++){let o=e[s];switch(o){case "--json":t.json=true;break;case "--verbose":case "-v":t.verbose=true;break;default:o&&!o.startsWith("-")&&r.push(o);}}return {aPath:r[0]??"",bPath:r[1]??"",opts:t}}function Ve(){console.error(`
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 B(s.verbose),n=Ze(t),a=Ze(r),c,m;try{c=o(n),m=o(a);}catch(l){console.error(f.red(`error: timeline JSON failed validation: ${l.message}`)),process.exit(1);}let d=i(c,m);s.json&&(console.log(JSON.stringify(d,null,2)),process.exit(d.identical?0:2)),d.identical&&(console.log(f.green("\u2713 identical:"),`both timelines have ${d.aFrameCount} frames and the same causal shape.`),process.exit(0)),console.log(f.bold("Timeline diff"),f.dim(`(${t} vs ${r})`)),console.log(""),console.log(`Frames: ${d.aFrameCount} \u2192 ${d.bFrameCount} (${X(d.frameCountDelta)})`),console.log(""),console.log(f.bold("Constraint fires:"));for(let l of Qe(d.constraintFires))console.log(l);console.log(""),console.log(f.bold("Mutations:"));for(let l of Qe(d.mutations))console.log(l);console.log(""),console.log(f.bold("Resolver runs:"));for(let l of vr(d.resolverRuns))console.log(l);console.log(""),console.log(f.bold("New errors:"));for(let l of br(d.newErrors))console.log(l);console.log(""),process.exit(2);}var wr=`
962
+ ${x} \u2014 CLI tools for Directive
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 Ae(e.slice(1));break}case "new":{let r=e[1],s=e[2];r==="module"?(s||(console.error("Usage: directive new module <name>"),process.exit(1)),await Me(s,e.slice(3))):r==="orchestrator"?(s||(console.error("Usage: directive new orchestrator <name>"),process.exit(1)),await Pe(s,e.slice(3))):(console.error(`Unknown subcommand: ${r??"(none)"}
1019
+ Usage: ${x} new module <name>
1020
+ ${x} new orchestrator <name>`),process.exit(1));break}case "inspect":{await Fe(e.slice(1));break}case "explain":{await We(e.slice(1));break}case "graph":{await Le(e.slice(1));break}case "doctor":{await Ge(e.slice(1));break}case "ai-rules":{let r=e[1];r==="init"?await Se(e.slice(2)):r==="update"?await Ce(e.slice(2)):r==="check"?await Re(e.slice(2)):(console.error(`Unknown subcommand: ${r??"(none)"}
1021
+ Usage: ${x} ai-rules init
1022
+ ${x} ai-rules update
1023
+ ${x} ai-rules check`),process.exit(1));break}case "examples":{let r=e[1];if(r==="list")await Be(e.slice(2));else if(r==="copy"){let s=e[2];s||(console.error("Usage: directive examples copy <name>"),process.exit(1)),await He(s,e.slice(3));}else console.error(`Unknown subcommand: ${r??"(none)"}
1024
+ Usage: ${x} examples list [--filter <category>]
1025
+ ${x} examples copy <name> [--dest <dir>]`),process.exit(1);break}case "replay":{await Ye(e.slice(1));break}case "bisect":{await Xe(e.slice(1));break}case "timeline":{let r=e[1];r==="diff"?await et(e.slice(2)):(console.error(`Unknown subcommand: ${r??"(none)"}
1026
+ Usage: ${x} timeline diff <a.json> <b.json>`),process.exit(1));break}default:console.error(`Unknown command: ${t}
1027
+ Run '${x} --help' for usage.`),process.exit(1);}}xr().catch(e=>{console.error(e.message||e),process.exit(1);});//# sourceMappingURL=cli.js.map
904
1028
  //# sourceMappingURL=cli.js.map