@directive-run/cli 1.15.0 → 1.17.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 {existsSync,readFileSync,mkdirSync,writeFileSync,readdirSync}from'fs';import {resolve,join,relative,dirname}from'path';import*as h from'@clack/prompts';import g from'picocolors';import {getAllExamples,getExample,getKnowledge}from'@directive-run/knowledge';var O="directive";var be="<!-- directive:start -->",ue="<!-- directive:end -->";var Ne=[{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 Ze(e){let t=[];for(let r of Ne)r.signals.some(n=>existsSync(join(e,n)))&&t.push({name:r.name,id:r.id,outputPath:join(e,r.outputPath)});return t}function de(e){let t=Ne.find(r=>r.id===e);if(!t)throw new Error(`Unknown tool: ${e}`);return t}function et(){return Ne.map(e=>e.id)}function re(e,t){let r=e.indexOf(be),s=e.indexOf(ue),n=`${be}
2
+ import {existsSync,readFileSync,mkdirSync,writeFileSync,readdirSync}from'fs';import {resolve,join,relative,dirname}from'path';import*as g from'@clack/prompts';import m from'picocolors';import {getAllExamples,getExample,getKnowledge}from'@directive-run/knowledge';import {validateModuleName,MODULE_SECTIONS,suggestFileNames,generateModule,generateOrchestrator}from'@directive-run/scaffold';var O="directive";var oe="<!-- directive:start -->",Y="<!-- directive:end -->";var Pe=[{id:"cursor",name:"Cursor",signals:[".cursor",".cursorrules"],outputPath:".cursorrules"},{id:"claude",name:"Claude Code",signals:[".claude"],outputPath:".claude/CLAUDE.md"},{id:"copilot",name:"GitHub Copilot",signals:[".github"],outputPath:".github/copilot-instructions.md"},{id:"windsurf",name:"Windsurf",signals:[".windsurfrules"],outputPath:".windsurfrules"},{id:"cline",name:"Cline",signals:[".clinerules"],outputPath:".clinerules"}];function nt(e){let t=[];for(let r of Pe)r.signals.some(n=>existsSync(join(e,n)))&&t.push({name:r.name,id:r.id,outputPath:join(e,r.outputPath)});return t}function ie(e){let t=Pe.find(r=>r.id===e);if(!t)throw new Error(`Unknown tool: ${e}`);return t}function qe(){return Pe.map(e=>e.id)}function X(e,t){let r=e.indexOf(oe),s=e.indexOf(Y),n=`${oe}
3
3
  ${t}
4
- ${ue}`;if(r!==-1&&s!==-1&&s>r)return e.slice(0,r)+n+e.slice(s+ue.length);let o=e.endsWith(`
4
+ ${Y}`;if(r!==-1&&s!==-1&&s>r)return e.slice(0,r)+n+e.slice(s+Y.length);let o=e.endsWith(`
5
5
  `)?`
6
6
  `:`
7
7
 
8
8
  `;return `${e+o+n}
9
- `}function ne(e){return e.includes(be)&&e.includes(ue)}var ar=[{file:"pnpm-workspace.yaml",tool:"pnpm"},{file:"turbo.json",tool:"turbo"}];function rt(e){let t=resolve(e);for(;t!==dirname(t);){for(let s of ar)if(existsSync(join(t,s.file)))return {isMonorepo:true,rootDir:t,tool:s.tool};let r=join(t,"package.json");if(existsSync(r))try{if(JSON.parse(readFileSync(r,"utf-8")).workspaces){let n=existsSync(join(t,"yarn.lock"))?"yarn":"npm";return {isMonorepo:!0,rootDir:t,tool:n}}}catch{}t=dirname(t);}return {isMonorepo:false,rootDir:e}}function st(){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 V(e){return e.includes(oe)&&e.includes(Y)}var ur=[{file:"pnpm-workspace.yaml",tool:"pnpm"},{file:"turbo.json",tool:"turbo"}];function We(e){let t=resolve(e);for(;t!==dirname(t);){for(let s of ur)if(existsSync(join(t,s.file)))return {isMonorepo:true,rootDir:t,tool:s.tool};let r=join(t,"package.json");if(existsSync(r))try{if(JSON.parse(readFileSync(r,"utf-8")).workspaces){let n=existsSync(join(t,"yarn.lock"))?"yarn":"npm";return {isMonorepo:!0,rootDir:t,tool:n}}}catch{}t=dirname(t);}return {isMonorepo:false,rootDir:e}}function it(){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\`
@@ -259,7 +259,7 @@ for await (const chunk of streamResult.stream) {
259
259
  \`\`\`
260
260
 
261
261
  Backpressure: \`"buffer"\` (default), \`"block"\`, \`"drop"\`
262
- `}function ke(){return '# Directive \u2014 AI Coding Rules\n\n> Constraint-driven runtime for TypeScript. `npm install @directive-run/core`\n> Full reference: https://directive.run/llms.txt\n\n## When to reach for Directive\n\nDirective is to **business state** what XState is to state machines and\nReact Query is to server state \u2014 a runtime that takes declarative rules\n("what must be true") and runs the resolvers ("how to make it true") for\nyou. It is NOT a Redux replacement for cross-cutting global UI state;\nit is a constraint engine you compose alongside Redux / Zustand / Jotai\n/ React Query.\n\nReach for Directive when:\n\n- The same business rule has to fire across React, Vue, server, and\n background workers. Directive runs the same module in every runtime.\n- You want a constraint to drive a side-effect (fetch, validate,\n cancel, retry) declaratively, without writing imperative thunks.\n- You are orchestrating LLM agents and need typed, replayable state +\n guardrails + budgets. `@directive-run/ai` is the only state-library\n ecosystem that ships AI orchestration as a sibling concept.\n- You want time-travel debugging, audit logs, or rules-diff replay on\n state mutations without instrumenting every component.\n\nYou do NOT need Directive for plain UI state (use signals / Zustand /\nJotai), simple server-state caching (use React Query / TanStack Query),\nor state machines that don\'t react to external facts (use XState).\n\n## Schema Shape (CRITICAL)\n\n```typescript\nimport { createModule, createSystem, t } from "@directive-run/core";\n\nconst myModule = createModule("name", {\n schema: {\n facts: { count: t.number(), items: t.array<string>() },\n derivations: { total: "number" },\n events: { increment: "void", addItem: "string" },\n requirements: { FETCH_DATA: { url: "string" } },\n },\n init: (facts) => { facts.count = 0; facts.items = []; },\n derive: {\n total: (facts) => facts.items.length + facts.count,\n },\n events: {\n increment: (facts) => { facts.count += 1; },\n addItem: (facts, item) => { facts.items = [...facts.items, item]; },\n },\n constraints: {\n fetchWhenReady: {\n when: (facts) => facts.count > 0 && facts.items.length === 0,\n require: (facts) => ({ type: "FETCH_DATA", url: "/api/items" }),\n },\n },\n resolvers: {\n fetchData: {\n requirement: "FETCH_DATA",\n resolve: async (req, context) => {\n const data = await fetch(req.url).then(r => r.json());\n context.facts.items = data;\n },\n },\n },\n});\n\nconst system = createSystem({ module: myModule });\nawait system.settle();\n```\n\n## Top 10 Anti-Patterns\n\n| # | WRONG | CORRECT |\n|---|-------|---------|\n| 1 | `facts.profile as ResourceState<Profile>` | Remove cast \u2014 schema provides types |\n| 2 | `{ phase: t.string() }` flat schema | `schema: { facts: { phase: t.string() } }` |\n| 3 | `facts.items` in multi-module | `facts.self.items` |\n| 4 | `t.map()`, `t.set()`, `t.promise()` | Don\'t exist. Use `t.object<Map<K,V>>()` |\n| 5 | `(req, ctx)` in resolver | `(req, context)` \u2014 never abbreviate |\n| 6 | `createModule("n", { phase: t.string() })` | Must wrap: `schema: { facts: { ... } }` |\n| 7 | `system.dispatch(\'login\', {...})` | `system.events.login({...})` |\n| 8 | `facts.items.push(item)` | `facts.items = [...facts.items, item]` |\n| 9 | `useEvent`/`DirectiveProvider` top-level imports | `useEvents`; `createDirectiveContext(system).Provider` |\n| 10 | `facts[\'auth::status\']` | `facts.auth.status` dot notation |\n\n## Naming\n\n- `req` = requirement (not request). Parameter: `(req, context)`\n- `derive` / derivations \u2014 never "computed" or "selectors"\n- Resolvers return `void` \u2014 mutate `context.facts` instead\n- Always use braces for returns: `if (x) { return y; }`\n- Multi-module: `facts.self.fieldName` for own module facts\n- Events: `system.events.eventName(payload)` \u2014 not `system.dispatch()`\n- Import from main: `import { createModule } from \'@directive-run/core\'`\n\n## Schema Types That Exist\n\n`t.string<T>()`, `t.number()`, `t.boolean()`, `t.array<T>()`, `t.object<T>()`,\n`t.enum("a","b")`, `t.literal(value)`, `t.nullable(inner)`, `t.optional(inner)`, `t.union(...)`\n\nChainable: `.default()`, `.validate()`, `.transform()`, `.brand<>()`, `.refine()`\n\n**DO NOT USE** (hallucinations): `t.map()`, `t.set()`, `t.date()`, `t.tuple()`, `t.record()`, `t.promise()`, `t.any()`\n\n## Key Pattern: Constraint \u2192 Requirement \u2192 Resolver\n\nWhen the user wants "do X when Y": create THREE things:\n1. **Constraint**: `when: (facts) => Y_condition` \u2192 `require: { type: "DO_X" }`\n2. **Resolver**: handles "DO_X", calls API, sets `context.facts`\n3. They are **decoupled**. Constraint declares need, resolver fulfills it.\n'}function se(){return ke()+"\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"+`
262
+ `}function Se(){return '# Directive \u2014 AI Coding Rules\n\n> Constraint-driven runtime for TypeScript. `npm install @directive-run/core`\n> Full reference: https://directive.run/llms.txt\n\n## When to reach for Directive\n\nDirective is to **business state** what XState is to state machines and\nReact Query is to server state \u2014 a runtime that takes declarative rules\n("what must be true") and runs the resolvers ("how to make it true") for\nyou. It is NOT a Redux replacement for cross-cutting global UI state;\nit is a constraint engine you compose alongside Redux / Zustand / Jotai\n/ React Query.\n\nReach for Directive when:\n\n- The same business rule has to fire across React, Vue, server, and\n background workers. Directive runs the same module in every runtime.\n- You want a constraint to drive a side-effect (fetch, validate,\n cancel, retry) declaratively, without writing imperative thunks.\n- You are orchestrating LLM agents and need typed, replayable state +\n guardrails + budgets. `@directive-run/ai` is the only state-library\n ecosystem that ships AI orchestration as a sibling concept.\n- You want time-travel debugging, audit logs, or rules-diff replay on\n state mutations without instrumenting every component.\n\nYou do NOT need Directive for plain UI state (use signals / Zustand /\nJotai), simple server-state caching (use React Query / TanStack Query),\nor state machines that don\'t react to external facts (use XState).\n\n## Schema Shape (CRITICAL)\n\n```typescript\nimport { createModule, createSystem, t } from "@directive-run/core";\n\nconst myModule = createModule("name", {\n schema: {\n facts: { count: t.number(), items: t.array<string>() },\n derivations: { total: "number" },\n events: { increment: "void", addItem: "string" },\n requirements: { FETCH_DATA: { url: "string" } },\n },\n init: (facts) => { facts.count = 0; facts.items = []; },\n derive: {\n total: (facts) => facts.items.length + facts.count,\n },\n events: {\n increment: (facts) => { facts.count += 1; },\n addItem: (facts, item) => { facts.items = [...facts.items, item]; },\n },\n constraints: {\n fetchWhenReady: {\n when: (facts) => facts.count > 0 && facts.items.length === 0,\n require: (facts) => ({ type: "FETCH_DATA", url: "/api/items" }),\n },\n },\n resolvers: {\n fetchData: {\n requirement: "FETCH_DATA",\n resolve: async (req, context) => {\n const data = await fetch(req.url).then(r => r.json());\n context.facts.items = data;\n },\n },\n },\n});\n\nconst system = createSystem({ module: myModule });\nawait system.settle();\n```\n\n## Top 10 Anti-Patterns\n\n| # | WRONG | CORRECT |\n|---|-------|---------|\n| 1 | `facts.profile as ResourceState<Profile>` | Remove cast \u2014 schema provides types |\n| 2 | `{ phase: t.string() }` flat schema | `schema: { facts: { phase: t.string() } }` |\n| 3 | `facts.items` in multi-module | `facts.self.items` |\n| 4 | `t.map()`, `t.set()`, `t.promise()` | Don\'t exist. Use `t.object<Map<K,V>>()` |\n| 5 | `(req, ctx)` in resolver | `(req, context)` \u2014 never abbreviate |\n| 6 | `createModule("n", { phase: t.string() })` | Must wrap: `schema: { facts: { ... } }` |\n| 7 | `system.dispatch(\'login\', {...})` | `system.events.login({...})` |\n| 8 | `facts.items.push(item)` | `facts.items = [...facts.items, item]` |\n| 9 | `useEvent`/`DirectiveProvider` top-level imports | `useEvents`; `createDirectiveContext(system).Provider` |\n| 10 | `facts[\'auth::status\']` | `facts.auth.status` dot notation |\n\n## Naming\n\n- `req` = requirement (not request). Parameter: `(req, context)`\n- `derive` / derivations \u2014 never "computed" or "selectors"\n- Resolvers return `void` \u2014 mutate `context.facts` instead\n- Always use braces for returns: `if (x) { return y; }`\n- Multi-module: `facts.self.fieldName` for own module facts\n- Events: `system.events.eventName(payload)` \u2014 not `system.dispatch()`\n- Import from main: `import { createModule } from \'@directive-run/core\'`\n\n## Schema Types That Exist\n\n`t.string<T>()`, `t.number()`, `t.boolean()`, `t.array<T>()`, `t.object<T>()`,\n`t.enum("a","b")`, `t.literal(value)`, `t.nullable(inner)`, `t.optional(inner)`, `t.union(...)`\n\nChainable: `.default()`, `.validate()`, `.transform()`, `.brand<>()`, `.refine()`\n\n**DO NOT USE** (hallucinations): `t.map()`, `t.set()`, `t.date()`, `t.tuple()`, `t.record()`, `t.promise()`, `t.any()`\n\n## Key Pattern: Constraint \u2192 Requirement \u2192 Resolver\n\nWhen the user wants "do X when Y": create THREE things:\n1. **Constraint**: `when: (facts) => Y_condition` \u2192 `require: { type: "DO_X" }`\n2. **Resolver**: handles "DO_X", calls API, sets `context.facts`\n3. They are **decoupled**. Constraint declares need, resolver fulfills it.\n'}function ae(){return Se()+"\n## Anti-Patterns 11-19\n\n| # | WRONG | CORRECT |\n|---|-------|---------|\n| 11 | Returning data from `resolve` | Resolvers return `void` \u2014 mutate `context.facts` |\n| 12 | Async logic in `init` | `init` is synchronous, facts assignment only |\n| 13 | `await system.start()` without settle | Add `await system.settle()` after start |\n| 14 | Missing `crossModuleDeps` | Declare `crossModuleDeps: { auth: authSchema }` |\n| 15 | `require: \"TYPE\"` string literal | `require: { type: \"TYPE\" }` object form |\n| 16 | Passthrough derivation `(f) => f.count` | Remove \u2014 read fact directly |\n| 17 | `from '@directive-run/core/module'` | `from '@directive-run/core'` (main export) |\n| 18 | `async when()` without `deps` | Add `deps: ['factName']` for async constraints |\n| 19 | No error boundary on resolver | Use try-catch or module error boundary config |\n"+`
263
263
  ## Multi-Module
264
264
 
265
265
  \`\`\`typescript
@@ -292,40 +292,44 @@ const result = await orchestrator.run(agent, "analyze this");
292
292
  - Subpath imports: \`from '@directive-run/ai/anthropic'\` not \`from '@directive-run/ai'\`
293
293
  - Token usage normalized: \`{ inputTokens, outputTokens }\` (not provider-specific)
294
294
  - \`facts.cache = [...facts.cache, item]\` not \`facts.cache.push(item)\`
295
- `}function ot(){return se()}function it(){return se()}var lr={cursor:ke,claude:st,copilot:se,windsurf:it,cline:ot};function xe(e){let t=lr[e];if(!t)throw new Error(`No template for tool: ${e}`);return t()}function We(e){let t={force:false,merge:false,tools:[],dir:process.cwd()};for(let r=0;r<e.length;r++)switch(e[r]){case "--force":t.force=true;break;case "--merge":t.merge=true;break;case "--tool":{let n=e[++r];n&&t.tools.push(n);break}case "--dir":{let n=e[++r];n&&(t.dir=n);break}}return t}async function at(e){let t=We(e);h.intro(g.bgCyan(g.black(" directive ai-rules ")));let r=rt(t.dir),s=t.dir;if(r.isMonorepo&&r.rootDir!==t.dir){let i=await h.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)})`}]});h.isCancel(i)&&(h.cancel("Cancelled."),process.exit(0)),i==="root"&&(s=r.rootDir);}let n;if(t.tools.length>0)n=t.tools.map(i=>{let c=de(i);return {name:c.name,id:c.id,outputPath:join(s,c.outputPath)}});else {let i=Ze(s);if(i.length>0){let c=await h.multiselect({message:`Detected ${i.length} AI tool(s). Which should get Directive rules?`,options:i.map(a=>({value:a.id,label:a.name,hint:relative(s,a.outputPath)})),initialValues:i.map(a=>a.id),required:true});h.isCancel(c)&&(h.cancel("Cancelled."),process.exit(0)),n=c.map(a=>{let l=de(a);return {name:l.name,id:l.id,outputPath:join(s,l.outputPath)}});}else {let c=await h.multiselect({message:"No AI tools detected. Which tools do you use?",options:et().map(a=>{let l=de(a);return {value:a,label:l.name}}),required:true});h.isCancel(c)&&(h.cancel("Cancelled."),process.exit(0)),n=c.map(a=>{let l=de(a);return {name:l.name,id:l.id,outputPath:join(s,l.outputPath)}});}}n.length===0&&(h.cancel("No tools selected."),process.exit(0));let o=h.spinner();for(let i of n){o.start(`Generating ${i.name} rules...`);let c=xe(i.id),a=i.outputPath,l=existsSync(a);if(o.stop(`Generated ${i.name} rules.`),l&&!t.force){let u=readFileSync(a,"utf-8");if(t.merge){Q(a,re(u,c)),h.log.success(`${g.green("Merged")} Directive section into ${g.dim(relative(s,a))}`);continue}if(ne(u)){let d=await h.select({message:`${relative(s,a)} already has a Directive section. What should we do?`,options:[{value:"merge",label:"Update Directive section only",hint:"recommended"},{value:"overwrite",label:"Overwrite entire file"},{value:"skip",label:"Skip this file"}]});h.isCancel(d)&&(h.cancel("Cancelled."),process.exit(0)),d==="merge"?(Q(a,re(u,c)),h.log.success(`${g.green("Updated")} ${g.dim(relative(s,a))}`)):d==="overwrite"?(Q(a,c),h.log.success(`${g.green("Wrote")} ${g.dim(relative(s,a))}`)):h.log.info(`Skipped ${g.dim(relative(s,a))}`);}else {let d=await h.select({message:`${relative(s,a)} already exists. What should we do?`,options:[{value:"append",label:"Append Directive section",hint:"preserves existing content"},{value:"overwrite",label:"Overwrite entire file"},{value:"skip",label:"Skip this file"}]});h.isCancel(d)&&(h.cancel("Cancelled."),process.exit(0)),d==="append"?(Q(a,re(u,c)),h.log.success(`${g.green("Appended")} to ${g.dim(relative(s,a))}`)):d==="overwrite"?(Q(a,c),h.log.success(`${g.green("Wrote")} ${g.dim(relative(s,a))}`)):h.log.info(`Skipped ${g.dim(relative(s,a))}`);}}else Q(a,c),h.log.success(`${g.green("Created")} ${g.dim(relative(s,a))}`);}h.outro(`Done! Run ${g.cyan(`${O} 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 ct(e){let r=We(e).dir,s=[{id:"cursor",path:join(r,".cursorrules")},{id:"claude",path:join(r,".claude/CLAUDE.md")},{id:"copilot",path:join(r,".github/copilot-instructions.md")},{id:"windsurf",path:join(r,".windsurfrules")},{id:"cline",path:join(r,".clinerules")}],n=0;for(let o of s){if(!existsSync(o.path))continue;let i=readFileSync(o.path,"utf-8");if(!ne(i))continue;let c=xe(o.id),a=re(i,c);Q(o.path,a),console.log(`${g.green("Updated")} ${g.dim(relative(r,o.path))}`),n++;}console.log(n===0?g.dim(`No existing rule files found. Run ${g.cyan(`${O} ai-rules init`)} first.`):g.green(`
296
- Updated ${n} file(s) to latest knowledge version.`));}async function lt(e){let r=We(e).dir,s=[{id:"cursor",path:join(r,".cursorrules"),name:"Cursor"},{id:"claude",path:join(r,".claude/CLAUDE.md"),name:"Claude Code"},{id:"copilot",path:join(r,".github/copilot-instructions.md"),name:"GitHub Copilot"},{id:"windsurf",path:join(r,".windsurfrules"),name:"Windsurf"},{id:"cline",path:join(r,".clinerules"),name:"Cline"}],n=0,o=0;for(let i of s){if(!existsSync(i.path))continue;let c=readFileSync(i.path,"utf-8");if(!ne(c))continue;n++;let a=xe(i.id);re(c,a)!==c?(console.log(`${g.red("\u2717")} ${i.name} rules are ${g.yellow("stale")}`),o++):console.log(`${g.green("\u2713")} ${i.name} rules are ${g.green("current")}`);}if(n===0){console.log(g.dim("No rule files found to check."));return}o>0?(console.log(`
297
- ${g.yellow(`${o} file(s) are stale.`)} Run ${g.cyan(`${O} ai-rules update`)} to refresh.`),process.exit(1)):console.log(g.green(`
298
- All rule files are current.`));}async function z(e){let t=resolve(e);if(!existsSync(t))throw new Error(`File not found: ${t}`);try{let r=await import(t);if(r.default&&Y(r.default))return r.default;if(r.system&&Y(r.system))return r.system;for(let s of Object.keys(r))if(Y(r[s]))return r[s];throw new Error(`No Directive system found in ${g.dim(e)}
295
+ `}function at(){return ae()}function ct(){return ae()}var fr={cursor:Se,claude:it,copilot:ae,windsurf:ct,cline:at};function me(e){let t=fr[e];if(!t)throw new Error(`No template for tool: ${e}`);return t()}function Ue(e){let t={force:false,merge:false,tools:[],dir:process.cwd()};for(let r=0;r<e.length;r++)switch(e[r]){case "--force":t.force=true;break;case "--merge":t.merge=true;break;case "--tool":{let n=e[++r];n&&t.tools.push(n);break}case "--dir":{let n=e[++r];n&&(t.dir=n);break}}return t}async function lt(e){let t=Ue(e);g.intro(m.bgCyan(m.black(" directive ai-rules ")));let r=We(t.dir),s=t.dir;if(r.isMonorepo&&r.rootDir!==t.dir){let c=await g.select({message:"Monorepo detected. Where should AI rules be installed?",options:[{value:"root",label:`Monorepo root (${relative(t.dir,r.rootDir)||"."})`,hint:"recommended"},{value:"workspace",label:`Current workspace (${relative(r.rootDir,t.dir)})`}]});g.isCancel(c)&&(g.cancel("Cancelled."),process.exit(0)),c==="root"&&(s=r.rootDir);}let n;if(t.tools.length>0)n=t.tools.map(c=>{let a=ie(c);return {name:a.name,id:a.id,outputPath:join(s,a.outputPath)}});else {let c=nt(s);if(c.length>0){let a=await g.multiselect({message:`Detected ${c.length} AI tool(s). Which should get Directive rules?`,options:c.map(i=>({value:i.id,label:i.name,hint:relative(s,i.outputPath)})),initialValues:c.map(i=>i.id),required:true});g.isCancel(a)&&(g.cancel("Cancelled."),process.exit(0)),n=a.map(i=>{let l=ie(i);return {name:l.name,id:l.id,outputPath:join(s,l.outputPath)}});}else {let a=await g.multiselect({message:"No AI tools detected. Which tools do you use?",options:qe().map(i=>{let l=ie(i);return {value:i,label:l.name}}),required:true});g.isCancel(a)&&(g.cancel("Cancelled."),process.exit(0)),n=a.map(i=>{let l=ie(i);return {name:l.name,id:l.id,outputPath:join(s,l.outputPath)}});}}n.length===0&&(g.cancel("No tools selected."),process.exit(0));let o=g.spinner();for(let c of n){o.start(`Generating ${c.name} rules...`);let a=me(c.id),i=c.outputPath,l=existsSync(i);if(o.stop(`Generated ${c.name} rules.`),l&&!t.force){let u=readFileSync(i,"utf-8");if(t.merge){U(i,X(u,a)),g.log.success(`${m.green("Merged")} Directive section into ${m.dim(relative(s,i))}`);continue}if(V(u)){let d=await g.select({message:`${relative(s,i)} already has a Directive section. What should we do?`,options:[{value:"merge",label:"Update Directive section only",hint:"recommended"},{value:"overwrite",label:"Overwrite entire file"},{value:"skip",label:"Skip this file"}]});g.isCancel(d)&&(g.cancel("Cancelled."),process.exit(0)),d==="merge"?(U(i,X(u,a)),g.log.success(`${m.green("Updated")} ${m.dim(relative(s,i))}`)):d==="overwrite"?(U(i,a),g.log.success(`${m.green("Wrote")} ${m.dim(relative(s,i))}`)):g.log.info(`Skipped ${m.dim(relative(s,i))}`);}else {let d=await g.select({message:`${relative(s,i)} already exists. What should we do?`,options:[{value:"append",label:"Append Directive section",hint:"preserves existing content"},{value:"overwrite",label:"Overwrite entire file"},{value:"skip",label:"Skip this file"}]});g.isCancel(d)&&(g.cancel("Cancelled."),process.exit(0)),d==="append"?(U(i,X(u,a)),g.log.success(`${m.green("Appended")} to ${m.dim(relative(s,i))}`)):d==="overwrite"?(U(i,a),g.log.success(`${m.green("Wrote")} ${m.dim(relative(s,i))}`)):g.log.info(`Skipped ${m.dim(relative(s,i))}`);}}else U(i,a),g.log.success(`${m.green("Created")} ${m.dim(relative(s,i))}`);}g.outro(`Done! Run ${m.cyan(`${O} ai-rules init --merge`)} anytime to update.`);}function U(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}function gr(e){let t={dir:process.cwd(),force:false};for(let r=0;r<e.length;r++){let s=e[r];if(s==="--force")t.force=true;else if(s==="--dir"){let n=e[++r];n&&(t.dir=n);}}return t}async function Le(e){let t=gr(e),r=We(t.dir),s=r.isMonorepo&&r.rootDir!==t.dir?r.rootDir:t.dir;s!==t.dir&&console.log(m.dim(`Monorepo detected \u2014 installing at root (${relative(t.dir,s)||"."})`));let o=qe().map(l=>{let u=ie(l);return {id:u.id,name:u.name,outputPath:join(s,u.outputPath)}}),c=0,a=0,i=0;for(let l of o){let u=me(l.id),d=`${oe}
296
+ ${u}
297
+ ${Y}`,f=l.outputPath,h=relative(s,f);if(!existsSync(f)){U(f,`${d}
298
+ `),console.log(`${m.green("\u2713")} ${l.name.padEnd(20)} ${m.dim(h)}`),c++;continue}let $=readFileSync(f,"utf-8");if(t.force){U(f,`${d}
299
+ `),console.log(`${m.yellow("\u21BB")} ${l.name.padEnd(20)} ${m.dim(h)} ${m.dim("(overwrote)")}`),c++;continue}if(V($)){U(f,X($,u)),console.log(`${m.green("\u2713")} ${l.name.padEnd(20)} ${m.dim(h)} ${m.dim("(merged section)")}`),a++;continue}console.log(`${m.dim("\xB7")} ${l.name.padEnd(20)} ${m.dim(h)} ${m.dim("(exists, no Directive section \u2014 pass --force to overwrite)")}`),i++;}console.log(""),console.log(m.green(`Installed Directive AI rules for ${o.length} tools.`)),console.log(m.dim(` ${c} written \xB7 ${a} merged \xB7 ${i} skipped (existing non-Directive content preserved)`)),console.log(""),console.log(m.dim("Next steps:")),console.log(m.dim(" \u2022 Restart your AI assistant so it picks up the new rules file.")),console.log(m.dim(` \u2022 Run ${m.cyan(`${O} ai-rules update`)} after each ${m.cyan("@directive-run/*")} version bump.`)),console.log(m.dim(` \u2022 For Claude Code, the plugin (${m.cyan("/plugin install directive@directive-plugins")}) is the canonical install \u2014 these files are the fallback for non-Claude editors.`));}async function ut(e){let r=Ue(e).dir,s=[{id:"cursor",path:join(r,".cursorrules")},{id:"claude",path:join(r,".claude/CLAUDE.md")},{id:"copilot",path:join(r,".github/copilot-instructions.md")},{id:"windsurf",path:join(r,".windsurfrules")},{id:"cline",path:join(r,".clinerules")}],n=0;for(let o of s){if(!existsSync(o.path))continue;let c=readFileSync(o.path,"utf-8");if(!V(c))continue;let a=me(o.id),i=X(c,a);U(o.path,i),console.log(`${m.green("Updated")} ${m.dim(relative(r,o.path))}`),n++;}console.log(n===0?m.dim(`No existing rule files found. Run ${m.cyan(`${O} ai-rules init`)} first.`):m.green(`
300
+ Updated ${n} file(s) to latest knowledge version.`));}async function dt(e){let r=Ue(e).dir,s=[{id:"cursor",path:join(r,".cursorrules"),name:"Cursor"},{id:"claude",path:join(r,".claude/CLAUDE.md"),name:"Claude Code"},{id:"copilot",path:join(r,".github/copilot-instructions.md"),name:"GitHub Copilot"},{id:"windsurf",path:join(r,".windsurfrules"),name:"Windsurf"},{id:"cline",path:join(r,".clinerules"),name:"Cline"}],n=0,o=0;for(let c of s){if(!existsSync(c.path))continue;let a=readFileSync(c.path,"utf-8");if(!V(a))continue;n++;let i=me(c.id);X(a,i)!==a?(console.log(`${m.red("\u2717")} ${c.name} rules are ${m.yellow("stale")}`),o++):console.log(`${m.green("\u2713")} ${c.name} rules are ${m.green("current")}`);}if(n===0){console.log(m.dim("No rule files found to check."));return}o>0?(console.log(`
301
+ ${m.yellow(`${o} file(s) are stale.`)} Run ${m.cyan(`${O} ai-rules update`)} to refresh.`),process.exit(1)):console.log(m.green(`
302
+ All rule files are current.`));}async function z(e){let t=resolve(e);if(!existsSync(t))throw new Error(`File not found: ${t}`);try{let r=await import(t);if(r.default&&Z(r.default))return r.default;if(r.system&&Z(r.system))return r.system;for(let s of Object.keys(r))if(Z(r[s]))return r[s];throw new Error(`No Directive system found in ${m.dim(e)}
299
303
  Export a system as default or named "system":
300
304
 
301
- ${g.cyan("export default")} createSystem({ module: myModule });
302
- ${g.cyan("export const system")} = createSystem({ module: myModule });`)}catch(r){throw r instanceof Error&&r.message.includes("No Directive system")?r:new Error(`Failed to load ${g.dim(e)}: ${r instanceof Error?r.message:String(r)}
305
+ ${m.cyan("export default")} createSystem({ module: myModule });
306
+ ${m.cyan("export const system")} = createSystem({ module: myModule });`)}catch(r){throw r instanceof Error&&r.message.includes("No Directive system")?r:new Error(`Failed to load ${m.dim(e)}: ${r instanceof Error?r.message:String(r)}
303
307
 
304
308
  Make sure the file is valid TypeScript and tsx is installed:
305
- ${g.cyan("npm install -D tsx")}`)}}function Y(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 ft(e){let t=resolve(e);if(!existsSync(t))throw new Error(`File not found: ${t}`);let r;try{r=await import(t);}catch(o){throw new Error(`Failed to load ${g.dim(e)}: ${o instanceof Error?o.message:String(o)}
309
+ ${m.cyan("npm install -D tsx")}`)}}function Z(e){if(typeof e!="object"||e===null)return false;let t=e;return typeof t.inspect=="function"&&typeof t.start=="function"&&typeof t.stop=="function"&&"facts"in t}async function mt(e){let t=resolve(e);if(!existsSync(t))throw new Error(`File not found: ${t}`);let r;try{r=await import(t);}catch(o){throw new Error(`Failed to load ${m.dim(e)}: ${o instanceof Error?o.message:String(o)}
306
310
 
307
311
  Make sure the file is valid TypeScript and tsx is installed:
308
- ${g.cyan("npm install -D tsx")}`)}let s=[["createSystem",r.createSystem],["systemFactory",r.systemFactory],["default",r.default]];for(let[o,i]of s)if(typeof i=="function")return async()=>{let c=await Promise.resolve(i());if(!Y(c))throw new Error(`Factory '${o}' from ${g.dim(e)} returned a value that is not a started Directive system.
309
- Expected an object with inspect/start/stop/facts. The factory must call sys.start() before returning.`);return c};throw Y(r.default)||Y(r.system)||Object.values(r).some(Y)?new Error(`Found a started Directive system in ${g.dim(e)}, but bisect needs a factory.
312
+ ${m.cyan("npm install -D tsx")}`)}let s=[["createSystem",r.createSystem],["systemFactory",r.systemFactory],["default",r.default]];for(let[o,c]of s)if(typeof c=="function")return async()=>{let a=await Promise.resolve(c());if(!Z(a))throw new Error(`Factory '${o}' from ${m.dim(e)} returned a value that is not a started Directive system.
313
+ Expected an object with inspect/start/stop/facts. The factory must call sys.start() before returning.`);return a};throw Z(r.default)||Z(r.system)||Object.values(r).some(Z)?new Error(`Found a started Directive system in ${m.dim(e)}, but bisect needs a factory.
310
314
  Bisect instantiates a fresh system for every midpoint replay (so each attempt is hermetic),
311
- which means it can't reuse a singleton instance the way ${g.cyan("directive replay")} does.
315
+ which means it can't reuse a singleton instance the way ${m.cyan("directive replay")} does.
312
316
 
313
317
  Wrap the existing export in a function:
314
318
 
315
- ${g.cyan("export function createSystem()")} {
319
+ ${m.cyan("export function createSystem()")} {
316
320
  const sys = createSystem({ module: yourModule });
317
321
  sys.start();
318
322
  return sys;
319
- }`):new Error(`No system factory found in ${g.dim(e)}
323
+ }`):new Error(`No system factory found in ${m.dim(e)}
320
324
  Bisect needs to instantiate a fresh system per midpoint replay. Export one of:
321
325
 
322
- ${g.cyan("export function createSystem()")} { ... return sys; }
323
- ${g.cyan("export const systemFactory")} = () => { ... return sys; };
324
- ${g.cyan("export default")} () => { ... return sys; };
326
+ ${m.cyan("export function createSystem()")} { ... return sys; }
327
+ ${m.cyan("export const systemFactory")} = () => { ... return sys; };
328
+ ${m.cyan("export default")} () => { ... return sys; };
325
329
 
326
330
  The factory MUST call sys.start() and return the started system.
327
- (Did you forget ${g.cyan("sys.start()")} before returning?)`)}async function oe(e=false){try{return await import('@directive-run/timeline')}catch(t){console.error(g.red(`error: @directive-run/timeline not installed in this project.
328
- Install it: npm install --save-dev @directive-run/timeline`)),e&&console.error(g.dim(t.message)),process.exit(1);}}function gr(e){let t={json:false,noDeterminismCheck:false,verbose:false},r="";for(let s=0;s<e.length;s++){let n=e[s];switch(n){case "--system":case "-s":{let o=e[++s];o&&(t.systemPath=o);break}case "--assert":case "-a":{let o=e[++s];o&&(t.assertExpr=o);break}case "--max-frames":{let o=e[++s],i=o?Number.parseInt(o,10):Number.NaN;Number.isFinite(i)&&i>0&&(t.maxFrames=i);break}case "--no-determinism-check":t.noDeterminismCheck=true;break;case "--json":t.json=true;break;case "--verbose":case "-v":t.verbose=true;break;default:n&&!n.startsWith("-")&&!r&&(r=n);}}return {jsonPath:r,opts:t}}function Ae(){console.error(`
331
+ (Did you forget ${m.cyan("sys.start()")} before returning?)`)}async function ce(e=false){try{return await import('@directive-run/timeline')}catch(t){console.error(m.red(`error: @directive-run/timeline not installed in this project.
332
+ Install it: npm install --save-dev @directive-run/timeline`)),e&&console.error(m.dim(t.message)),process.exit(1);}}function wr(e){let t={json:false,noDeterminismCheck:false,verbose:false},r="";for(let s=0;s<e.length;s++){let n=e[s];switch(n){case "--system":case "-s":{let o=e[++s];o&&(t.systemPath=o);break}case "--assert":case "-a":{let o=e[++s];o&&(t.assertExpr=o);break}case "--max-frames":{let o=e[++s],c=o?Number.parseInt(o,10):Number.NaN;Number.isFinite(c)&&c>0&&(t.maxFrames=c);break}case "--no-determinism-check":t.noDeterminismCheck=true;break;case "--json":t.json=true;break;case "--verbose":case "-v":t.verbose=true;break;default:n&&!n.startsWith("-")&&!r&&(r=n);}}return {jsonPath:r,opts:t}}function je(){console.error(`
329
333
  Usage: directive bisect <timeline.json> --system <factory.ts> --assert <expr>
330
334
 
331
335
  Binary-search a recorded timeline for the first frame that triggers a
@@ -360,29 +364,29 @@ Examples:
360
364
  --assert 'facts.count >= 0'
361
365
 
362
366
  directive bisect crash.json -s factory.ts -a 'facts.status !== "error"' --json
363
- `);}function yr(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}
364
- expression: ${e}`)}return r=>{let s=r?.facts;return !!t(s,r)}}async function mt(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(Ae(),process.exit(e.length===0?1:0));let{jsonPath:t,opts:r}=gr(e);t||(console.error(g.red("error: missing <timeline.json> argument")),Ae(),process.exit(1)),r.systemPath||(console.error(g.red("error: --system <path> is required"),g.dim(`
365
- (bisect needs a factory to instantiate a fresh system per midpoint)`)),Ae(),process.exit(1)),r.assertExpr||(console.error(g.red("error: --assert <expression> is required"),g.dim(`
366
- (assertion distinguishes 'good' from 'bad' system state)`)),Ae(),process.exit(1));let s=resolve(t);existsSync(s)||(console.error(g.red(`error: timeline file not found: ${s}`)),process.exit(1));let n;try{n=readFileSync(s,"utf8");}catch(w){console.error(g.red(`error: failed to read ${s}: ${w.message}`)),process.exit(1);}let o;try{o=JSON.parse(n);}catch(w){console.error(g.red(`error: ${s} is not valid JSON: ${w.message}`)),process.exit(1);}let{deserializeTimeline:i,bisectTimeline:c}=await oe(r.verbose),a;try{a=i(o);}catch(w){console.error(g.red(`error: timeline JSON failed validation: ${w.message}`)),process.exit(1);}let l;try{l=yr(r.assertExpr);}catch(w){console.error(g.red(`error: ${w.message}`)),process.exit(1);}let u;try{u=await ft(r.systemPath);}catch(w){console.error(g.red(`error: failed to load system factory: ${w.message}`)),process.exit(1);}r.verbose&&console.error(g.dim(`bisecting ${a.frames.length} frames with assertion: ${r.assertExpr}`));let d=await c(a,u,l,{maxFrames:r.maxFrames,determinismCheck:!r.noDeterminismCheck});if(r.json){let w={firstFailingFrameIndex:d.firstFailingFrameIndex??null,iterations:d.iterations,noFailureFound:d.noFailureFound,failsOnEmptyReplay:d.failsOnEmptyReplay,nonDeterministic:d.nonDeterministic};console.log(JSON.stringify(w,null,2)),process.exit(0);}d.nonDeterministic&&(console.error(g.red("\u2717 bisect aborted: timeline is non-deterministic")),console.error(g.dim(` Two full-timeline replays produced different oracle verdicts.
367
+ `);}function br(e){let t;try{t=new Function("facts","system",`"use strict"; return (${e});`);}catch(r){throw new Error(`Failed to compile --assert expression: ${r.message}
368
+ expression: ${e}`)}return r=>{let s=r?.facts;return !!t(s,r)}}async function gt(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(je(),process.exit(e.length===0?1:0));let{jsonPath:t,opts:r}=wr(e);t||(console.error(m.red("error: missing <timeline.json> argument")),je(),process.exit(1)),r.systemPath||(console.error(m.red("error: --system <path> is required"),m.dim(`
369
+ (bisect needs a factory to instantiate a fresh system per midpoint)`)),je(),process.exit(1)),r.assertExpr||(console.error(m.red("error: --assert <expression> is required"),m.dim(`
370
+ (assertion distinguishes 'good' from 'bad' system state)`)),je(),process.exit(1));let s=resolve(t);existsSync(s)||(console.error(m.red(`error: timeline file not found: ${s}`)),process.exit(1));let n;try{n=readFileSync(s,"utf8");}catch(w){console.error(m.red(`error: failed to read ${s}: ${w.message}`)),process.exit(1);}let o;try{o=JSON.parse(n);}catch(w){console.error(m.red(`error: ${s} is not valid JSON: ${w.message}`)),process.exit(1);}let{deserializeTimeline:c,bisectTimeline:a}=await ce(r.verbose),i;try{i=c(o);}catch(w){console.error(m.red(`error: timeline JSON failed validation: ${w.message}`)),process.exit(1);}let l;try{l=br(r.assertExpr);}catch(w){console.error(m.red(`error: ${w.message}`)),process.exit(1);}let u;try{u=await mt(r.systemPath);}catch(w){console.error(m.red(`error: failed to load system factory: ${w.message}`)),process.exit(1);}r.verbose&&console.error(m.dim(`bisecting ${i.frames.length} frames with assertion: ${r.assertExpr}`));let d=await a(i,u,l,{maxFrames:r.maxFrames,determinismCheck:!r.noDeterminismCheck});if(r.json){let w={firstFailingFrameIndex:d.firstFailingFrameIndex??null,iterations:d.iterations,noFailureFound:d.noFailureFound,failsOnEmptyReplay:d.failsOnEmptyReplay,nonDeterministic:d.nonDeterministic};console.log(JSON.stringify(w,null,2)),process.exit(0);}d.nonDeterministic&&(console.error(m.red("\u2717 bisect aborted: timeline is non-deterministic")),console.error(m.dim(` Two full-timeline replays produced different oracle verdicts.
367
371
  Bisection is unreliable on non-deterministic timelines.
368
372
  Either fix the timeline source (deterministic clocks/seeds)
369
- or re-run with --no-determinism-check if you accept the risk.`)),process.exit(2)),d.noFailureFound&&(console.error(g.yellow("\u26A0 no failure to bisect: assertion passes on the full timeline")),console.error(g.dim(` The recorded timeline does not exhibit the bug your
373
+ or re-run with --no-determinism-check if you accept the risk.`)),process.exit(2)),d.noFailureFound&&(console.error(m.yellow("\u26A0 no failure to bisect: assertion passes on the full timeline")),console.error(m.dim(` The recorded timeline does not exhibit the bug your
370
374
  --assert expression checks. Verify the assertion or
371
- try a different bad.json.`)),process.exit(0)),d.failsOnEmptyReplay&&(console.error(g.yellow("\u26A0 assertion fails BEFORE any frame replays \u2014 bug is in initialization")),console.error(g.dim(` The freshly-started system already violates the assertion.
375
+ try a different bad.json.`)),process.exit(0)),d.failsOnEmptyReplay&&(console.error(m.yellow("\u26A0 assertion fails BEFORE any frame replays \u2014 bug is in initialization")),console.error(m.dim(` The freshly-started system already violates the assertion.
372
376
  Bisect cannot narrow further. Inspect the system factory
373
- or initial fact values.`)),process.exit(0));let f=d.firstFailingFrameIndex??-1,m=d.firstFailingFrame,$=m?.event.type??"<unknown>";console.log(`${g.green("\u2713")} bisect complete: ${g.bold(`first failing frame is #${f}`)} ${g.dim(`(${$})`)}`),console.log(g.dim(` \u2022 iterations: ${d.iterations} | timeline frames: ${a.frames.length}`)),r.verbose&&m&&(console.log(g.dim(" \u2022 frame:")),console.log(g.dim(` ${JSON.stringify(m,null,2).split(`
377
+ or initial fact values.`)),process.exit(0));let f=d.firstFailingFrameIndex??-1,h=d.firstFailingFrame,$=h?.event.type??"<unknown>";console.log(`${m.green("\u2713")} bisect complete: ${m.bold(`first failing frame is #${f}`)} ${m.dim(`(${$})`)}`),console.log(m.dim(` \u2022 iterations: ${d.iterations} | timeline frames: ${i.frames.length}`)),r.verbose&&h&&(console.log(m.dim(" \u2022 frame:")),console.log(m.dim(` ${JSON.stringify(h,null,2).split(`
374
378
  `).join(`
375
- `)}`))),process.exit(2);}function vr(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 wr(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 br(e){let t=join(e,"package.json");if(!existsSync(t))return {label:"Package version compatibility",passed:true,message:"Skipped (no package.json)"};let r=JSON.parse(readFileSync(t,"utf-8")),s={...r.dependencies,...r.devDependencies},n=Object.keys(s).filter(o=>o.startsWith("@directive-run/"));return n.length<=1?{label:"Package version compatibility",passed:true,message:n.length===0?"No packages found":"Single package"}:{label:"Package version compatibility",passed:true,message:`${n.length} packages: ${n.join(", ")}`}}function kr(e){let t=join(e,"tsconfig.json");if(!existsSync(t))return {label:"TypeScript configuration",passed:false,message:"No tsconfig.json found",fix:"Run `tsc --init` to create a TypeScript configuration"};try{let s=readFileSync(t,"utf-8").replace(/\/\/.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,""),o=JSON.parse(s).compilerOptions||{},i=[];return o.strict!==!0&&i.push("strict mode not enabled"),o.moduleResolution&&!["bundler","nodenext","node16"].includes(o.moduleResolution.toLowerCase())&&i.push(`moduleResolution is "${o.moduleResolution}"`),i.length>0?{label:"TypeScript configuration",passed:!1,message:i.join(", "),fix:'Set "strict": true and "moduleResolution": "bundler" in tsconfig.json'}:{label:"TypeScript configuration",passed:!0,message:"strict mode, correct module resolution"}}catch{return {label:"TypeScript configuration",passed:true,message:"Found (could not parse for detailed checks)"}}}function xr(e){let t=join(e,"node_modules");if(!existsSync(t))return {label:"No duplicate Directive instances",passed:true,message:"No node_modules found"};let r=[];try{let s=join(t,"@directive-run");if(existsSync(s)){let n=readdirSync(s);for(let o of n){let i=join(s,o,"node_modules","@directive-run","core");existsSync(i)&&r.push(`@directive-run/${o}/node_modules/@directive-run/core`);}}}catch{}return r.length>0?{label:"No duplicate Directive instances",passed:false,message:`Found ${r.length} duplicate(s): ${r.join(", ")}`,fix:"Run `npm dedupe` or check for version mismatches"}:{label:"No duplicate Directive instances",passed:true,message:"No duplicates detected"}}function Sr(e){let t=[".cursorrules",".claude/CLAUDE.md",".github/copilot-instructions.md",".windsurfrules",".clinerules"],r=[];for(let s of t){let n=join(e,s);if(existsSync(n)){let o=readFileSync(n,"utf-8");ne(o)&&r.push(s);}}return r.length===0?{label:"AI coding rules",passed:true,message:"Not installed (optional)"}:{label:"AI coding rules",passed:true,message:`Installed for: ${r.join(", ")}`}}async function ht(e){let t=vr(e);console.log(),console.log(g.bold(g.cyan("Directive Doctor"))),console.log(g.dim("\u2500".repeat(40))),console.log();let r=[wr(t.dir),br(t.dir),kr(t.dir),xr(t.dir),Sr(t.dir)],s=0;for(let n of r){let o=n.passed?g.green("\u2713"):g.red("\u2717");console.log(`${o} ${g.bold(n.label)}`),console.log(` ${g.dim(n.message)}`),!n.passed&&n.fix&&(console.log(` ${g.yellow("Fix:")} ${n.fix}`),s++),console.log();}s>0?(console.log(g.yellow(`${s} issue(s) found. See suggested fixes above.`)),process.exit(1)):console.log(g.green("All checks passed!"));}var $t={"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 Dr(e){for(let[t,r]of Object.entries($t))if(r.includes(e))return t;return "Other"}function Rr(e){let t=e.split(`
376
- `);for(let r of t){let s=r.trim();if(s.startsWith("// Example:")||s.startsWith("// Source:")||s.startsWith("// Extracted"))continue;let n=s.match(/^\*\s+(.+?)(?:\s*\*\/)?$/);if(n?.[1]&&!n[1].startsWith("@"))return n[1];if(s.startsWith("//")&&s.length>3)return s.slice(2).trim();if(s!==""&&!s.startsWith("//")&&!s.startsWith("/*")&&!s.startsWith("*"))break}return ""}async function vt(e){let t;for(let i=0;i<e.length;i++)e[i]==="--filter"&&(t=e[++i]?.toLowerCase());let r=getAllExamples();console.log(),console.log(g.bold(g.cyan("Directive Examples"))),console.log(g.dim("\u2500".repeat(50))),console.log();let s=new Map;for(let[i,c]of r){let a=Dr(i);t&&!a.toLowerCase().includes(t)&&!i.includes(t)||(s.has(a)||s.set(a,[]),s.get(a).push({name:i,desc:Rr(c)}));}if(s.size===0){console.log(g.dim("No examples match the filter."));return}let n=Object.keys($t),o=[...s.keys()].sort((i,c)=>(n.indexOf(i)??99)-(n.indexOf(c)??99));for(let i of o){let c=s.get(i);console.log(g.bold(i));for(let a of c){let l=a.desc?g.dim(` \u2014 ${a.desc}`):"";console.log(` ${g.cyan(a.name)}${l}`);}console.log();}console.log(g.dim(`${r.size} examples available. Run ${g.cyan("directive examples copy <name>")} to extract one.`));}async function wt(e,t){let r=process.cwd();for(let a=0;a<t.length;a++)if(t[a]==="--dest"){let l=t[++a];l&&(r=l);}e||(console.error("Usage: directive examples copy <name> [--dest <dir>]"),process.exit(1));let s=getExample(e);s||(console.error(`Example "${e}" not found.`),console.error(`Run ${g.cyan("directive examples list")} to see available examples.`),process.exit(1));let n=s.replace(/from\s+["']@directive-run\/core\/plugins["']/g,'from "@directive-run/core/plugins"').replace(/from\s+["']@directive-run\/core["']/g,'from "@directive-run/core"').replace(/from\s+["']@directive-run\/ai["']/g,'from "@directive-run/ai"'),o=join(r,`${e}.ts`);existsSync(o)&&(console.error(`File already exists: ${relative(process.cwd(),o)}`),process.exit(1));let i=dirname(o);existsSync(i)||mkdirSync(i,{recursive:true}),writeFileSync(o,n,"utf-8");let c=relative(process.cwd(),o);console.log(`${g.green("Copied")} ${g.cyan(e)} \u2192 ${g.dim(c)}`);}function Tr(e){let t={},r="",s;for(let n=0;n<e.length;n++){let o=e[n];if(o==="--module"){let i=e[++n];i&&(t.module=i);}else o&&!o.startsWith("-")&&(r?s||(s=o):r=o);}return {filePath:r,requirementId:s,opts:t}}async function kt(e){let{filePath:t,requirementId:r}=Tr(e);t||(console.error("Usage: directive explain <file> [requirement-id]"),process.exit(1));let s=await z(t);s.isRunning||s.start();let n=s.inspect();if(r){let o=s.explain(r);if(!o){if(console.error(`Requirement "${r}" not found.
379
+ `)}`))),process.exit(2);}function xr(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 Sr(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 Ar(e){let t=join(e,"package.json");if(!existsSync(t))return {label:"Package version compatibility",passed:true,message:"Skipped (no package.json)"};let r=JSON.parse(readFileSync(t,"utf-8")),s={...r.dependencies,...r.devDependencies},n=Object.keys(s).filter(o=>o.startsWith("@directive-run/"));return n.length<=1?{label:"Package version compatibility",passed:true,message:n.length===0?"No packages found":"Single package"}:{label:"Package version compatibility",passed:true,message:`${n.length} packages: ${n.join(", ")}`}}function jr(e){let t=join(e,"tsconfig.json");if(!existsSync(t))return {label:"TypeScript configuration",passed:false,message:"No tsconfig.json found",fix:"Run `tsc --init` to create a TypeScript configuration"};try{let s=readFileSync(t,"utf-8").replace(/\/\/.*$/gm,"").replace(/\/\*[\s\S]*?\*\//g,""),o=JSON.parse(s).compilerOptions||{},c=[];return o.strict!==!0&&c.push("strict mode not enabled"),o.moduleResolution&&!["bundler","nodenext","node16"].includes(o.moduleResolution.toLowerCase())&&c.push(`moduleResolution is "${o.moduleResolution}"`),c.length>0?{label:"TypeScript configuration",passed:!1,message:c.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 Er(e){let t=join(e,"node_modules");if(!existsSync(t))return {label:"No duplicate Directive instances",passed:true,message:"No node_modules found"};let r=[];try{let s=join(t,"@directive-run");if(existsSync(s)){let n=readdirSync(s);for(let o of n){let c=join(s,o,"node_modules","@directive-run","core");existsSync(c)&&r.push(`@directive-run/${o}/node_modules/@directive-run/core`);}}}catch{}return r.length>0?{label:"No duplicate Directive instances",passed:false,message:`Found ${r.length} duplicate(s): ${r.join(", ")}`,fix:"Run `npm dedupe` or check for version mismatches"}:{label:"No duplicate Directive instances",passed:true,message:"No duplicates detected"}}function Or(e){let t=[".cursorrules",".claude/CLAUDE.md",".github/copilot-instructions.md",".windsurfrules",".clinerules"],r=[];for(let s of t){let n=join(e,s);if(existsSync(n)){let o=readFileSync(n,"utf-8");V(o)&&r.push(s);}}return r.length===0?{label:"AI coding rules",passed:true,message:"Not installed (optional)"}:{label:"AI coding rules",passed:true,message:`Installed for: ${r.join(", ")}`}}async function yt(e){let t=xr(e);console.log(),console.log(m.bold(m.cyan("Directive Doctor"))),console.log(m.dim("\u2500".repeat(40))),console.log();let r=[Sr(t.dir),Ar(t.dir),jr(t.dir),Er(t.dir),Or(t.dir)],s=0;for(let n of r){let o=n.passed?m.green("\u2713"):m.red("\u2717");console.log(`${o} ${m.bold(n.label)}`),console.log(` ${m.dim(n.message)}`),!n.passed&&n.fix&&(console.log(` ${m.yellow("Fix:")} ${n.fix}`),s++),console.log();}s>0?(console.log(m.yellow(`${s} issue(s) found. See suggested fixes above.`)),process.exit(1)):console.log(m.green("All checks passed!"));}var wt={"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 Mr(e){for(let[t,r]of Object.entries(wt))if(r.includes(e))return t;return "Other"}function Nr(e){let t=e.split(`
380
+ `);for(let r of t){let s=r.trim();if(s.startsWith("// Example:")||s.startsWith("// Source:")||s.startsWith("// Extracted"))continue;let n=s.match(/^\*\s+(.+?)(?:\s*\*\/)?$/);if(n?.[1]&&!n[1].startsWith("@"))return n[1];if(s.startsWith("//")&&s.length>3)return s.slice(2).trim();if(s!==""&&!s.startsWith("//")&&!s.startsWith("/*")&&!s.startsWith("*"))break}return ""}async function bt(e){let t;for(let c=0;c<e.length;c++)e[c]==="--filter"&&(t=e[++c]?.toLowerCase());let r=getAllExamples();console.log(),console.log(m.bold(m.cyan("Directive Examples"))),console.log(m.dim("\u2500".repeat(50))),console.log();let s=new Map;for(let[c,a]of r){let i=Mr(c);t&&!i.toLowerCase().includes(t)&&!c.includes(t)||(s.has(i)||s.set(i,[]),s.get(i).push({name:c,desc:Nr(a)}));}if(s.size===0){console.log(m.dim("No examples match the filter."));return}let n=Object.keys(wt),o=[...s.keys()].sort((c,a)=>(n.indexOf(c)??99)-(n.indexOf(a)??99));for(let c of o){let a=s.get(c);console.log(m.bold(c));for(let i of a){let l=i.desc?m.dim(` \u2014 ${i.desc}`):"";console.log(` ${m.cyan(i.name)}${l}`);}console.log();}console.log(m.dim(`${r.size} examples available. Run ${m.cyan("directive examples copy <name>")} to extract one.`));}async function kt(e,t){let r=process.cwd();for(let i=0;i<t.length;i++)if(t[i]==="--dest"){let l=t[++i];l&&(r=l);}e||(console.error("Usage: directive examples copy <name> [--dest <dir>]"),process.exit(1));let s=getExample(e);s||(console.error(`Example "${e}" not found.`),console.error(`Run ${m.cyan("directive examples list")} to see available examples.`),process.exit(1));let n=s.replace(/from\s+["']@directive-run\/core\/plugins["']/g,'from "@directive-run/core/plugins"').replace(/from\s+["']@directive-run\/core["']/g,'from "@directive-run/core"').replace(/from\s+["']@directive-run\/ai["']/g,'from "@directive-run/ai"'),o=join(r,`${e}.ts`);existsSync(o)&&(console.error(`File already exists: ${relative(process.cwd(),o)}`),process.exit(1));let c=dirname(o);existsSync(c)||mkdirSync(c,{recursive:true}),writeFileSync(o,n,"utf-8");let a=relative(process.cwd(),o);console.log(`${m.green("Copied")} ${m.cyan(e)} \u2192 ${m.dim(a)}`);}function Pr(e){let t={},r="",s;for(let n=0;n<e.length;n++){let o=e[n];if(o==="--module"){let c=e[++n];c&&(t.module=c);}else o&&!o.startsWith("-")&&(r?s||(s=o):r=o);}return {filePath:r,requirementId:s,opts:t}}async function St(e){let{filePath:t,requirementId:r}=Pr(e);t||(console.error("Usage: directive explain <file> [requirement-id]"),process.exit(1));let s=await z(t);s.isRunning||s.start();let n=s.inspect();if(r){let o=s.explain(r);if(!o){if(console.error(`Requirement "${r}" not found.
377
381
 
378
- Current requirements:`),n.unmet.length===0)console.log(g.dim(" (no unmet requirements)"));else for(let i of n.unmet)console.log(` ${g.cyan(i.id)} \u2014 ${i.requirement.type} (from ${i.fromConstraint})`);s.stop(),process.exit(1);}console.log(),console.log(g.bold(g.cyan("Requirement Explanation"))),console.log(g.dim("\u2500".repeat(40))),console.log(),console.log(o),console.log();}else if(console.log(),console.log(g.bold(g.cyan("All Requirements"))),console.log(g.dim("\u2500".repeat(40))),console.log(),n.unmet.length===0){console.log(g.green("All requirements are met.")),console.log();let o=Object.entries(n.resolvers);if(o.length>0){console.log(g.bold("Recent Resolver Activity:"));for(let[i,c]of o){let a=bt(c.state),l=c.duration!==void 0?` (${c.duration}ms)`:"";console.log(` ${g.cyan(i)} ${a}${l}`);}console.log();}}else {console.log(`${g.yellow(String(n.unmet.length))} unmet requirement(s):
379
- `);for(let o of n.unmet){console.log(`${g.yellow("\u25CF")} ${g.bold(o.requirement.type)} (id: ${g.dim(o.id)})`),console.log(` From constraint: ${g.cyan(o.fromConstraint)}`);let i={...o.requirement};delete i.type,Object.keys(i).length>0&&console.log(` Payload: ${JSON.stringify(i)}`);let a=n.resolvers[o.id];a?console.log(` Resolver: ${bt(a.state)}${a.error?` \u2014 ${a.error}`:""}`):n.resolverDefs.some(u=>u.requirement===o.requirement.type||u.requirement==="(predicate)")||console.log(` ${g.red("No resolver registered for this type")}`),console.log();}console.log(g.dim(`Run ${g.cyan("directive explain <file> <requirement-id>")} for detailed explanation.`));}s.stop();}function bt(e){switch(e){case "resolved":return g.green("resolved");case "errored":return g.red("errored");case "inflight":return g.yellow("inflight");case "pending":return g.yellow("pending");case "cancelled":return g.dim("cancelled");default:return g.dim(e)}}function Nr(e){let t={ascii:false,open:true},r="";for(let s=0;s<e.length;s++){let n=e[s];switch(n){case "--ascii":t.ascii=true;break;case "--no-open":t.open=false;break;case "--output":{let o=e[++s];o&&(t.output=o);break}default:n&&!n.startsWith("-")&&!r&&(r=n);}}return {filePath:r,opts:t}}function Pr(e){let t=[];t.push(g.bold("Dependency Graph")),t.push(g.dim("\u2550".repeat(50))),t.push("");let r=new Map;for(let c of e.constraints)r.set(c.id,{reqTypes:new Set,active:c.active,priority:c.priority});for(let c of e.unmet){let a=r.get(c.fromConstraint);a&&a.reqTypes.add(c.requirement.type);}let s=new Map;for(let c of e.resolverDefs)s.has(c.requirement)||s.set(c.requirement,[]),s.get(c.requirement).push(c.id);t.push(g.bold("Constraints \u2192 Requirements \u2192 Resolvers")),t.push("");for(let[c,a]of r){let l=a.active?g.green("\u25CF"):g.dim("\u25CB");if(t.push(`${l} ${g.cyan(c)} (priority: ${a.priority})`),a.reqTypes.size>0)for(let u of a.reqTypes){t.push(` \u2514\u2500\u25B6 ${g.yellow(u)}`);let d=s.get(u)||[];if(d.length>0)for(let f of d)t.push(` \u2514\u2500\u25B6 ${g.magenta(f)}`);else t.push(` \u2514\u2500\u25B6 ${g.red("(no resolver)")}`);}else t.push(` \u2514\u2500\u25B6 ${g.dim("(no active requirements)")}`);t.push("");}let n=new Set;for(let c of s.values())for(let a of c)n.add(a);if(e.resolverDefs.map(c=>c.id).filter(c=>!n.has(c)).length>0){t.push(g.bold("Standalone Resolvers:"));for(let c of e.resolverDefs)n.has(c.id)||t.push(` ${g.magenta(c.id)} handles ${g.yellow(c.requirement)}`);}return t.join(`
380
- `)}function qr(e,t){let r=[],s=[],a=Object.keys(t);for(let p=0;p<a.length;p++){let y=a[p];r.push({id:`fact-${y}`,label:y,type:"fact",x:40,y:60+p*50,color:"#3b82f6"});}for(let p=0;p<e.constraints.length;p++){let y=e.constraints[p];r.push({id:`constraint-${y.id}`,label:y.id,type:"constraint",x:260,y:60+p*50,color:y.active?"#22c55e":"#6b7280"});}let l=new Set;for(let p of e.unmet)l.add(p.requirement.type);let u=0;for(let p of l)r.push({id:`req-${p}`,label:p,type:"requirement",x:480,y:60+u*50,color:"#eab308"}),u++;for(let p=0;p<e.resolverDefs.length;p++){let y=e.resolverDefs[p];r.push({id:`resolver-${y.id}`,label:y.id,type:"resolver",x:700,y:60+p*50,color:"#a855f7"});}for(let p of e.unmet)s.push({from:`constraint-${p.fromConstraint}`,to:`req-${p.requirement.type}`});for(let p of e.resolverDefs)l.has(p.requirement)&&s.push({from:`req-${p.requirement}`,to:`resolver-${p.id}`});let d=new Map(r.map(p=>[p.id,p])),f=960,m=Math.max(...r.map(p=>p.y))+50+20,$=s.map(p=>{let y=d.get(p.from),D=d.get(p.to);return !y||!D?"":`<line x1="${y.x+90}" y1="${y.y+15}" x2="${D.x}" y2="${D.y+15}" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#arrow)"/>`}).join(`
382
+ Current requirements:`),n.unmet.length===0)console.log(m.dim(" (no unmet requirements)"));else for(let c of n.unmet)console.log(` ${m.cyan(c.id)} \u2014 ${c.requirement.type} (from ${c.fromConstraint})`);s.stop(),process.exit(1);}console.log(),console.log(m.bold(m.cyan("Requirement Explanation"))),console.log(m.dim("\u2500".repeat(40))),console.log(),console.log(o),console.log();}else if(console.log(),console.log(m.bold(m.cyan("All Requirements"))),console.log(m.dim("\u2500".repeat(40))),console.log(),n.unmet.length===0){console.log(m.green("All requirements are met.")),console.log();let o=Object.entries(n.resolvers);if(o.length>0){console.log(m.bold("Recent Resolver Activity:"));for(let[c,a]of o){let i=xt(a.state),l=a.duration!==void 0?` (${a.duration}ms)`:"";console.log(` ${m.cyan(c)} ${i}${l}`);}console.log();}}else {console.log(`${m.yellow(String(n.unmet.length))} unmet requirement(s):
383
+ `);for(let o of n.unmet){console.log(`${m.yellow("\u25CF")} ${m.bold(o.requirement.type)} (id: ${m.dim(o.id)})`),console.log(` From constraint: ${m.cyan(o.fromConstraint)}`);let c={...o.requirement};delete c.type,Object.keys(c).length>0&&console.log(` Payload: ${JSON.stringify(c)}`);let i=n.resolvers[o.id];i?console.log(` Resolver: ${xt(i.state)}${i.error?` \u2014 ${i.error}`:""}`):n.resolverDefs.some(u=>u.requirement===o.requirement.type||u.requirement==="(predicate)")||console.log(` ${m.red("No resolver registered for this type")}`),console.log();}console.log(m.dim(`Run ${m.cyan("directive explain <file> <requirement-id>")} for detailed explanation.`));}s.stop();}function xt(e){switch(e){case "resolved":return m.green("resolved");case "errored":return m.red("errored");case "inflight":return m.yellow("inflight");case "pending":return m.yellow("pending");case "cancelled":return m.dim("cancelled");default:return m.dim(e)}}function Fr(e){let t={ascii:false,open:true},r="";for(let s=0;s<e.length;s++){let n=e[s];switch(n){case "--ascii":t.ascii=true;break;case "--no-open":t.open=false;break;case "--output":{let o=e[++s];o&&(t.output=o);break}default:n&&!n.startsWith("-")&&!r&&(r=n);}}return {filePath:r,opts:t}}function Wr(e){let t=[];t.push(m.bold("Dependency Graph")),t.push(m.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 i=r.get(a.fromConstraint);i&&i.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(m.bold("Constraints \u2192 Requirements \u2192 Resolvers")),t.push("");for(let[a,i]of r){let l=i.active?m.green("\u25CF"):m.dim("\u25CB");if(t.push(`${l} ${m.cyan(a)} (priority: ${i.priority})`),i.reqTypes.size>0)for(let u of i.reqTypes){t.push(` \u2514\u2500\u25B6 ${m.yellow(u)}`);let d=s.get(u)||[];if(d.length>0)for(let f of d)t.push(` \u2514\u2500\u25B6 ${m.magenta(f)}`);else t.push(` \u2514\u2500\u25B6 ${m.red("(no resolver)")}`);}else t.push(` \u2514\u2500\u25B6 ${m.dim("(no active requirements)")}`);t.push("");}let n=new Set;for(let a of s.values())for(let i of a)n.add(i);if(e.resolverDefs.map(a=>a.id).filter(a=>!n.has(a)).length>0){t.push(m.bold("Standalone Resolvers:"));for(let a of e.resolverDefs)n.has(a.id)||t.push(` ${m.magenta(a.id)} handles ${m.yellow(a.requirement)}`);}return t.join(`
384
+ `)}function _r(e,t){let r=[],s=[],i=Object.keys(t);for(let p=0;p<i.length;p++){let v=i[p];r.push({id:`fact-${v}`,label:v,type:"fact",x:40,y:60+p*50,color:"#3b82f6"});}for(let p=0;p<e.constraints.length;p++){let v=e.constraints[p];r.push({id:`constraint-${v.id}`,label:v.id,type:"constraint",x:260,y:60+p*50,color:v.active?"#22c55e":"#6b7280"});}let l=new Set;for(let p of e.unmet)l.add(p.requirement.type);let u=0;for(let p of l)r.push({id:`req-${p}`,label:p,type:"requirement",x:480,y:60+u*50,color:"#eab308"}),u++;for(let p=0;p<e.resolverDefs.length;p++){let v=e.resolverDefs[p];r.push({id:`resolver-${v.id}`,label:v.id,type:"resolver",x:700,y:60+p*50,color:"#a855f7"});}for(let p of e.unmet)s.push({from:`constraint-${p.fromConstraint}`,to:`req-${p.requirement.type}`});for(let p of e.resolverDefs)l.has(p.requirement)&&s.push({from:`req-${p.requirement}`,to:`resolver-${p.id}`});let d=new Map(r.map(p=>[p.id,p])),f=960,h=Math.max(...r.map(p=>p.y))+50+20,$=s.map(p=>{let v=d.get(p.from),D=d.get(p.to);return !v||!D?"":`<line x1="${v.x+90}" y1="${v.y+15}" x2="${D.x}" y2="${D.y+15}" stroke="#94a3b8" stroke-width="1.5" marker-end="url(#arrow)"/>`}).join(`
381
385
  `),w=r.map(p=>`<g>
382
386
  <rect x="${p.x}" y="${p.y}" width="180" height="30" rx="6" fill="${p.color}" opacity="0.15" stroke="${p.color}" stroke-width="1.5"/>
383
- <text x="${p.x+90}" y="${p.y+19}" text-anchor="middle" font-size="12" font-family="monospace" fill="${p.color}">${Ir(p.label)}</text>
387
+ <text x="${p.x+90}" y="${p.y+19}" text-anchor="middle" font-size="12" font-family="monospace" fill="${p.color}">${Ur(p.label)}</text>
384
388
  </g>`).join(`
385
- `),W=["Facts","Constraints","Requirements","Resolvers"].map((p,y)=>`<text x="${40+y*220+90}" y="35" text-anchor="middle" font-size="14" font-weight="bold" font-family="system-ui" fill="#e2e8f0">${p}</text>`).join(`
389
+ `),W=["Facts","Constraints","Requirements","Resolvers"].map((p,v)=>`<text x="${40+v*220+90}" y="35" text-anchor="middle" font-size="14" font-weight="bold" font-family="system-ui" fill="#e2e8f0">${p}</text>`).join(`
386
390
  `);return `<!DOCTYPE html>
387
391
  <html>
388
392
  <head>
@@ -393,7 +397,7 @@ Current requirements:`),n.unmet.length===0)console.log(g.dim(" (no unmet requir
393
397
  </style>
394
398
  </head>
395
399
  <body>
396
- <svg width="${f}" height="${m}" xmlns="http://www.w3.org/2000/svg">
400
+ <svg width="${f}" height="${h}" xmlns="http://www.w3.org/2000/svg">
397
401
  <defs>
398
402
  <marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
399
403
  <path d="M 0 0 L 10 5 L 0 10 z" fill="#94a3b8"/>
@@ -404,7 +408,7 @@ Current requirements:`),n.unmet.length===0)console.log(g.dim(" (no unmet requir
404
408
  ${w}
405
409
  </svg>
406
410
  </body>
407
- </html>`}function Ir(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function xt(e){let{filePath:t,opts:r}=Nr(e);t||(console.error("Usage: directive graph <file> [--ascii] [--no-open] [--output <path>]"),process.exit(1));let s=await z(t);s.isRunning||s.start();let n=s.inspect();if(r.ascii){console.log(Pr(n)),s.stop();return}let o={};if(s.facts)for(let a of Object.keys(s.facts))try{o[a]=s.facts[a];}catch{o[a]=null;}let i=qr(n,o),c=r.output||join(process.cwd(),".directive-graph.html");if(writeFileSync(c,i,"utf-8"),console.log(`${g.green("Generated")} ${g.dim(c)}`),r.open)try{let{execFile:a}=await import('child_process'),l=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";a(l,[c]),console.log(g.dim("Opened in browser."));}catch{console.log(g.dim(`Open ${c} in your browser to view the graph.`));}s.stop();}function zr(e){let t={dir:process.cwd(),noInteractive:false};for(let r=0;r<e.length;r++)switch(e[r]){case "--template":{let n=e[++r];n&&(t.template=n);break}case "--dir":{let n=e[++r];n&&(t.dir=n);break}case "--no-interactive":t.noInteractive=true;break}return t}function Lr(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 Jr(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 _e(e){return {counter:{id:"counter",label:"Counter (minimal)",hint:"schema + init + derive + events \u2014 simplest starting point",files:[{path:`src/${e}.ts`,content:Kr(e)},{path:"src/main.ts",content:Gr(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:Br(e)},{path:"src/main.ts",content:Hr(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:Qr(e)},{path:"src/main.ts",content:Yr(e)}],deps:["@directive-run/core","@directive-run/ai"]}}}function Kr(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
411
+ </html>`}function Ur(e){return e.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function At(e){let{filePath:t,opts:r}=Fr(e);t||(console.error("Usage: directive graph <file> [--ascii] [--no-open] [--output <path>]"),process.exit(1));let s=await z(t);s.isRunning||s.start();let n=s.inspect();if(r.ascii){console.log(Wr(n)),s.stop();return}let o={};if(s.facts)for(let i of Object.keys(s.facts))try{o[i]=s.facts[i];}catch{o[i]=null;}let c=_r(n,o),a=r.output||join(process.cwd(),".directive-graph.html");if(writeFileSync(a,c,"utf-8"),console.log(`${m.green("Generated")} ${m.dim(a)}`),r.open)try{let{execFile:i}=await import('child_process'),l=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";i(l,[a]),console.log(m.dim("Opened in browser."));}catch{console.log(m.dim(`Open ${a} in your browser to view the graph.`));}s.stop();}function Gr(e){let t={dir:process.cwd(),noInteractive:false};for(let r=0;r<e.length;r++)switch(e[r]){case "--template":{let n=e[++r];n&&(t.template=n);break}case "--dir":{let n=e[++r];n&&(t.dir=n);break}case "--no-interactive":t.noInteractive=true;break}return t}function Br(e){return existsSync(join(e,"pnpm-lock.yaml"))?"pnpm":existsSync(join(e,"bun.lockb"))||existsSync(join(e,"bun.lock"))?"bun":existsSync(join(e,"yarn.lock"))?"yarn":"npm"}function Hr(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 ze(e){return {counter:{id:"counter",label:"Counter (minimal)",hint:"schema + init + derive + events \u2014 simplest starting point",files:[{path:`src/${e}.ts`,content:Qr(e)},{path:"src/main.ts",content:Yr(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:Xr(e)},{path:"src/main.ts",content:Vr(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:Zr(e)},{path:"src/main.ts",content:en(e)}],deps:["@directive-run/core","@directive-run/ai"]}}}function Qr(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
408
412
 
409
413
  const schema = {
410
414
  facts: {
@@ -423,7 +427,7 @@ const schema = {
423
427
  },
424
428
  } satisfies ModuleSchema;
425
429
 
426
- export const ${ae(e)} = createModule("${e}", {
430
+ export const ${ue(e)} = createModule("${e}", {
427
431
  schema,
428
432
 
429
433
  init: (facts) => {
@@ -451,7 +455,7 @@ export const ${ae(e)} = createModule("${e}", {
451
455
  },
452
456
  },
453
457
  });
454
- `}function Gr(e){let t=ae(e);return `import { createSystem } from "@directive-run/core";
458
+ `}function Yr(e){let t=ue(e);return `import { createSystem } from "@directive-run/core";
455
459
  import { ${t} } from "./${e}.js";
456
460
 
457
461
  const system = createSystem({
@@ -477,7 +481,7 @@ system.events.increment();
477
481
  system.events.increment();
478
482
 
479
483
  export default system;
480
- `}function Br(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
484
+ `}function Xr(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
481
485
 
482
486
  type AuthStatus = "idle" | "authenticating" | "authenticated" | "expired";
483
487
 
@@ -504,7 +508,7 @@ const schema = {
504
508
  },
505
509
  } satisfies ModuleSchema;
506
510
 
507
- export const ${ae(e)} = createModule("${e}", {
511
+ export const ${ue(e)} = createModule("${e}", {
508
512
  schema,
509
513
 
510
514
  init: (facts) => {
@@ -581,7 +585,7 @@ export const ${ae(e)} = createModule("${e}", {
581
585
  },
582
586
  },
583
587
  });
584
- `}function Hr(e){let t=ae(e);return `import { createSystem } from "@directive-run/core";
588
+ `}function Vr(e){let t=ue(e);return `import { createSystem } from "@directive-run/core";
585
589
  import { ${t} } from "./${e}.js";
586
590
 
587
591
  const system = createSystem({
@@ -602,7 +606,7 @@ console.log("authenticated:", system.read("isAuthenticated"));
602
606
  console.log("token:", system.facts.token);
603
607
 
604
608
  export default system;
605
- `}function Qr(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
609
+ `}function Zr(e){return `import { type ModuleSchema, createModule, t } from "@directive-run/core";
606
610
  import {
607
611
  createAgentOrchestrator,
608
612
  createAgentMemory,
@@ -636,7 +640,7 @@ const schema = {
636
640
  },
637
641
  } satisfies ModuleSchema;
638
642
 
639
- export const ${ae(e)} = createModule("${e}", {
643
+ export const ${ue(e)} = createModule("${e}", {
640
644
  schema,
641
645
 
642
646
  init: (facts) => {
@@ -710,7 +714,7 @@ export const memory = createAgentMemory({
710
714
  // maxTokenBudget: 50000,
711
715
  // memory,
712
716
  // });
713
- `}function Yr(e){let t=ae(e);return `import { createSystem } from "@directive-run/core";
717
+ `}function en(e){let t=ue(e);return `import { createSystem } from "@directive-run/core";
714
718
  import { ${t} } from "./${e}.js";
715
719
 
716
720
  const system = createSystem({
@@ -729,222 +733,20 @@ await system.settle();
729
733
  console.log("output:", system.facts.output);
730
734
 
731
735
  export default system;
732
- `}function ae(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}function Xr(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}async function St(e){let t=zr(e);h.intro(g.bgCyan(g.black(" directive init ")));let r;if(t.noInteractive)r="my-module";else {let d=await h.text({message:"Module name:",placeholder:"my-module",defaultValue:"my-module",validate:f=>{if(!/^[a-z][a-z0-9-]*$/.test(f))return "Must start with a letter, use lowercase letters, numbers, and hyphens"}});h.isCancel(d)&&(h.cancel("Cancelled."),process.exit(0)),r=d;}let s;if(t.template){let d=_e(r);t.template in d||(h.log.error(`Unknown template: ${t.template}. Available: ${Object.keys(d).join(", ")}`),process.exit(1)),s=t.template;}else if(t.noInteractive)s="counter";else {let d=_e(r),f=await h.select({message:"Project template:",options:Object.values(d).map(m=>({value:m.id,label:m.label,hint:m.hint}))});h.isCancel(f)&&(h.cancel("Cancelled."),process.exit(0)),s=f;}let o=_e(r)[s],i=Lr(t.dir);h.log.info(`Package manager: ${g.cyan(i)}`);let c=h.spinner();c.start("Creating project files...");let l=0;for(let d of o.files){let f=join(t.dir,d.path);if(existsSync(f)){l++;continue}Xr(f,d.content);}c.stop("Project files created.");for(let d of o.files){let f=join(t.dir,d.path),m=relative(t.dir,f);existsSync(f)&&h.log.success(`${g.green("Created")} ${g.dim(m)}`);}l>0&&h.log.warn(`Skipped ${l} file(s) that already exist.`);let u=Jr(i,o.deps.join(" "));h.outro(`Next steps:
733
- ${g.cyan(u)}
734
- ${g.cyan(`${O} ai-rules init`)}
735
- ${g.dim("Start building!")}`);}function Vr(e){let t={json:false},r="";for(let s=0;s<e.length;s++){let n=e[s];switch(n){case "--json":t.json=true;break;case "--module":{let o=e[++s];o&&(t.module=o);break}default:n&&!n.startsWith("-")&&!r&&(r=n);}}return {filePath:r,opts:t}}function Zr(e){let t=[];t.push(g.bold("Facts:"));let r=Object.entries(e);if(r.length===0)return t.push(" (none)"),t.join(`
736
- `);for(let[s,n]of r){let o=on(n);t.push(` ${g.cyan(s)} = ${o}`);}return t.join(`
737
- `)}function en(e){let t=[];if(t.push(g.bold("Constraints:")),e.length===0)return t.push(" (none)"),t.join(`
738
- `);for(let r of e){let s=r.disabled?g.dim("disabled"):r.active?g.green("active"):g.dim("inactive"),n=r.hitCount>0?g.yellow(` (${r.hitCount} hits)`):"";t.push(` ${g.cyan(r.id)} ${s} priority=${r.priority}${n}`);}return t.join(`
739
- `)}function tn(e,t){let r=[];if(r.push(g.bold("Resolvers:")),e.length===0)return r.push(" (none)"),r.join(`
740
- `);for(let s of e){let n=t[s.id],o=n?sn(n.state,n.error,n.duration):g.dim("idle");r.push(` ${g.cyan(s.id)} \u2192 ${s.requirement} ${o}`);}return r.join(`
741
- `)}function rn(e){let t=[];if(t.push(g.bold("Unmet Requirements:")),e.length===0)return t.push(` ${g.green("(all requirements met)")}`),t.join(`
742
- `);for(let r of e)t.push(` ${g.yellow(r.requirement.type)} (id: ${g.dim(r.id)}) from ${g.dim(r.fromConstraint)}`);return t.join(`
743
- `)}function nn(e){let t=[];if(t.push(g.bold("Inflight:")),e.length===0)return t.push(` ${g.green("(none)")}`),t.join(`
744
- `);let r=Date.now();for(let s of e){let n=r-s.startedAt;t.push(` ${g.cyan(s.resolverId)} \u2192 req ${g.dim(s.id)} ${g.yellow(`${n}ms`)}`);}return t.join(`
745
- `)}function sn(e,t,r){let s=r!==void 0?` ${r}ms`:"";switch(e){case "resolved":return g.green(`resolved${s}`);case "errored":return g.red(`errored${s}${t?` \u2014 ${t}`:""}`);case "inflight":return g.yellow("inflight");case "cancelled":return g.dim("cancelled");default:return g.dim(e)}}function on(e){return e===null?g.dim("null"):e===void 0?g.dim("undefined"):typeof e=="string"?e.length>60?`"${e.slice(0,57)}..."`:`"${e}"`:typeof e=="number"||typeof e=="boolean"?String(e):Array.isArray(e)?`[${e.length} items]`:JSON.stringify(e).slice(0,60)}function an(e){let t=[];new Set(e.unmet.map(o=>o.requirement.type));new Set(e.resolverDefs.map(o=>o.requirement));for(let o of e.resolverDefs)o.requirement;for(let o of e.unmet)e.resolverDefs.some(c=>c.requirement===o.requirement.type||c.requirement==="(predicate)")||t.push(`No resolver for requirement type "${o.requirement.type}"`);return t}async function At(e){let{filePath:t,opts:r}=Vr(e);t||(console.error("Usage: directive inspect <file> [--json] [--module <name>]"),process.exit(1));let s=await z(t);s.isRunning||s.start();let n=s.inspect();if(r.json){let c={};if(s.facts)for(let a of Object.keys(s.facts))try{c[a]=s.facts[a];}catch{c[a]="(error reading)";}console.log(JSON.stringify({facts:c,...n},null,2)),s.stop();return}console.log(),console.log(g.bold(g.cyan("Directive System Inspection"))),console.log(g.dim("\u2500".repeat(40))),console.log();let o={};if(s.facts)for(let c of Object.keys(s.facts))try{o[c]=s.facts[c];}catch{o[c]="(error reading)";}console.log(Zr(o)),console.log(),console.log(en(n.constraints)),console.log(),console.log(tn(n.resolverDefs,n.resolvers)),console.log(),console.log(rn(n.unmet)),console.log(),n.inflight.length>0&&(console.log(nn(n.inflight)),console.log());let i=an(n);if(i.length>0){console.log(g.bold(g.yellow("Warnings:")));for(let c of i)console.log(` ${g.yellow("\u26A0")} ${c}`);console.log();}s.stop();}function Et(e){let t={with:[],minimal:false,dir:process.cwd()};for(let r=0;r<e.length;r++)switch(e[r]){case "--with":{let n=e[++r];n&&(t.with=n.split(",").map(o=>o.trim()));break}case "--minimal":t.minimal=true;break;case "--dir":{let n=e[++r];n&&(t.dir=n);break}}return t}var jt=["derive","events","constraints","resolvers","effects"];function dn(e,t){let r=Ot(e),s=t.includes("constraints"),n=t.includes("resolvers"),i=`import { ${["type ModuleSchema","createModule","t"].join(", ")} } from "@directive-run/core";
746
-
747
- `;return i+=`const schema = {
748
- `,i+=` facts: {
749
- `,i+=` // Add your facts here
750
- `,i+=` status: t.string(),
751
- `,i+=` },
752
- `,t.includes("derive")&&(i+=` derivations: {
753
- `,i+=` // Add derivation types here
754
- `,i+=` isReady: t.boolean(),
755
- `,i+=` },
756
- `),t.includes("events")&&(i+=` events: {
757
- `,i+=` // Add event shapes here
758
- `,i+=` setStatus: { value: t.string() },
759
- `,i+=` },
760
- `),(s||n)&&(i+=` requirements: {
761
- `,i+=` // Add requirement shapes here
762
- `,i+=` PROCESS: { input: t.string() },
763
- `,i+=` },
764
- `),i+=`} satisfies ModuleSchema;
765
-
766
- `,i+=`export const ${r} = createModule("${e}", {
767
- `,i+=` schema,
768
-
769
- `,i+=` init: (facts) => {
770
- `,i+=` facts.status = "idle";
771
- `,i+=` },
772
- `,t.includes("derive")&&(i+=`
773
- derive: {
774
- `,i+=` isReady: (facts) => facts.status === "ready",
775
- `,i+=` },
776
- `),t.includes("events")&&(i+=`
777
- events: {
778
- `,i+=` setStatus: (facts, { value }) => {
779
- `,i+=` facts.status = value;
780
- `,i+=` },
781
- `,i+=` },
782
- `),s&&(i+=`
783
- constraints: {
784
- `,i+=` needsProcessing: {
785
- `,i+=` priority: 100,
786
- `,i+=` when: (facts) => facts.status === "pending",
787
- `,i+=` require: (facts) => ({
788
- `,i+=` type: "PROCESS",
789
- `,i+=` input: facts.status,
790
- `,i+=` }),
791
- `,i+=` },
792
- `,i+=` },
793
- `),n&&(i+=`
794
- resolvers: {
795
- `,i+=` process: {
796
- `,i+=` requirement: "PROCESS",
797
- `,i+=` resolve: async (req, context) => {
798
- `,i+=` // Implement resolution logic here
799
- `,i+=` context.facts.status = "done";
800
- `,i+=` },
801
- `,i+=` },
802
- `,i+=` },
803
- `),t.includes("effects")&&(i+=`
804
- effects: {
805
- `,i+=` logChange: {
806
- `,i+=` deps: ["status"],
807
- `,i+=` run: (facts, prev) => {
808
- `,i+=` if (prev && prev.status !== facts.status) {
809
- `,i+=" console.log(`Status: ${prev.status} \u2192 ${facts.status}`);\n",i+=` }
810
- `,i+=` },
811
- `,i+=` },
812
- `,i+=` },
813
- `),i+=`});
814
- `,i}function fn(e){let t=Ot(e);return `import { type ModuleSchema, createModule, createSystem, t } from "@directive-run/core";
815
- import {
816
- createAgentOrchestrator,
817
- createAgentMemory,
818
- createSlidingWindowStrategy,
819
- } from "@directive-run/ai";
820
-
821
- // ============================================================================
822
- // Types
823
- // ============================================================================
824
-
825
- type AgentStatus = "idle" | "thinking" | "done" | "error";
826
-
827
- // ============================================================================
828
- // Schema
829
- // ============================================================================
830
-
831
- const schema = {
832
- facts: {
833
- input: t.string(),
834
- output: t.string(),
835
- status: t.string<AgentStatus>(),
836
- error: t.string(),
837
- totalTokens: t.number(),
838
- },
839
- derivations: {
840
- isThinking: t.boolean(),
841
- hasOutput: t.boolean(),
842
- },
843
- events: {
844
- setInput: { value: t.string() },
845
- requestRun: {},
846
- reset: {},
847
- },
848
- requirements: {
849
- RUN_AGENT: { input: t.string() },
850
- },
851
- } satisfies ModuleSchema;
852
-
853
- // ============================================================================
854
- // Module
855
- // ============================================================================
856
-
857
- export const ${t} = createModule("${e}", {
858
- schema,
859
-
860
- init: (facts) => {
861
- facts.input = "";
862
- facts.output = "";
863
- facts.status = "idle";
864
- facts.error = "";
865
- facts.totalTokens = 0;
866
- },
867
-
868
- derive: {
869
- isThinking: (facts) => facts.status === "thinking",
870
- hasOutput: (facts) => facts.output !== "",
871
- },
872
-
873
- events: {
874
- setInput: (facts, { value }) => {
875
- facts.input = value;
876
- },
877
- requestRun: (facts) => {
878
- facts.status = "thinking";
879
- facts.output = "";
880
- facts.error = "";
881
- },
882
- reset: (facts) => {
883
- facts.input = "";
884
- facts.output = "";
885
- facts.status = "idle";
886
- facts.error = "";
887
- facts.totalTokens = 0;
888
- },
889
- },
890
-
891
- constraints: {
892
- needsRun: {
893
- priority: 100,
894
- when: (facts) => facts.status === "thinking",
895
- require: (facts) => ({
896
- type: "RUN_AGENT",
897
- input: facts.input,
898
- }),
899
- },
900
- },
901
-
902
- resolvers: {
903
- runAgent: {
904
- requirement: "RUN_AGENT",
905
- timeout: 30000,
906
- resolve: async (req, context) => {
907
- // TODO: Replace with your agent runner
908
- const result = \`Echo: \${req.input}\`;
909
-
910
- context.facts.output = result;
911
- context.facts.status = "done";
912
- },
913
- },
914
- },
915
- });
916
-
917
- // ============================================================================
918
- // AI Features
919
- // ============================================================================
920
-
921
- export const memory = createAgentMemory({
922
- strategy: createSlidingWindowStrategy(),
923
- strategyConfig: { maxMessages: 30, preserveRecentCount: 6 },
924
- autoManage: true,
925
- });
926
-
927
- // TODO: Add your agent runner and configure the orchestrator
928
- // export const orchestrator = createAgentOrchestrator({
929
- // runner: yourAgentRunner,
930
- // maxTokenBudget: 50000,
931
- // memory,
932
- // guardrails: {
933
- // input: [],
934
- // output: [],
935
- // },
936
- // });
937
-
938
- // ============================================================================
939
- // System
940
- // ============================================================================
941
-
942
- export const system = createSystem({
943
- module: ${t},
944
- });
945
- `}function Ot(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}function Dt(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}function Rt(e){return join(e,"src")}async function Tt(e,t){let r=Et(t);(!e||!/^[a-z][a-z0-9-]*$/.test(e))&&(console.error(`Invalid module name: ${e||"(none)"}
946
- Must start with a letter, use lowercase letters, numbers, and hyphens.`),process.exit(1));let s;r.minimal?s=[]:r.with.length>0?s=r.with.filter(a=>jt.includes(a)):s=jt;let n=Rt(r.dir),o=join(n,`${e}.ts`);existsSync(o)&&(console.error(`File already exists: ${relative(r.dir,o)}`),process.exit(1));let i=dn(e,s);Dt(o,i);let c=relative(r.dir,o);console.log(`${g.green("Created")} ${g.dim(c)}`),s.length===0?console.log(g.dim(" Minimal module (schema + init only)")):console.log(g.dim(` Sections: ${s.join(", ")}`));}async function Ct(e,t){let r=Et(t);(!e||!/^[a-z][a-z0-9-]*$/.test(e))&&(console.error(`Invalid orchestrator name: ${e||"(none)"}
947
- Must start with a letter, use lowercase letters, numbers, and hyphens.`),process.exit(1));let s=Rt(r.dir),n=join(s,`${e}.ts`);existsSync(n)&&(console.error(`File already exists: ${relative(r.dir,n)}`),process.exit(1));let o=fn(e);Dt(n,o);let i=relative(r.dir,n);console.log(`${g.green("Created")} ${g.dim(i)}`),console.log(g.dim(" AI orchestrator with memory, guardrails, and streaming"));}var pe=typeof process<"u"&&process.env?.NODE_ENV!=="production";function ce(e,t=50){let r=new WeakSet;function s(a){if(a===null)return "null";if(a===void 0)return "undefined";let l=typeof a;if(l==="string")return JSON.stringify(a);if(l==="number"||l==="boolean")return String(a);if(l==="function")return '"[function]"';if(l==="symbol")return '"[symbol]"'}function n(a,l){if(r.has(a))return '"[circular]"';r.add(a);let u=l();return r.delete(a),u}function o(a,l){return n(a,()=>`[${a.map(u=>c(u,l+1)).join(",")}]`)}function i(a,l){return n(a,()=>`{${Object.keys(a).sort().map(u=>`${JSON.stringify(u)}:${c(a[u],l+1)}`).join(",")}}`)}function c(a,l){if(l>t)return '"[max depth exceeded]"';if(typeof a=="bigint")return `${a.toString()}n`;let u=s(a);if(u!==void 0)return u;if(a instanceof Date)return `D:${a.toISOString()}`;if(a instanceof RegExp)return `R:${a.source}:${a.flags}`;if(a instanceof Map){let d=[...a.entries()].sort();return `M:${c(d,l+1)}`}if(a instanceof Set){let d=[...a].sort();return `S:${c(d,l+1)}`}return Array.isArray(a)?o(a,l):typeof a=="object"?i(a,l):'"[unknown]"'}return c(e,0)}var J=new Set(["$eq","$ne","$in","$nin","$exists","$gt","$gte","$lt","$lte","$between","$matches","$startsWith","$endsWith","$contains","$changed"]),Nt=new Set(["$all","$any","$not"]);var K=64;function I(e){return typeof e!="object"||e===null||Array.isArray(e)?false:!(e instanceof Date)&&!(e instanceof RegExp)}function Oe(e){if(typeof e!="object"||e===null||Array.isArray(e))return false;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function Je(e){if(!I(e))return false;let t=0,r=false;for(let s of Object.keys(e)){if(s.startsWith("$"))r=true,J.has(s)||he(`predicate: unknown operator "${s}" \u2014 looks like a typo. Known operators: ${[...J].join(", ")}`);else if(r||t===0)return false;t++;}return r?t>0:false}function Pt(e){return e===null?false:Array.isArray(e)?e.every(t=>Oe(t)&&"fact"in t&&"op"in t):Oe(e)}function me(e,t,r="",s=new WeakSet,n=0){if(n>K){pe&&console.warn(`[Directive] predicate depth limit (${K}) exceeded \u2014 flatten the predicate or split it into multiple constraints. If this is unexpected, check for a cyclic spec object.`),t.bail?.("depth");return}if(Array.isArray(e)){e.forEach((i,c)=>{if(!I(i))return;let a=i;if(typeof a.fact=="string"&&typeof a.op=="string"){let l=r?`${r}[${c}]`:`[${c}]`;t.operator?.(r?`${r}.${a.fact}`:a.fact,a.op,a.value,`${l}.value`);}});return}if(!I(e))return;if(s.has(e)){pe&&console.warn("[Directive] walkPredicate: cyclic predicate spec"),t.bail?.("cycle");return}s.add(e);let o=e;for(let i of ["$all","$any","$not"])if(i in o){if(t.combinator?.(i)===false)return;let c=i==="$not"?[o.$not]:o[i]??[];for(let a of c)me(a,t,r,s,n+1);return}for(let i of Object.keys(o)){let c=r?`${r}.${i}`:i;if(i.startsWith("$")){t.strayOperatorKey?.(i,c);continue}let a=o[i];if(Je(a)){let l=a;for(let u of Object.keys(l))t.operator?.(c,u,l[u],`${c}.${u}`);continue}if(Oe(a)){if(t.nested?.(i)===false)continue;me(a,t,c,s,n+1);continue}t.literal?.(c,a);}}function qt(e,t=""){function r(n,o,i,c){if(typeof n=="bigint")throw new Error(`[Directive] validatePredicate: bigint operand at "${o}" is not JSON-serializable (JSON.stringify throws on bigint).`);if(n instanceof Set)throw new Error(`[Directive] validatePredicate: Set operand at "${o}" is not JSON-serializable (serializes to {} and loses all members).`);if(n instanceof Map)throw new Error(`[Directive] validatePredicate: Map operand at "${o}" is not JSON-serializable (serializes to {} and loses all entries).`);if(n instanceof RegExp)throw new Error(`[Directive] validatePredicate: RegExp operand at "${o}" is not JSON-serializable (a regex lost to JSON.parse becomes {}). Only a direct $matches operand may be a RegExp.`);if(!(n===null||typeof n!="object")&&!(c>K)&&!i.has(n)){if(i.add(n),Array.isArray(n)){n.forEach((a,l)=>{r(a,`${o}[${l}]`,i,c+1);});return}for(let a of Object.keys(n))r(n[a],o?`${o}.${a}`:a,i,c+1);}}function s(n,o,i){if(typeof n=="bigint")throw new Error(`[Directive] validatePredicate: bigint operand at "${i}" is not JSON-serializable (JSON.stringify throws on bigint).`);if(n instanceof Set)throw new Error(`[Directive] validatePredicate: Set operand at "${i}" is not JSON-serializable (serializes to {} and loses all members).`);if(n instanceof Map)throw new Error(`[Directive] validatePredicate: Map operand at "${i}" is not JSON-serializable (serializes to {} and loses all entries).`);if(o==="$matches"&&!(n instanceof RegExp))throw new Error(`[Directive] validatePredicate: $matches operand at "${i}" must be a RegExp; got ${n===null?"null":typeof n}. A regex lost to JSON.parse becomes {} \u2014 reify with new RegExp(pattern, flags) before installing.`);if(Array.isArray(n))n.forEach((c,a)=>{r(c,`${i}[${a}]`,new WeakSet,1);});else if(Oe(n))for(let c of Object.keys(n))r(n[c],`${i}.${c}`,new WeakSet,1);}if(e instanceof Set)throw new Error(`[Directive] validatePredicate: Set operand${t?` at "${t}"`:""} is not JSON-serializable (serializes to {} and loses all members).`);if(e instanceof Map)throw new Error(`[Directive] validatePredicate: Map operand${t?` at "${t}"`:""} is not JSON-serializable (serializes to {} and loses all entries).`);me(e,{operator(n,o,i,c){s(i,o,t?`${t}.${c}`:c);},literal(n,o){s(o,"",t?`${t}.${n}`:n);}});}function pn(){return {ids:new WeakMap,next:{v:1},pairs:new Set}}function Mt(e,t){let r=e.ids.get(t);return r===void 0&&(r=e.next.v++,e.ids.set(t,r)),r}function q(e,t,r){if(Object.is(e,t))return true;if(e instanceof Date&&t instanceof Date)return e.getTime()===t.getTime();if(typeof e!="object"||typeof t!="object"||e===null||t===null)return false;let s=r??pn(),n=`${Mt(s,e)}:${Mt(s,t)}`;if(s.pairs.has(n))return true;if(s.pairs.add(n),Array.isArray(e)||Array.isArray(t))return !Array.isArray(e)||!Array.isArray(t)||e.length!==t.length?false:e.every((c,a)=>q(c,t[a],s));if(e instanceof Set||t instanceof Set){if(!(e instanceof Set)||!(t instanceof Set)||e.size!==t.size)return false;let c=[...t];return [...e].every(a=>c.some(l=>q(a,l,s)))}if(e instanceof Map||t instanceof Map){if(!(e instanceof Map)||!(t instanceof Map)||e.size!==t.size)return false;let c=[...t.entries()],a=new Array(c.length).fill(false);for(let[l,u]of e){let d=false;for(let f=0;f<c.length;f++){if(a[f])continue;let[m,$]=c[f];if(q(l,m,s)&&q(u,$,s)){a[f]=true,d=true;break}}if(!d)return false}return true}let o=Object.keys(e),i=Object.keys(t);return o.length!==i.length?false:o.every(c=>Object.hasOwn(t,c)&&q(e[c],t[c],s))}function De(e){if(e instanceof Date)return e.getTime();if(typeof e=="number"||typeof e=="bigint"||typeof e=="string")return e}function Le(e,t,r){let s=De(t),n=De(r);if(s===void 0||n===void 0||typeof s!=typeof n)return false;switch(e){case "$gt":return s>n;case "$gte":return s>=n;case "$lt":return s<n;case "$lte":return s<=n;default:return false}}function Re(e,t,r,s){switch(e){case "$eq":return q(t,r);case "$ne":return !q(t,r);case "$in":return Array.isArray(r)&&r.some(n=>q(t,n));case "$nin":return Array.isArray(r)&&!r.some(n=>q(t,n));case "$exists":return r===(t!==void 0);case "$changed":return !q(t,s);case "$gt":case "$gte":case "$lt":case "$lte":return Le(e,t,r);case "$between":{if(!Array.isArray(r)||r.length!==2)return false;let n=De(r[0]),o=De(r[1]);return n!==void 0&&o!==void 0&&typeof n==typeof o&&n>o?(he("$between: reversed pair \u2014 [min, max] required"),false):Le("$gte",t,r[0])&&Le("$lte",t,r[1])}case "$matches":{if(!(r instanceof RegExp))throw new Error("[Directive] $matches: operand must be a RegExp (string operands are no longer accepted; pass /pattern/flags directly).");return typeof t!="string"?false:r.test(t)}case "$startsWith":return typeof t!="string"?false:t.startsWith(String(r));case "$endsWith":return typeof t!="string"?false:t.endsWith(String(r));case "$contains":return typeof t=="string"?t.includes(String(r)):Array.isArray(t)?t.some(n=>q(n,r)):t instanceof Set?t.has(r):false;default:return false}}function he(e){pe&&console.warn(`[Directive] ${e}`);}function mn(e,t,r,s){if(Je(e)){let n=Object.keys(e);n.length>1&&he(`predicate: operator object has ${n.length} operators (${n.join(", ")}) \u2014 write the array form or $all instead. The runtime ANDs them as a best-effort fallback.`);for(let o of n)if(!Re(o,t,e[o],r))return false;return true}return I(e)?te(e,I(t)?t:Object.create(null),I(r)?r:void 0,s+1):q(t,e)}function te(e,t,r,s=0){if(s>K)return he(`predicate depth limit (${K}) exceeded \u2014 flatten the predicate or split it into multiple constraints. If this is unexpected, check for a cyclic spec object.`),false;if(Array.isArray(e))return e.every(n=>{if(!I(n))return false;let{fact:o,op:i,value:c}=n;return Re(i,t?.[o],c,r?.[o])});if(!I(e))return !!e;if("$all"in e)return e.$all.every(n=>te(n,t,r,s+1));if("$any"in e)return e.$any.some(n=>te(n,t,r,s+1));if("$not"in e)return !te(e.$not,t,r,s+1);for(let n of Object.keys(e)){if(J.has(n))return he(`predicate: operator "${n}" mixed with fact keys \u2014 wrap operators in a per-fact object`),false;if(!mn(e[n],t?.[n],r?.[n],s))return false}return true}function ge(e,t,r,s=""){let n=[];if(Array.isArray(e)){for(let o of e){if(!I(o))continue;let{fact:i,op:c,value:a}=o,l=t?.[i];n.push({path:s+i,op:c,expected:a,actual:l,pass:Re(c,l,a,r?.[i])});}return n}if(!I(e))return n;for(let o of ["$all","$any","$not"])if(o in e){let i=o==="$not"?[e.$not]:e[o],c=[];for(let u of i)c.push(...ge(u,t,r,s));let a=c.filter(u=>u.pass).length,l;return o==="$all"?l=c.length===0||a===c.length:o==="$any"?l=c.length>0&&a>0:l=!c.every(u=>u.pass),n.push({path:s||o,op:o,expected:i.length,actual:a,pass:l,children:c}),n}for(let o of Object.keys(e)){if(J.has(o))continue;let i=e[o],c=t?.[o],a=s+o;if(Je(i))for(let l of Object.keys(i))n.push({path:a,op:l,expected:i[l],actual:c,pass:Re(l,c,i[l],r?.[o])});else I(i)?n.push(...ge(i,I(c)?c:Object.create(null),I(r?.[o])?r?.[o]:void 0,`${a}.`)):n.push({path:a,op:"$eq",expected:i,actual:c,pass:q(c,i)});}return n}var le=1e6;function It(e,t){try{qt(e);}catch(s){let n=s instanceof Error?s.message:String(s);throw new Error(`[Directive] replayUnder: the ${t} predicate is invalid \u2014 ${n}`)}if(!Pt(e)){let s=e===null||typeof e!="object"?`${typeof e} \u2014 ${JSON.stringify(e)}`:JSON.stringify(e).slice(0,80);throw new Error(`[Directive] replayUnder: the ${t} predicate is not a valid FactPredicate (got ${s})`)}let r;if(me(e,{operator(s,n){r===void 0&&n.startsWith("$")&&!J.has(n)&&(r=n);},strayOperatorKey(s){r===void 0&&!J.has(s)&&!Nt.has(s)&&(r=s);}}),r!==void 0)throw new Error(`[Directive] replayUnder: the ${t} predicate uses an unknown operator "${r}" \u2014 known operators: ${[...J].join(", ")}`)}function ye(e){if(e&&typeof e=="object"&&!Array.isArray(e)&&Array.isArray(e.snapshots))return hn(e);let t=Array.isArray(e)?e:e&&typeof e=="object"&&Array.isArray(e.frames)?e.frames:null;if(!t)throw new Error("[Directive] toReplayFrames: history must be a JSON array of frames, an object with a `frames` array, or a history export with a `snapshots` array");if(t.length>le)throw new Error(`[Directive] toReplayFrames: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${le}) \u2014 split or down-sample the history`);return t.map((r,s)=>{if(r&&typeof r=="object"&&"facts"in r){let n=r,o={id:n.id??`#${s}`,facts:n.facts??{}};return typeof n.timestamp=="number"&&(o.timestamp=n.timestamp),o}return {id:`#${s}`,facts:r??{}}})}function hn(e){let t=typeof e=="string"?JSON.parse(e):e;if(Array.isArray(t))return Ft(t);if(!t||typeof t!="object")throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");let r=t;if(r.version!==void 0&&r.version!==1)throw new Error(`[Directive] framesFromHistory: unsupported history export version ${JSON.stringify(r.version)} \u2014 expected 1`);if(!Array.isArray(r.snapshots))throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");return Ft(r.snapshots)}function Ft(e){if(!Array.isArray(e))throw new Error("[Directive] framesFromSnapshots: expected an array of fact-state snapshots");if(e.length>le)throw new Error(`[Directive] framesFromSnapshots: history has ${e.length} snapshots, exceeds the MAX_REPLAY_FRAMES limit (${le}) \u2014 split or down-sample the history`);for(let t=0;t<e.length;t++){let r=e[t];if(!r||typeof r!="object"||!("facts"in r))throw new Error(`[Directive] framesFromSnapshots: snapshot at index ${t} is not a { facts, ... } object`)}return ye(e)}function Te(e){let{frames:t,original:r,proposed:s,entityKey:n}=e,o=e.maxSamples??20,i=o>0?o:0;if(t.length>le)throw new Error(`[Directive] replayUnder: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${le}) \u2014 split or down-sample the history`);It(r,"original"),It(s,"proposed");let c=0,a=0,l=0,u=0,d=0,f=[],m=[],$=n?new Set:void 0,w=n?new Set:void 0,F;for(let p of t){let y=p.facts,D=te(r,y,F),_=te(s,y,F);D&&(c++,$?.add(y[n])),_&&(a++,w?.add(y[n])),D===_?d++:!D&&_?(l++,f.length<i&&f.push(Wt(p,r,s,F))):(u++,m.length<i&&m.push(Wt(p,r,s,F))),F=y;}let W={framesEvaluated:t.length,original:{matched:c},proposed:{matched:a},delta:a-c,newMatchCount:l,lostMatchCount:u,unchanged:d,newMatches:f,lostMatches:m};return $&&w&&(W.original.matchedEntities=$.size,W.proposed.matchedEntities=w.size),W}function Wt(e,t,r,s){let n=e.facts,o={frameId:e.id,facts:n,originalExplain:ge(t,n,s),proposedExplain:ge(r,n,s)};return e.timestamp!==void 0&&(o.timestamp=e.timestamp),o}var _t=1e4,Ut=5e7;function gn(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===1&&typeof e.$hole=="string"}function Ke(e,t,r=new Set,s=0){if(s>K)throw new Error(`[Directive] sweepUnder: template exceeds MAX_PREDICATE_DEPTH (${K}) \u2014 flatten the template or split the sweep`);if(gn(e)){let n=e.$hole;if(!(n in t))throw new Error(`[Directive] sweepUnder: template references hole "${n}" but sweep has no values for it`);return t[n]}if(e===null||typeof e!="object")return e;if(r.has(e))throw new Error("[Directive] sweepUnder: template contains a cycle \u2014 predicate templates must be a tree");r.add(e);try{if(Array.isArray(e))return e.map(o=>Ke(o,t,r,s+1));let n={};for(let[o,i]of Object.entries(e))n[o]=Ke(i,t,r,s+1);return n}finally{r.delete(e);}}function*Lt(e,t){if(e.length===0){yield {};return}let r=e[0],s=e.slice(1),n=t[r]??[];for(let o of n)for(let i of Lt(s,t))yield {[r]:o,...i};}function yn(e){let t=1;for(let r of Object.values(e))t*=r.length;return t}function Jt(e){let{frames:t,original:r,template:s,sweep:n,objective:o=y=>y.proposed.matched,entityKey:i,maxSamples:c=0}=e,a=Object.keys(n);if(a.length===0)throw new Error("[Directive] sweepUnder: `sweep` must contain at least one hole name");let l=yn(n);if(l>_t)throw new Error(`[Directive] sweepUnder: grid has ${l} points, exceeds the MAX_SWEEP_POINTS limit (${_t}) \u2014 narrow the sweep ranges or split the run`);if(l===0)throw new Error("[Directive] sweepUnder: at least one hole has zero candidate values");let u=l*t.length;if(u>Ut)throw new Error(`[Directive] sweepUnder: ${l} points \xD7 ${t.length} frames = ${u} per-frame evaluations, exceeds the MAX_SWEEP_EVALUATIONS limit (${Ut}) \u2014 narrow the sweep, down-sample the history, or split the run`);let d=false,f=y=>{let D;try{D=o(y);}catch(_){return d||(d=true,console.warn(`[Directive] sweepUnder: objective threw \u2014 point will not rank (${_.message})`)),Number.NEGATIVE_INFINITY}return typeof D!="number"||!Number.isFinite(D)?(d||(d=true,console.warn(`[Directive] sweepUnder: objective returned a non-finite number (${String(D)}) \u2014 point will not rank`)),Number.NEGATIVE_INFINITY):D},m=Te({frames:t,original:r,proposed:r,entityKey:i,maxSamples:c}),$={values:{},report:m,score:f(m)},w=[],F=0,W=Number.NEGATIVE_INFINITY;for(let y of Lt(a,n)){let D=Ke(s,y),_=Te({frames:t,original:r,proposed:D,entityKey:i,maxSamples:c}),Me=f(_);Me>W&&(W=Me,F=w.length),w.push({values:y,report:_,score:Me});}let p=w[F];return {points:w,bestIndex:F,best:p,baseline:$}}function zt(e){let t=e&&typeof e=="object"&&!Array.isArray(e)&&"constraints"in e?e.constraints:e;if(Array.isArray(t)){let r={};for(let s of t){if(!s||typeof s!="object"||!("id"in s))throw new Error("[Directive] diffRules: array entries must be `{ id, whenSpec }` objects");let n=s;if(typeof n.id!="string")throw new Error("[Directive] diffRules: constraint `id` must be a string");r[n.id]=n.whenSpec;}return r}if(t&&typeof t=="object")return t;throw new Error("[Directive] diffRules: expected a `{ id: whenSpec }` map, an array of `{ id, whenSpec }`, or `{ constraints: ... }`")}var $n=new Set(["$eq","$ne","$in","$nin","$exists","$gt","$gte","$lt","$lte","$between","$matches","$startsWith","$endsWith","$contains","$changed"]),vn=new Set(["$all","$any","$not"]);function Kt(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function wn(e){if(!Kt(e))return false;let t=Object.keys(e);if(t.length===0)return false;let r=false;for(let s of t){if(!s.startsWith("$"))return false;$n.has(s)&&(r=true);}return r}function B(e,t="",r=[]){if(e===null||typeof e!="object")return r;if(Array.isArray(e)){for(let s of e)if(s&&typeof s=="object"&&"fact"in s&&"op"in s){let n=s;r.push({path:t?`${t}.${String(n.fact)}`:String(n.fact),op:String(n.op),value:n.value});}return r}if("$all"in e&&Array.isArray(e.$all))return e.$all.forEach((s,n)=>{B(s,`${t}$all[${n}]`,r);}),r;if("$any"in e&&Array.isArray(e.$any))return e.$any.forEach((s,n)=>{B(s,`${t}$any[${n}]`,r);}),r;if("$not"in e)return B(e.$not,`${t}$not`,r),r;for(let[s,n]of Object.entries(e)){let o=t?`${t}.${s}`:s;if(wn(n))for(let[i,c]of Object.entries(n))r.push({path:o,op:i,value:c});else Kt(n)&&!vn.has(s)?B(n,o,r):r.push({path:o,op:"$eq",value:n});}return r}function G(e){return typeof e=="number"&&Number.isFinite(e)}function bn(e,t,r){switch(e){case "$gte":case "$gt":if(G(t)&&G(r)){if(r<t)return "relaxed";if(r>t)return "tightened"}return null;case "$lte":case "$lt":if(G(t)&&G(r)){if(r>t)return "relaxed";if(r<t)return "tightened"}return null;case "$between":{if(Array.isArray(t)&&Array.isArray(r)&&t.length===2&&r.length===2&&G(t[0])&&G(t[1])&&G(r[0])&&G(r[1])){let s=t[1]-t[0],n=r[1]-r[0];if(n>s)return "relaxed";if(n<s)return "tightened"}return null}case "$in":case "$nin":{if(Array.isArray(t)&&Array.isArray(r))if(e==="$in"){if(r.length>t.length)return "relaxed";if(r.length<t.length)return "tightened"}else {if(r.length>t.length)return "tightened";if(r.length<t.length)return "relaxed"}return null}case "$contains":{if(Array.isArray(t)&&Array.isArray(r)){if(r.length>t.length)return "relaxed";if(r.length<t.length)return "tightened"}return null}default:return null}}function Gt(e){let t=zt(e.before),r=zt(e.after),s=[...new Set([...Object.keys(t),...Object.keys(r)])].sort(),n=[],o={added:0,removed:0,changed:0,unchanged:0,totalClauseChanges:0};for(let i of s){let c=t[i],a=r[i],l=i in t,u=i in r;if(l&&!u){let f=B(c),m=f.length===0?[{path:"(function-form predicate)",kind:"removed"}]:f.map($=>({path:$.path,kind:"removed",before:{op:$.op,value:$.value}}));Ge(m),n.push({id:i,status:"removed",changes:m}),o.removed++,o.totalClauseChanges+=m.length;continue}if(!l&&u){let f=B(a),m=f.length===0?[{path:"(function-form predicate)",kind:"added"}]:f.map($=>({path:$.path,kind:"added",after:{op:$.op,value:$.value}}));Ge(m),n.push({id:i,status:"added",changes:m}),o.added++,o.totalClauseChanges+=m.length;continue}let d=kn(c,a);d.length===0?(n.push({id:i,status:"unchanged",changes:[]}),o.unchanged++):(n.push({id:i,status:"changed",changes:d}),o.changed++,o.totalClauseChanges+=d.length);}return {constraints:n,summary:o}}function kn(e,t){if(e!==void 0&&t!==void 0&&(e===null||t===null||typeof e!="object"||typeof t!="object"))return ce(e)===ce(t)?[]:[{path:"",kind:"changed",before:{op:"$eq",value:e},after:{op:"$eq",value:t}}];let r=e===void 0?[]:B(e),s=t===void 0?[]:B(t),n=l=>`${l.path}::${l.op}`,o=new Map(r.map(l=>[n(l),l])),i=new Map(s.map(l=>[n(l),l])),c=new Set([...o.keys(),...i.keys()]),a=[];for(let l of c){let u=o.get(l),d=i.get(l);if(u&&!d){a.push({path:u.path,kind:"removed",before:{op:u.op,value:u.value}});continue}if(!u&&d){a.push({path:d.path,kind:"added",after:{op:d.op,value:d.value}});continue}if(u&&d){if(ce(u.value)===ce(d.value))continue;let f=bn(u.op,u.value,d.value);a.push({path:u.path,kind:f??"changed",before:{op:u.op,value:u.value},after:{op:d.op,value:d.value}});}}return Ge(a),a}function Ge(e){e.sort((t,r)=>{let s=t.path.localeCompare(r.path);if(s!==0)return s;let n=t.before?.op??t.after?.op??"",o=r.before?.op??r.after?.op??"";return n.localeCompare(o)});}function jn(e){let t={maxSamples:20,json:false};for(let r=0;r<e.length;r++)switch(e[r]){case "--history":{let n=e[++r];n&&(t.historyPath=n);break}case "--proposed":case "-p":{let n=e[++r];n&&(t.proposedPath=n);break}case "--original":case "-o":{let n=e[++r];n&&(t.originalPath=n);break}case "--max-samples":{let n=e[++r],o=n?Number.parseInt(n,10):Number.NaN;Number.isFinite(o)&&o>=0&&(t.maxSamples=o);break}case "--entity-key":{let n=e[++r];n&&(t.entityKey=n);break}case "--json":t.json=true;break}return t}function Ce(){console.error(`
736
+ `}function ue(e){return e.replace(/-([a-z])/g,(t,r)=>r.toUpperCase())}function tn(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}async function jt(e){let t=Gr(e);g.intro(m.bgCyan(m.black(" directive init ")));let r;if(t.noInteractive)r="my-module";else {let d=await g.text({message:"Module name:",placeholder:"my-module",defaultValue:"my-module",validate:f=>{if(!/^[a-z][a-z0-9-]*$/.test(f))return "Must start with a letter, use lowercase letters, numbers, and hyphens"}});g.isCancel(d)&&(g.cancel("Cancelled."),process.exit(0)),r=d;}let s;if(t.template){let d=ze(r);t.template in d||(g.log.error(`Unknown template: ${t.template}. Available: ${Object.keys(d).join(", ")}`),process.exit(1)),s=t.template;}else if(t.noInteractive)s="counter";else {let d=ze(r),f=await g.select({message:"Project template:",options:Object.values(d).map(h=>({value:h.id,label:h.label,hint:h.hint}))});g.isCancel(f)&&(g.cancel("Cancelled."),process.exit(0)),s=f;}let o=ze(r)[s],c=Br(t.dir);g.log.info(`Package manager: ${m.cyan(c)}`);let a=g.spinner();a.start("Creating project files...");let l=0;for(let d of o.files){let f=join(t.dir,d.path);if(existsSync(f)){l++;continue}tn(f,d.content);}a.stop("Project files created.");for(let d of o.files){let f=join(t.dir,d.path),h=relative(t.dir,f);existsSync(f)&&g.log.success(`${m.green("Created")} ${m.dim(h)}`);}l>0&&g.log.warn(`Skipped ${l} file(s) that already exist.`);let u=Hr(c,o.deps.join(" "));g.outro(`Next steps:
737
+ ${m.cyan(u)}
738
+ ${m.cyan(`${O} ai-rules init`)}
739
+ ${m.dim("Start building!")}`);}function rn(e){let t={json:false},r="";for(let s=0;s<e.length;s++){let n=e[s];switch(n){case "--json":t.json=true;break;case "--module":{let o=e[++s];o&&(t.module=o);break}default:n&&!n.startsWith("-")&&!r&&(r=n);}}return {filePath:r,opts:t}}function nn(e){let t=[];t.push(m.bold("Facts:"));let r=Object.entries(e);if(r.length===0)return t.push(" (none)"),t.join(`
740
+ `);for(let[s,n]of r){let o=un(n);t.push(` ${m.cyan(s)} = ${o}`);}return t.join(`
741
+ `)}function sn(e){let t=[];if(t.push(m.bold("Constraints:")),e.length===0)return t.push(" (none)"),t.join(`
742
+ `);for(let r of e){let s=r.disabled?m.dim("disabled"):r.active?m.green("active"):m.dim("inactive"),n=r.hitCount>0?m.yellow(` (${r.hitCount} hits)`):"";t.push(` ${m.cyan(r.id)} ${s} priority=${r.priority}${n}`);}return t.join(`
743
+ `)}function on(e,t){let r=[];if(r.push(m.bold("Resolvers:")),e.length===0)return r.push(" (none)"),r.join(`
744
+ `);for(let s of e){let n=t[s.id],o=n?ln(n.state,n.error,n.duration):m.dim("idle");r.push(` ${m.cyan(s.id)} \u2192 ${s.requirement} ${o}`);}return r.join(`
745
+ `)}function an(e){let t=[];if(t.push(m.bold("Unmet Requirements:")),e.length===0)return t.push(` ${m.green("(all requirements met)")}`),t.join(`
746
+ `);for(let r of e)t.push(` ${m.yellow(r.requirement.type)} (id: ${m.dim(r.id)}) from ${m.dim(r.fromConstraint)}`);return t.join(`
747
+ `)}function cn(e){let t=[];if(t.push(m.bold("Inflight:")),e.length===0)return t.push(` ${m.green("(none)")}`),t.join(`
748
+ `);let r=Date.now();for(let s of e){let n=r-s.startedAt;t.push(` ${m.cyan(s.resolverId)} \u2192 req ${m.dim(s.id)} ${m.yellow(`${n}ms`)}`);}return t.join(`
749
+ `)}function ln(e,t,r){let s=r!==void 0?` ${r}ms`:"";switch(e){case "resolved":return m.green(`resolved${s}`);case "errored":return m.red(`errored${s}${t?` \u2014 ${t}`:""}`);case "inflight":return m.yellow("inflight");case "cancelled":return m.dim("cancelled");default:return m.dim(e)}}function un(e){return e===null?m.dim("null"):e===void 0?m.dim("undefined"):typeof e=="string"?e.length>60?`"${e.slice(0,57)}..."`:`"${e}"`:typeof e=="number"||typeof e=="boolean"?String(e):Array.isArray(e)?`[${e.length} items]`:JSON.stringify(e).slice(0,60)}function dn(e){let t=[];new Set(e.unmet.map(o=>o.requirement.type));new Set(e.resolverDefs.map(o=>o.requirement));for(let o of e.resolverDefs)o.requirement;for(let o of e.unmet)e.resolverDefs.some(a=>a.requirement===o.requirement.type||a.requirement==="(predicate)")||t.push(`No resolver for requirement type "${o.requirement.type}"`);return t}async function Et(e){let{filePath:t,opts:r}=rn(e);t||(console.error("Usage: directive inspect <file> [--json] [--module <name>]"),process.exit(1));let s=await z(t);s.isRunning||s.start();let n=s.inspect();if(r.json){let a={};if(s.facts)for(let i of Object.keys(s.facts))try{a[i]=s.facts[i];}catch{a[i]="(error reading)";}console.log(JSON.stringify({facts:a,...n},null,2)),s.stop();return}console.log(),console.log(m.bold(m.cyan("Directive System Inspection"))),console.log(m.dim("\u2500".repeat(40))),console.log();let o={};if(s.facts)for(let a of Object.keys(s.facts))try{o[a]=s.facts[a];}catch{o[a]="(error reading)";}console.log(nn(o)),console.log(),console.log(sn(n.constraints)),console.log(),console.log(on(n.resolverDefs,n.resolvers)),console.log(),console.log(an(n.unmet)),console.log(),n.inflight.length>0&&(console.log(cn(n.inflight)),console.log());let c=dn(n);if(c.length>0){console.log(m.bold(m.yellow("Warnings:")));for(let a of c)console.log(` ${m.yellow("\u26A0")} ${a}`);console.log();}s.stop();}function Ct(e){let t={with:[],minimal:false,dir:process.cwd()};for(let r=0;r<e.length;r++)switch(e[r]){case "--with":{let n=e[++r];n&&(t.with=n.split(",").map(o=>o.trim()));break}case "--minimal":t.minimal=true;break;case "--dir":{let n=e[++r];n&&(t.dir=n);break}}return t}function Rt(e,t){let r=dirname(e);existsSync(r)||mkdirSync(r,{recursive:true}),writeFileSync(e,t,"utf-8");}function Tt(e){return join(e,"src")}function Mt(e,t){let r=validateModuleName(t),s=r===true?"":`: ${r}`;console.error(`Invalid ${e} name: ${t||"(none)"}${s}`),console.error("Must start with a lowercase letter, use lowercase letters, numbers, and hyphens."),process.exit(1);}async function Nt(e,t){let r=Ct(t);if(validateModuleName(e)!==true){Mt("module",e);return}let s;r.minimal?s=[]:r.with.length>0?s=r.with.filter(l=>MODULE_SECTIONS.includes(l)):s=[...MODULE_SECTIONS];let{sourceFileName:n}=suggestFileNames(e,"module"),o=Tt(r.dir),c=join(o,n);existsSync(c)&&(console.error(`File already exists: ${relative(r.dir,c)}`),process.exit(1));let a=generateModule(e,s);Rt(c,a);let i=relative(r.dir,c);console.log(`${m.green("Created")} ${m.dim(i)}`),s.length===0?console.log(m.dim(" Minimal module (schema + init only)")):console.log(m.dim(` Sections: ${s.join(", ")}`));}async function Pt(e,t){let r=Ct(t);if(validateModuleName(e)!==true){Mt("orchestrator",e);return}let{sourceFileName:s}=suggestFileNames(e,"orchestrator"),n=Tt(r.dir),o=join(n,s);existsSync(o)&&(console.error(`File already exists: ${relative(r.dir,o)}`),process.exit(1));let c=generateOrchestrator(e);Rt(o,c);let a=relative(r.dir,o);console.log(`${m.green("Created")} ${m.dim(a)}`),console.log(m.dim(" AI orchestrator with memory, guardrails, and streaming"));}var ge=typeof process<"u"&&process.env?.NODE_ENV!=="production";function de(e,t=50){let r=new WeakSet;function s(i){if(i===null)return "null";if(i===void 0)return "undefined";let l=typeof i;if(l==="string")return JSON.stringify(i);if(l==="number"||l==="boolean")return String(i);if(l==="function")return '"[function]"';if(l==="symbol")return '"[symbol]"'}function n(i,l){if(r.has(i))return '"[circular]"';r.add(i);let u=l();return r.delete(i),u}function o(i,l){return n(i,()=>`[${i.map(u=>a(u,l+1)).join(",")}]`)}function c(i,l){return n(i,()=>`{${Object.keys(i).sort().map(u=>`${JSON.stringify(u)}:${a(i[u],l+1)}`).join(",")}}`)}function a(i,l){if(l>t)return '"[max depth exceeded]"';if(typeof i=="bigint")return `${i.toString()}n`;let u=s(i);if(u!==void 0)return u;if(i instanceof Date)return `D:${i.toISOString()}`;if(i instanceof RegExp)return `R:${i.source}:${i.flags}`;if(i instanceof Map){let d=[...i.entries()].sort();return `M:${a(d,l+1)}`}if(i instanceof Set){let d=[...i].sort();return `S:${a(d,l+1)}`}return Array.isArray(i)?o(i,l):typeof i=="object"?c(i,l):'"[unknown]"'}return a(e,0)}var K=new Set(["$eq","$ne","$in","$nin","$exists","$gt","$gte","$lt","$lte","$between","$matches","$startsWith","$endsWith","$contains","$changed"]),It=new Set(["$all","$any","$not"]);var G=64;function I(e){return typeof e!="object"||e===null||Array.isArray(e)?false:!(e instanceof Date)&&!(e instanceof RegExp)}function De(e){if(typeof e!="object"||e===null||Array.isArray(e))return false;let t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function He(e){if(!I(e))return false;let t=0,r=false;for(let s of Object.keys(e)){if(s.startsWith("$"))r=true,K.has(s)||$e(`predicate: unknown operator "${s}" \u2014 looks like a typo. Known operators: ${[...K].join(", ")}`);else if(r||t===0)return false;t++;}return r?t>0:false}function Ft(e){return e===null?false:Array.isArray(e)?e.every(t=>De(t)&&"fact"in t&&"op"in t):De(e)}function ye(e,t,r="",s=new WeakSet,n=0){if(n>G){ge&&console.warn(`[Directive] predicate depth limit (${G}) exceeded \u2014 flatten the predicate or split it into multiple constraints. If this is unexpected, check for a cyclic spec object.`),t.bail?.("depth");return}if(Array.isArray(e)){e.forEach((c,a)=>{if(!I(c))return;let i=c;if(typeof i.fact=="string"&&typeof i.op=="string"){let l=r?`${r}[${a}]`:`[${a}]`;t.operator?.(r?`${r}.${i.fact}`:i.fact,i.op,i.value,`${l}.value`);}});return}if(!I(e))return;if(s.has(e)){ge&&console.warn("[Directive] walkPredicate: cyclic predicate spec"),t.bail?.("cycle");return}s.add(e);let o=e;for(let c of ["$all","$any","$not"])if(c in o){if(t.combinator?.(c)===false)return;let a=c==="$not"?[o.$not]:o[c]??[];for(let i of a)ye(i,t,r,s,n+1);return}for(let c of Object.keys(o)){let a=r?`${r}.${c}`:c;if(c.startsWith("$")){t.strayOperatorKey?.(c,a);continue}let i=o[c];if(He(i)){let l=i;for(let u of Object.keys(l))t.operator?.(a,u,l[u],`${a}.${u}`);continue}if(De(i)){if(t.nested?.(c)===false)continue;ye(i,t,a,s,n+1);continue}t.literal?.(a,i);}}function Wt(e,t=""){function r(n,o,c,a){if(typeof n=="bigint")throw new Error(`[Directive] validatePredicate: bigint operand at "${o}" is not JSON-serializable (JSON.stringify throws on bigint).`);if(n instanceof Set)throw new Error(`[Directive] validatePredicate: Set operand at "${o}" is not JSON-serializable (serializes to {} and loses all members).`);if(n instanceof Map)throw new Error(`[Directive] validatePredicate: Map operand at "${o}" is not JSON-serializable (serializes to {} and loses all entries).`);if(n instanceof RegExp)throw new Error(`[Directive] validatePredicate: RegExp operand at "${o}" is not JSON-serializable (a regex lost to JSON.parse becomes {}). Only a direct $matches operand may be a RegExp.`);if(!(n===null||typeof n!="object")&&!(a>G)&&!c.has(n)){if(c.add(n),Array.isArray(n)){n.forEach((i,l)=>{r(i,`${o}[${l}]`,c,a+1);});return}for(let i of Object.keys(n))r(n[i],o?`${o}.${i}`:i,c,a+1);}}function s(n,o,c){if(typeof n=="bigint")throw new Error(`[Directive] validatePredicate: bigint operand at "${c}" is not JSON-serializable (JSON.stringify throws on bigint).`);if(n instanceof Set)throw new Error(`[Directive] validatePredicate: Set operand at "${c}" is not JSON-serializable (serializes to {} and loses all members).`);if(n instanceof Map)throw new Error(`[Directive] validatePredicate: Map operand at "${c}" is not JSON-serializable (serializes to {} and loses all entries).`);if(o==="$matches"&&!(n instanceof RegExp))throw new Error(`[Directive] validatePredicate: $matches operand at "${c}" must be a RegExp; got ${n===null?"null":typeof n}. A regex lost to JSON.parse becomes {} \u2014 reify with new RegExp(pattern, flags) before installing.`);if(Array.isArray(n))n.forEach((a,i)=>{r(a,`${c}[${i}]`,new WeakSet,1);});else if(De(n))for(let a of Object.keys(n))r(n[a],`${c}.${a}`,new WeakSet,1);}if(e instanceof Set)throw new Error(`[Directive] validatePredicate: Set operand${t?` at "${t}"`:""} is not JSON-serializable (serializes to {} and loses all members).`);if(e instanceof Map)throw new Error(`[Directive] validatePredicate: Map operand${t?` at "${t}"`:""} is not JSON-serializable (serializes to {} and loses all entries).`);ye(e,{operator(n,o,c,a){s(c,o,t?`${t}.${a}`:a);},literal(n,o){s(o,"",t?`${t}.${n}`:n);}});}function yn(){return {ids:new WeakMap,next:{v:1},pairs:new Set}}function qt(e,t){let r=e.ids.get(t);return r===void 0&&(r=e.next.v++,e.ids.set(t,r)),r}function q(e,t,r){if(Object.is(e,t))return true;if(e instanceof Date&&t instanceof Date)return e.getTime()===t.getTime();if(typeof e!="object"||typeof t!="object"||e===null||t===null)return false;let s=r??yn(),n=`${qt(s,e)}:${qt(s,t)}`;if(s.pairs.has(n))return true;if(s.pairs.add(n),Array.isArray(e)||Array.isArray(t))return !Array.isArray(e)||!Array.isArray(t)||e.length!==t.length?false:e.every((a,i)=>q(a,t[i],s));if(e instanceof Set||t instanceof Set){if(!(e instanceof Set)||!(t instanceof Set)||e.size!==t.size)return false;let a=[...t];return [...e].every(i=>a.some(l=>q(i,l,s)))}if(e instanceof Map||t instanceof Map){if(!(e instanceof Map)||!(t instanceof Map)||e.size!==t.size)return false;let a=[...t.entries()],i=new Array(a.length).fill(false);for(let[l,u]of e){let d=false;for(let f=0;f<a.length;f++){if(i[f])continue;let[h,$]=a[f];if(q(l,h,s)&&q(u,$,s)){i[f]=true,d=true;break}}if(!d)return false}return true}let o=Object.keys(e),c=Object.keys(t);return o.length!==c.length?false:o.every(a=>Object.hasOwn(t,a)&&q(e[a],t[a],s))}function Ce(e){if(e instanceof Date)return e.getTime();if(typeof e=="number"||typeof e=="bigint"||typeof e=="string")return e}function Be(e,t,r){let s=Ce(t),n=Ce(r);if(s===void 0||n===void 0||typeof s!=typeof n)return false;switch(e){case "$gt":return s>n;case "$gte":return s>=n;case "$lt":return s<n;case "$lte":return s<=n;default:return false}}function Re(e,t,r,s){switch(e){case "$eq":return q(t,r);case "$ne":return !q(t,r);case "$in":return Array.isArray(r)&&r.some(n=>q(t,n));case "$nin":return Array.isArray(r)&&!r.some(n=>q(t,n));case "$exists":return r===(t!==void 0);case "$changed":return !q(t,s);case "$gt":case "$gte":case "$lt":case "$lte":return Be(e,t,r);case "$between":{if(!Array.isArray(r)||r.length!==2)return false;let n=Ce(r[0]),o=Ce(r[1]);return n!==void 0&&o!==void 0&&typeof n==typeof o&&n>o?($e("$between: reversed pair \u2014 [min, max] required"),false):Be("$gte",t,r[0])&&Be("$lte",t,r[1])}case "$matches":{if(!(r instanceof RegExp))throw new Error("[Directive] $matches: operand must be a RegExp (string operands are no longer accepted; pass /pattern/flags directly).");return typeof t!="string"?false:r.test(t)}case "$startsWith":return typeof t!="string"?false:t.startsWith(String(r));case "$endsWith":return typeof t!="string"?false:t.endsWith(String(r));case "$contains":return typeof t=="string"?t.includes(String(r)):Array.isArray(t)?t.some(n=>q(n,r)):t instanceof Set?t.has(r):false;default:return false}}function $e(e){ge&&console.warn(`[Directive] ${e}`);}function $n(e,t,r,s){if(He(e)){let n=Object.keys(e);n.length>1&&$e(`predicate: operator object has ${n.length} operators (${n.join(", ")}) \u2014 write the array form or $all instead. The runtime ANDs them as a best-effort fallback.`);for(let o of n)if(!Re(o,t,e[o],r))return false;return true}return I(e)?se(e,I(t)?t:Object.create(null),I(r)?r:void 0,s+1):q(t,e)}function se(e,t,r,s=0){if(s>G)return $e(`predicate depth limit (${G}) exceeded \u2014 flatten the predicate or split it into multiple constraints. If this is unexpected, check for a cyclic spec object.`),false;if(Array.isArray(e))return e.every(n=>{if(!I(n))return false;let{fact:o,op:c,value:a}=n;return Re(c,t?.[o],a,r?.[o])});if(!I(e))return !!e;if("$all"in e)return e.$all.every(n=>se(n,t,r,s+1));if("$any"in e)return e.$any.some(n=>se(n,t,r,s+1));if("$not"in e)return !se(e.$not,t,r,s+1);for(let n of Object.keys(e)){if(K.has(n))return $e(`predicate: operator "${n}" mixed with fact keys \u2014 wrap operators in a per-fact object`),false;if(!$n(e[n],t?.[n],r?.[n],s))return false}return true}function ve(e,t,r,s=""){let n=[];if(Array.isArray(e)){for(let o of e){if(!I(o))continue;let{fact:c,op:a,value:i}=o,l=t?.[c];n.push({path:s+c,op:a,expected:i,actual:l,pass:Re(a,l,i,r?.[c])});}return n}if(!I(e))return n;for(let o of ["$all","$any","$not"])if(o in e){let c=o==="$not"?[e.$not]:e[o],a=[];for(let u of c)a.push(...ve(u,t,r,s));let i=a.filter(u=>u.pass).length,l;return o==="$all"?l=a.length===0||i===a.length:o==="$any"?l=a.length>0&&i>0:l=!a.every(u=>u.pass),n.push({path:s||o,op:o,expected:c.length,actual:i,pass:l,children:a}),n}for(let o of Object.keys(e)){if(K.has(o))continue;let c=e[o],a=t?.[o],i=s+o;if(He(c))for(let l of Object.keys(c))n.push({path:i,op:l,expected:c[l],actual:a,pass:Re(l,a,c[l],r?.[o])});else I(c)?n.push(...ve(c,I(a)?a:Object.create(null),I(r?.[o])?r?.[o]:void 0,`${i}.`)):n.push({path:i,op:"$eq",expected:c,actual:a,pass:q(a,c)});}return n}var fe=1e6;function _t(e,t){try{Wt(e);}catch(s){let n=s instanceof Error?s.message:String(s);throw new Error(`[Directive] replayUnder: the ${t} predicate is invalid \u2014 ${n}`)}if(!Ft(e)){let s=e===null||typeof e!="object"?`${typeof e} \u2014 ${JSON.stringify(e)}`:JSON.stringify(e).slice(0,80);throw new Error(`[Directive] replayUnder: the ${t} predicate is not a valid FactPredicate (got ${s})`)}let r;if(ye(e,{operator(s,n){r===void 0&&n.startsWith("$")&&!K.has(n)&&(r=n);},strayOperatorKey(s){r===void 0&&!K.has(s)&&!It.has(s)&&(r=s);}}),r!==void 0)throw new Error(`[Directive] replayUnder: the ${t} predicate uses an unknown operator "${r}" \u2014 known operators: ${[...K].join(", ")}`)}function we(e){if(e&&typeof e=="object"&&!Array.isArray(e)&&Array.isArray(e.snapshots))return vn(e);let t=Array.isArray(e)?e:e&&typeof e=="object"&&Array.isArray(e.frames)?e.frames:null;if(!t)throw new Error("[Directive] toReplayFrames: history must be a JSON array of frames, an object with a `frames` array, or a history export with a `snapshots` array");if(t.length>fe)throw new Error(`[Directive] toReplayFrames: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${fe}) \u2014 split or down-sample the history`);return t.map((r,s)=>{if(r&&typeof r=="object"&&"facts"in r){let n=r,o={id:n.id??`#${s}`,facts:n.facts??{}};return typeof n.timestamp=="number"&&(o.timestamp=n.timestamp),o}return {id:`#${s}`,facts:r??{}}})}function vn(e){let t=typeof e=="string"?JSON.parse(e):e;if(Array.isArray(t))return Ut(t);if(!t||typeof t!="object")throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");let r=t;if(r.version!==void 0&&r.version!==1)throw new Error(`[Directive] framesFromHistory: unsupported history export version ${JSON.stringify(r.version)} \u2014 expected 1`);if(!Array.isArray(r.snapshots))throw new Error("[Directive] framesFromHistory: expected a history export object with a `snapshots` array (from system.history.export())");return Ut(r.snapshots)}function Ut(e){if(!Array.isArray(e))throw new Error("[Directive] framesFromSnapshots: expected an array of fact-state snapshots");if(e.length>fe)throw new Error(`[Directive] framesFromSnapshots: history has ${e.length} snapshots, exceeds the MAX_REPLAY_FRAMES limit (${fe}) \u2014 split or down-sample the history`);for(let t=0;t<e.length;t++){let r=e[t];if(!r||typeof r!="object"||!("facts"in r))throw new Error(`[Directive] framesFromSnapshots: snapshot at index ${t} is not a { facts, ... } object`)}return we(e)}function Te(e){let{frames:t,original:r,proposed:s,entityKey:n}=e,o=e.maxSamples??20,c=o>0?o:0;if(t.length>fe)throw new Error(`[Directive] replayUnder: history has ${t.length} frames, exceeds the MAX_REPLAY_FRAMES limit (${fe}) \u2014 split or down-sample the history`);_t(r,"original"),_t(s,"proposed");let a=0,i=0,l=0,u=0,d=0,f=[],h=[],$=n?new Set:void 0,w=n?new Set:void 0,F;for(let p of t){let v=p.facts,D=se(r,v,F),_=se(s,v,F);D&&(a++,$?.add(v[n])),_&&(i++,w?.add(v[n])),D===_?d++:!D&&_?(l++,f.length<c&&f.push(Lt(p,r,s,F))):(u++,h.length<c&&h.push(Lt(p,r,s,F))),F=v;}let W={framesEvaluated:t.length,original:{matched:a},proposed:{matched:i},delta:i-a,newMatchCount:l,lostMatchCount:u,unchanged:d,newMatches:f,lostMatches:h};return $&&w&&(W.original.matchedEntities=$.size,W.proposed.matchedEntities=w.size),W}function Lt(e,t,r,s){let n=e.facts,o={frameId:e.id,facts:n,originalExplain:ve(t,n,s),proposedExplain:ve(r,n,s)};return e.timestamp!==void 0&&(o.timestamp=e.timestamp),o}var zt=1e4,Jt=5e7;function wn(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===1&&typeof e.$hole=="string"}function Qe(e,t,r=new Set,s=0){if(s>G)throw new Error(`[Directive] sweepUnder: template exceeds MAX_PREDICATE_DEPTH (${G}) \u2014 flatten the template or split the sweep`);if(wn(e)){let n=e.$hole;if(!(n in t))throw new Error(`[Directive] sweepUnder: template references hole "${n}" but sweep has no values for it`);return t[n]}if(e===null||typeof e!="object")return e;if(r.has(e))throw new Error("[Directive] sweepUnder: template contains a cycle \u2014 predicate templates must be a tree");r.add(e);try{if(Array.isArray(e))return e.map(o=>Qe(o,t,r,s+1));let n={};for(let[o,c]of Object.entries(e))n[o]=Qe(c,t,r,s+1);return n}finally{r.delete(e);}}function*Gt(e,t){if(e.length===0){yield {};return}let r=e[0],s=e.slice(1),n=t[r]??[];for(let o of n)for(let c of Gt(s,t))yield {[r]:o,...c};}function bn(e){let t=1;for(let r of Object.values(e))t*=r.length;return t}function Bt(e){let{frames:t,original:r,template:s,sweep:n,objective:o=v=>v.proposed.matched,entityKey:c,maxSamples:a=0}=e,i=Object.keys(n);if(i.length===0)throw new Error("[Directive] sweepUnder: `sweep` must contain at least one hole name");let l=bn(n);if(l>zt)throw new Error(`[Directive] sweepUnder: grid has ${l} points, exceeds the MAX_SWEEP_POINTS limit (${zt}) \u2014 narrow the sweep ranges or split the run`);if(l===0)throw new Error("[Directive] sweepUnder: at least one hole has zero candidate values");let u=l*t.length;if(u>Jt)throw new Error(`[Directive] sweepUnder: ${l} points \xD7 ${t.length} frames = ${u} per-frame evaluations, exceeds the MAX_SWEEP_EVALUATIONS limit (${Jt}) \u2014 narrow the sweep, down-sample the history, or split the run`);let d=false,f=v=>{let D;try{D=o(v);}catch(_){return d||(d=true,console.warn(`[Directive] sweepUnder: objective threw \u2014 point will not rank (${_.message})`)),Number.NEGATIVE_INFINITY}return typeof D!="number"||!Number.isFinite(D)?(d||(d=true,console.warn(`[Directive] sweepUnder: objective returned a non-finite number (${String(D)}) \u2014 point will not rank`)),Number.NEGATIVE_INFINITY):D},h=Te({frames:t,original:r,proposed:r,entityKey:c,maxSamples:a}),$={values:{},report:h,score:f(h)},w=[],F=0,W=Number.NEGATIVE_INFINITY;for(let v of Gt(i,n)){let D=Qe(s,v),_=Te({frames:t,original:r,proposed:D,entityKey:c,maxSamples:a}),Ne=f(_);Ne>W&&(W=Ne,F=w.length),w.push({values:v,report:_,score:Ne});}let p=w[F];return {points:w,bestIndex:F,best:p,baseline:$}}function Kt(e){let t=e&&typeof e=="object"&&!Array.isArray(e)&&"constraints"in e?e.constraints:e;if(Array.isArray(t)){let r={};for(let s of t){if(!s||typeof s!="object"||!("id"in s))throw new Error("[Directive] diffRules: array entries must be `{ id, whenSpec }` objects");let n=s;if(typeof n.id!="string")throw new Error("[Directive] diffRules: constraint `id` must be a string");r[n.id]=n.whenSpec;}return r}if(t&&typeof t=="object")return t;throw new Error("[Directive] diffRules: expected a `{ id: whenSpec }` map, an array of `{ id, whenSpec }`, or `{ constraints: ... }`")}var kn=new Set(["$eq","$ne","$in","$nin","$exists","$gt","$gte","$lt","$lte","$between","$matches","$startsWith","$endsWith","$contains","$changed"]),xn=new Set(["$all","$any","$not"]);function Ht(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function Sn(e){if(!Ht(e))return false;let t=Object.keys(e);if(t.length===0)return false;let r=false;for(let s of t){if(!s.startsWith("$"))return false;kn.has(s)&&(r=true);}return r}function H(e,t="",r=[]){if(e===null||typeof e!="object")return r;if(Array.isArray(e)){for(let s of e)if(s&&typeof s=="object"&&"fact"in s&&"op"in s){let n=s;r.push({path:t?`${t}.${String(n.fact)}`:String(n.fact),op:String(n.op),value:n.value});}return r}if("$all"in e&&Array.isArray(e.$all))return e.$all.forEach((s,n)=>{H(s,`${t}$all[${n}]`,r);}),r;if("$any"in e&&Array.isArray(e.$any))return e.$any.forEach((s,n)=>{H(s,`${t}$any[${n}]`,r);}),r;if("$not"in e)return H(e.$not,`${t}$not`,r),r;for(let[s,n]of Object.entries(e)){let o=t?`${t}.${s}`:s;if(Sn(n))for(let[c,a]of Object.entries(n))r.push({path:o,op:c,value:a});else Ht(n)&&!xn.has(s)?H(n,o,r):r.push({path:o,op:"$eq",value:n});}return r}function B(e){return typeof e=="number"&&Number.isFinite(e)}function An(e,t,r){switch(e){case "$gte":case "$gt":if(B(t)&&B(r)){if(r<t)return "relaxed";if(r>t)return "tightened"}return null;case "$lte":case "$lt":if(B(t)&&B(r)){if(r>t)return "relaxed";if(r<t)return "tightened"}return null;case "$between":{if(Array.isArray(t)&&Array.isArray(r)&&t.length===2&&r.length===2&&B(t[0])&&B(t[1])&&B(r[0])&&B(r[1])){let s=t[1]-t[0],n=r[1]-r[0];if(n>s)return "relaxed";if(n<s)return "tightened"}return null}case "$in":case "$nin":{if(Array.isArray(t)&&Array.isArray(r))if(e==="$in"){if(r.length>t.length)return "relaxed";if(r.length<t.length)return "tightened"}else {if(r.length>t.length)return "tightened";if(r.length<t.length)return "relaxed"}return null}case "$contains":{if(Array.isArray(t)&&Array.isArray(r)){if(r.length>t.length)return "relaxed";if(r.length<t.length)return "tightened"}return null}default:return null}}function Qt(e){let t=Kt(e.before),r=Kt(e.after),s=[...new Set([...Object.keys(t),...Object.keys(r)])].sort(),n=[],o={added:0,removed:0,changed:0,unchanged:0,totalClauseChanges:0};for(let c of s){let a=t[c],i=r[c],l=c in t,u=c in r;if(l&&!u){let f=H(a),h=f.length===0?[{path:"(function-form predicate)",kind:"removed"}]:f.map($=>({path:$.path,kind:"removed",before:{op:$.op,value:$.value}}));Ye(h),n.push({id:c,status:"removed",changes:h}),o.removed++,o.totalClauseChanges+=h.length;continue}if(!l&&u){let f=H(i),h=f.length===0?[{path:"(function-form predicate)",kind:"added"}]:f.map($=>({path:$.path,kind:"added",after:{op:$.op,value:$.value}}));Ye(h),n.push({id:c,status:"added",changes:h}),o.added++,o.totalClauseChanges+=h.length;continue}let d=jn(a,i);d.length===0?(n.push({id:c,status:"unchanged",changes:[]}),o.unchanged++):(n.push({id:c,status:"changed",changes:d}),o.changed++,o.totalClauseChanges+=d.length);}return {constraints:n,summary:o}}function jn(e,t){if(e!==void 0&&t!==void 0&&(e===null||t===null||typeof e!="object"||typeof t!="object"))return de(e)===de(t)?[]:[{path:"",kind:"changed",before:{op:"$eq",value:e},after:{op:"$eq",value:t}}];let r=e===void 0?[]:H(e),s=t===void 0?[]:H(t),n=l=>`${l.path}::${l.op}`,o=new Map(r.map(l=>[n(l),l])),c=new Map(s.map(l=>[n(l),l])),a=new Set([...o.keys(),...c.keys()]),i=[];for(let l of a){let u=o.get(l),d=c.get(l);if(u&&!d){i.push({path:u.path,kind:"removed",before:{op:u.op,value:u.value}});continue}if(!u&&d){i.push({path:d.path,kind:"added",after:{op:d.op,value:d.value}});continue}if(u&&d){if(de(u.value)===de(d.value))continue;let f=An(u.op,u.value,d.value);i.push({path:u.path,kind:f??"changed",before:{op:u.op,value:u.value},after:{op:d.op,value:d.value}});}}return Ye(i),i}function Ye(e){e.sort((t,r)=>{let s=t.path.localeCompare(r.path);if(s!==0)return s;let n=t.before?.op??t.after?.op??"",o=r.before?.op??r.after?.op??"";return n.localeCompare(o)});}function Cn(e){let t={maxSamples:20,json:false};for(let r=0;r<e.length;r++)switch(e[r]){case "--history":{let n=e[++r];n&&(t.historyPath=n);break}case "--proposed":case "-p":{let n=e[++r];n&&(t.proposedPath=n);break}case "--original":case "-o":{let n=e[++r];n&&(t.originalPath=n);break}case "--max-samples":{let n=e[++r],o=n?Number.parseInt(n,10):Number.NaN;Number.isFinite(o)&&o>=0&&(t.maxSamples=o);break}case "--entity-key":{let n=e[++r];n&&(t.entityKey=n);break}case "--json":t.json=true;break}return t}function Me(){console.error(`
948
750
  Usage: directive replay-under --history <frames.json> --proposed <spec.json>
949
751
 
950
752
  Replay a recorded fact-frame history through a proposed constraint
@@ -968,13 +770,13 @@ Examples:
968
770
  --original current-rule.json --proposed tightened-rule.json
969
771
  directive replay-under --history sessions.json \\
970
772
  --original a.json --proposed b.json --entity-key userId --json
971
- `);}function Be(e,t){let r=resolve(e);existsSync(r)||(console.error(g.red(`error: ${t} file not found: ${r}`)),process.exit(1));try{return JSON.parse(readFileSync(r,"utf8"))}catch(s){console.error(g.red(`error: failed to parse ${t} (${r}): `)+s.message),process.exit(1);}}function En(e){try{return ye(e)}catch(t){console.error(g.red(`error: ${t.message}`)),process.exit(1);}}function Bt(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===0}function Ht(e){let t=Object.entries(e).slice(0,6).map(([s,n])=>`${s}=${JSON.stringify(n)}`),r=Object.keys(e).length-t.length;return t.join(" ")+(r>0?g.dim(` +${r} more`):"")}function On(e,t){let{original:r,proposed:s,delta:n}=e,o=n>0?g.green(`+${n}`):n<0?g.red(`${n}`):g.dim("\xB10");if(console.log(`
972
- ${g.bold("replay-under")} \u2014 predicate backtest
773
+ `);}function Xe(e,t){let r=resolve(e);existsSync(r)||(console.error(m.red(`error: ${t} file not found: ${r}`)),process.exit(1));try{return JSON.parse(readFileSync(r,"utf8"))}catch(s){console.error(m.red(`error: failed to parse ${t} (${r}): `)+s.message),process.exit(1);}}function Rn(e){try{return we(e)}catch(t){console.error(m.red(`error: ${t.message}`)),process.exit(1);}}function Yt(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)&&Object.keys(e).length===0}function Xt(e){let t=Object.entries(e).slice(0,6).map(([s,n])=>`${s}=${JSON.stringify(n)}`),r=Object.keys(e).length-t.length;return t.join(" ")+(r>0?m.dim(` +${r} more`):"")}function Tn(e,t){let{original:r,proposed:s,delta:n}=e,o=n>0?m.green(`+${n}`):n<0?m.red(`${n}`):m.dim("\xB10");if(console.log(`
774
+ ${m.bold("replay-under")} \u2014 predicate backtest
973
775
  `),console.log(` frames evaluated ${e.framesEvaluated}`),console.log(` original spec matched ${r.matched} frames`),console.log(` proposed spec matched ${s.matched} frames (${o})`),t&&r.matchedEntities!==void 0&&s.matchedEntities!==void 0&&(console.log(`
974
- original spec matched across ${r.matchedEntities} ${t}s`),console.log(` proposed spec matched across ${s.matchedEntities} ${t}s`)),console.log(""),console.log(` ${g.green(`+${e.newMatchCount}`)} new matches ${g.dim("frames that now match the rule")}`),console.log(` ${g.red(`-${e.lostMatchCount}`)} lost matches ${g.dim("frames that no longer match")}`),e.newMatches.length>0){console.log(`
975
- ${g.green("sample new matches:")}`);for(let a of e.newMatches.slice(0,8))console.log(` frame ${a.frameId} ${g.dim(Ht(a.facts))}`);}if(e.lostMatches.length>0){console.log(`
976
- ${g.red("sample lost matches:")}`);for(let a of e.lostMatches.slice(0,8))console.log(` frame ${a.frameId} ${g.dim(Ht(a.facts))}`);}let i=e.newMatches.length+e.lostMatches.length,c=e.newMatchCount+e.lostMatchCount;i<c&&console.log(g.dim(`
977
- ${i} of ${c} diff frames sampled \u2014 --json for the full report`)),console.log("");}async function Qt(e){(e.includes("--help")||e.length===0)&&(Ce(),process.exit(e.length===0?1:0));let t=jn(e);t.historyPath||(console.error(g.red("error: --history <frames.json> is required")),Ce(),process.exit(1)),t.proposedPath||(console.error(g.red("error: --proposed <spec.json> is required")),Ce(),process.exit(1)),t.originalPath||(console.error(g.red("error: --original <spec.json> is required")+g.dim("\n (v1 cannot recover the constraint's current `when` from a live system)")),Ce(),process.exit(1));let r=En(Be(t.historyPath,"--history")),s=Be(t.originalPath,"--original"),n=Be(t.proposedPath,"--proposed");Bt(s)&&console.error(g.yellow("warning: --original is an empty predicate {} \u2014 it matches every frame")),Bt(n)&&console.error(g.yellow("warning: --proposed is an empty predicate {} \u2014 it matches every frame"));let o;try{o=Te({frames:r,original:s,proposed:n,maxSamples:t.maxSamples,entityKey:t.entityKey});}catch(i){console.error(g.red(`error: ${i.message}`)),process.exit(1);}if(t.json){console.log(JSON.stringify(o,null,2));return}On(o,t.entityKey);}function Cn(e){let t={json:false,dispatchableOnly:true,verbose:false},r="";for(let s=0;s<e.length;s++){let n=e[s];switch(n){case "--system":case "-s":{let o=e[++s];o&&(t.systemPath=o);break}case "--max-frames":{let o=e[++s],i=o?Number.parseInt(o,10):Number.NaN;Number.isFinite(i)&&i>0&&(t.maxFrames=i);break}case "--all-frames":case "--no-dispatchable-only":t.dispatchableOnly=false;break;case "--json":t.json=true;break;case "--verbose":case "-v":t.verbose=true;break;default:n&&!n.startsWith("-")&&!r&&(r=n);}}return {jsonPath:r,opts:t}}function He(){console.error(`
776
+ original spec matched across ${r.matchedEntities} ${t}s`),console.log(` proposed spec matched across ${s.matchedEntities} ${t}s`)),console.log(""),console.log(` ${m.green(`+${e.newMatchCount}`)} new matches ${m.dim("frames that now match the rule")}`),console.log(` ${m.red(`-${e.lostMatchCount}`)} lost matches ${m.dim("frames that no longer match")}`),e.newMatches.length>0){console.log(`
777
+ ${m.green("sample new matches:")}`);for(let i of e.newMatches.slice(0,8))console.log(` frame ${i.frameId} ${m.dim(Xt(i.facts))}`);}if(e.lostMatches.length>0){console.log(`
778
+ ${m.red("sample lost matches:")}`);for(let i of e.lostMatches.slice(0,8))console.log(` frame ${i.frameId} ${m.dim(Xt(i.facts))}`);}let c=e.newMatches.length+e.lostMatches.length,a=e.newMatchCount+e.lostMatchCount;c<a&&console.log(m.dim(`
779
+ ${c} of ${a} diff frames sampled \u2014 --json for the full report`)),console.log("");}async function Vt(e){(e.includes("--help")||e.length===0)&&(Me(),process.exit(e.length===0?1:0));let t=Cn(e);t.historyPath||(console.error(m.red("error: --history <frames.json> is required")),Me(),process.exit(1)),t.proposedPath||(console.error(m.red("error: --proposed <spec.json> is required")),Me(),process.exit(1)),t.originalPath||(console.error(m.red("error: --original <spec.json> is required")+m.dim("\n (v1 cannot recover the constraint's current `when` from a live system)")),Me(),process.exit(1));let r=Rn(Xe(t.historyPath,"--history")),s=Xe(t.originalPath,"--original"),n=Xe(t.proposedPath,"--proposed");Yt(s)&&console.error(m.yellow("warning: --original is an empty predicate {} \u2014 it matches every frame")),Yt(n)&&console.error(m.yellow("warning: --proposed is an empty predicate {} \u2014 it matches every frame"));let o;try{o=Te({frames:r,original:s,proposed:n,maxSamples:t.maxSamples,entityKey:t.entityKey});}catch(c){console.error(m.red(`error: ${c.message}`)),process.exit(1);}if(t.json){console.log(JSON.stringify(o,null,2));return}Tn(o,t.entityKey);}function qn(e){let t={json:false,dispatchableOnly:true,verbose:false},r="";for(let s=0;s<e.length;s++){let n=e[s];switch(n){case "--system":case "-s":{let o=e[++s];o&&(t.systemPath=o);break}case "--max-frames":{let o=e[++s],c=o?Number.parseInt(o,10):Number.NaN;Number.isFinite(c)&&c>0&&(t.maxFrames=c);break}case "--all-frames":case "--no-dispatchable-only":t.dispatchableOnly=false;break;case "--json":t.json=true;break;case "--verbose":case "-v":t.verbose=true;break;default:n&&!n.startsWith("-")&&!r&&(r=n);}}return {jsonPath:r,opts:t}}function Ve(){console.error(`
978
780
  Usage: directive replay <timeline.json> [options]
979
781
 
980
782
  Replay a serialized Directive timeline against a fresh system.
@@ -996,8 +798,8 @@ Examples:
996
798
  directive replay bug-1234.json --system src/app/system.ts
997
799
  directive replay error.json --system src/system.ts --json
998
800
  directive replay error.json --system src/system.ts --verbose
999
- `);}async function Yt(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(He(),process.exit(e.length===0?1:0));let{jsonPath:t,opts:r}=Cn(e);t||(console.error(g.red("error: missing <timeline.json> argument")),He(),process.exit(1)),r.systemPath||(console.error(g.red("error: --system <path> is required"),g.dim(`
1000
- (replay needs a fresh system to dispatch against)`)),He(),process.exit(1));let s=resolve(t);existsSync(s)||(console.error(g.red(`error: timeline file not found: ${s}`)),process.exit(1));let n;try{n=readFileSync(s,"utf8");}catch(f){console.error(g.red(`error: failed to read ${s}: ${f.message}`)),process.exit(1);}let o;try{o=JSON.parse(n);}catch(f){console.error(g.red(`error: ${s} is not valid JSON: ${f.message}`)),process.exit(1);}let{deserializeTimeline:i,replayTimeline:c}=await oe(r.verbose),a;try{a=i(o);}catch(f){console.error(g.red(`error: timeline JSON failed validation: ${f.message}`)),process.exit(1);}let l;try{l=await z(r.systemPath);}catch(f){console.error(g.red(`error: failed to load system file: ${f.message}`)),process.exit(1);}let u=l;if(typeof u.dispatch!="function"&&(console.error(g.red("error: loaded system has no dispatch() method. The --system file must export a started Directive system or a factory.")),process.exit(1)),typeof u.start=="function")try{u.start();}catch{}let d=await c(a,u,{dispatchableOnly:r.dispatchableOnly,maxFrames:r.maxFrames});if(r.json)console.log(JSON.stringify(d,null,2));else {let{dispatched:f,skipped:m,truncated:$}=d,w=f>0;console.log(`${w?g.green("\u2713"):g.yellow("\u26A0")} replay complete:`,g.bold(`${f} dispatched`),g.dim(`/ ${m} skipped`),$>0?g.yellow(`/ ${$} TRUNCATED`):""),f===0&&console.error(g.yellow("warning: 0 frames dispatched. Either the timeline contains only non-dispatchable frames (system lifecycle, derivations, etc.) or the system shape doesn't match what the timeline recorded.")),$>0&&console.error(g.yellow(`warning: ${$} frames truncated by --max-frames cap. Raise it with --max-frames <n> if you need them.`));}process.exit(0);}function qn(e){let t={json:false,markdown:false};for(let r=0;r<e.length;r++)switch(e[r]){case "--before":case "-b":{let n=e[++r];n&&(t.beforePath=n);break}case "--after":case "-a":{let n=e[++r];n&&(t.afterPath=n);break}case "--json":t.json=true;break;case "--markdown":case "--md":t.markdown=true;break}return t}function Qe(){console.error(`
801
+ `);}async function Zt(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(Ve(),process.exit(e.length===0?1:0));let{jsonPath:t,opts:r}=qn(e);t||(console.error(m.red("error: missing <timeline.json> argument")),Ve(),process.exit(1)),r.systemPath||(console.error(m.red("error: --system <path> is required"),m.dim(`
802
+ (replay needs a fresh system to dispatch against)`)),Ve(),process.exit(1));let s=resolve(t);existsSync(s)||(console.error(m.red(`error: timeline file not found: ${s}`)),process.exit(1));let n;try{n=readFileSync(s,"utf8");}catch(f){console.error(m.red(`error: failed to read ${s}: ${f.message}`)),process.exit(1);}let o;try{o=JSON.parse(n);}catch(f){console.error(m.red(`error: ${s} is not valid JSON: ${f.message}`)),process.exit(1);}let{deserializeTimeline:c,replayTimeline:a}=await ce(r.verbose),i;try{i=c(o);}catch(f){console.error(m.red(`error: timeline JSON failed validation: ${f.message}`)),process.exit(1);}let l;try{l=await z(r.systemPath);}catch(f){console.error(m.red(`error: failed to load system file: ${f.message}`)),process.exit(1);}let u=l;if(typeof u.dispatch!="function"&&(console.error(m.red("error: loaded system has no dispatch() method. The --system file must export a started Directive system or a factory.")),process.exit(1)),typeof u.start=="function")try{u.start();}catch{}let d=await a(i,u,{dispatchableOnly:r.dispatchableOnly,maxFrames:r.maxFrames});if(r.json)console.log(JSON.stringify(d,null,2));else {let{dispatched:f,skipped:h,truncated:$}=d,w=f>0;console.log(`${w?m.green("\u2713"):m.yellow("\u26A0")} replay complete:`,m.bold(`${f} dispatched`),m.dim(`/ ${h} skipped`),$>0?m.yellow(`/ ${$} TRUNCATED`):""),f===0&&console.error(m.yellow("warning: 0 frames dispatched. Either the timeline contains only non-dispatchable frames (system lifecycle, derivations, etc.) or the system shape doesn't match what the timeline recorded.")),$>0&&console.error(m.yellow(`warning: ${$} frames truncated by --max-frames cap. Raise it with --max-frames <n> if you need them.`));}process.exit(0);}function _n(e){let t={json:false,markdown:false};for(let r=0;r<e.length;r++)switch(e[r]){case "--before":case "-b":{let n=e[++r];n&&(t.beforePath=n);break}case "--after":case "-a":{let n=e[++r];n&&(t.afterPath=n);break}case "--json":t.json=true;break;case "--markdown":case "--md":t.markdown=true;break}return t}function Ze(){console.error(`
1001
803
  Usage: directive rules-diff --before <a.json> --after <b.json>
1002
804
 
1003
805
  Structural diff between two snapshots of constraint whenSpec. Reports
@@ -1023,10 +825,10 @@ Or pull one from a git ref:
1023
825
  git show HEAD~1:path/to/snapshot.json > before.json
1024
826
  git show HEAD:path/to/snapshot.json > after.json
1025
827
  directive rules-diff --before before.json --after after.json
1026
- `);}function Xt(e,t){let r=resolve(e);existsSync(r)||(console.error(g.red(`error: ${t} file not found: ${r}`)),process.exit(1));try{return JSON.parse(readFileSync(r,"utf8"))}catch(s){console.error(g.red(`error: failed to parse ${t} (${r}): `)+s.message),process.exit(1);}}function In(e){switch(e){case "added":return g.green("+");case "removed":return g.red("-");case "relaxed":return g.green("\u25B2");case "tightened":return g.red("\u25BD");default:return g.yellow("~")}}function H(e){return e?e.op==="$eq"?JSON.stringify(e.value):`${e.op} ${JSON.stringify(e.value)}`:"\u2014"}function $e(e){return e.replace(/\|/g,"\\|").replace(/`/g,"'").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function Fn(e){let{summary:t,constraints:r}=e;console.log(`
1027
- ${g.bold("rules-diff")} \u2014 structural predicate diff
1028
- `),console.log(` ${g.green(`+${t.added}`)} added ${g.red(`-${t.removed}`)} removed ${g.yellow(`~${t.changed}`)} changed ${g.dim(`\xB7${t.unchanged} unchanged`)}`),console.log(` ${t.totalClauseChanges} clause-level change${t.totalClauseChanges===1?"":"s"}
1029
- `);for(let s of r){if(s.status==="unchanged")continue;let n=s.status==="added"?g.green("ADDED"):s.status==="removed"?g.red("REMOVED"):g.yellow("CHANGED");console.log(` ${g.bold(s.id)} ${n}`);for(let o of s.changes){let i=g.cyan(o.path||"(predicate)"),c=In(o.kind);if(o.kind==="added")console.log(` ${c} ${i} ${H(o.after)}`);else if(o.kind==="removed")console.log(` ${c} ${i} ${H(o.before)}`);else {let a=o.kind==="relaxed"?g.green("relaxed"):o.kind==="tightened"?g.red("tightened"):g.yellow("changed");console.log(` ${c} ${i} ${H(o.before)} ${g.dim("\u2192")} ${H(o.after)} ${g.dim(`[${a}]`)}`);}}console.log("");}}function Wn(e){let{summary:t,constraints:r}=e;console.log("## \u{1F4CB} Rules diff"),console.log(""),console.log(`**+${t.added} added \xB7 -${t.removed} removed \xB7 ~${t.changed} changed \xB7 \xB7${t.unchanged} unchanged** \u2014 ${t.totalClauseChanges} clause change${t.totalClauseChanges===1?"":"s"}`),console.log("");for(let s of r){if(s.status==="unchanged")continue;let n=s.status==="added"?"\u{1F195} ADDED":s.status==="removed"?"\u{1F5D1} REMOVED":"\u270F\uFE0F CHANGED";console.log(`### \`${s.id}\` \u2014 ${n}`),console.log(""),console.log("| | path | change |"),console.log("|---|---|---|");for(let o of s.changes){let i=`\`${$e(o.path||"(predicate)")}\``,c;o.kind==="added"?c=`| \u2795 | ${i} | ${$e(H(o.after))} |`:o.kind==="removed"?c=`| \u2796 | ${i} | ${$e(H(o.before))} |`:c=`| ${o.kind==="relaxed"?"\u25B2 relaxed":o.kind==="tightened"?"\u25BD tightened":"\u2194 changed"} | ${i} | ${$e(H(o.before))} \u2192 ${$e(H(o.after))} |`,console.log(c);}console.log("");}}async function Vt(e){(e.includes("--help")||e.length===0)&&(Qe(),process.exit(e.length===0?1:0));let t=qn(e);t.beforePath||(console.error(g.red("error: --before <a.json> is required")),Qe(),process.exit(1)),t.afterPath||(console.error(g.red("error: --after <b.json> is required")),Qe(),process.exit(1));let r=Xt(t.beforePath,"--before"),s=Xt(t.afterPath,"--after"),n;try{n=Gt({before:r,after:s});}catch(o){console.error(g.red(`error: ${o.message}`)),process.exit(1);}if(t.json){console.log(JSON.stringify(n,null,2));return}if(t.markdown){Wn(n);return}Fn(n);}function Ln(e){let t={json:false,verbose:false},r=[];for(let s=0;s<e.length;s++){let n=e[s];switch(n){case "--json":t.json=true;break;case "--verbose":case "-v":t.verbose=true;break;default:n&&!n.startsWith("-")&&r.push(n);}}return {aPath:r[0]??"",bPath:r[1]??"",opts:t}}function Zt(){console.error(`
828
+ `);}function er(e,t){let r=resolve(e);existsSync(r)||(console.error(m.red(`error: ${t} file not found: ${r}`)),process.exit(1));try{return JSON.parse(readFileSync(r,"utf8"))}catch(s){console.error(m.red(`error: failed to parse ${t} (${r}): `)+s.message),process.exit(1);}}function Un(e){switch(e){case "added":return m.green("+");case "removed":return m.red("-");case "relaxed":return m.green("\u25B2");case "tightened":return m.red("\u25BD");default:return m.yellow("~")}}function Q(e){return e?e.op==="$eq"?JSON.stringify(e.value):`${e.op} ${JSON.stringify(e.value)}`:"\u2014"}function be(e){return e.replace(/\|/g,"\\|").replace(/`/g,"'").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function Ln(e){let{summary:t,constraints:r}=e;console.log(`
829
+ ${m.bold("rules-diff")} \u2014 structural predicate diff
830
+ `),console.log(` ${m.green(`+${t.added}`)} added ${m.red(`-${t.removed}`)} removed ${m.yellow(`~${t.changed}`)} changed ${m.dim(`\xB7${t.unchanged} unchanged`)}`),console.log(` ${t.totalClauseChanges} clause-level change${t.totalClauseChanges===1?"":"s"}
831
+ `);for(let s of r){if(s.status==="unchanged")continue;let n=s.status==="added"?m.green("ADDED"):s.status==="removed"?m.red("REMOVED"):m.yellow("CHANGED");console.log(` ${m.bold(s.id)} ${n}`);for(let o of s.changes){let c=m.cyan(o.path||"(predicate)"),a=Un(o.kind);if(o.kind==="added")console.log(` ${a} ${c} ${Q(o.after)}`);else if(o.kind==="removed")console.log(` ${a} ${c} ${Q(o.before)}`);else {let i=o.kind==="relaxed"?m.green("relaxed"):o.kind==="tightened"?m.red("tightened"):m.yellow("changed");console.log(` ${a} ${c} ${Q(o.before)} ${m.dim("\u2192")} ${Q(o.after)} ${m.dim(`[${i}]`)}`);}}console.log("");}}function zn(e){let{summary:t,constraints:r}=e;console.log("## \u{1F4CB} Rules diff"),console.log(""),console.log(`**+${t.added} added \xB7 -${t.removed} removed \xB7 ~${t.changed} changed \xB7 \xB7${t.unchanged} unchanged** \u2014 ${t.totalClauseChanges} clause change${t.totalClauseChanges===1?"":"s"}`),console.log("");for(let s of r){if(s.status==="unchanged")continue;let n=s.status==="added"?"\u{1F195} ADDED":s.status==="removed"?"\u{1F5D1} REMOVED":"\u270F\uFE0F CHANGED";console.log(`### \`${s.id}\` \u2014 ${n}`),console.log(""),console.log("| | path | change |"),console.log("|---|---|---|");for(let o of s.changes){let c=`\`${be(o.path||"(predicate)")}\``,a;o.kind==="added"?a=`| \u2795 | ${c} | ${be(Q(o.after))} |`:o.kind==="removed"?a=`| \u2796 | ${c} | ${be(Q(o.before))} |`:a=`| ${o.kind==="relaxed"?"\u25B2 relaxed":o.kind==="tightened"?"\u25BD tightened":"\u2194 changed"} | ${c} | ${be(Q(o.before))} \u2192 ${be(Q(o.after))} |`,console.log(a);}console.log("");}}async function tr(e){(e.includes("--help")||e.length===0)&&(Ze(),process.exit(e.length===0?1:0));let t=_n(e);t.beforePath||(console.error(m.red("error: --before <a.json> is required")),Ze(),process.exit(1)),t.afterPath||(console.error(m.red("error: --after <b.json> is required")),Ze(),process.exit(1));let r=er(t.beforePath,"--before"),s=er(t.afterPath,"--after"),n;try{n=Qt({before:r,after:s});}catch(o){console.error(m.red(`error: ${o.message}`)),process.exit(1);}if(t.json){console.log(JSON.stringify(n,null,2));return}if(t.markdown){zn(n);return}Ln(n);}function Bn(e){let t={json:false,verbose:false},r=[];for(let s=0;s<e.length;s++){let n=e[s];switch(n){case "--json":t.json=true;break;case "--verbose":case "-v":t.verbose=true;break;default:n&&!n.startsWith("-")&&r.push(n);}}return {aPath:r[0]??"",bPath:r[1]??"",opts:t}}function rr(){console.error(`
1030
832
  Usage: directive timeline diff <a.json> <b.json>
1031
833
 
1032
834
  Compare two serialized Directive timelines as a structured causal-graph
@@ -1050,7 +852,7 @@ Exit codes:
1050
852
  Examples:
1051
853
  directive timeline diff baseline.json regression.json
1052
854
  directive timeline diff a.json b.json --json | jq .constraintFires
1053
- `);}function ve(e){return e>0?g.green(`+${e}`):e<0?g.red(`${e}`):g.dim(" 0")}function er(e){return e.length===0?[g.dim(" (no differences)")]:e.map(t=>` ${g.bold(t.id.padEnd(28))} ${String(t.aCount).padStart(4)} \u2192 ${String(t.bCount).padStart(4)} (${ve(t.delta)})`)}function Jn(e){return e.length===0?[g.dim(" (no differences)")]:e.map(t=>` ${g.bold(t.resolver.padEnd(28))} starts ${t.aStarts}\u2192${t.bStarts} (${ve(t.bStarts-t.aStarts)}) completes ${t.aCompletes}\u2192${t.bCompletes} (${ve(t.bCompletes-t.aCompletes)}) errors ${t.aErrors}\u2192${t.bErrors} (${ve(t.bErrors-t.aErrors)})`)}function Kn(e){return e.length===0?[g.dim(" (no new errors)")]:e.map(t=>{let r=t.side==="a"?g.cyan("a-only"):g.yellow("b-only"),s=(()=>{try{return JSON.stringify(t.error)}catch{return `[${typeof t.error}]`}})();return ` ${r} frame #${t.frameIndex} ${g.bold(t.kind)} '${t.id}' ${g.dim(s)}`})}function tr(e){let t=resolve(e);existsSync(t)||(console.error(g.red(`error: timeline file not found: ${t}`)),process.exit(1));let r;try{r=readFileSync(t,"utf8");}catch(s){console.error(g.red(`error: failed to read ${t}: ${s.message}`)),process.exit(1);}try{return JSON.parse(r)}catch(s){console.error(g.red(`error: ${t} is not valid JSON: ${s.message}`)),process.exit(1);}}async function rr(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(Zt(),process.exit(e.length===0?1:0));let{aPath:t,bPath:r,opts:s}=Ln(e);(!t||!r)&&(console.error(g.red("error: both <a.json> and <b.json> are required")),Zt(),process.exit(1));let{deserializeTimeline:n,diffTimelines:o}=await oe(s.verbose),i=tr(t),c=tr(r),a,l;try{a=n(i),l=n(c);}catch(d){console.error(g.red(`error: timeline JSON failed validation: ${d.message}`)),process.exit(1);}let u=o(a,l);s.json&&(console.log(JSON.stringify(u,null,2)),process.exit(u.identical?0:2)),u.identical&&(console.log(g.green("\u2713 identical:"),`both timelines have ${u.aFrameCount} frames and the same causal shape.`),process.exit(0)),console.log(g.bold("Timeline diff"),g.dim(`(${t} vs ${r})`)),console.log(""),console.log(`Frames: ${u.aFrameCount} \u2192 ${u.bFrameCount} (${ve(u.frameCountDelta)})`),console.log(""),console.log(g.bold("Constraint fires:"));for(let d of er(u.constraintFires))console.log(d);console.log(""),console.log(g.bold("Mutations:"));for(let d of er(u.mutations))console.log(d);console.log(""),console.log(g.bold("Resolver runs:"));for(let d of Jn(u.resolverRuns))console.log(d);console.log(""),console.log(g.bold("New errors:"));for(let d of Kn(u.newErrors))console.log(d);console.log(""),process.exit(2);}function Qn(e){let t={sweepArgs:[],json:false};for(let r=0;r<e.length;r++)switch(e[r]){case "--history":{let n=e[++r];n&&(t.historyPath=n);break}case "--original":case "-o":{let n=e[++r];n&&(t.originalPath=n);break}case "--template":case "-t":{let n=e[++r];n&&(t.templatePath=n);break}case "--sweep":case "-s":{let n=e[++r];n&&t.sweepArgs.push(n);break}case "--entity-key":{let n=e[++r];n&&(t.entityKey=n);break}case "--json":t.json=true;break}return t}function we(){console.error(`
855
+ `);}function ke(e){return e>0?m.green(`+${e}`):e<0?m.red(`${e}`):m.dim(" 0")}function nr(e){return e.length===0?[m.dim(" (no differences)")]:e.map(t=>` ${m.bold(t.id.padEnd(28))} ${String(t.aCount).padStart(4)} \u2192 ${String(t.bCount).padStart(4)} (${ke(t.delta)})`)}function Hn(e){return e.length===0?[m.dim(" (no differences)")]:e.map(t=>` ${m.bold(t.resolver.padEnd(28))} starts ${t.aStarts}\u2192${t.bStarts} (${ke(t.bStarts-t.aStarts)}) completes ${t.aCompletes}\u2192${t.bCompletes} (${ke(t.bCompletes-t.aCompletes)}) errors ${t.aErrors}\u2192${t.bErrors} (${ke(t.bErrors-t.aErrors)})`)}function Qn(e){return e.length===0?[m.dim(" (no new errors)")]:e.map(t=>{let r=t.side==="a"?m.cyan("a-only"):m.yellow("b-only"),s=(()=>{try{return JSON.stringify(t.error)}catch{return `[${typeof t.error}]`}})();return ` ${r} frame #${t.frameIndex} ${m.bold(t.kind)} '${t.id}' ${m.dim(s)}`})}function sr(e){let t=resolve(e);existsSync(t)||(console.error(m.red(`error: timeline file not found: ${t}`)),process.exit(1));let r;try{r=readFileSync(t,"utf8");}catch(s){console.error(m.red(`error: failed to read ${t}: ${s.message}`)),process.exit(1);}try{return JSON.parse(r)}catch(s){console.error(m.red(`error: ${t} is not valid JSON: ${s.message}`)),process.exit(1);}}async function or(e){(e.includes("--help")||e.includes("-h")||e.length===0)&&(rr(),process.exit(e.length===0?1:0));let{aPath:t,bPath:r,opts:s}=Bn(e);(!t||!r)&&(console.error(m.red("error: both <a.json> and <b.json> are required")),rr(),process.exit(1));let{deserializeTimeline:n,diffTimelines:o}=await ce(s.verbose),c=sr(t),a=sr(r),i,l;try{i=n(c),l=n(a);}catch(d){console.error(m.red(`error: timeline JSON failed validation: ${d.message}`)),process.exit(1);}let u=o(i,l);s.json&&(console.log(JSON.stringify(u,null,2)),process.exit(u.identical?0:2)),u.identical&&(console.log(m.green("\u2713 identical:"),`both timelines have ${u.aFrameCount} frames and the same causal shape.`),process.exit(0)),console.log(m.bold("Timeline diff"),m.dim(`(${t} vs ${r})`)),console.log(""),console.log(`Frames: ${u.aFrameCount} \u2192 ${u.bFrameCount} (${ke(u.frameCountDelta)})`),console.log(""),console.log(m.bold("Constraint fires:"));for(let d of nr(u.constraintFires))console.log(d);console.log(""),console.log(m.bold("Mutations:"));for(let d of nr(u.mutations))console.log(d);console.log(""),console.log(m.bold("Resolver runs:"));for(let d of Hn(u.resolverRuns))console.log(d);console.log(""),console.log(m.bold("New errors:"));for(let d of Qn(u.newErrors))console.log(d);console.log(""),process.exit(2);}function Zn(e){let t={sweepArgs:[],json:false};for(let r=0;r<e.length;r++)switch(e[r]){case "--history":{let n=e[++r];n&&(t.historyPath=n);break}case "--original":case "-o":{let n=e[++r];n&&(t.originalPath=n);break}case "--template":case "-t":{let n=e[++r];n&&(t.templatePath=n);break}case "--sweep":case "-s":{let n=e[++r];n&&t.sweepArgs.push(n);break}case "--entity-key":{let n=e[++r];n&&(t.entityKey=n);break}case "--json":t.json=true;break}return t}function xe(){console.error(`
1054
856
  Usage: directive tune --history <frames.json> --original <orig.json> \\
1055
857
  --template <tmpl.json> --sweep <key:range>
1056
858
 
@@ -1073,13 +875,13 @@ Example:
1073
875
  directive tune --history sessions.json \\
1074
876
  --original current.json --template proposed-template.json \\
1075
877
  --sweep threshold:25..200:25
1076
- `);}function Ye(e,t){let r=resolve(e);existsSync(r)||(console.error(g.red(`error: ${t} file not found: ${r}`)),process.exit(1));try{return JSON.parse(readFileSync(r,"utf8"))}catch(s){console.error(g.red(`error: failed to parse ${t} (${r}): `)+s.message),process.exit(1);}}function Yn(e){try{return ye(e)}catch(t){console.error(g.red(`error: ${t.message}`)),process.exit(1);}}function Xn(e){let t=e.indexOf(":");t<1&&(console.error(g.red(`error: --sweep ${e}: missing ':' between hole name and values`)),process.exit(1));let r=e.slice(0,t),s=e.slice(t+1),n=s.match(/^(-?\d+(?:\.\d+)?)\.\.(-?\d+(?:\.\d+)?)(?::(-?\d+(?:\.\d+)?))?$/);if(n){let[,c,a,l]=n,u=Number(c),d=Number(a),f=l?Number(l):1;f<=0&&(console.error(g.red(`error: --sweep ${e}: step must be positive`)),process.exit(1)),d<u&&(console.error(g.red(`error: --sweep ${e}: end (${d}) must be >= start (${u})`)),process.exit(1));let m=[];for(let $=u;$<=d+1e-9;$+=f)m.push(Math.round($*1e6)/1e6);return [r,m]}let o=s.split(",").map(c=>c.trim()).filter(c=>c.length>0);o.length===0&&(console.error(g.red(`error: --sweep ${e}: no values after ':'`)),process.exit(1));let i=o.map(c=>{let a=Number(c);return Number.isNaN(a)?c:a});return [r,i]}var Xe=["\u2581","\u2582","\u2583","\u2584","\u2585","\u2586","\u2587","\u2588"];function Vn(e,t){let r=e.points;Math.max(...r.map(f=>f.report.proposed.matched));let n=e.baseline.report.original.matched,o=r.map(f=>f.score),i=Math.min(...o),a=Math.max(...o)-i,l=r.map(f=>{let m=a>0?(f.score-i)/a:0;return Xe[Math.min(Xe.length-1,Math.round(m*(Xe.length-1)))]}).join("");console.log(`
1077
- ${g.bold("directive tune")} \u2014 parameter sweep`),console.log(`
878
+ `);}function et(e,t){let r=resolve(e);existsSync(r)||(console.error(m.red(`error: ${t} file not found: ${r}`)),process.exit(1));try{return JSON.parse(readFileSync(r,"utf8"))}catch(s){console.error(m.red(`error: failed to parse ${t} (${r}): `)+s.message),process.exit(1);}}function es(e){try{return we(e)}catch(t){console.error(m.red(`error: ${t.message}`)),process.exit(1);}}function ts(e){let t=e.indexOf(":");t<1&&(console.error(m.red(`error: --sweep ${e}: missing ':' between hole name and values`)),process.exit(1));let r=e.slice(0,t),s=e.slice(t+1),n=s.match(/^(-?\d+(?:\.\d+)?)\.\.(-?\d+(?:\.\d+)?)(?::(-?\d+(?:\.\d+)?))?$/);if(n){let[,a,i,l]=n,u=Number(a),d=Number(i),f=l?Number(l):1;f<=0&&(console.error(m.red(`error: --sweep ${e}: step must be positive`)),process.exit(1)),d<u&&(console.error(m.red(`error: --sweep ${e}: end (${d}) must be >= start (${u})`)),process.exit(1));let h=[];for(let $=u;$<=d+1e-9;$+=f)h.push(Math.round($*1e6)/1e6);return [r,h]}let o=s.split(",").map(a=>a.trim()).filter(a=>a.length>0);o.length===0&&(console.error(m.red(`error: --sweep ${e}: no values after ':'`)),process.exit(1));let c=o.map(a=>{let i=Number(a);return Number.isNaN(i)?a:i});return [r,c]}var tt=["\u2581","\u2582","\u2583","\u2584","\u2585","\u2586","\u2587","\u2588"];function rs(e,t){let r=e.points;Math.max(...r.map(f=>f.report.proposed.matched));let n=e.baseline.report.original.matched,o=r.map(f=>f.score),c=Math.min(...o),i=Math.max(...o)-c,l=r.map(f=>{let h=i>0?(f.score-c)/i:0;return tt[Math.min(tt.length-1,Math.round(h*(tt.length-1)))]}).join("");console.log(`
879
+ ${m.bold("directive tune")} \u2014 parameter sweep`),console.log(`
1078
880
  frames evaluated ${r[0]?.report.framesEvaluated??0}`),console.log(` baseline (current) matched ${n} frames`),console.log(` points evaluated ${r.length}
1079
- `),console.log(` sparkline ${g.cyan(l)}
1080
- `);let u=Object.keys(r[0]?.values??{}),d=`${u.map(f=>f.padEnd(12)).join(" ")} ${"matched".padStart(8)} ${"delta".padStart(7)}${t?` ${`${t}s`.padStart(8)}`:""} bar`;console.log(g.dim(` ${d}`));for(let f of r){let m=u.map(_=>String(f.values[_]??"").padEnd(12)).join(" "),$=f.report.proposed.matched,w=f.report.delta,F=t?String(f.report.proposed.matchedEntities??"").padStart(8):"",W=w>0?g.green(`+${w}`.padStart(7)):w<0?g.red(`${w}`.padStart(7)):g.dim("\xB10".padStart(7)),p=a>0?Math.round((f.score-i)/a*24):0,y=`${m} ${String($).padStart(8)} ${W}${t?` ${F}`:""} ${"\u2588".repeat(p).padEnd(24)}`,D=f===e.best;console.log(D?g.green(` ${y}`):` ${y}`);}console.log(`
1081
- ${g.bold(g.green("best"))} \u2014 ${u.map(f=>`${f}=${e.best.values[f]}`).join(", ")} \u2192 matched ${e.best.report.proposed.matched} (score ${e.best.score})
1082
- `);}async function nr(e){(e.includes("--help")||e.length===0)&&(we(),process.exit(e.length===0?1:0));let t=Qn(e);t.historyPath||(console.error(g.red("error: --history <frames.json> is required")),we(),process.exit(1)),t.originalPath||(console.error(g.red("error: --original <spec.json> is required")),we(),process.exit(1)),t.templatePath||(console.error(g.red("error: --template <spec.json> is required")),we(),process.exit(1)),t.sweepArgs.length===0&&(console.error(g.red("error: at least one --sweep <key:range> is required")),we(),process.exit(1));let r=Yn(Ye(t.historyPath,"--history")),s=Ye(t.originalPath,"--original"),n=Ye(t.templatePath,"--template"),o={};for(let c of t.sweepArgs){let[a,l]=Xn(c);o[a]=l;}let i;try{i=Jt({frames:r,original:s,template:n,sweep:o,entityKey:t.entityKey});}catch(c){console.error(g.red(`error: ${c.message}`)),process.exit(1);}if(t.json){console.log(JSON.stringify(i,null,2));return}Vn(i,t.entityKey);}var Zn=`
881
+ `),console.log(` sparkline ${m.cyan(l)}
882
+ `);let u=Object.keys(r[0]?.values??{}),d=`${u.map(f=>f.padEnd(12)).join(" ")} ${"matched".padStart(8)} ${"delta".padStart(7)}${t?` ${`${t}s`.padStart(8)}`:""} bar`;console.log(m.dim(` ${d}`));for(let f of r){let h=u.map(_=>String(f.values[_]??"").padEnd(12)).join(" "),$=f.report.proposed.matched,w=f.report.delta,F=t?String(f.report.proposed.matchedEntities??"").padStart(8):"",W=w>0?m.green(`+${w}`.padStart(7)):w<0?m.red(`${w}`.padStart(7)):m.dim("\xB10".padStart(7)),p=i>0?Math.round((f.score-c)/i*24):0,v=`${h} ${String($).padStart(8)} ${W}${t?` ${F}`:""} ${"\u2588".repeat(p).padEnd(24)}`,D=f===e.best;console.log(D?m.green(` ${v}`):` ${v}`);}console.log(`
883
+ ${m.bold(m.green("best"))} \u2014 ${u.map(f=>`${f}=${e.best.values[f]}`).join(", ")} \u2192 matched ${e.best.report.proposed.matched} (score ${e.best.score})
884
+ `);}async function ir(e){(e.includes("--help")||e.length===0)&&(xe(),process.exit(e.length===0?1:0));let t=Zn(e);t.historyPath||(console.error(m.red("error: --history <frames.json> is required")),xe(),process.exit(1)),t.originalPath||(console.error(m.red("error: --original <spec.json> is required")),xe(),process.exit(1)),t.templatePath||(console.error(m.red("error: --template <spec.json> is required")),xe(),process.exit(1)),t.sweepArgs.length===0&&(console.error(m.red("error: at least one --sweep <key:range> is required")),xe(),process.exit(1));let r=es(et(t.historyPath,"--history")),s=et(t.originalPath,"--original"),n=et(t.templatePath,"--template"),o={};for(let a of t.sweepArgs){let[i,l]=ts(a);o[i]=l;}let c;try{c=Bt({frames:r,original:s,template:n,sweep:o,entityKey:t.entityKey});}catch(a){console.error(m.red(`error: ${a.message}`)),process.exit(1);}if(t.json){console.log(JSON.stringify(c,null,2));return}rs(c,t.entityKey);}var ns=`
1083
885
  ${O} \u2014 CLI tools for Directive
1084
886
 
1085
887
  Usage: ${O} <command> [options]
@@ -1092,7 +894,12 @@ Commands:
1092
894
  explain <file> [req-id] Explain why a requirement exists
1093
895
  graph <file> Visual dependency graph
1094
896
  doctor Health check for project setup
1095
- ai-rules init Install AI coding rules
897
+ install One-shot: drop AI rules for every
898
+ supported assistant (Cursor, Copilot,
899
+ Windsurf, Cline, Codex, Claude). No
900
+ prompts. Alias for ai-rules install.
901
+ ai-rules install Same as above (non-interactive)
902
+ ai-rules init Interactive install (prompts per tool)
1096
903
  ai-rules update Refresh rules to latest version
1097
904
  ai-rules check Validate rules are current (CI)
1098
905
  examples list Browse available examples
@@ -1134,6 +941,12 @@ graph options:
1134
941
  --no-open Don't open in browser
1135
942
  --output <path> Output file path
1136
943
 
944
+ install / ai-rules install options:
945
+ --force Overwrite existing files (default: merge
946
+ Directive section when present, otherwise
947
+ skip files without a Directive section)
948
+ --dir <path> Target directory (default: cwd)
949
+
1137
950
  ai-rules init options:
1138
951
  --force Overwrite existing files without asking
1139
952
  --merge Use section markers to update only the Directive section
@@ -1143,14 +956,15 @@ ai-rules init options:
1143
956
  examples options:
1144
957
  --filter <category> Filter by category or name
1145
958
  --dest <dir> Destination directory for copy
1146
- `.trim();async function es(){let e=process.argv.slice(2),t=e[0];if((e.length===0||t==="--help"||t==="-h")&&(console.log(Zn),process.exit(0)),t==="--version"||t==="-v"){let{readFileSync:n}=await import('fs'),{fileURLToPath:o}=await import('url'),{dirname:i,join:c}=await import('path'),a=i(o(import.meta.url)),l=JSON.parse(n(c(a,"..","package.json"),"utf-8"));console.log(l.version),process.exit(0);}let s=e[0];switch(s){case "init":{await St(e.slice(1));break}case "new":{let n=e[1],o=e[2];n==="module"?(o||(console.error("Usage: directive new module <name>"),process.exit(1)),await Tt(o,e.slice(3))):n==="orchestrator"?(o||(console.error("Usage: directive new orchestrator <name>"),process.exit(1)),await Ct(o,e.slice(3))):(console.error(`Unknown subcommand: ${n??"(none)"}
959
+ `.trim();async function ss(){let e=process.argv.slice(2),t=e[0];if((e.length===0||t==="--help"||t==="-h")&&(console.log(ns),process.exit(0)),t==="--version"||t==="-v"){let{readFileSync:n}=await import('fs'),{fileURLToPath:o}=await import('url'),{dirname:c,join:a}=await import('path'),i=c(o(import.meta.url)),l=JSON.parse(n(a(i,"..","package.json"),"utf-8"));console.log(l.version),process.exit(0);}let s=e[0];switch(s){case "init":{await jt(e.slice(1));break}case "new":{let n=e[1],o=e[2];n==="module"?(o||(console.error("Usage: directive new module <name>"),process.exit(1)),await Nt(o,e.slice(3))):n==="orchestrator"?(o||(console.error("Usage: directive new orchestrator <name>"),process.exit(1)),await Pt(o,e.slice(3))):(console.error(`Unknown subcommand: ${n??"(none)"}
1147
960
  Usage: ${O} new module <name>
1148
- ${O} new orchestrator <name>`),process.exit(1));break}case "inspect":{await At(e.slice(1));break}case "explain":{await kt(e.slice(1));break}case "graph":{await xt(e.slice(1));break}case "doctor":{await ht(e.slice(1));break}case "ai-rules":{let n=e[1];n==="init"?await at(e.slice(2)):n==="update"?await ct(e.slice(2)):n==="check"?await lt(e.slice(2)):(console.error(`Unknown subcommand: ${n??"(none)"}
1149
- Usage: ${O} ai-rules init
961
+ ${O} new orchestrator <name>`),process.exit(1));break}case "inspect":{await Et(e.slice(1));break}case "explain":{await St(e.slice(1));break}case "graph":{await At(e.slice(1));break}case "doctor":{await yt(e.slice(1));break}case "install":{await Le(e.slice(1));break}case "ai-rules":{let n=e[1];n==="init"?await lt(e.slice(2)):n==="install"?await Le(e.slice(2)):n==="update"?await ut(e.slice(2)):n==="check"?await dt(e.slice(2)):(console.error(`Unknown subcommand: ${n??"(none)"}
962
+ Usage: ${O} ai-rules install
963
+ ${O} ai-rules init
1150
964
  ${O} ai-rules update
1151
- ${O} ai-rules check`),process.exit(1));break}case "examples":{let n=e[1];if(n==="list")await vt(e.slice(2));else if(n==="copy"){let o=e[2];o||(console.error("Usage: directive examples copy <name>"),process.exit(1)),await wt(o,e.slice(3));}else console.error(`Unknown subcommand: ${n??"(none)"}
965
+ ${O} ai-rules check`),process.exit(1));break}case "examples":{let n=e[1];if(n==="list")await bt(e.slice(2));else if(n==="copy"){let o=e[2];o||(console.error("Usage: directive examples copy <name>"),process.exit(1)),await kt(o,e.slice(3));}else console.error(`Unknown subcommand: ${n??"(none)"}
1152
966
  Usage: ${O} examples list [--filter <category>]
1153
- ${O} examples copy <name> [--dest <dir>]`),process.exit(1);break}case "replay":{await Yt(e.slice(1));break}case "replay-under":{await Qt(e.slice(1));break}case "tune":{await nr(e.slice(1));break}case "rules-diff":{await Vt(e.slice(1));break}case "bisect":{await mt(e.slice(1));break}case "timeline":{let n=e[1];n==="diff"?await rr(e.slice(2)):(console.error(`Unknown subcommand: ${n??"(none)"}
967
+ ${O} examples copy <name> [--dest <dir>]`),process.exit(1);break}case "replay":{await Zt(e.slice(1));break}case "replay-under":{await Vt(e.slice(1));break}case "tune":{await ir(e.slice(1));break}case "rules-diff":{await tr(e.slice(1));break}case "bisect":{await gt(e.slice(1));break}case "timeline":{let n=e[1];n==="diff"?await or(e.slice(2)):(console.error(`Unknown subcommand: ${n??"(none)"}
1154
968
  Usage: ${O} timeline diff <a.json> <b.json>`),process.exit(1));break}default:console.error(`Unknown command: ${s}
1155
- Run '${O} --help' for usage.`),process.exit(1);}}es().catch(e=>{console.error(e.message||e),process.exit(1);});//# sourceMappingURL=cli.js.map
969
+ Run '${O} --help' for usage.`),process.exit(1);}}ss().catch(e=>{console.error(e.message||e),process.exit(1);});//# sourceMappingURL=cli.js.map
1156
970
  //# sourceMappingURL=cli.js.map