@a-company/paradigm 5.28.0 → 5.31.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.
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- export{b as ROSTER_SUGGESTIONS,a as detectProjectType}from'./chunk-4DVT5IEY.js';import'./chunk-5TAVYPOV.js';
2
+ export{b as ROSTER_SUGGESTIONS,a as detectProjectType}from'./chunk-TZZNHUAR.js';import'./chunk-5TAVYPOV.js';
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import {a as a$1,f,c,e,g as g$1,b as b$1,d}from'./chunk-WR6D3SC6.js';import {a}from'./chunk-LKAT7IAK.js';import'./chunk-5TAVYPOV.js';import*as g from'fs';import*as m from'path';import*as b from'os';import r from'chalk';import*as $ from'js-yaml';var x=m.join(b.homedir(),".paradigm","agents"),O=".agent";function C(){return m.join(process.cwd(),".paradigm","roster.yaml")}function k(){let n=C();if(!g.existsSync(n))return null;try{return $.load(g.readFileSync(n,"utf-8"))}catch{return null}}function F(n){let s=C(),c=m.dirname(s);g.existsSync(c)||g.mkdirSync(c,{recursive:true}),g.writeFileSync(s,$.dump(n,{lineWidth:-1,noRefs:true,sortKeys:false}),"utf-8");}function E(){if(!g.existsSync(x))return [];try{return g.readdirSync(x).filter(n=>n.endsWith(O)).map(n=>n.replace(O,"")).sort()}catch{return []}}function P(n){let s=m.join(x,`${n}${O}`);if(!g.existsSync(s))return null;try{let c=$.load(g.readFileSync(s,"utf-8"));return {id:c.id||n,nickname:c.nickname,role:c.role||"Unknown"}}catch{return null}}async function U(n={}){let s=process.cwd(),c$1=a.command("agent-roster-show").start("Showing project roster",{cwd:s}),o=E().length,i=k();if(!i){n.json?a$1(JSON.stringify({roster:null,message:"No roster configured",totalAgents:o})):(f("Agent Roster"),a$1(""),c(`No roster configured \u2014 all ${o} agents are active.`),e(` Run ${r.cyan("paradigm agent roster init")} to create one.`),a$1("")),c$1.success("No roster found");return}let t=i.active||[];if(n.json){let h=t.map(y=>P(y)||{id:y,role:"Unknown"});a$1(JSON.stringify({count:t.length,total:o,project:i.project,type:i.type,agents:h},null,2)),c$1.success(`${t.length} of ${o} agents active`);return}f("Agent Roster"),a$1("");let a$2="ID".padEnd(16),l="Nickname".padEnd(12);a$1(` ${r.dim(a$2)} ${r.dim(l)} ${r.dim("Role")}`),a$1(` ${r.dim("-".repeat(16))} ${r.dim("-".repeat(12))} ${r.dim("-".repeat(30))}`);for(let h of t.sort()){let y=P(h),f=y?.nickname||r.dim("\u2014"),S=y?.role||r.dim("Unknown");a$1(` ${r.white.bold(h.padEnd(16))} ${f.toString().padEnd(12)} ${r.gray(S)}`);}a$1(""),a$1(` ${r.cyan(String(t.length))} of ${r.cyan(String(o))} agents active on this project`),i.type&&g$1("Project type",i.type),a$1(""),c$1.success(`${t.length} of ${o} agents active`);}async function G(n={}){let s=process.cwd(),c$1=a.command("agent-roster-init").start("Initializing project roster",{cwd:s}),u=C();if(g.existsSync(u)&&!n.force){let S=k()?.active?.length??0;n.json?a$1(JSON.stringify({error:"Roster already exists",count:S})):(c(`Roster already exists with ${S} agents.`),e(` Use ${r.cyan("--force")} to reinitialize, or ${r.cyan("paradigm agent roster add/remove")} to modify.`)),c$1.error("Roster already exists");return}let{detectProjectType:o,ROSTER_SUGGESTIONS:i}=await import('./project-type-4Y6CESWP.js'),t=o(s),a$2=i[t]||i.generic,l=m.basename(s),d=m.join(s,".paradigm","config.yaml");if(g.existsSync(d))try{let f=$.load(g.readFileSync(d,"utf-8"));f?.project&&typeof f.project=="string"&&(l=f.project);}catch{}let h={version:"1.0",project:l,type:t,active:a$2.sort()};F(h);let y=E();n.json?a$1(JSON.stringify({created:true,project:l,type:t,active:a$2.sort(),count:a$2.length,total:y.length},null,2)):(f("Agent Roster Initialized"),a$1(""),g$1("Project",l),g$1("Detected type",t),g$1("Active agents",`${a$2.length} of ${y.length}`),a$1(""),a$1(` ${r.cyan(a$2.sort().join(", "))}`),a$1(""),b$1(`Roster written to ${r.dim(".paradigm/roster.yaml")}`),e(` Modify with ${r.cyan("paradigm agent roster add/remove <agent-id>")}`),a$1("")),c$1.success(`Created roster: ${a$2.length} agents for ${t}`);}async function _(n,s={}){let c=process.cwd(),u=a.command("agent-roster-add").start(`Adding agents: ${n.join(", ")}`,{cwd:c}),o=k();if(!o){s.json?a$1(JSON.stringify({error:"No roster found. Run `paradigm agent roster init` first."})):(d("No roster found."),e(` Run ${r.cyan("paradigm agent roster init")} first.`)),u.error("No roster found");return}let i=E(),t=[],a$2=[],l=[];for(let d of n){if(!i.includes(d)){t.push(d);continue}if(o.active.includes(d)){a$2.push(d);continue}o.active.push(d),l.push(d);}l.length>0&&(o.active.sort(),F(o)),s.json?a$1(JSON.stringify({added:l,alreadyActive:a$2,invalid:t,total:o.active.length},null,2)):(l.length>0&&b$1(`Added: ${r.cyan(l.join(", "))}`),a$2.length>0&&e(` Already active: ${a$2.join(", ")}`),t.length>0&&(d(`Unknown agent(s): ${t.join(", ")}`),e(` Available: ${i.join(", ")}`)),l.length>0&&a$1(` Roster now has ${r.cyan(String(o.active.length))} active agents.`)),u.success(`Added ${l.length}, skipped ${a$2.length}, invalid ${t.length}`);}async function z(n,s={}){let c$1=process.cwd(),u=a.command("agent-roster-remove").start(`Removing agents: ${n.join(", ")}`,{cwd:c$1}),o=k();if(!o){s.json?a$1(JSON.stringify({error:"No roster found. Run `paradigm agent roster init` first."})):(d("No roster found."),e(` Run ${r.cyan("paradigm agent roster init")} first.`)),u.error("No roster found");return}let i=[],t=[];for(let a of n){let l=o.active.indexOf(a);if(l<0){i.push(a);continue}o.active.splice(l,1),t.push(a);}t.length>0&&F(o),s.json?a$1(JSON.stringify({removed:t,notFound:i,total:o.active.length},null,2)):(t.length>0&&b$1(`Removed: ${r.cyan(t.join(", "))}`),i.length>0&&c(`Not in roster: ${i.join(", ")}`),t.length>0&&a$1(` Roster now has ${r.cyan(String(o.active.length))} active agents.`)),u.success(`Removed ${t.length}, not found ${i.length}`);}export{_ as rosterAddCommand,G as rosterInitCommand,z as rosterRemoveCommand,U as rosterShowCommand};
2
+ import {a as a$1,f,c,e,g as g$1,b as b$1,d}from'./chunk-WR6D3SC6.js';import {a}from'./chunk-LKAT7IAK.js';import'./chunk-5TAVYPOV.js';import*as g from'fs';import*as m from'path';import*as b from'os';import r from'chalk';import*as $ from'js-yaml';var x=m.join(b.homedir(),".paradigm","agents"),O=".agent";function C(){return m.join(process.cwd(),".paradigm","roster.yaml")}function k(){let n=C();if(!g.existsSync(n))return null;try{return $.load(g.readFileSync(n,"utf-8"))}catch{return null}}function F(n){let s=C(),c=m.dirname(s);g.existsSync(c)||g.mkdirSync(c,{recursive:true}),g.writeFileSync(s,$.dump(n,{lineWidth:-1,noRefs:true,sortKeys:false}),"utf-8");}function E(){if(!g.existsSync(x))return [];try{return g.readdirSync(x).filter(n=>n.endsWith(O)).map(n=>n.replace(O,"")).sort()}catch{return []}}function P(n){let s=m.join(x,`${n}${O}`);if(!g.existsSync(s))return null;try{let c=$.load(g.readFileSync(s,"utf-8"));return {id:c.id||n,nickname:c.nickname,role:c.role||"Unknown"}}catch{return null}}async function U(n={}){let s=process.cwd(),c$1=a.command("agent-roster-show").start("Showing project roster",{cwd:s}),o=E().length,i=k();if(!i){n.json?a$1(JSON.stringify({roster:null,message:"No roster configured",totalAgents:o})):(f("Agent Roster"),a$1(""),c(`No roster configured \u2014 all ${o} agents are active.`),e(` Run ${r.cyan("paradigm agent roster init")} to create one.`),a$1("")),c$1.success("No roster found");return}let t=i.active||[];if(n.json){let h=t.map(y=>P(y)||{id:y,role:"Unknown"});a$1(JSON.stringify({count:t.length,total:o,project:i.project,type:i.type,agents:h},null,2)),c$1.success(`${t.length} of ${o} agents active`);return}f("Agent Roster"),a$1("");let a$2="ID".padEnd(16),l="Nickname".padEnd(12);a$1(` ${r.dim(a$2)} ${r.dim(l)} ${r.dim("Role")}`),a$1(` ${r.dim("-".repeat(16))} ${r.dim("-".repeat(12))} ${r.dim("-".repeat(30))}`);for(let h of t.sort()){let y=P(h),f=y?.nickname||r.dim("\u2014"),S=y?.role||r.dim("Unknown");a$1(` ${r.white.bold(h.padEnd(16))} ${f.toString().padEnd(12)} ${r.gray(S)}`);}a$1(""),a$1(` ${r.cyan(String(t.length))} of ${r.cyan(String(o))} agents active on this project`),i.type&&g$1("Project type",i.type),a$1(""),c$1.success(`${t.length} of ${o} agents active`);}async function G(n={}){let s=process.cwd(),c$1=a.command("agent-roster-init").start("Initializing project roster",{cwd:s}),u=C();if(g.existsSync(u)&&!n.force){let S=k()?.active?.length??0;n.json?a$1(JSON.stringify({error:"Roster already exists",count:S})):(c(`Roster already exists with ${S} agents.`),e(` Use ${r.cyan("--force")} to reinitialize, or ${r.cyan("paradigm agent roster add/remove")} to modify.`)),c$1.error("Roster already exists");return}let{detectProjectType:o,ROSTER_SUGGESTIONS:i}=await import('./project-type-AGO6VUKF.js'),t=o(s),a$2=i[t]||i.generic,l=m.basename(s),d=m.join(s,".paradigm","config.yaml");if(g.existsSync(d))try{let f=$.load(g.readFileSync(d,"utf-8"));f?.project&&typeof f.project=="string"&&(l=f.project);}catch{}let h={version:"1.0",project:l,type:t,active:a$2.sort()};F(h);let y=E();n.json?a$1(JSON.stringify({created:true,project:l,type:t,active:a$2.sort(),count:a$2.length,total:y.length},null,2)):(f("Agent Roster Initialized"),a$1(""),g$1("Project",l),g$1("Detected type",t),g$1("Active agents",`${a$2.length} of ${y.length}`),a$1(""),a$1(` ${r.cyan(a$2.sort().join(", "))}`),a$1(""),b$1(`Roster written to ${r.dim(".paradigm/roster.yaml")}`),e(` Modify with ${r.cyan("paradigm agent roster add/remove <agent-id>")}`),a$1("")),c$1.success(`Created roster: ${a$2.length} agents for ${t}`);}async function _(n,s={}){let c=process.cwd(),u=a.command("agent-roster-add").start(`Adding agents: ${n.join(", ")}`,{cwd:c}),o=k();if(!o){s.json?a$1(JSON.stringify({error:"No roster found. Run `paradigm agent roster init` first."})):(d("No roster found."),e(` Run ${r.cyan("paradigm agent roster init")} first.`)),u.error("No roster found");return}let i=E(),t=[],a$2=[],l=[];for(let d of n){if(!i.includes(d)){t.push(d);continue}if(o.active.includes(d)){a$2.push(d);continue}o.active.push(d),l.push(d);}l.length>0&&(o.active.sort(),F(o)),s.json?a$1(JSON.stringify({added:l,alreadyActive:a$2,invalid:t,total:o.active.length},null,2)):(l.length>0&&b$1(`Added: ${r.cyan(l.join(", "))}`),a$2.length>0&&e(` Already active: ${a$2.join(", ")}`),t.length>0&&(d(`Unknown agent(s): ${t.join(", ")}`),e(` Available: ${i.join(", ")}`)),l.length>0&&a$1(` Roster now has ${r.cyan(String(o.active.length))} active agents.`)),u.success(`Added ${l.length}, skipped ${a$2.length}, invalid ${t.length}`);}async function z(n,s={}){let c$1=process.cwd(),u=a.command("agent-roster-remove").start(`Removing agents: ${n.join(", ")}`,{cwd:c$1}),o=k();if(!o){s.json?a$1(JSON.stringify({error:"No roster found. Run `paradigm agent roster init` first."})):(d("No roster found."),e(` Run ${r.cyan("paradigm agent roster init")} first.`)),u.error("No roster found");return}let i=[],t=[];for(let a of n){let l=o.active.indexOf(a);if(l<0){i.push(a);continue}o.active.splice(l,1),t.push(a);}t.length>0&&F(o),s.json?a$1(JSON.stringify({removed:t,notFound:i,total:o.active.length},null,2)):(t.length>0&&b$1(`Removed: ${r.cyan(t.join(", "))}`),i.length>0&&c(`Not in roster: ${i.join(", ")}`),t.length>0&&a$1(` Roster now has ${r.cyan(String(o.active.length))} active agents.`)),u.success(`Removed ${t.length}, not found ${i.length}`);}export{_ as rosterAddCommand,G as rosterInitCommand,z as rosterRemoveCommand,U as rosterShowCommand};
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import {b}from'./chunk-VPMJWJ5R.js';import'./chunk-DG236EXP.js';import'./chunk-TYWB5IQJ.js';import'./chunk-WESTEMIM.js';import'./chunk-FYDRENK7.js';import'./chunk-IZSBGW6E.js';import {d as d$1}from'./chunk-AO7ZSRME.js';import'./chunk-Y4XFVDZC.js';import {a as a$5}from'./chunk-FSOI3CCD.js';import {d}from'./chunk-W5IWDW4Y.js';import {a as a$3,b as b$1}from'./chunk-4DVT5IEY.js';import'./chunk-SHD27BQX.js';import {a as a$6}from'./chunk-CSXVL2U7.js';import'./chunk-EKZDFEJW.js';import {a as a$1}from'./chunk-33LKBMVK.js';import {b as b$2}from'./chunk-JBDMCRPP.js';import'./chunk-4TXOVRWD.js';import'./chunk-T6IDXUUA.js';import'./chunk-JIXHEBGK.js';import'./chunk-QT2LKB3P.js';import'./chunk-VCKKJDLP.js';import'./chunk-WR6D3SC6.js';import {a as a$2}from'./chunk-UIKLE3WD.js';import {a as a$4}from'./chunk-QNZEG7IT.js';import'./chunk-HMQ5BHP2.js';import'./chunk-JQKKVAAN.js';import {a}from'./chunk-LKAT7IAK.js';import'./chunk-5TAVYPOV.js';import*as r from'fs';import*as n from'path';import e from'chalk';import U from'ora';import*as g from'js-yaml';async function oe(l={}){let s=process.cwd(),h=n.basename(s),u=n.join(s,".paradigm"),k=r.existsSync(u)&&r.statSync(u).isDirectory();console.log(e.blue(`
2
+ import {b}from'./chunk-VPMJWJ5R.js';import'./chunk-DG236EXP.js';import'./chunk-TYWB5IQJ.js';import'./chunk-WESTEMIM.js';import'./chunk-FYDRENK7.js';import'./chunk-IZSBGW6E.js';import {d as d$1}from'./chunk-AO7ZSRME.js';import'./chunk-Y4XFVDZC.js';import {a as a$5}from'./chunk-FSOI3CCD.js';import {d}from'./chunk-W5IWDW4Y.js';import {a as a$3,b as b$1}from'./chunk-TZZNHUAR.js';import'./chunk-SHD27BQX.js';import {a as a$6}from'./chunk-CSXVL2U7.js';import'./chunk-EKZDFEJW.js';import {a as a$1}from'./chunk-33LKBMVK.js';import {b as b$2}from'./chunk-JBDMCRPP.js';import'./chunk-4TXOVRWD.js';import'./chunk-T6IDXUUA.js';import'./chunk-JIXHEBGK.js';import'./chunk-QT2LKB3P.js';import'./chunk-VCKKJDLP.js';import'./chunk-WR6D3SC6.js';import {a as a$2}from'./chunk-UIKLE3WD.js';import {a as a$4}from'./chunk-QNZEG7IT.js';import'./chunk-HMQ5BHP2.js';import'./chunk-JQKKVAAN.js';import {a}from'./chunk-LKAT7IAK.js';import'./chunk-5TAVYPOV.js';import*as r from'fs';import*as n from'path';import e from'chalk';import U from'ora';import*as g from'js-yaml';async function oe(l={}){let s=process.cwd(),h=n.basename(s),u=n.join(s,".paradigm"),k=r.existsSync(u)&&r.statSync(u).isDirectory();console.log(e.blue(`
3
3
  \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510`)),console.log(e.blue("\u2502")+e.white.bold(" paradigm shift ")+e.blue("\u2502")),console.log(e.blue("\u2502")+e.gray(" Full project setup in one command ")+e.blue("\u2502")),console.log(e.blue(`\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518
4
4
  `)),console.log(e.white(` \u{1F4C1} Project: ${e.cyan(h)}`)),console.log(e.white(` \u{1F4CD} Status: ${k?e.green("Paradigm detected"):e.yellow("New project")}`)),console.log("");let j=a.command("shift").start("Running paradigm shift",{project:h}),i=U();if(!k||l.force){i.start("Step 1/6: Initializing Paradigm...");try{await a$1({force:l.force,quick:!0,name:h,stack:l.stack}),i.succeed(e.green("Paradigm initialized"));}catch(o){i.fail(e.red(`Init failed: ${o.message}`)),j.error("Shift failed at init",{error:o.message});return}}else {i.succeed(e.gray("Step 1/6: Already initialized (use --force to reinit)"));let o=n.join(u,"config.yaml");if(r.existsSync(o))try{let t=r.readFileSync(o,"utf8"),a=g.load(t);if(!a.discipline||a.discipline==="auto"){let c=a$2(s);if(c!=="backend"){let f=t.replace(/^discipline:\s*auto\b.*$/m,`discipline: ${c}`);f!==t&&(r.writeFileSync(o,f,"utf8"),console.log(e.green(` \u2713 Detected discipline: ${e.cyan(c)} (updated config.yaml)`)));}else if(!a.discipline){let f=t.replace(/^(project:\s*.+)$/m,`$1
5
5
  discipline: ${c}`);f!==t&&(r.writeFileSync(o,f,"utf8"),console.log(e.green(` \u2713 Added discipline: ${e.cyan(c)} to config.yaml`)));}}}catch(t){a.operation("shift").debug("Discipline detection failed",{error:t.message});}}if(k){i.start("Step 1b/6: Checking for migrations...");try{let{migrateCommand:o}=await import('./migrate-WT56YYAM.js');await o({apply:!0,quiet:!0,noSync:!0}),i.succeed(e.green("Migrations applied"));}catch(o){i.warn(e.yellow(`Migration warning: ${o.message}`));}}{let o=n.join(u,"config.yaml");if(l.workspace&&r.existsSync(o)){let t=l.workspacePath?n.resolve(s,l.workspacePath):n.join(n.dirname(s),".paradigm-workspace");if(r.existsSync(t))try{let a=g.load(r.readFileSync(t,"utf8")),c=n.basename(s),f=n.dirname(t),d$1="./"+n.relative(f,s);if(a.members.some(y=>n.resolve(f,y.path)===s))console.log(e.green(` \u2713 Already a member of workspace: ${e.cyan(a.name)}`));else {let y=d(c,s);a.members.push({name:c,path:d$1,...y&&{role:y}}),r.writeFileSync(t,g.dump(a,{indent:2,lineWidth:120,noRefs:!0,sortKeys:!1,quotingType:'"'}),"utf8"),console.log(e.green(` \u2713 Joined workspace: ${e.cyan(a.name)} (added as member)`));}}catch(a){console.log(e.yellow(` \u26A0 Failed to join workspace: ${a.message}`));}else try{let a=n.basename(s),c=n.dirname(t),f="./"+n.relative(c,s),d$1=d(a,s),p={version:"1.0",name:l.workspace,members:[{name:a,path:f,...d$1&&{role:d$1}}]};r.mkdirSync(n.dirname(t),{recursive:!0}),r.writeFileSync(t,g.dump(p,{indent:2,lineWidth:120,noRefs:!0,sortKeys:!1,quotingType:'"'}),"utf8"),console.log(e.green(` \u2713 Created workspace: ${e.cyan(l.workspace)} at ${e.gray(n.relative(s,t))}`));}catch(a){console.log(e.yellow(` \u26A0 Failed to create workspace: ${a.message}`));}try{let a=r.readFileSync(o,"utf8"),c=g.load(a),f=n.relative(s,t);if(c.workspace!==f){if(c.workspace){let d=a.replace(/^workspace:\s*.*$/m,`workspace: "${f}"`);r.writeFileSync(o,d,"utf8");}else {let d=a.trimEnd()+`
@@ -1,9 +1,29 @@
1
1
  version: 2.0.0
2
2
  name: university-courses
3
- description: Course content for Paradigm University — 7 courses, 75 lessons. Each lesson is mapped to the Paradigm concepts it teaches so that ripple analysis can identify which lessons need updating when a concept changes.
3
+ description: Course content for Paradigm University — 8 courses, 82 lessons. Each lesson is mapped to the Paradigm concepts it teaches so that ripple analysis can identify which lessons need updating when a concept changes.
4
4
 
5
5
  components:
6
- # PARA 101: Foundations (9 lessons)
6
+ # PARA 001: Quick Start (3 lessons)
7
+
8
+ para-001-shift-setup:
9
+ description: "Quick Start — Your First paradigm shift: one-command setup, what gets created"
10
+ file: para-001.json
11
+ tags: [course-content, para-001]
12
+ references: ["#shift-command", "#enforcement-hooks"]
13
+
14
+ para-001-meet-the-team:
15
+ description: "Quick Start — Meet Your Agent Team: 8 core agents, tiers, Maestro model"
16
+ file: para-001.json
17
+ tags: [course-content, para-001]
18
+ references: ["#orchestration", "#agent-loader"]
19
+
20
+ para-001-build-something:
21
+ description: "Quick Start — Build With the Team: full orchestration loop, quick-check, commit conventions"
22
+ file: para-001.json
23
+ tags: [course-content, para-001]
24
+ references: ["#orchestration", "#symbol-system", "#enforcement-hooks"]
25
+
26
+ # PARA 101: Foundations (9 lessons — reordered: first-steps at position 2)
7
27
 
8
28
  para-101-welcome:
9
29
  description: "Welcome to Paradigm — three pillars, why structured context matters"
@@ -74,7 +94,7 @@ components:
74
94
  references: ["#aspect-anchoring"]
75
95
 
76
96
  para-201-aspect-graph:
77
- description: "Aspect Graph — symbol relationships, graph visualization"
97
+ description: "Aspect Graph Introduction condensed overview, 5 categories, 7 MCP tools, pointer to PARA 501 for internals"
78
98
  file: para-201.json
79
99
  tags: [course-content, para-201]
80
100
  references: ["#symbol-graph", "#aspect-anchoring"]
@@ -121,7 +141,7 @@ components:
121
141
  tags: [course-content, para-201]
122
142
  references: ["#flow-validation", "#portal-protocol", "#aspect-anchoring", "#symbol-system"]
123
143
 
124
- # PARA 301: Operations (11 lessons)
144
+ # PARA 301: Operations (13 lessons — added enforcement-levels and paradigm-shift)
125
145
 
126
146
  para-301-history-system:
127
147
  description: "History System — implementation history, event tracking"
@@ -153,6 +173,18 @@ components:
153
173
  tags: [course-content, para-301]
154
174
  references: ["#navigation"]
155
175
 
176
+ para-301-enforcement-levels:
177
+ description: "Enforcement Levels — minimal/balanced/strict, 13 checks, per-check overrides, progression strategy"
178
+ file: para-301.json
179
+ tags: [course-content, para-301]
180
+ references: ["#enforcement-hooks", "#enforcement-presets"]
181
+
182
+ para-301-paradigm-shift:
183
+ description: "The paradigm shift Command — 6-step onboarding, flags, when to re-run, idempotent setup"
184
+ file: para-301.json
185
+ tags: [course-content, para-301]
186
+ references: ["#shift-command", "#scan-index", "#enforcement-hooks"]
187
+
156
188
  para-301-navigation-system:
157
189
  description: "Navigation System — paradigm_navigate, find/explore/context intents"
158
190
  file: para-301.json
@@ -189,7 +221,7 @@ components:
189
221
  tags: [course-content, para-301]
190
222
  references: ["#lore-system", "#wisdom-system", "#ripple-analysis", "#navigation", "#sentinel", "#protocol-system"]
191
223
 
192
- # PARA 401: Orchestration (11 lessons)
224
+ # PARA 401: Orchestration (12 lessons — added quick-check, updated agent-roles with Rune + roster bridge)
193
225
 
194
226
  para-401-mcp-tools-overview:
195
227
  description: "MCP Tools Overview — 95 tools, token budgets, query vs file read"
@@ -204,10 +236,10 @@ components:
204
236
  references: ["#orchestration"]
205
237
 
206
238
  para-401-agent-roles:
207
- description: "Agent Roles — architect, builder, reviewer, tester, security"
239
+ description: "Agent Roles — 8 core + 54 total, three-tier hierarchy, Rune compliance, facets, handoff, reviewer protocol"
208
240
  file: para-401.json
209
241
  tags: [course-content, para-401]
210
- references: ["#orchestration"]
242
+ references: ["#orchestration", "#agent-loader"]
211
243
 
212
244
  para-401-provider-cascade:
213
245
  description: "Provider Cascade — auto, claude, claude-code, cursor-cli, manual"
@@ -221,6 +253,12 @@ components:
221
253
  tags: [course-content, para-401]
222
254
  references: ["#orchestration", "#pm-governance"]
223
255
 
256
+ para-401-quick-check:
257
+ description: "Quick-Check: Ask Before You Build — lightweight risk assessment, Jinx + reviewer, GREENLIGHT vs ESCALATE"
258
+ file: para-401.json
259
+ tags: [course-content, para-401]
260
+ references: ["#orchestration"]
261
+
224
262
  para-401-pm-governance:
225
263
  description: "PM Governance — preflight, postflight, compliance checks"
226
264
  file: para-401.json
@@ -256,7 +294,7 @@ components:
256
294
  type: lesson
257
295
  tags: [university, notebooks, agent-identity, permissions]
258
296
 
259
- # PARA 501: Advanced Systems (14 lessons)
297
+ # PARA 501: Advanced Systems (15 lessons — added conductor-workspace)
260
298
 
261
299
  para-501-lore-system:
262
300
  description: "Lore System — entries, types, arcs, linked entries, timeline"
@@ -324,6 +362,12 @@ components:
324
362
  tags: [course-content, para-501]
325
363
  references: ["#PlatformServer", "#PlatformWebSocket", "#AgentPresenceManager", "#UserStateTracker", "#AgentCommandRoute", "#PlatformTools", "#AgentStore", "#AgentToast", "#AgentCallout"]
326
364
 
365
+ para-501-conductor-workspace:
366
+ description: "Conductor: Visual Mission Control — workspace tiling, Symphony integration, task protocol, agent health, local ML"
367
+ file: para-501.json
368
+ tags: [course-content, para-501]
369
+ references: ["#conductor", "#orchestration"]
370
+
327
371
  para-501-review-compliance:
328
372
  description: "University lesson: Automated Review Pipeline — paradigm review, compliance-checker, dynamic tool loading, response format"
329
373
  type: lesson
@@ -0,0 +1,166 @@
1
+ {
2
+ "id": "para-001",
3
+ "title": "PARA 001: Quick Start",
4
+ "description": "Get productive with Paradigm in 15 minutes. Initialize a project, meet your agent team, and build your first feature with orchestration. Hands-on from the first minute — theory comes later.",
5
+ "lessons": [
6
+ {
7
+ "id": "shift-setup",
8
+ "title": "Your First paradigm shift",
9
+ "content": "## Hands On in 60 Seconds\n\nOpen a terminal in any project directory and run:\n\n```bash\nparadigm shift\n```\n\nThat is it. One command, and your project is Paradigm-aware.\n\n### What Just Happened?\n\nLook at your directory. Several new files and a new folder appeared:\n\n```\n.paradigm/ ← Configuration, roster, tags, indexes\n config.yaml ← Project settings (name, discipline, enforcement)\n roster.yaml ← Your agent team\n agents.yaml ← Model tier assignments\n tags.yaml ← Tag taxonomy\nCLAUDE.md ← Instructions for Claude Code\nAGENTS.md ← Instructions for any AI agent\n.purpose ← Root-level purpose file (describes your project)\n```\n\nEach file has a specific job:\n\n- **`.paradigm/config.yaml`** is the brain — it stores your project name, discipline (web, backend, mobile, etc.), enforcement level, and feature flags. Paradigm auto-detected your discipline from project markers like `package.json`, `Cargo.toml`, or `go.mod`.\n\n- **`CLAUDE.md`** and **`AGENTS.md`** are instruction files that AI tools read automatically. They are generated from your Paradigm configuration — you do not edit them by hand. When you change config, re-running `paradigm shift` regenerates them.\n\n- **`.purpose`** is the most important file type in Paradigm. It describes what code in a directory does using a structured format with **symbols** — you will learn all five symbol types in PARA 101. For now, just know that `.purpose` files are how AI agents understand your codebase.\n\n- **`roster.yaml`** lists which agents are on your team. More on this in the next lesson.\n\n### Hooks Are Installed\n\n`paradigm shift` also installed Git hooks and Claude Code hooks. These run automatically when you commit or finish a task, checking that your Paradigm metadata stays in sync with your code.\n\nBy default, hooks use **minimal enforcement** — they warn but never block. You will not lose work or get stuck. As you get comfortable, you can upgrade to balanced or strict enforcement (covered in PARA 301).\n\n### Try It: Explore What Was Created\n\nRun these commands to see what Paradigm set up:\n\n```bash\ncat .paradigm/config.yaml # Your project configuration\ncat .paradigm/roster.yaml # Your agent team\ncat .purpose # Root purpose file\n```\n\nNotice how `config.yaml` already knows your project type, and `roster.yaml` has agents selected for that type. This is the auto-detection at work — no manual configuration needed.",
10
+ "keyConcepts": [
11
+ "paradigm shift is the one-command setup — run it in any project directory",
12
+ ".paradigm/ directory holds configuration, roster, tags, and indexes",
13
+ "CLAUDE.md and AGENTS.md are auto-generated AI instruction files",
14
+ ".purpose files describe code directories using structured symbols",
15
+ "Hooks use minimal enforcement by default — warn but never block"
16
+ ],
17
+ "quiz": [
18
+ {
19
+ "id": "q1",
20
+ "question": "You just ran paradigm shift in a Node.js project. Which of the following was NOT created or configured automatically?",
21
+ "choices": {
22
+ "A": ".paradigm/config.yaml with discipline auto-detected from package.json",
23
+ "B": "CLAUDE.md with AI instructions derived from your configuration",
24
+ "C": "A comprehensive test suite for your existing code",
25
+ "D": "Git hooks for automated compliance checking",
26
+ "E": ".paradigm/roster.yaml with agents suited for a Node.js project"
27
+ },
28
+ "correct": "C",
29
+ "explanation": "paradigm shift sets up Paradigm metadata and tooling — it does not generate tests, modify your source code, or create application logic. It creates configuration, instruction files, hooks, and an agent roster. Testing is handled by the Vigil agent during orchestration, not during initialization."
30
+ },
31
+ {
32
+ "id": "q2",
33
+ "question": "After running paradigm shift, you edit .paradigm/config.yaml to change your enforcement level. Now CLAUDE.md is out of date. How do you update it?",
34
+ "choices": {
35
+ "A": "Edit CLAUDE.md manually to match your changes",
36
+ "B": "Run paradigm shift again — it regenerates CLAUDE.md from your updated config",
37
+ "C": "Delete CLAUDE.md and it will regenerate on the next commit",
38
+ "D": "Run paradigm sync to rebuild only the instruction files",
39
+ "E": "Both B and D would work — shift re-runs all steps including sync, while sync targets just the instruction files"
40
+ },
41
+ "correct": "E",
42
+ "explanation": "CLAUDE.md is a derived file — always generated from config, never hand-edited. Both paradigm shift (full re-run) and paradigm sync (targeted) will regenerate it. Use sync when you only changed config; use shift when you want the full pipeline (migrate, scan, hooks, etc.)."
43
+ },
44
+ {
45
+ "id": "q3",
46
+ "question": "A teammate says \"I ran paradigm shift but it broke my project — hooks are blocking my commits.\" This should not happen with default settings. What likely went wrong?",
47
+ "choices": {
48
+ "A": "paradigm shift always uses strict enforcement",
49
+ "B": "The project already had a config.yaml with enforcement level set to strict or balanced from a previous setup",
50
+ "C": "Hooks always block on the first run to teach discipline",
51
+ "D": "The teammate's Git version is incompatible with Paradigm hooks",
52
+ "E": "paradigm shift requires admin privileges to install hooks"
53
+ },
54
+ "correct": "B",
55
+ "explanation": "New projects default to minimal enforcement, which warns but never blocks. But paradigm shift is idempotent — if the project already had a .paradigm/config.yaml with a higher enforcement level, shift preserves that setting. The teammate's project was likely previously configured with balanced or strict enforcement. Check config.yaml and adjust enforcement.level if needed."
56
+ }
57
+ ]
58
+ },
59
+ {
60
+ "id": "meet-the-team",
61
+ "title": "Meet Your Agent Team",
62
+ "content": "## Your AI Team\n\nOpen `.paradigm/roster.yaml`. You will see a list of agents — your project's AI team. Each agent has a specific role, and the orchestrator assigns them to tasks based on what the task needs.\n\n### The 8 Core Agents\n\nEvery project gets these eight. They are the backbone of Paradigm's orchestration:\n\n| Agent | Role | What They Do |\n|-------|------|-------------|\n| **Architect** | Design | Plans multi-file changes, defines structure |\n| **Builder** | Implementation | Writes the code |\n| **Reviewer** | Quality | Two-stage review: spec compliance → code quality |\n| **Sage** | Advocacy | Represents the user's perspective, UX implications |\n| **Jinx** | Advocacy | Stress-tests assumptions, finds edge cases |\n| **Sentinel** | Security | Threat analysis, auth review, vulnerability scanning |\n| **Vigil** | Testing | Writes tests, checks coverage, validates edge cases |\n| **Doc** | Documentation | Maintains .purpose files and portal.yaml |\n| **Rune** | Compliance | Plans symbols before building, validates after |\n\n### Model Tiers\n\nNot every agent needs the most powerful (and expensive) model. Paradigm assigns agents to tiers:\n\n- **Tier 1 (opus)** — Architect, Sentinel. Complex reasoning, design decisions, threat analysis.\n- **Tier 2 (sonnet)** — Reviewer, Sage, Jinx, Doc, Rune. Balanced depth and speed.\n- **Tier 3 (haiku)** — Builder, Vigil. Fast, cost-effective for implementation and testing.\n\nThis is not a quality ranking — it is a complexity match. Building code is well-defined work that a fast model handles efficiently. Designing architecture requires deeper reasoning that benefits from a more capable model.\n\n### Specialized and Ecosystem Agents\n\nBeyond the 8 core agents, Paradigm has **54+ agents** total:\n\n- **Specialized agents** (~20) cover domains like mobile, database, DevOps, accessibility, performance, and internationalization. They are added to your roster when your project type matches.\n\n- **Ecosystem agents** (~26+) are language/platform-specific: Swift, TypeScript, Rust, Python ML, iOS, Android, etc. They accumulate knowledge through notebooks that transfer across projects.\n\nYou do not need to manage these manually. `paradigm shift` detected your project type and selected the right mix. You can view and customize your roster with:\n\n```bash\nparadigm agent list # See your full roster\nparadigm agent activate <id> # Add an agent\nparadigm agent bench <id> # Remove an agent\n```\n\n### The Maestro Model\n\nYou are **Maestro** — the orchestrator. When you give a task to Paradigm, you are not talking to one AI. You are conducting a team:\n\n1. **Rune** plans the symbols the task needs\n2. **Architect** designs the approach (for complex tasks)\n3. **Sentinel** reviews security implications (when auth or data is involved)\n4. **Builder** writes the code\n5. **Reviewer** checks spec compliance and code quality\n6. **Doc** updates .purpose files and Paradigm metadata\n7. **Rune** validates the symbols match the implementation\n\nNot every task uses every agent. A simple CSS fix might only need Builder. A new API endpoint might need Architect → Sentinel → Builder → Reviewer → Doc → Rune. The orchestrator decides based on the task.\n\n> **Going deeper:** PARA 401 covers orchestration mechanics (facets, handoffs, trigger patterns). PARA 701 covers the full agent roster, profiles, notebooks, and learning loops.",
63
+ "keyConcepts": [
64
+ "8 core agents are in every project: Architect, Builder, Reviewer, Sage, Jinx, Sentinel, Vigil, Doc, Rune",
65
+ "54+ total agents across three tiers: core, specialized, ecosystem",
66
+ "Model tiers match agent complexity: opus for design, sonnet for analysis, haiku for execution",
67
+ "paradigm shift auto-selects agents based on project type",
68
+ "You are Maestro — the human orchestrator conducting the agent team"
69
+ ],
70
+ "quiz": [
71
+ {
72
+ "id": "q1",
73
+ "question": "Your project is a React frontend with no backend. Which of these agents would paradigm shift likely NOT include in your roster?",
74
+ "choices": {
75
+ "A": "Builder — every project needs code implementation",
76
+ "B": "A database specialist — there is no database in a frontend-only project",
77
+ "C": "Reviewer — code review is universal",
78
+ "D": "Rune — symbol compliance applies to all projects",
79
+ "E": "Sentinel — even frontend apps have security concerns (XSS, CSRF)"
80
+ },
81
+ "correct": "B",
82
+ "explanation": "Specialized agents like a database specialist are only rostered when the project type matches. A React frontend with no backend has no database layer, so database agents would not be selected. The 8 core agents (including Sentinel — frontend security matters) appear in every roster. Specialized and ecosystem agents are added based on detection."
83
+ },
84
+ {
85
+ "id": "q2",
86
+ "question": "The Architect uses opus (tier-1) while the Builder uses haiku (tier-3). A junior developer asks: \"Does that mean the builder writes worse code?\" How do you explain?",
87
+ "choices": {
88
+ "A": "Yes — tier-3 is lower quality, but it is faster and cheaper",
89
+ "B": "No — tiers match complexity, not quality. Architecture requires open-ended reasoning (opus). Building is well-defined implementation work where speed matters more (haiku).",
90
+ "C": "The tiers are just labels with no real difference",
91
+ "D": "The builder should be upgraded to opus for important features",
92
+ "E": "All agents should use the same model for consistency"
93
+ },
94
+ "correct": "B",
95
+ "explanation": "Model tier assignment is about matching the nature of the work, not ranking quality. Architectural design is open-ended — \"how should we structure this?\" benefits from deeper reasoning. Implementation is well-defined — \"write this function that does X\" benefits from speed. A fast model writing clearly specified code often produces better results than an overthinking model."
96
+ },
97
+ {
98
+ "id": "q3",
99
+ "question": "You want to add a DevOps specialist agent to your web project's roster. What command would you use?",
100
+ "choices": {
101
+ "A": "Edit roster.yaml by hand and add the agent definition",
102
+ "B": "paradigm agent activate devops — it adds the agent to your project roster",
103
+ "C": "paradigm shift --add-agent devops",
104
+ "D": "Re-run paradigm shift and hope it detects the need",
105
+ "E": "DevOps agents cannot be added to web projects"
106
+ },
107
+ "correct": "B",
108
+ "explanation": "paradigm agent activate <id> adds an agent to your project roster. This is the proper way to customize your team — the CLI updates roster.yaml, agents.yaml, and any related configuration atomically. While you could edit roster.yaml by hand, using the CLI ensures all related files stay in sync."
109
+ }
110
+ ]
111
+ },
112
+ {
113
+ "id": "build-something",
114
+ "title": "Build With the Team",
115
+ "content": "## Your First Orchestrated Task\n\nYou have a project set up and a team rostered. Now let's build something and see the full loop in action.\n\n### The Workflow\n\nEvery task in Paradigm follows this pattern:\n\n```\n1. Quick-check or plan → Is this task ready to build?\n2. Orchestrate → Assign the right agents\n3. Build → Agents do the work\n4. Review → Spec compliance + code quality\n5. Commit → With symbol references in the message\n```\n\n### Step 1: Start with a Quick-Check\n\nBefore writing any code, ask the orchestrator if your task is ready:\n\n```\nparadigm_orchestrate_inline({\n task: \"Add a health check endpoint at GET /health\",\n mode: \"quick\"\n})\n```\n\nQuick-check runs two agents — **Jinx** stress-tests your assumptions (\"What should /health return? Just 200 OK, or system status?\") and a **reviewer** checks feasibility (\"Single file change, no auth needed\"). You get back either:\n\n- **GREENLIGHT** — go ahead and build\n- **ESCALATE** — needs full planning first\n\nA simple health endpoint would likely get GREENLIGHT.\n\n### Step 2: Build\n\nWith a greenlight, proceed to implementation. If you are using Claude Code with Paradigm, the agent team handles this automatically during orchestration. For a simple task:\n\n- **Builder** writes the endpoint\n- **Rune** ensures the component is documented in `.purpose`\n- **Reviewer** checks that the implementation matches Paradigm metadata\n\n### Step 3: Review the Output\n\nThe reviewer runs two stages:\n\n1. **Spec Compliance** — Is `#health-check` registered in a `.purpose` file? If a gate is needed, is it in `portal.yaml`? (A public health endpoint typically needs no gate.)\n2. **Code Quality** — Is the implementation clean, secure, and tested?\n\nIf Stage 1 fails, the reviewer stops and sends the task back. No point reviewing code quality of undocumented code.\n\n### Step 4: Commit\n\nParadigm uses structured commit messages with symbol references:\n\n```\nfeat(#health-check): add GET /health endpoint\n\n- Add #health-check component returning system status\n- No gate required — public endpoint\n\nSymbols: #health-check\n```\n\nThe `Symbols:` trailer is parsed by the post-commit hook for automatic history capture. This means every change is traceable to the symbols it affected.\n\n### What If You Skip Orchestration?\n\nYou can always write code directly without orchestrating. On minimal enforcement (the default), nothing blocks you. But you lose:\n\n- **Pre-build risk assessment** — Jinx might have caught an edge case you missed\n- **Automatic symbol planning** — Rune would have ensured `.purpose` coverage before you started\n- **Structured review** — the reviewer's two-stage protocol catches spec drift early\n- **Traceability** — the orchestration record links task → agents → decisions → code\n\nAs enforcement increases (balanced, strict), skipping orchestration triggers warnings or blocks. The system is designed to let you learn the value of orchestration before it becomes mandatory.\n\n### The Full Loop\n\nHere is the complete picture of what happens when you build a feature with Paradigm:\n\n```\nYou (Maestro)\n │\n ├─ \"Add a health check endpoint\"\n │\n ├─ Quick-check → GREENLIGHT\n │\n ├─ Rune → Symbol plan: #health-check component\n │\n ├─ Builder → src/routes/health.ts\n │\n ├─ Reviewer → Stage 1 pass, Stage 2 pass (3 findings: 0 blocking)\n │\n ├─ Doc → Updates .purpose with #health-check\n │\n ├─ Rune → Compliance report: 1 component, 1 aspect ✓\n │\n └─ Commit → feat(#health-check): add GET /health endpoint\n```\n\nThis loop — plan, build, review, document, validate — is the heartbeat of Paradigm development. Every feature, bug fix, and refactor follows the same pattern. The agents change, the complexity varies, but the loop is always the same.\n\n> **What's next:** PARA 101 covers the five symbols (#, $, ^, !, ~) and purpose files in depth. PARA 301 covers enforcement levels and operations. PARA 401 covers the orchestration mechanics behind what you just experienced.",
116
+ "keyConcepts": [
117
+ "Every task follows: quick-check → orchestrate → build → review → commit",
118
+ "Quick-check returns GREENLIGHT (proceed) or ESCALATE (needs full planning)",
119
+ "Reviewer runs two stages: spec compliance first, code quality only if spec passes",
120
+ "Commit messages use Symbols: trailer for automatic history tracking",
121
+ "Skipping orchestration is allowed on minimal enforcement but loses traceability and risk assessment"
122
+ ],
123
+ "quiz": [
124
+ {
125
+ "id": "q1",
126
+ "question": "You built a new API endpoint without running quick-check or orchestration. The code works fine. On minimal enforcement, what happens when you commit?",
127
+ "choices": {
128
+ "A": "The commit is blocked — orchestration is always required",
129
+ "B": "The commit succeeds but the stop hook warns that no orchestration record exists for the changed files",
130
+ "C": "Nothing — minimal enforcement has no checks",
131
+ "D": "The commit is reverted automatically",
132
+ "E": "Git rejects the commit because the pre-commit hook fails"
133
+ },
134
+ "correct": "B",
135
+ "explanation": "On minimal enforcement, orchestration-required is set to off, so the stop hook does not block. However, the purpose-coverage check (which is set to warn on minimal) may warn if you did not create a .purpose file for the new endpoint. The commit succeeds either way — minimal enforcement never blocks. But you have no orchestration record, no Rune compliance report, and no structured review."
136
+ },
137
+ {
138
+ "id": "q2",
139
+ "question": "During the build step, Rune creates a symbol plan with #health-check as a component. After the builder writes the code, Rune's compliance report says \"1 component, 0 aspects — blocking.\" Why is this a problem?",
140
+ "choices": {
141
+ "A": "Aspects are required for documentation completeness but have no real purpose",
142
+ "B": "Every component needs at least one aspect (rule, constraint, or configuration) — the 1:1 ratio means you must define what rules govern the health endpoint",
143
+ "C": "Rune made an error — health endpoints do not need aspects",
144
+ "D": "The builder should have created the aspect automatically",
145
+ "E": "This only matters on strict enforcement"
146
+ },
147
+ "correct": "B",
148
+ "explanation": "Rune enforces a 1:1 component-to-aspect ratio. Even a health endpoint has rules: response format, which checks it runs, timeout behavior, whether it includes dependency status. Defining an aspect like ~health-check-format forces you to document what the endpoint actually guarantees. This is not busywork — it is how Paradigm ensures every component has a documented contract."
149
+ },
150
+ {
151
+ "id": "q3",
152
+ "question": "The commit message for your feature reads: feat(#health-check): add GET /health endpoint. The Symbols: trailer says Symbols: #health-check. What does the post-commit hook do with this information?",
153
+ "choices": {
154
+ "A": "Nothing — the Symbols trailer is just for human readability",
155
+ "B": "It parses the Symbols trailer and records the commit in Paradigm's history system, linking the change to #health-check for traceability",
156
+ "C": "It validates that #health-check exists in a .purpose file",
157
+ "D": "It sends a notification to the agent team",
158
+ "E": "It automatically creates a changelog entry"
159
+ },
160
+ "correct": "B",
161
+ "explanation": "The post-commit hook parses the Symbols: trailer and records the commit in Paradigm's history system. This creates a traceable link: commit → symbols affected. Later, when someone asks \"what changed about #health-check?\" or runs paradigm_history_context, the answer includes this commit. The pre-commit hook handles index rebuilding; the post-commit hook handles history capture."
162
+ }
163
+ ]
164
+ }
165
+ ]
166
+ }
@@ -56,16 +56,82 @@
56
56
  },
57
57
  {
58
58
  "id": "q4",
59
- "question": "How many operational symbols does Paradigm define?",
59
+ "question": "You open a .purpose file and see symbols prefixed with #, $, ^, !, and ~. A new team member asks what the ~ symbol means. What do you tell them?",
60
60
  "choices": {
61
- "A": "3",
62
- "B": "4",
63
- "C": "5",
64
- "D": "7",
65
- "E": "10"
61
+ "A": "~ marks a component — a documented code unit",
62
+ "B": "~ marks a flow — a multi-step process",
63
+ "C": "~ marks a gate — a security checkpoint",
64
+ "D": "~ marks a signal — an event notification",
65
+ "E": "~ marks an aspect — a cross-cutting rule, constraint, or configuration anchored to specific code"
66
+ },
67
+ "correct": "E",
68
+ "explanation": "The five symbols are: # (Component), $ (Flow), ^ (Gate), ! (Signal), and ~ (Aspect). Aspects represent cross-cutting concerns — rules, constraints, and configuration values that are anchored to specific lines of code. They are the only symbol type that requires code anchors."
69
+ }
70
+ ]
71
+ },
72
+ {
73
+ "id": "first-steps",
74
+ "title": "Your First Steps",
75
+ "content": "## Getting Started with Paradigm\n\nBefore diving into theory, let's get your hands dirty. This lesson walks through the concrete steps to set up Paradigm in a real project. You will encounter terms like *symbols*, *purpose files*, and *gates* — each gets its own deep-dive lesson later in this course. For now, focus on the workflow: initialize, document, scan, go.\n\n## Step 1: Initialize the Project\n\nRun `paradigm shift` in your project root. This creates the `.paradigm/` directory with a starter `config.yaml`:\n\n```bash\nparadigm shift\n```\n\n`paradigm shift` runs non-interactively by default — it auto-detects your discipline from project markers (`package.json`, `Cargo.toml`, `go.mod`, etc.), selects an appropriate agent roster, configures model tiers, installs hooks, and generates AI instruction files (CLAUDE.md, AGENTS.md). One command, full setup.\n\nYou can customize later with flags like `--verify` (health check) or `--workspace <name>` (multi-project workspace).\n\nAfter init, you will have:\n```\n.paradigm/\n config.yaml # Includes detected discipline and stack\n tags.yaml\n agents.yaml\n```\n\n## Step 2: Create Your First Purpose File\n\nPick a source directory that contains meaningful code — perhaps your main feature module or your API routes. Create a `.purpose` file:\n\n```yaml\nname: User Authentication\ndescription: Handles user login, registration, and session management\ncontext:\n - Uses bcrypt for password hashing\n - Sessions stored in Redis with 24h TTL\n - Rate limited to 5 login attempts per minute\n\ncomponents:\n #auth-handler:\n description: POST /auth/login and POST /auth/register endpoints\n file: auth.ts\n tags: [feature, auth]\n signals: [\"!login-success\", \"!login-failed\"]\n gates: [\"^authenticated\"]\n\n #session-manager:\n description: Creates and validates user sessions in Redis\n file: session.ts\n tags: [state, auth]\n```\n\nStart small. You do not need to document every file on day one. Begin with the most important module and expand over time.\n\n## Step 3: Set Up portal.yaml (If Needed)\n\nIf your application has any protected endpoints, create `portal.yaml` at the project root:\n\n```yaml\nversion: \"1.0\"\n\ngates:\n ^authenticated:\n description: User must have a valid session\n check: req.session.userId != null\n type: auth\n effects: []\n\nroutes:\n \"POST /auth/login\": []\n \"POST /auth/register\": []\n \"GET /api/profile\": [^authenticated]\n \"PUT /api/profile\": [^authenticated]\n```\n\nNote that public routes like login and register have empty gate arrays `[]` — they are listed to document that they are intentionally unprotected.\n\n## Step 4: Run Your First Scan\n\nGenerate the navigator map so AI agents can find symbols quickly:\n\n```bash\nparadigm scan\n```\n\nThis reads all `.purpose` files and `portal.yaml`, builds a symbol index, and writes `navigator.yaml`.\n\n## Step 5: The Orientation Protocol\n\nWhen starting a new AI session (or when an AI agent first encounters your project), the agent should follow this protocol:\n\n1. **Call `paradigm_status`** — Gets a project overview: symbol counts, health, available features.\n2. **Read `config.yaml`** — Understands the discipline, conventions, and preferences.\n3. **Check `portal.yaml`** — Knows about security gates if they exist.\n4. **Use `paradigm_navigate`** — Finds the relevant code area for the current task.\n\nThis four-step orientation takes ~500 tokens total and gives the agent everything it needs to work effectively.\n\n## Step 6: Iterate\n\nParadigm grows with your project. As you add features:\n- Create `.purpose` files for new directories\n- Add gates to `portal.yaml` for new protected routes\n- Record team decisions in `.paradigm/wisdom/decisions.yaml`\n- Log antipatterns in `.paradigm/wisdom/antipatterns.yaml`\n- Run `paradigm scan` periodically to rebuild the navigator\n\n## Common Pitfalls\n\n- **Do not document everything on day one.** Start with the most critical module and expand.\n- **Do not skip portal.yaml.** If you have any gates or preconditions, you need it.\n- **Do not forget to re-scan.** After adding new `.purpose` files, run `paradigm scan` to update the navigator.\n- **Do not put .purpose files in .paradigm/.** They live alongside source code.\n- **Do not use raw console.log.** Use the Paradigm logger from the start to build good habits.",
76
+ "keyConcepts": [
77
+ "paradigm shift creates the .paradigm/ directory",
78
+ "Start with one .purpose file in your most important module",
79
+ "Create portal.yaml if your project has gates (conditions to check)",
80
+ "paradigm scan generates navigator.yaml",
81
+ "The orientation protocol: status, config, portal, navigate"
82
+ ],
83
+ "quiz": [
84
+ {
85
+ "id": "q1",
86
+ "question": "What is the correct order for the AI agent orientation protocol?",
87
+ "choices": {
88
+ "A": "Read source code, write tests, check coverage, deploy",
89
+ "B": "Call paradigm_status, read config.yaml, check portal.yaml, use paradigm_navigate",
90
+ "C": "Run paradigm scan, edit navigator.yaml, read .purpose files, commit changes",
91
+ "D": "Read package.json, install dependencies, run build, check logs",
92
+ "E": "Create .purpose files, define gates, emit signals, validate flows"
93
+ },
94
+ "correct": "B",
95
+ "explanation": "The orientation protocol is: (1) paradigm_status for project overview, (2) read config.yaml for conventions, (3) check portal.yaml for security gates, (4) paradigm_navigate to find the relevant code area. This takes ~500 tokens and gives the agent full context."
96
+ },
97
+ {
98
+ "id": "q2",
99
+ "question": "After creating new .purpose files, what command should you run?",
100
+ "choices": {
101
+ "A": "paradigm shift",
102
+ "B": "paradigm validate",
103
+ "C": "paradigm scan",
104
+ "D": "paradigm deploy",
105
+ "E": "paradigm build"
66
106
  },
67
107
  "correct": "C",
68
- "explanation": "Paradigm defines exactly five operational symbols: # (Component), $ (Flow), ^ (Gate), ! (Signal), and ~ (Aspect). Classification beyond these five is handled by the tag system."
108
+ "explanation": "paradigm scan reads all .purpose files and portal.yaml, builds the symbol index, and regenerates navigator.yaml. Without rescanning, AI agents will not find the newly defined symbols through navigation tools."
109
+ },
110
+ {
111
+ "id": "q3",
112
+ "question": "In portal.yaml, what does an empty gate array on a route mean?",
113
+ "choices": {
114
+ "A": "The route is disabled and will return 404",
115
+ "B": "The route requires all gates to pass",
116
+ "C": "The route is intentionally unprotected — documented as public",
117
+ "D": "The route has not been configured yet and will return 500",
118
+ "E": "The route inherits gates from its parent path"
119
+ },
120
+ "correct": "C",
121
+ "explanation": "An empty gate array [] means the route is intentionally public. Listing it in portal.yaml with no gates documents the decision that this route should be accessible without authentication — it is not an oversight."
122
+ },
123
+ {
124
+ "id": "q4",
125
+ "question": "Which of these is a common pitfall when starting with Paradigm?",
126
+ "choices": {
127
+ "A": "Creating too many .purpose files on day one instead of starting small",
128
+ "B": "Using the Paradigm logger instead of console.log",
129
+ "C": "Running paradigm scan after adding new purpose files",
130
+ "D": "Putting portal.yaml at the project root",
131
+ "E": "Using tags to classify components"
132
+ },
133
+ "correct": "A",
134
+ "explanation": "A common pitfall is trying to document everything on day one. The recommended approach is to start with the most critical module, create one .purpose file, and expand incrementally as the project grows."
69
135
  }
70
136
  ]
71
137
  },
@@ -96,16 +162,16 @@
96
162
  },
97
163
  {
98
164
  "id": "q2",
99
- "question": "Which symbol REQUIRES code anchors in its definition?",
165
+ "question": "After a refactor, you run paradigm doctor and it reports \"3 broken anchors detected.\" Which symbol type was affected?",
100
166
  "choices": {
101
- "A": "# Component",
102
- "B": "$ Flow",
103
- "C": "^ Gate",
104
- "D": "! Signal",
105
- "E": "~ Aspect"
167
+ "A": "# Component — components have code anchors that broke during refactoring",
168
+ "B": "$ Flow — flow steps reference line numbers that shifted",
169
+ "C": "^ Gate — gate definitions include file paths that changed",
170
+ "D": "! Signal — signal emitters moved to different files",
171
+ "E": "~ Aspect — aspects are the only symbol with code anchors, and the refactor moved the anchored lines"
106
172
  },
107
173
  "correct": "E",
108
- "explanation": "Aspects (~) are the only symbol that requires code anchors. An aspect represents a cross-cutting rule, and without anchors pointing to the enforcement code, the rule is just a wish not a verified constraint."
174
+ "explanation": "Aspects (~) are the only symbol type that requires code anchors specific file:line references pointing to where the rule is enforced. When code is refactored and lines move, those anchors break. paradigm doctor detects this via SHA-256 hash comparison, and paradigm_aspect_drift can show exactly which anchors drifted."
109
175
  },
110
176
  {
111
177
  "id": "q3",
@@ -135,16 +201,16 @@
135
201
  },
136
202
  {
137
203
  "id": "q5",
138
- "question": "A system emits `!payment-completed` after a successful charge. Which statement is true about signals?",
204
+ "question": "Your payment module emits !payment-completed after charging a card. Later, the marketing team adds a \"send receipt email\" listener, and the analytics team adds a \"record conversion\" listener. Neither team modified the payment module. How is this possible?",
139
205
  "choices": {
140
- "A": "The signal must directly invoke the notification service",
141
- "B": "Signals can only be emitted by gate components",
142
- "C": "The emitter does not need to know who listens to the signal",
143
- "D": "Signals replace flows you use one or the other, never both",
144
- "E": "Signals must be defined in portal.yaml"
206
+ "A": "The payment module was refactored to call both services directly",
207
+ "B": "Signals promote loose coupling the emitter fires the event without knowing who listens, so new listeners can be added independently",
208
+ "C": "The listeners were added to the payment module's .purpose file",
209
+ "D": "Both teams used the same $flow as the payment module",
210
+ "E": "The ^payment gate routes events to registered handlers"
145
211
  },
146
- "correct": "C",
147
- "explanation": "Signals promote loose coupling. The emitting component fires the event, and any number of listeners can react independently. The emitter has no knowledge of and no dependency onthe listeners."
212
+ "correct": "B",
213
+ "explanation": "This is the core value of signals: loose coupling. The payment module emits !payment-completed and has zero knowledge of who listens. The marketing team and analytics team independently subscribe to the signal. No code in the payment module was modified. This is why Paradigm separates signals (!) from flows ($) flows define explicit steps, while signals enable independent, decoupled reactions."
148
214
  }
149
215
  ]
150
216
  },
@@ -492,72 +558,6 @@
492
558
  }
493
559
  ]
494
560
  },
495
- {
496
- "id": "first-steps",
497
- "title": "Your First Steps",
498
- "content": "## Getting Started with Paradigm\n\nYou have learned the concepts — now it is time to put them into practice. This lesson walks through the concrete steps to initialize Paradigm in a new project and set up the foundational files.\n\n## Step 1: Initialize the Project\n\nRun `paradigm shift` in your project root. This creates the `.paradigm/` directory with a starter `config.yaml`:\n\n```bash\nparadigm shift\n```\n\nThe init command will prompt you for:\n- **Project name** — Used in config.yaml and as a display name\n- **Discipline** — `web`, `backend`, `fullstack`, `mobile`, `cli`, etc. (auto-detected from your project)\n- **Agent provider** — Which AI tool you use (`claude-code`, `cursor-cli`, etc.)\n\nParadigm automatically detects your discipline from project markers (`package.json`, `Cargo.toml`, `go.mod`, etc.) and your **stack preset** from framework dependencies. For example, a project with Next.js in its dependencies will be detected as `discipline: fullstack` with `stack: nextjs`. The stack preset provides framework-specific scan patterns, purpose-required paths, and refined symbol mappings.\n\nYou can also specify a stack explicitly: `paradigm init --stack fastapi`.\n\nAfter init, you will have:\n```\n.paradigm/\n config.yaml # Includes detected discipline and stack\n tags.yaml\n agents.yaml\n```\n\n## Step 2: Create Your First Purpose File\n\nPick a source directory that contains meaningful code — perhaps your main feature module or your API routes. Create a `.purpose` file:\n\n```yaml\nname: User Authentication\ndescription: Handles user login, registration, and session management\ncontext:\n - Uses bcrypt for password hashing\n - Sessions stored in Redis with 24h TTL\n - Rate limited to 5 login attempts per minute\n\ncomponents:\n #auth-handler:\n description: POST /auth/login and POST /auth/register endpoints\n file: auth.ts\n tags: [feature, auth]\n signals: [\"!login-success\", \"!login-failed\"]\n gates: [\"^authenticated\"]\n\n #session-manager:\n description: Creates and validates user sessions in Redis\n file: session.ts\n tags: [state, auth]\n```\n\nStart small. You do not need to document every file on day one. Begin with the most important module and expand over time.\n\n## Step 3: Set Up portal.yaml (If Needed)\n\nIf your application has any protected endpoints, create `portal.yaml` at the project root:\n\n```yaml\nversion: \"1.0\"\n\ngates:\n ^authenticated:\n description: User must have a valid session\n check: req.session.userId != null\n type: auth\n effects: []\n\nroutes:\n \"POST /auth/login\": []\n \"POST /auth/register\": []\n \"GET /api/profile\": [^authenticated]\n \"PUT /api/profile\": [^authenticated]\n```\n\nNote that public routes like login and register have empty gate arrays `[]` — they are listed to document that they are intentionally unprotected.\n\n## Step 4: Run Your First Scan\n\nGenerate the navigator map so AI agents can find symbols quickly:\n\n```bash\nparadigm scan\n```\n\nThis reads all `.purpose` files and `portal.yaml`, builds a symbol index, and writes `navigator.yaml`.\n\n## Step 5: The Orientation Protocol\n\nWhen starting a new AI session (or when an AI agent first encounters your project), the agent should follow this protocol:\n\n1. **Call `paradigm_status`** — Gets a project overview: symbol counts, health, available features.\n2. **Read `config.yaml`** — Understands the discipline, conventions, and preferences.\n3. **Check `portal.yaml`** — Knows about security gates if they exist.\n4. **Use `paradigm_navigate`** — Finds the relevant code area for the current task.\n\nThis four-step orientation takes ~500 tokens total and gives the agent everything it needs to work effectively.\n\n## Step 6: Iterate\n\nParadigm grows with your project. As you add features:\n- Create `.purpose` files for new directories\n- Add gates to `portal.yaml` for new protected routes\n- Record team decisions in `.paradigm/wisdom/decisions.yaml`\n- Log antipatterns in `.paradigm/wisdom/antipatterns.yaml`\n- Run `paradigm scan` periodically to rebuild the navigator\n\n## Common Pitfalls\n\n- **Do not document everything on day one.** Start with the most critical module and expand.\n- **Do not skip portal.yaml.** If you have any gates or preconditions, you need it.\n- **Do not forget to re-scan.** After adding new `.purpose` files, run `paradigm scan` to update the navigator.\n- **Do not put .purpose files in .paradigm/.** They live alongside source code.\n- **Do not use raw console.log.** Use the Paradigm logger from the start to build good habits.",
499
- "keyConcepts": [
500
- "paradigm shift creates the .paradigm/ directory",
501
- "Start with one .purpose file in your most important module",
502
- "Create portal.yaml if your project has gates (conditions to check)",
503
- "paradigm scan generates navigator.yaml",
504
- "The orientation protocol: status, config, portal, navigate"
505
- ],
506
- "quiz": [
507
- {
508
- "id": "q1",
509
- "question": "What is the correct order for the AI agent orientation protocol?",
510
- "choices": {
511
- "A": "Read source code, write tests, check coverage, deploy",
512
- "B": "Call paradigm_status, read config.yaml, check portal.yaml, use paradigm_navigate",
513
- "C": "Run paradigm scan, edit navigator.yaml, read .purpose files, commit changes",
514
- "D": "Read package.json, install dependencies, run build, check logs",
515
- "E": "Create .purpose files, define gates, emit signals, validate flows"
516
- },
517
- "correct": "B",
518
- "explanation": "The orientation protocol is: (1) paradigm_status for project overview, (2) read config.yaml for conventions, (3) check portal.yaml for security gates, (4) paradigm_navigate to find the relevant code area. This takes ~500 tokens and gives the agent full context."
519
- },
520
- {
521
- "id": "q2",
522
- "question": "After creating new .purpose files, what command should you run?",
523
- "choices": {
524
- "A": "paradigm shift",
525
- "B": "paradigm validate",
526
- "C": "paradigm scan",
527
- "D": "paradigm deploy",
528
- "E": "paradigm build"
529
- },
530
- "correct": "C",
531
- "explanation": "paradigm scan reads all .purpose files and portal.yaml, builds the symbol index, and regenerates navigator.yaml. Without rescanning, AI agents will not find the newly defined symbols through navigation tools."
532
- },
533
- {
534
- "id": "q3",
535
- "question": "In portal.yaml, what does an empty gate array on a route mean?",
536
- "choices": {
537
- "A": "The route is disabled and will return 404",
538
- "B": "The route requires all gates to pass",
539
- "C": "The route is intentionally unprotected — documented as public",
540
- "D": "The route has not been configured yet and will return 500",
541
- "E": "The route inherits gates from its parent path"
542
- },
543
- "correct": "C",
544
- "explanation": "An empty gate array [] means the route is intentionally public. Listing it in portal.yaml with no gates documents the decision that this route should be accessible without authentication — it is not an oversight."
545
- },
546
- {
547
- "id": "q4",
548
- "question": "Which of these is a common pitfall when starting with Paradigm?",
549
- "choices": {
550
- "A": "Creating too many .purpose files on day one instead of starting small",
551
- "B": "Using the Paradigm logger instead of console.log",
552
- "C": "Running paradigm scan after adding new purpose files",
553
- "D": "Putting portal.yaml at the project root",
554
- "E": "Using tags to classify components"
555
- },
556
- "correct": "A",
557
- "explanation": "A common pitfall is trying to document everything on day one. The recommended approach is to start with the most critical module, create one .purpose file, and expand incrementally as the project grows."
558
- }
559
- ]
560
- },
561
561
  {
562
562
  "id": "component-types",
563
563
  "title": "Component Types & Hierarchy",