@zuzuucodes/cli 1.4.0 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/zuzuu.mjs +20 -4
- package/package.json +1 -1
- package/web-app/dist/auth.js +91 -0
- package/web-app/dist/server.js +16 -79
- package/web-app/dist/zuzuu-cli.js +124 -0
- package/web-app/dist/{zuzuu-api.js → zuzuu-routes.js} +158 -133
- package/web-app/web-dist/assets/CommandPalette-DhBdR7X3.js +45 -0
- package/web-app/web-dist/assets/DiffTab-CqxwSjI2.js +1 -0
- package/web-app/web-dist/assets/EditorPane-94QPFR9R.js +41 -0
- package/web-app/web-dist/assets/MonacoFile-D76epTrG.js +1 -0
- package/web-app/web-dist/assets/angular-html-BVBpGdXr.js +1 -0
- package/web-app/web-dist/assets/{angular-ts-CD_OonCa.js → angular-ts-BfdufMKP.js} +1 -1
- package/web-app/web-dist/assets/{apl-uOGC3x4e.js → apl-DWBSSoBH.js} +1 -1
- package/web-app/web-dist/assets/{astro-B6ybQmWG.js → astro-3LtMP0Sq.js} +1 -1
- package/web-app/web-dist/assets/{blade-B1QGRlVx.js → blade-llJRbbtR.js} +1 -1
- package/web-app/web-dist/assets/c-Wt1voDr2.js +1 -0
- package/web-app/web-dist/assets/{cobol-BgqgtYWn.js → cobol-x_HIyl2P.js} +1 -1
- package/web-app/web-dist/assets/{coffee-0wIRKYlr.js → coffee-CThvmt4R.js} +1 -1
- package/web-app/web-dist/assets/cpp-NtAeskI3.js +1 -0
- package/web-app/web-dist/assets/{crystal-CyTK3qFN.js → crystal-DNu_sX0G.js} +1 -1
- package/web-app/web-dist/assets/css-DJp_X0uY.js +1 -0
- package/web-app/web-dist/assets/{cssMode-B9jnrWOz.js → cssMode-ByQBaInt.js} +1 -1
- package/web-app/web-dist/assets/dist-DQqjtuhV.js +153 -0
- package/web-app/web-dist/assets/{edge-CvML9pwC.js → edge-ozw5tpLl.js} +1 -1
- package/web-app/web-dist/assets/{editor.api2-BmGoRSl4.js → editor.api2-C7skgoRB.js} +1 -1
- package/web-app/web-dist/assets/{elixir-CrjqTiSc.js → elixir-VhA6FeZt.js} +1 -1
- package/web-app/web-dist/assets/{elm-C4JtJ0Au.js → elm-dREJmIFz.js} +1 -1
- package/web-app/web-dist/assets/{erb-Cmeb-29V.js → erb-CIg6G69l.js} +1 -1
- package/web-app/web-dist/assets/{freemarker2-B5LAi19B.js → freemarker2-CBBwP9JV.js} +1 -1
- package/web-app/web-dist/assets/{git-rebase-CXqdToiP.js → git-rebase-B44mJPta.js} +1 -1
- package/web-app/web-dist/assets/{glimmer-js-Kq-kdTyV.js → glimmer-js-vH_gHG0-.js} +1 -1
- package/web-app/web-dist/assets/{glimmer-ts-D0RKLJNf.js → glimmer-ts--abOzSAQ.js} +1 -1
- package/web-app/web-dist/assets/glsl-Dv5r7kPw.js +1 -0
- package/web-app/web-dist/assets/graphql-CB4jsw2E.js +1 -0
- package/web-app/web-dist/assets/{hack-trjVF3Po.js → hack-DvEYX148.js} +1 -1
- package/web-app/web-dist/assets/haml-zE6W3STP.js +1 -0
- package/web-app/web-dist/assets/{handlebars-B8_x7Zx7.js → handlebars-CzBR2SDs.js} +1 -1
- package/web-app/web-dist/assets/{handlebars-g7ZhGhI_.js → handlebars-tXdfxEd6.js} +1 -1
- package/web-app/web-dist/assets/html-C8UlPnhE.js +1 -0
- package/web-app/web-dist/assets/{html-CfvRMgoC.js → html-DgPn1QYH.js} +1 -1
- package/web-app/web-dist/assets/{html-derivative-BYX_F_XH.js → html-derivative-CY6NRz-J.js} +1 -1
- package/web-app/web-dist/assets/{htmlMode-Bi8vSvwb.js → htmlMode-BtdIDgA2.js} +1 -1
- package/web-app/web-dist/assets/{http-BIVDpHT-.js → http-Cyd7bS_S.js} +1 -1
- package/web-app/web-dist/assets/{hurl-CFsshMju.js → hurl-CWPsiEpf.js} +1 -1
- package/web-app/web-dist/assets/index-B27_WOhS.css +2 -0
- package/web-app/web-dist/assets/index-De6DWTZM.js +7 -0
- package/web-app/web-dist/assets/java-CGc3VwQr.js +1 -0
- package/web-app/web-dist/assets/{javascript-Bxx2wV4w.js → javascript-5m05n-Be.js} +1 -1
- package/web-app/web-dist/assets/javascript-CUt1pgmJ.js +1 -0
- package/web-app/web-dist/assets/{jinja-_ZS5zWwe.js → jinja-CD-Z-FLd.js} +1 -1
- package/web-app/web-dist/assets/{jison-D8mMEpcs.js → jison-imPNup1l.js} +1 -1
- package/web-app/web-dist/assets/json-Bg9ijW3F.js +1 -0
- package/web-app/web-dist/assets/{jsonMode-C6ELX5GM.js → jsonMode-BG32YnTY.js} +1 -1
- package/web-app/web-dist/assets/jsx-CY6oMTks.js +1 -0
- package/web-app/web-dist/assets/{julia-D4h2DZrs.js → julia-Dc3O-irA.js} +1 -1
- package/web-app/web-dist/assets/{just-bMqQi3xg.js → just-BhOq_Kbv.js} +1 -1
- package/web-app/web-dist/assets/{latex-DThYi3CX.js → latex-Cu4Y1d5w.js} +1 -1
- package/web-app/web-dist/assets/lib-KIOQTlcs.js +1 -0
- package/web-app/web-dist/assets/{liquid-CUjzzP4r.js → liquid-3ZnQzTbs.js} +1 -1
- package/web-app/web-dist/assets/{liquid-CesB-zzl.js → liquid-CvXMrjlQ.js} +1 -1
- package/web-app/web-dist/assets/{lspLanguageFeatures-gTnJsses.js → lspLanguageFeatures-6KXALSrl.js} +1 -1
- package/web-app/web-dist/assets/lua-BjLEUjKY.js +1 -0
- package/web-app/web-dist/assets/{marko-yoGoLK2m.js → marko-DvhNOisQ.js} +1 -1
- package/web-app/web-dist/assets/{mdc-BvtXU6eH.js → mdc-Bm9TpL1X.js} +1 -1
- package/web-app/web-dist/assets/{mdx-DrXGQbNB.js → mdx-DffTEkNE.js} +1 -1
- package/web-app/web-dist/assets/{monaco-setup-CsR6EfHe.js → monaco-setup-DM3A5_VI.js} +3 -3
- package/web-app/web-dist/assets/{nginx-DoUz032F.js → nginx-Bhc82uuv.js} +1 -1
- package/web-app/web-dist/assets/{nim-B0Pl8B4R.js → nim-DXTVBFnF.js} +1 -1
- package/web-app/web-dist/assets/{perl-D2tfAALb.js → perl-C7veXV9z.js} +1 -1
- package/web-app/web-dist/assets/{php-BImCcX5X.js → php-BRiuMnnr.js} +1 -1
- package/web-app/web-dist/assets/{pug-BcnpC8P_.js → pug-C5hz5LQ7.js} +1 -1
- package/web-app/web-dist/assets/{python-ypRCBnvu.js → python-DyLAD3Wt.js} +1 -1
- package/web-app/web-dist/assets/{qml-DFDAunHY.js → qml-BdUV3aTS.js} +1 -1
- package/web-app/web-dist/assets/r-8R7vtdQc.js +1 -0
- package/web-app/web-dist/assets/{razor-aqrhpwqZ.js → razor-C49xQTPQ.js} +1 -1
- package/web-app/web-dist/assets/{razor-1_376SZM.js → razor-DRL52XO2.js} +1 -1
- package/web-app/web-dist/assets/react-vendor-CCIEwYL0.js +9 -0
- package/web-app/web-dist/assets/regexp-Omp9DhTb.js +1 -0
- package/web-app/web-dist/assets/{rst-2vG6f11Y.js → rst-BHX71KW9.js} +1 -1
- package/web-app/web-dist/assets/{ruby-Dj6bCFXR.js → ruby-B--HzjGU.js} +1 -1
- package/web-app/web-dist/assets/{sas-BhVZ4qL2.js → sas-DrLaYOK_.js} +1 -1
- package/web-app/web-dist/assets/scss-DdSxiZKl.js +1 -0
- package/web-app/web-dist/assets/shellscript-DwcUjJBL.js +1 -0
- package/web-app/web-dist/assets/{shellsession-CyO2fnhB.js → shellsession-CPZkydE6.js} +1 -1
- package/web-app/web-dist/assets/{soy-DIkw6E88.js → soy-Br5FhD7c.js} +1 -1
- package/web-app/web-dist/assets/sql-DNssxck8.js +1 -0
- package/web-app/web-dist/assets/{stata-DvkM932O.js → stata-DXn1tqOr.js} +1 -1
- package/web-app/web-dist/assets/{surrealql-B4-Q8tqV.js → surrealql-IeLNQw0f.js} +1 -1
- package/web-app/web-dist/assets/{svelte-p6yBy-Ki.js → svelte-DOdLCIlh.js} +1 -1
- package/web-app/web-dist/assets/{templ-C7EkuiZr.js → templ-CIwIngms.js} +1 -1
- package/web-app/web-dist/assets/{tex-DkmD8uFC.js → tex-D8QMumu5.js} +1 -1
- package/web-app/web-dist/assets/{ts-tags-U-hncHg4.js → ts-tags-BMVY4q-l.js} +1 -1
- package/web-app/web-dist/assets/{tsMode-a8OvovQd.js → tsMode-BndVBac5.js} +1 -1
- package/web-app/web-dist/assets/tsx-5Eka4NBX.js +1 -0
- package/web-app/web-dist/assets/{twig-CU0OP-IA.js → twig-C8o_5mgw.js} +1 -1
- package/web-app/web-dist/assets/{typescript-DnLjiKtn.js → typescript-B1w9vqKF.js} +1 -1
- package/web-app/web-dist/assets/typescript-DOu2WMV5.js +1 -0
- package/web-app/web-dist/assets/{vue-Db7nY3ba.js → vue-BU18DNDL.js} +1 -1
- package/web-app/web-dist/assets/{vue-html-BvAbiAw1.js → vue-html-BeluIYX0.js} +1 -1
- package/web-app/web-dist/assets/{vue-vine-BEaIQIlA.js → vue-vine-DGUAbOCX.js} +1 -1
- package/web-app/web-dist/assets/{xml-an4Nuuqq.js → xml-D8uAlVv5.js} +1 -1
- package/web-app/web-dist/assets/xml-DIqSwXR3.js +1 -0
- package/web-app/web-dist/assets/{xsl-D3NQgH22.js → xsl-Ct_-YIAy.js} +1 -1
- package/web-app/web-dist/assets/xterm-B1ffpRuj.js +36 -0
- package/web-app/web-dist/assets/xterm-addons-psDEiUMC.js +136 -0
- package/web-app/web-dist/assets/{yaml-Diiu6O9P.js → yaml-Bb7jXyQv.js} +1 -1
- package/web-app/web-dist/assets/yaml-DTtCYNlS.js +1 -0
- package/web-app/web-dist/index.html +6 -3
- package/zuzuu/actions/convert.mjs +10 -9
- package/zuzuu/actions/dispatch.mjs +12 -7
- package/zuzuu/actions/inbox.mjs +5 -5
- package/zuzuu/actions/manifest.mjs +48 -30
- package/zuzuu/actions/schema.mjs +9 -3
- package/zuzuu/actions/trail.mjs +1 -1
- package/zuzuu/commands/act-author.mjs +23 -13
- package/zuzuu/commands/act.mjs +4 -6
- package/zuzuu/commands/capture.mjs +2 -2
- package/zuzuu/commands/code.mjs +2 -2
- package/zuzuu/commands/digest.mjs +2 -2
- package/zuzuu/commands/distill.mjs +15 -16
- package/zuzuu/commands/doctor.mjs +41 -19
- package/zuzuu/commands/enable.mjs +1 -1
- package/zuzuu/commands/eval.mjs +3 -36
- package/zuzuu/commands/explain.mjs +4 -4
- package/zuzuu/commands/faculty.mjs +158 -0
- package/zuzuu/commands/generation.mjs +5 -8
- package/zuzuu/commands/hook.mjs +14 -12
- package/zuzuu/commands/inbox.mjs +1 -6
- package/zuzuu/commands/init.mjs +18 -4
- package/zuzuu/commands/knowledge.mjs +1 -1
- package/zuzuu/commands/migrations/home.mjs +96 -0
- package/zuzuu/commands/migrations/index.mjs +48 -0
- package/zuzuu/commands/migrations/items.mjs +360 -0
- package/zuzuu/commands/migrations/proposals.mjs +100 -0
- package/zuzuu/commands/proposals.mjs +131 -0
- package/zuzuu/commands/review.mjs +13 -227
- package/zuzuu/commands/session.mjs +8 -2
- package/zuzuu/commands/sessions.mjs +159 -0
- package/zuzuu/commands/status.mjs +3 -3
- package/zuzuu/commands/trace.mjs +1 -1
- package/zuzuu/{capture-core.mjs → core/capture-core.mjs} +3 -3
- package/zuzuu/{store.mjs → core/store.mjs} +1 -1
- package/zuzuu/digest/compose.mjs +96 -0
- package/zuzuu/eval/score.mjs +14 -1
- package/zuzuu/faculties/actions/index.mjs +283 -0
- package/zuzuu/faculties/guardrails/index.mjs +320 -0
- package/zuzuu/faculties/instructions/index.mjs +288 -0
- package/zuzuu/faculties/knowledge/index.mjs +185 -0
- package/zuzuu/faculties/memory/index.mjs +124 -0
- package/zuzuu/faculty/envelope.mjs +290 -0
- package/zuzuu/faculty/generation/read.mjs +206 -0
- package/zuzuu/faculty/generation/write.mjs +207 -0
- package/zuzuu/faculty/items.mjs +81 -0
- package/zuzuu/faculty/module.mjs +74 -0
- package/zuzuu/faculty/pending.mjs +63 -0
- package/zuzuu/faculty/registry.mjs +204 -18
- package/zuzuu/faculty/render.mjs +59 -0
- package/zuzuu/faculty/trail.mjs +1 -1
- package/zuzuu/guardrails/engine.mjs +137 -0
- package/zuzuu/{scaffold.mjs → home/scaffold.mjs} +110 -39
- package/zuzuu/knowledge/items.mjs +56 -91
- package/zuzuu/live/install.mjs +1 -1
- package/zuzuu/live/live-store.mjs +2 -2
- package/zuzuu/live/reconcile.mjs +2 -2
- package/zuzuu/sessions/git.mjs +47 -0
- package/zuzuu/{session-git.mjs → sessions/session-git.mjs} +5 -43
- package/web-app/web-dist/assets/DiffTab-BuWonUNJ.js +0 -1
- package/web-app/web-dist/assets/MonacoFile-CL3DhFKG.js +0 -1
- package/web-app/web-dist/assets/angular-html-CmT26mqM.js +0 -1
- package/web-app/web-dist/assets/c-BvoqrSVH.js +0 -1
- package/web-app/web-dist/assets/cpp-BXsk94m0.js +0 -1
- package/web-app/web-dist/assets/css-Z8oOGxII.js +0 -1
- package/web-app/web-dist/assets/dist-ChcDQ_7s.js +0 -153
- package/web-app/web-dist/assets/glsl-KwyfU2aa.js +0 -1
- package/web-app/web-dist/assets/graphql-DSeOUAa2.js +0 -1
- package/web-app/web-dist/assets/haml-azVoxQRV.js +0 -1
- package/web-app/web-dist/assets/html-D_7P5S4m.js +0 -1
- package/web-app/web-dist/assets/index--5yy8RbA.js +0 -267
- package/web-app/web-dist/assets/index-BVG4hgk7.css +0 -2
- package/web-app/web-dist/assets/java-D4RbCvBe.js +0 -1
- package/web-app/web-dist/assets/javascript-Cb010CKM.js +0 -1
- package/web-app/web-dist/assets/json-DWgqV4D1.js +0 -1
- package/web-app/web-dist/assets/jsx-CZjSJa1f.js +0 -1
- package/web-app/web-dist/assets/lua-TGj_6NzO.js +0 -1
- package/web-app/web-dist/assets/r-fCpuAR7u.js +0 -1
- package/web-app/web-dist/assets/regexp-B4yxx-Ty.js +0 -1
- package/web-app/web-dist/assets/scss-QdjMO_xV.js +0 -1
- package/web-app/web-dist/assets/shellscript-BnlgeVVx.js +0 -1
- package/web-app/web-dist/assets/sql-DGnQv6iD.js +0 -1
- package/web-app/web-dist/assets/tsx-MJ0-9sYG.js +0 -1
- package/web-app/web-dist/assets/typescript-C17ZkDe8.js +0 -1
- package/web-app/web-dist/assets/xml-CA9lHFQV.js +0 -1
- package/web-app/web-dist/assets/yaml-CwRYMJka.js +0 -1
- package/zuzuu/actions/adapter.mjs +0 -130
- package/zuzuu/commands/migrate.mjs +0 -225
- package/zuzuu/digest.mjs +0 -149
- package/zuzuu/faculty/generation.mjs +0 -392
- package/zuzuu/guardrails/adapter.mjs +0 -134
- package/zuzuu/guardrails.mjs +0 -89
- package/zuzuu/instructions/adapter.mjs +0 -93
- package/zuzuu/knowledge/adapter.mjs +0 -99
- package/zuzuu/memory/adapter.mjs +0 -121
- package/zuzuu/miners/actions.mjs +0 -118
- package/zuzuu/miners/guardrails.mjs +0 -179
- package/zuzuu/miners/instructions.mjs +0 -157
- package/zuzuu/miners/knowledge.mjs +0 -25
- package/zuzuu/miners/memory.mjs +0 -27
- package/zuzuu/miners/registry.mjs +0 -31
- /package/web-app/web-dist/assets/{chunk-QTnfLwEv.js → rolldown-runtime-QTnfLwEv.js} +0 -0
- /package/zuzuu/{session.mjs → core/session.mjs} +0 -0
- /package/zuzuu/{inject.mjs → home/inject.mjs} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import{h as e}from"./editor.api2-
|
|
1
|
+
import{h as e}from"./editor.api2-C7skgoRB.js";var t={comments:{lineComment:`#`},brackets:[[`{`,`}`],[`[`,`]`],[`(`,`)`]],autoClosingPairs:[{open:`{`,close:`}`},{open:`[`,close:`]`},{open:`(`,close:`)`},{open:`"`,close:`"`},{open:`'`,close:`'`}],surroundingPairs:[{open:`{`,close:`}`},{open:`[`,close:`]`},{open:`(`,close:`)`},{open:`"`,close:`"`},{open:`'`,close:`'`}],folding:{offSide:!0},onEnterRules:[{beforeText:/:\s*$/,action:{indentAction:e.IndentAction.Indent}}]},n={tokenPostfix:`.yaml`,brackets:[{token:`delimiter.bracket`,open:`{`,close:`}`},{token:`delimiter.square`,open:`[`,close:`]`}],keywords:[`true`,`True`,`TRUE`,`false`,`False`,`FALSE`,`null`,`Null`,`Null`,`~`],numberInteger:/(?:0|[+-]?[0-9]+)/,numberFloat:/(?:0|[+-]?[0-9]+)(?:\.[0-9]+)?(?:e[-+][1-9][0-9]*)?/,numberOctal:/0o[0-7]+/,numberHex:/0x[0-9a-fA-F]+/,numberInfinity:/[+-]?\.(?:inf|Inf|INF)/,numberNaN:/\.(?:nan|Nan|NAN)/,numberDate:/\d{4}-\d\d-\d\d([Tt ]\d\d:\d\d:\d\d(\.\d+)?(( ?[+-]\d\d?(:\d\d)?)|Z)?)?/,escapes:/\\(?:[btnfr\\"']|[0-7][0-7]?|[0-3][0-7]{2})/,tokenizer:{root:[{include:`@whitespace`},{include:`@comment`},[/%[^ ]+.*$/,`meta.directive`],[/---/,`operators.directivesEnd`],[/\.{3}/,`operators.documentEnd`],[/[-?:](?= )/,`operators`],{include:`@anchor`},{include:`@tagHandle`},{include:`@flowCollections`},{include:`@blockStyle`},[/@numberInteger(?![ \t]*\S+)/,`number`],[/@numberFloat(?![ \t]*\S+)/,`number.float`],[/@numberOctal(?![ \t]*\S+)/,`number.octal`],[/@numberHex(?![ \t]*\S+)/,`number.hex`],[/@numberInfinity(?![ \t]*\S+)/,`number.infinity`],[/@numberNaN(?![ \t]*\S+)/,`number.nan`],[/@numberDate(?![ \t]*\S+)/,`number.date`],[/(".*?"|'.*?'|[^#'"]*?)([ \t]*)(:)( |$)/,[`type`,`white`,`operators`,`white`]],{include:`@flowScalars`},[/.+?(?=(\s+#|$))/,{cases:{"@keywords":`keyword`,"@default":`string`}}]],object:[{include:`@whitespace`},{include:`@comment`},[/\}/,`@brackets`,`@pop`],[/,/,`delimiter.comma`],[/:(?= )/,`operators`],[/(?:".*?"|'.*?'|[^,\{\[]+?)(?=: )/,`type`],{include:`@flowCollections`},{include:`@flowScalars`},{include:`@tagHandle`},{include:`@anchor`},{include:`@flowNumber`},[/[^\},]+/,{cases:{"@keywords":`keyword`,"@default":`string`}}]],array:[{include:`@whitespace`},{include:`@comment`},[/\]/,`@brackets`,`@pop`],[/,/,`delimiter.comma`],{include:`@flowCollections`},{include:`@flowScalars`},{include:`@tagHandle`},{include:`@anchor`},{include:`@flowNumber`},[/[^\],]+/,{cases:{"@keywords":`keyword`,"@default":`string`}}]],multiString:[[/^( +).+$/,`string`,`@multiStringContinued.$1`]],multiStringContinued:[[/^( *).+$/,{cases:{"$1==$S2":`string`,"@default":{token:`@rematch`,next:`@popall`}}}]],whitespace:[[/[ \t\r\n]+/,`white`]],comment:[[/#.*$/,`comment`]],flowCollections:[[/\[/,`@brackets`,`@array`],[/\{/,`@brackets`,`@object`]],flowScalars:[[/"([^"\\]|\\.)*$/,`string.invalid`],[/'([^'\\]|\\.)*$/,`string.invalid`],[/'[^']*'/,`string`],[/"/,`string`,`@doubleQuotedString`]],doubleQuotedString:[[/[^\\"]+/,`string`],[/@escapes/,`string.escape`],[/\\./,`string.escape.invalid`],[/"/,`string`,`@pop`]],blockStyle:[[/[>|][0-9]*[+-]?$/,`operators`,`@multiString`]],flowNumber:[[/@numberInteger(?=[ \t]*[,\]\}])/,`number`],[/@numberFloat(?=[ \t]*[,\]\}])/,`number.float`],[/@numberOctal(?=[ \t]*[,\]\}])/,`number.octal`],[/@numberHex(?=[ \t]*[,\]\}])/,`number.hex`],[/@numberInfinity(?=[ \t]*[,\]\}])/,`number.infinity`],[/@numberNaN(?=[ \t]*[,\]\}])/,`number.nan`],[/@numberDate(?=[ \t]*[,\]\}])/,`number.date`]],tagHandle:[[/\![^ ]*/,`tag`]],anchor:[[/[&*][^ ]+/,`namespace`]]}};export{t as conf,n as language};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{n as e}from"./rolldown-runtime-QTnfLwEv.js";var t=e({default:()=>n}),n=[Object.freeze(JSON.parse(`{"displayName":"YAML","fileTypes":["yaml","yml","rviz","reek","clang-format","yaml-tmlanguage","syntax","sublime-syntax"],"firstLineMatch":"^%YAML( ?1.\\\\d+)?","name":"yaml","patterns":[{"include":"#comment"},{"include":"#property"},{"include":"#directive"},{"match":"^---","name":"entity.other.document.begin.yaml"},{"match":"^\\\\.{3}","name":"entity.other.document.end.yaml"},{"include":"#node"}],"repository":{"block-collection":{"patterns":[{"include":"#block-sequence"},{"include":"#block-mapping"}]},"block-mapping":{"patterns":[{"include":"#block-pair"}]},"block-node":{"patterns":[{"include":"#prototype"},{"include":"#block-scalar"},{"include":"#block-collection"},{"include":"#flow-scalar-plain-out"},{"include":"#flow-node"}]},"block-pair":{"patterns":[{"begin":"\\\\?","beginCaptures":{"1":{"name":"punctuation.definition.key-value.begin.yaml"}},"end":"(?=\\\\?)|^ *(:)|(:)","endCaptures":{"1":{"name":"punctuation.separator.key-value.mapping.yaml"},"2":{"name":"invalid.illegal.expected-newline.yaml"}},"name":"meta.block-mapping.yaml","patterns":[{"include":"#block-node"}]},{"begin":"(?=(?:[^-\\\\]!\\"#%\\\\&'*,:>?@\\\\[\`{|}\\\\s]|[-:?]\\\\S)([^:\\\\s]|:\\\\S|\\\\s+(?![#\\\\s]))*\\\\s*:(\\\\s|$))","end":"(?=\\\\s*$|\\\\s+#|\\\\s*:(\\\\s|$))","patterns":[{"include":"#flow-scalar-plain-out-implicit-type"},{"begin":"[^-\\\\]!\\"#%\\\\&'*,:>?@\\\\[\`{|}\\\\s]|[-:?]\\\\S","beginCaptures":{"0":{"name":"entity.name.tag.yaml"}},"contentName":"entity.name.tag.yaml","end":"(?=\\\\s*$|\\\\s+#|\\\\s*:(\\\\s|$))","name":"string.unquoted.plain.out.yaml"}]},{"match":":(?=\\\\s|$)","name":"punctuation.separator.key-value.mapping.yaml"}]},"block-scalar":{"begin":"(?:(\\\\|)|(>))([1-9])?([-+])?(.*\\\\n?)","beginCaptures":{"1":{"name":"keyword.control.flow.block-scalar.literal.yaml"},"2":{"name":"keyword.control.flow.block-scalar.folded.yaml"},"3":{"name":"constant.numeric.indentation-indicator.yaml"},"4":{"name":"storage.modifier.chomping-indicator.yaml"},"5":{"patterns":[{"include":"#comment"},{"match":".+","name":"invalid.illegal.expected-comment-or-newline.yaml"}]}},"end":"^(?=\\\\S)|(?!\\\\G)","patterns":[{"begin":"^( +)(?! )","end":"^(?!\\\\1|\\\\s*$)","name":"string.unquoted.block.yaml"}]},"block-sequence":{"match":"(-)(?!\\\\S)","name":"punctuation.definition.block.sequence.item.yaml"},"comment":{"begin":"(?:^([\\\\t ]*)|[\\\\t ]+)(?=#\\\\p{print}*$)","beginCaptures":{"1":{"name":"punctuation.whitespace.comment.leading.yaml"}},"end":"(?!\\\\G)","patterns":[{"begin":"#","beginCaptures":{"0":{"name":"punctuation.definition.comment.yaml"}},"end":"\\\\n","name":"comment.line.number-sign.yaml"}]},"directive":{"begin":"^%","beginCaptures":{"0":{"name":"punctuation.definition.directive.begin.yaml"}},"end":"(?=$|[\\\\t ]+($|#))","name":"meta.directive.yaml","patterns":[{"captures":{"1":{"name":"keyword.other.directive.yaml.yaml"},"2":{"name":"constant.numeric.yaml-version.yaml"}},"match":"\\\\G(YAML)[\\\\t ]+(\\\\d+\\\\.\\\\d+)"},{"captures":{"1":{"name":"keyword.other.directive.tag.yaml"},"2":{"name":"storage.type.tag-handle.yaml"},"3":{"name":"support.type.tag-prefix.yaml"}},"match":"\\\\G(TAG)(?:[\\\\t ]+(!(?:[-0-9A-Za-z]*!)?)(?:[\\\\t ]+(!(?:%\\\\h{2}|[]!#$\\\\&-;=?-\\\\[_a-z~])*|(?![]!,\\\\[{}])(?:%\\\\h{2}|[]!#$\\\\&-;=?-\\\\[_a-z~])+))?)?"},{"captures":{"1":{"name":"support.other.directive.reserved.yaml"},"2":{"name":"string.unquoted.directive-name.yaml"},"3":{"name":"string.unquoted.directive-parameter.yaml"}},"match":"\\\\G(\\\\w+)(?:[\\\\t ]+(\\\\w+)(?:[\\\\t ]+(\\\\w+))?)?"},{"match":"\\\\S+","name":"invalid.illegal.unrecognized.yaml"}]},"flow-alias":{"captures":{"1":{"name":"keyword.control.flow.alias.yaml"},"2":{"name":"punctuation.definition.alias.yaml"},"3":{"name":"variable.other.alias.yaml"},"4":{"name":"invalid.illegal.character.anchor.yaml"}},"match":"((\\\\*))([^],/\\\\[{}\\\\s]+)([^],}\\\\s]\\\\S*)?"},"flow-collection":{"patterns":[{"include":"#flow-sequence"},{"include":"#flow-mapping"}]},"flow-mapping":{"begin":"\\\\{","beginCaptures":{"0":{"name":"punctuation.definition.mapping.begin.yaml"}},"end":"}","endCaptures":{"0":{"name":"punctuation.definition.mapping.end.yaml"}},"name":"meta.flow-mapping.yaml","patterns":[{"include":"#prototype"},{"match":",","name":"punctuation.separator.mapping.yaml"},{"include":"#flow-pair"}]},"flow-node":{"patterns":[{"include":"#prototype"},{"include":"#flow-alias"},{"include":"#flow-collection"},{"include":"#flow-scalar"}]},"flow-pair":{"patterns":[{"begin":"\\\\?","beginCaptures":{"0":{"name":"punctuation.definition.key-value.begin.yaml"}},"end":"(?=[],}])","name":"meta.flow-pair.explicit.yaml","patterns":[{"include":"#prototype"},{"include":"#flow-pair"},{"include":"#flow-node"},{"begin":":(?=\\\\s|$|[],\\\\[{}])","beginCaptures":{"0":{"name":"punctuation.separator.key-value.mapping.yaml"}},"end":"(?=[],}])","patterns":[{"include":"#flow-value"}]}]},{"begin":"(?=(?:[^-\\\\]!\\"#%\\\\&'*,:>?@\\\\[\`{|}\\\\s]|[-:?][^],\\\\[{}\\\\s])([^],:\\\\[{}\\\\s]|:[^],\\\\[{}\\\\s]|\\\\s+(?![#\\\\s]))*\\\\s*:(\\\\s|$))","end":"(?=\\\\s*$|\\\\s+#|\\\\s*:(\\\\s|$)|\\\\s*:[],\\\\[{}]|\\\\s*[],\\\\[{}])","name":"meta.flow-pair.key.yaml","patterns":[{"include":"#flow-scalar-plain-in-implicit-type"},{"begin":"[^-\\\\]!\\"#%\\\\&'*,:>?@\\\\[\`{|}\\\\s]|[-:?][^],\\\\[{}\\\\s]","beginCaptures":{"0":{"name":"entity.name.tag.yaml"}},"contentName":"entity.name.tag.yaml","end":"(?=\\\\s*$|\\\\s+#|\\\\s*:(\\\\s|$)|\\\\s*:[],\\\\[{}]|\\\\s*[],\\\\[{}])","name":"string.unquoted.plain.in.yaml"}]},{"include":"#flow-node"},{"begin":":(?=\\\\s|$|[],\\\\[{}])","captures":{"0":{"name":"punctuation.separator.key-value.mapping.yaml"}},"end":"(?=[],}])","name":"meta.flow-pair.yaml","patterns":[{"include":"#flow-value"}]}]},"flow-scalar":{"patterns":[{"include":"#flow-scalar-double-quoted"},{"include":"#flow-scalar-single-quoted"},{"include":"#flow-scalar-plain-in"}]},"flow-scalar-double-quoted":{"begin":"\\"","beginCaptures":{"0":{"name":"punctuation.definition.string.begin.yaml"}},"end":"\\"","endCaptures":{"0":{"name":"punctuation.definition.string.end.yaml"}},"name":"string.quoted.double.yaml","patterns":[{"match":"\\\\\\\\([ \\"/0LN\\\\\\\\_abefnprtv]|x\\\\d\\\\d|u\\\\d{4}|U\\\\d{8})","name":"constant.character.escape.yaml"},{"match":"\\\\\\\\\\\\n","name":"constant.character.escape.double-quoted.newline.yaml"}]},"flow-scalar-plain-in":{"patterns":[{"include":"#flow-scalar-plain-in-implicit-type"},{"begin":"[^-\\\\]!\\"#%\\\\&'*,:>?@\\\\[\`{|}\\\\s]|[-:?][^],\\\\[{}\\\\s]","end":"(?=\\\\s*$|\\\\s+#|\\\\s*:(\\\\s|$)|\\\\s*:[],\\\\[{}]|\\\\s*[],\\\\[{}])","name":"string.unquoted.plain.in.yaml"}]},"flow-scalar-plain-in-implicit-type":{"patterns":[{"captures":{"1":{"name":"constant.language.null.yaml"},"2":{"name":"constant.language.boolean.yaml"},"3":{"name":"constant.numeric.integer.yaml"},"4":{"name":"constant.numeric.float.yaml"},"5":{"name":"constant.other.timestamp.yaml"},"6":{"name":"constant.language.value.yaml"},"7":{"name":"constant.language.merge.yaml"}},"match":"(?:(null|Null|NULL|~)|([Yy]|yes|Yes|YES|[Nn]|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF)|([-+]?0b[01_]+|[-+]?0[0-7_]+|[-+]?(?:0|[1-9][0-9_]*)|[-+]?0x[_\\\\h]+|[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)|([-+]?(?:[0-9][0-9_]*)?\\\\.[.0-9]*(?:[Ee][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\\\.[0-9_]*|[-+]?\\\\.(?:inf|Inf|INF)|\\\\.(?:nan|NaN|NAN))|(\\\\d{4}-\\\\d{2}-\\\\d{2}|\\\\d{4}-\\\\d{1,2}-\\\\d{1,2}(?:[Tt]|[\\\\t ]+)\\\\d{1,2}:\\\\d{2}:\\\\d{2}(?:\\\\.\\\\d*)?(?:[\\\\t ]*Z|[-+]\\\\d{1,2}(?::\\\\d{1,2})?)?)|(=)|(<<))(?=\\\\s*$|\\\\s+#|\\\\s*:(\\\\s|$)|\\\\s*:[],\\\\[{}]|\\\\s*[],\\\\[{}])"}]},"flow-scalar-plain-out":{"patterns":[{"include":"#flow-scalar-plain-out-implicit-type"},{"begin":"[^-\\\\]!\\"#%\\\\&'*,:>?@\\\\[\`{|}\\\\s]|[-:?]\\\\S","end":"(?=\\\\s*$|\\\\s+#|\\\\s*:(\\\\s|$))","name":"string.unquoted.plain.out.yaml"}]},"flow-scalar-plain-out-implicit-type":{"patterns":[{"captures":{"1":{"name":"constant.language.null.yaml"},"2":{"name":"constant.language.boolean.yaml"},"3":{"name":"constant.numeric.integer.yaml"},"4":{"name":"constant.numeric.float.yaml"},"5":{"name":"constant.other.timestamp.yaml"},"6":{"name":"constant.language.value.yaml"},"7":{"name":"constant.language.merge.yaml"}},"match":"(?:(null|Null|NULL|~)|([Yy]|yes|Yes|YES|[Nn]|no|No|NO|true|True|TRUE|false|False|FALSE|on|On|ON|off|Off|OFF)|([-+]?0b[01_]+|[-+]?0[0-7_]+|[-+]?(?:0|[1-9][0-9_]*)|[-+]?0x[_\\\\h]+|[-+]?[1-9][0-9_]*(?::[0-5]?[0-9])+)|([-+]?(?:[0-9][0-9_]*)?\\\\.[.0-9]*(?:[Ee][-+][0-9]+)?|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\\\.[0-9_]*|[-+]?\\\\.(?:inf|Inf|INF)|\\\\.(?:nan|NaN|NAN))|(\\\\d{4}-\\\\d{2}-\\\\d{2}|\\\\d{4}-\\\\d{1,2}-\\\\d{1,2}(?:[Tt]|[\\\\t ]+)\\\\d{1,2}:\\\\d{2}:\\\\d{2}(?:\\\\.\\\\d*)?(?:[\\\\t ]*Z|[-+]\\\\d{1,2}(?::\\\\d{1,2})?)?)|(=)|(<<))(?=\\\\s*$|\\\\s+#|\\\\s*:(\\\\s|$))"}]},"flow-scalar-single-quoted":{"begin":"'","beginCaptures":{"0":{"name":"punctuation.definition.string.begin.yaml"}},"end":"'(?!')","endCaptures":{"0":{"name":"punctuation.definition.string.end.yaml"}},"name":"string.quoted.single.yaml","patterns":[{"match":"''","name":"constant.character.escape.single-quoted.yaml"}]},"flow-sequence":{"begin":"\\\\[","beginCaptures":{"0":{"name":"punctuation.definition.sequence.begin.yaml"}},"end":"]","endCaptures":{"0":{"name":"punctuation.definition.sequence.end.yaml"}},"name":"meta.flow-sequence.yaml","patterns":[{"include":"#prototype"},{"match":",","name":"punctuation.separator.sequence.yaml"},{"include":"#flow-pair"},{"include":"#flow-node"}]},"flow-value":{"patterns":[{"begin":"\\\\G(?![],}])","end":"(?=[],}])","name":"meta.flow-pair.value.yaml","patterns":[{"include":"#flow-node"}]}]},"node":{"patterns":[{"include":"#block-node"}]},"property":{"begin":"(?=[!\\\\&])","end":"(?!\\\\G)","name":"meta.property.yaml","patterns":[{"captures":{"1":{"name":"keyword.control.property.anchor.yaml"},"2":{"name":"punctuation.definition.anchor.yaml"},"3":{"name":"entity.name.type.anchor.yaml"},"4":{"name":"invalid.illegal.character.anchor.yaml"}},"match":"\\\\G((&))([^],/\\\\[{}\\\\s]+)(\\\\S+)?"},{"match":"\\\\G!(?:<(?:%\\\\h{2}|[]!#$\\\\&-;=?-\\\\[_a-z~])+>|(?:[-0-9A-Za-z]*!)?(?:%\\\\h{2}|[#$\\\\&-+\\\\--;=?-Z_a-z~])+|)(?=[\\\\t ]|$)","name":"storage.type.tag-handle.yaml"},{"match":"\\\\S+","name":"invalid.illegal.tag-handle.yaml"}]},"prototype":{"patterns":[{"include":"#comment"},{"include":"#property"}]}},"scopeName":"source.yaml","aliases":["yml"]}`))];export{t as n,n as t};
|
|
@@ -6,9 +6,12 @@
|
|
|
6
6
|
<meta name="color-scheme" content="dark" />
|
|
7
7
|
<title>zuzuu-web</title>
|
|
8
8
|
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' rx='7' fill='%230d1117'/%3E%3Ctext x='6' y='22' font-family='monospace' font-size='16' fill='%2358e6c0'%3E%E2%9D%AF_%3C/text%3E%3C/svg%3E" />
|
|
9
|
-
<script type="module" crossorigin src="/assets/index
|
|
10
|
-
<link rel="modulepreload" crossorigin href="/assets/
|
|
11
|
-
<link rel="
|
|
9
|
+
<script type="module" crossorigin src="/assets/index-De6DWTZM.js"></script>
|
|
10
|
+
<link rel="modulepreload" crossorigin href="/assets/rolldown-runtime-QTnfLwEv.js">
|
|
11
|
+
<link rel="modulepreload" crossorigin href="/assets/xterm-addons-psDEiUMC.js">
|
|
12
|
+
<link rel="modulepreload" crossorigin href="/assets/xterm-B1ffpRuj.js">
|
|
13
|
+
<link rel="modulepreload" crossorigin href="/assets/react-vendor-CCIEwYL0.js">
|
|
14
|
+
<link rel="stylesheet" crossorigin href="/assets/index-B27_WOhS.css">
|
|
12
15
|
</head>
|
|
13
16
|
<body>
|
|
14
17
|
<div id="root"></div>
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
// zuzuu/actions/convert.mjs
|
|
2
2
|
// Pure manifest → tool-definition converters (the _labs tool-definition pattern).
|
|
3
|
-
//
|
|
4
|
-
//
|
|
3
|
+
// Manifests are ACTION.md envelopes (W24): name = the envelope id, description =
|
|
4
|
+
// the prompt snippet (body first line) or title. The envelope carries no
|
|
5
|
+
// inputs/outputs JSON-schemas (clean break) — tool definitions expose the
|
|
6
|
+
// permissive object schema; the runner validates the same way.
|
|
5
7
|
//
|
|
6
8
|
// STATUS (2026-06-11): used today only by `zuzuu act schema <slug> [--mcp|--openai|
|
|
7
9
|
// --anthropic]` for inspection. There is NO runtime MCP/native-tool *serving* yet —
|
|
@@ -9,19 +11,18 @@
|
|
|
9
11
|
// agent in the digest. Live "Actions over MCP" serving is DEFERRED (DESIGN §6 /
|
|
10
12
|
// Stage 2 / OpenCode bundle); these converters are the seam for it, not the thing.
|
|
11
13
|
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
+
const name = (m) => m.id ?? m.slug;
|
|
15
|
+
const desc = (m) => m.promptSnippet ?? m.title ?? name(m);
|
|
16
|
+
const inputs = () => ({ type: 'object' });
|
|
14
17
|
|
|
15
18
|
export function toMcpTool(m) {
|
|
16
|
-
|
|
17
|
-
if (m.outputs) t.outputSchema = m.outputs;
|
|
18
|
-
return t;
|
|
19
|
+
return { name: name(m), description: desc(m), inputSchema: inputs() };
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export function toOpenAITool(m) {
|
|
22
|
-
return { type: 'function', function: { name: m
|
|
23
|
+
return { type: 'function', function: { name: name(m), description: desc(m), parameters: inputs() } };
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
export function toAnthropicTool(m) {
|
|
26
|
-
return { name: m
|
|
27
|
+
return { name: name(m), description: desc(m), input_schema: inputs() };
|
|
27
28
|
}
|
|
@@ -8,7 +8,7 @@ import { spawnSync } from 'node:child_process';
|
|
|
8
8
|
import { fileURLToPath } from 'node:url';
|
|
9
9
|
import { join, dirname } from 'node:path';
|
|
10
10
|
import { existsSync } from 'node:fs';
|
|
11
|
-
import { loadManifest, actionsDir } from './manifest.mjs';
|
|
11
|
+
import { loadManifest, execOf, actionsDir } from './manifest.mjs';
|
|
12
12
|
import { MARKER } from './marker.mjs';
|
|
13
13
|
|
|
14
14
|
const MAX_DEPTH = 8;
|
|
@@ -51,16 +51,21 @@ export function runAction(agentDir, slug, callerArgs = {}, { timeoutMs = ACTION_
|
|
|
51
51
|
if (depth >= MAX_DEPTH) return { ok: false, error: 'depth_exceeded', detail: `depth ${depth} ≥ ${MAX_DEPTH}`, logs: '' };
|
|
52
52
|
|
|
53
53
|
const manifest = loadManifest(agentDir, slug);
|
|
54
|
-
if (!manifest) return { ok: false, error: 'not_found', detail: `no action '${slug}' (missing
|
|
54
|
+
if (!manifest) return { ok: false, error: 'not_found', detail: `no action '${slug}' (missing ACTION.md)`, logs: '' };
|
|
55
55
|
|
|
56
|
-
const
|
|
57
|
-
if (!
|
|
56
|
+
const exec = execOf(manifest);
|
|
57
|
+
if (!exec) return { ok: false, error: 'not_runnable', detail: `'${slug}' has an unsafe exec entry`, logs: '' };
|
|
58
|
+
const runPath = join(actionsDir(agentDir), slug, exec);
|
|
59
|
+
if (!existsSync(runPath)) return { ok: false, error: 'not_runnable', detail: `'${slug}' has no ${exec}`, logs: '' };
|
|
58
60
|
|
|
61
|
+
// The envelope carries no inputs/outputs JSON-schemas (clean break, W24) —
|
|
62
|
+
// the runner validates against the permissive object schema; payload.args
|
|
63
|
+
// are the default args (caller args win).
|
|
59
64
|
const payload = JSON.stringify({
|
|
60
65
|
runPath,
|
|
61
|
-
inputs:
|
|
62
|
-
outputs:
|
|
63
|
-
default_args: manifest.
|
|
66
|
+
inputs: { type: 'object' },
|
|
67
|
+
outputs: { type: 'object' },
|
|
68
|
+
default_args: manifest.payload?.args ?? {},
|
|
64
69
|
args: callerArgs ?? {},
|
|
65
70
|
});
|
|
66
71
|
|
package/zuzuu/actions/inbox.mjs
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { join } from 'node:path';
|
|
8
8
|
import { existsSync, readFileSync, renameSync, mkdirSync, rmSync } from 'node:fs';
|
|
9
9
|
import { actionsDir, inboxDir, listActions, isSafeSlug } from './manifest.mjs';
|
|
10
|
+
import { parseEnvelope } from '../faculty/envelope.mjs';
|
|
10
11
|
|
|
11
12
|
/** Archive dir for rejected action proposals: .zuzuu/actions/proposals/archive/. */
|
|
12
13
|
const archiveBaseDir = (agentDir) => join(actionsDir(agentDir), 'proposals', 'archive');
|
|
@@ -26,12 +27,11 @@ export function activateAction(agentDir, slug) {
|
|
|
26
27
|
const to = join(actionsDir(agentDir), slug);
|
|
27
28
|
if (!existsSync(from)) return { ok: false, error: `no proposed action '${slug}'` };
|
|
28
29
|
if (existsSync(to)) return { ok: false, error: `an active action '${slug}' already exists — reject or rename first` };
|
|
29
|
-
const manPath = join(from, '
|
|
30
|
+
const manPath = join(from, 'ACTION.md');
|
|
30
31
|
if (existsSync(manPath)) {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (man.slug && man.slug !== slug) return { ok: false, error: `manifest slug '${man.slug}' ≠ dir '${slug}'` };
|
|
32
|
+
const { ok, item } = parseEnvelope(readFileSync(manPath, 'utf8'));
|
|
33
|
+
if (!ok) return { ok: false, error: 'ACTION.md is not a valid envelope' };
|
|
34
|
+
if (item.id && item.id !== slug) return { ok: false, error: `ACTION.md id '${item.id}' ≠ dir '${slug}'` };
|
|
35
35
|
}
|
|
36
36
|
renameSync(from, to);
|
|
37
37
|
return { ok: true };
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
// zuzuu/actions/manifest.mjs
|
|
2
|
-
// Reads the Actions faculty off disk: one action per dir under .zuzuu/actions
|
|
3
|
-
//
|
|
2
|
+
// Reads the Actions faculty off disk: one action per dir under .zuzuu/actions/,
|
|
3
|
+
// described by an ACTION.md envelope (the Faculty Standard, W24 — SKILL.md-shaped:
|
|
4
|
+
// frontmatter + instruction prose body; scripts stay siblings):
|
|
5
|
+
//
|
|
6
|
+
// actions/<slug>/ACTION.md kind: script|runbook; payload.exec (script entry,
|
|
7
|
+
// default run.mjs) + payload.args (default args)
|
|
8
|
+
// actions/<slug>/run.mjs the script (kind: script)
|
|
9
|
+
//
|
|
4
10
|
// Pure-ish: filesystem reads only, no logging, no process control.
|
|
5
11
|
|
|
6
12
|
import { join } from 'node:path';
|
|
7
13
|
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
14
|
+
import { parseEnvelope, deriveTitle } from '../faculty/envelope.mjs';
|
|
8
15
|
|
|
9
16
|
// Action slugs: letters/digits start, then letters/digits/-/_. No dots or slashes
|
|
10
17
|
// → cannot escape .zuzuu/actions/ via path traversal.
|
|
@@ -13,60 +20,71 @@ export function isSafeSlug(slug) {
|
|
|
13
20
|
return typeof slug === 'string' && SAFE_SLUG.test(slug);
|
|
14
21
|
}
|
|
15
22
|
|
|
23
|
+
// payload.exec must be a plain sibling filename — never a path.
|
|
24
|
+
const SAFE_EXEC = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
|
|
25
|
+
|
|
16
26
|
export const actionsDir = (agentDir) => join(agentDir, 'actions');
|
|
17
27
|
export const inboxDir = (agentDir) => join(actionsDir(agentDir), 'inbox');
|
|
18
28
|
const actionDir = (agentDir, slug) => join(actionsDir(agentDir), slug);
|
|
19
29
|
|
|
20
|
-
/**
|
|
30
|
+
/** First non-empty body line — the one-liner the digest shows. */
|
|
31
|
+
function snippetOf(item) {
|
|
32
|
+
const first = String(item.body ?? '').split('\n').map((l) => l.trim()).find(Boolean);
|
|
33
|
+
return first || item.title || item.id;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Read and parse ACTION.md for a slug → envelope manifest, or null if
|
|
38
|
+
* absent/unparseable. Shape: { id, kind, title, status, created_at,
|
|
39
|
+
* payload: {exec?, args?}, body } + promptSnippet derived from the body.
|
|
40
|
+
*/
|
|
21
41
|
export function loadManifest(agentDir, slug) {
|
|
22
|
-
const path = join(actionDir(agentDir, slug), '
|
|
42
|
+
const path = join(actionDir(agentDir, slug), 'ACTION.md');
|
|
23
43
|
try {
|
|
24
|
-
|
|
44
|
+
const { ok, item } = parseEnvelope(readFileSync(path, 'utf8'));
|
|
45
|
+
if (!ok || item.faculty !== 'actions') return null;
|
|
46
|
+
item.title = item.title ?? deriveTitle(item.body, item.id);
|
|
47
|
+
item.promptSnippet = snippetOf(item);
|
|
48
|
+
return item;
|
|
25
49
|
} catch {
|
|
26
50
|
return null;
|
|
27
51
|
}
|
|
28
52
|
}
|
|
29
53
|
|
|
30
|
-
/**
|
|
31
|
-
function
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
if (m) {
|
|
35
|
-
for (const line of m[1].split('\n')) {
|
|
36
|
-
const kv = line.match(/^(\w+):\s*(.*)$/);
|
|
37
|
-
if (kv) fm[kv[1]] = kv[2].trim();
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
return fm;
|
|
54
|
+
/** The script entry file for a manifest (validated sibling name), or null. */
|
|
55
|
+
export function execOf(manifest) {
|
|
56
|
+
const exec = manifest?.payload?.exec ?? 'run.mjs';
|
|
57
|
+
return SAFE_EXEC.test(exec) ? exec : null;
|
|
41
58
|
}
|
|
42
59
|
|
|
43
60
|
/**
|
|
44
61
|
* List actions in a base dir as {slug, kind, title, promptSnippet}.
|
|
45
|
-
*
|
|
46
|
-
*
|
|
62
|
+
* An action is a dir carrying ACTION.md; kind comes from its envelope
|
|
63
|
+
* (`script` | `runbook`). Other entries are skipped (READMEs, stray files,
|
|
64
|
+
* unparseable envelopes — the latter surface via `zuzuu faculty items actions`).
|
|
65
|
+
* Reads directly from each entry dir (works for any baseDir, e.g. the inbox).
|
|
47
66
|
*/
|
|
48
67
|
export function listActions(baseDir) {
|
|
49
68
|
if (!existsSync(baseDir)) return [];
|
|
50
69
|
const out = [];
|
|
51
|
-
for (const name of readdirSync(baseDir)) {
|
|
70
|
+
for (const name of readdirSync(baseDir).sort()) {
|
|
52
71
|
const d = join(baseDir, name);
|
|
53
72
|
let isDir = false;
|
|
54
73
|
try { isDir = statSync(d).isDirectory(); } catch { /* skip */ }
|
|
55
74
|
if (!isDir) continue; // ignores README.md and any stray files
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
75
|
+
const actionMd = join(d, 'ACTION.md');
|
|
76
|
+
if (!existsSync(actionMd)) continue;
|
|
77
|
+
try {
|
|
78
|
+
const { ok, item } = parseEnvelope(readFileSync(actionMd, 'utf8'));
|
|
79
|
+
if (!ok) continue;
|
|
80
|
+
const kind = item.kind === 'script' ? 'script' : 'runbook';
|
|
81
|
+
out.push({ slug: name, kind, title: item.title ?? name, promptSnippet: snippetOf(item) });
|
|
82
|
+
} catch { /* unreadable → skip */ }
|
|
65
83
|
}
|
|
66
84
|
return out;
|
|
67
85
|
}
|
|
68
86
|
|
|
69
|
-
/** Active actions under .zuzuu/actions/ (
|
|
87
|
+
/** Active actions under .zuzuu/actions/ (inbox/proposals subdirs excluded). */
|
|
70
88
|
export function allActions(agentDir) {
|
|
71
|
-
return listActions(actionsDir(agentDir)).filter((a) => a.slug !== 'inbox');
|
|
89
|
+
return listActions(actionsDir(agentDir)).filter((a) => a.slug !== 'inbox' && a.slug !== 'proposals' && a.slug !== '_rolledback');
|
|
72
90
|
}
|
package/zuzuu/actions/schema.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
// zuzuu/actions/schema.mjs
|
|
2
2
|
// A hand-rolled JSON-Schema *subset* validator — zero-dep (no Ajv), matching the
|
|
3
3
|
// project's node-builtins-only policy. Supports: object (properties, required),
|
|
4
|
-
// array (items), string/number/integer/boolean scalars, enum, and basic
|
|
5
|
-
// range constraints. Returns an array of error strings ([] = valid). No
|
|
6
|
-
// values are expected to already carry real JSON types.
|
|
4
|
+
// array (items), string/number/integer/boolean scalars, enum, pattern, and basic
|
|
5
|
+
// length/range constraints. Returns an array of error strings ([] = valid). No
|
|
6
|
+
// coercion: values are expected to already carry real JSON types. Shared by the
|
|
7
|
+
// actions runner AND the faculty envelope (payload validation — W24).
|
|
7
8
|
|
|
8
9
|
function isPlainObject(v) {
|
|
9
10
|
return v !== null && typeof v === 'object' && !Array.isArray(v);
|
|
@@ -41,6 +42,11 @@ export function validate(schema, value, path = '$') {
|
|
|
41
42
|
if (typeof value === 'string') {
|
|
42
43
|
if (schema.minLength != null && value.length < schema.minLength) errors.push(`${path}: shorter than minLength ${schema.minLength}`);
|
|
43
44
|
if (schema.maxLength != null && value.length > schema.maxLength) errors.push(`${path}: longer than maxLength ${schema.maxLength}`);
|
|
45
|
+
if (schema.pattern != null) {
|
|
46
|
+
try {
|
|
47
|
+
if (!new RegExp(schema.pattern).test(value)) errors.push(`${path}: does not match pattern ${schema.pattern}`);
|
|
48
|
+
} catch { /* an unparseable authored pattern never blocks (fail-open) */ }
|
|
49
|
+
}
|
|
44
50
|
}
|
|
45
51
|
if (typeof value === 'number') {
|
|
46
52
|
if (schema.minimum != null && value < schema.minimum) errors.push(`${path}: below minimum ${schema.minimum}`);
|
package/zuzuu/actions/trail.mjs
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
import { join } from 'node:path';
|
|
8
8
|
import { mkdirSync, appendFileSync } from 'node:fs';
|
|
9
|
-
import { liveDir } from '../store.mjs';
|
|
9
|
+
import { liveDir } from '../core/store.mjs';
|
|
10
10
|
|
|
11
11
|
/** Append a fail-soft outcome record. Never throws. */
|
|
12
12
|
export function recordOutcome(agentDir, { slug, ok, error } = {}) {
|
|
@@ -1,23 +1,33 @@
|
|
|
1
1
|
// zuzuu/commands/act-author.mjs
|
|
2
2
|
// `zuzuu act new <slug>` — scaffold a script action (idempotent, no-clobber).
|
|
3
3
|
// `zuzuu act schema <slug> [--mcp|--openai|--anthropic]` — convert the manifest.
|
|
4
|
+
// Actions are described by ACTION.md (the Faculty Standard envelope, W24).
|
|
4
5
|
|
|
5
6
|
import { mkdirSync, existsSync, writeFileSync } from 'node:fs';
|
|
6
7
|
import { join } from 'node:path';
|
|
7
8
|
import { actionsDir, inboxDir, loadManifest, isSafeSlug } from '../actions/manifest.mjs';
|
|
8
9
|
import { toMcpTool, toOpenAITool, toAnthropicTool } from '../actions/convert.mjs';
|
|
10
|
+
import { serializeEnvelope } from '../faculty/envelope.mjs';
|
|
9
11
|
|
|
10
|
-
function
|
|
11
|
-
return
|
|
12
|
-
slug,
|
|
12
|
+
function actionMdStub(slug) {
|
|
13
|
+
return serializeEnvelope({
|
|
14
|
+
id: slug,
|
|
15
|
+
faculty: 'actions',
|
|
16
|
+
kind: 'script',
|
|
13
17
|
title: slug,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
status: 'active',
|
|
19
|
+
created_at: new Date().toISOString().replace(/\.\d+Z$/, 'Z'),
|
|
20
|
+
payload: { exec: 'run.mjs' },
|
|
21
|
+
body: [
|
|
22
|
+
`What ${slug} does — the first line is the one-liner the digest shows.`,
|
|
23
|
+
'',
|
|
24
|
+
'## Usage',
|
|
25
|
+
'',
|
|
26
|
+
`\`zuzuu act ${slug} --args '{"key":"value"}'\``,
|
|
27
|
+
'',
|
|
28
|
+
'Describe inputs, outputs, and when to reach for this action here.',
|
|
29
|
+
].join('\n'),
|
|
30
|
+
});
|
|
21
31
|
}
|
|
22
32
|
|
|
23
33
|
const RUN_TEMPLATE = `// run.mjs — implement the action. Export async main(args) → a JSON object.
|
|
@@ -26,7 +36,7 @@ const RUN_TEMPLATE = `// run.mjs — implement the action. Export async main(arg
|
|
|
26
36
|
// export function prepareArguments(args) { return args; }
|
|
27
37
|
|
|
28
38
|
export async function main(args) {
|
|
29
|
-
// args
|
|
39
|
+
// args = ACTION.md payload.args defaults merged with caller --args (caller wins).
|
|
30
40
|
return { ok: true };
|
|
31
41
|
}
|
|
32
42
|
`;
|
|
@@ -41,7 +51,7 @@ function scaffoldInto(baseDir, slug) {
|
|
|
41
51
|
const p = join(dir, name);
|
|
42
52
|
if (!existsSync(p)) { writeFileSync(p, body); created.push(name); }
|
|
43
53
|
};
|
|
44
|
-
write('
|
|
54
|
+
write('ACTION.md', actionMdStub(slug));
|
|
45
55
|
write('run.mjs', RUN_TEMPLATE);
|
|
46
56
|
return { created };
|
|
47
57
|
}
|
|
@@ -66,7 +76,7 @@ export function newAction(agentDir, slug) {
|
|
|
66
76
|
export function schema(agentDir, slug, args = {}) {
|
|
67
77
|
if (!slug) { console.error('usage: zuzuu act schema <slug> [--mcp|--openai|--anthropic]'); process.exit(1); }
|
|
68
78
|
const man = loadManifest(agentDir, slug);
|
|
69
|
-
if (!man) { console.error(`no action '${slug}' (missing
|
|
79
|
+
if (!man) { console.error(`no action '${slug}' (missing ACTION.md)`); process.exit(1); }
|
|
70
80
|
const def = args.openai ? toOpenAITool(man) : args.anthropic ? toAnthropicTool(man) : toMcpTool(man);
|
|
71
81
|
console.log(JSON.stringify(def, null, 2));
|
|
72
82
|
}
|
package/zuzuu/commands/act.mjs
CHANGED
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
|
|
10
10
|
import { readFileSync, existsSync } from 'node:fs';
|
|
11
11
|
import { join } from 'node:path';
|
|
12
|
-
import { paths } from '../store.mjs';
|
|
13
|
-
import { allActions,
|
|
12
|
+
import { paths } from '../core/store.mjs';
|
|
13
|
+
import { allActions, actionsDir, isSafeSlug } from '../actions/manifest.mjs';
|
|
14
14
|
import { runAction } from '../actions/dispatch.mjs';
|
|
15
15
|
import { MARKER } from '../actions/marker.mjs';
|
|
16
16
|
import { newAction, schema as schemaCmd, proposeAction } from './act-author.mjs';
|
|
@@ -35,10 +35,8 @@ function list(agentDir) {
|
|
|
35
35
|
|
|
36
36
|
function show(agentDir, slug) {
|
|
37
37
|
if (!slug) { console.error('usage: zuzuu act show <slug>'); process.exit(1); }
|
|
38
|
-
const
|
|
39
|
-
if (
|
|
40
|
-
const skill = join(actionsDir(agentDir), slug, 'SKILL.md');
|
|
41
|
-
if (existsSync(skill)) return process.stdout.write(readFileSync(skill, 'utf8'));
|
|
38
|
+
const actionMd = join(actionsDir(agentDir), slug, 'ACTION.md');
|
|
39
|
+
if (existsSync(actionMd)) return process.stdout.write(readFileSync(actionMd, 'utf8'));
|
|
42
40
|
console.error(`no action '${slug}'`);
|
|
43
41
|
process.exit(1);
|
|
44
42
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
// `zuzuu capture` — post-hoc: parse a host transcript into a git-native trace + record.
|
|
2
2
|
|
|
3
3
|
import { ADAPTERS, byName, detected } from '../capture/adapters/registry.mjs';
|
|
4
|
-
import { captureTrace } from '../capture-core.mjs';
|
|
5
|
-
import { paths } from '../store.mjs';
|
|
4
|
+
import { captureTrace } from '../core/capture-core.mjs';
|
|
5
|
+
import { paths } from '../core/store.mjs';
|
|
6
6
|
|
|
7
7
|
function chooseRef(adapter, args) {
|
|
8
8
|
if (args.file) return args.file;
|
package/zuzuu/commands/code.mjs
CHANGED
|
@@ -11,8 +11,8 @@ import { resolve } from 'node:path';
|
|
|
11
11
|
import { spawnSync } from 'node:child_process';
|
|
12
12
|
import { init } from './init.mjs';
|
|
13
13
|
import { enable } from './enable.mjs';
|
|
14
|
-
import { repoRoot } from '../store.mjs';
|
|
15
|
-
import { homeExists } from '../scaffold.mjs';
|
|
14
|
+
import { repoRoot } from '../core/store.mjs';
|
|
15
|
+
import { homeExists } from '../home/scaffold.mjs';
|
|
16
16
|
|
|
17
17
|
// Run a command inside `dir` without permanently changing the process cwd —
|
|
18
18
|
// init/enable resolve their target from process.cwd(), so we chdir around them.
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
// start would inject. Lets a human (or a hookless host) see exactly what the
|
|
4
4
|
// agent sees.
|
|
5
5
|
|
|
6
|
-
import { paths } from '../store.mjs';
|
|
7
|
-
import { computeDigest } from '../digest.mjs';
|
|
6
|
+
import { paths } from '../core/store.mjs';
|
|
7
|
+
import { computeDigest } from '../digest/compose.mjs';
|
|
8
8
|
|
|
9
9
|
/** Pure: the digest payload — the zuzuu-web /digest source (the daemon also reads .zuzuu/.live/digest.md directly). */
|
|
10
10
|
export function digestData(agentDir, opts = {}) {
|
|
@@ -2,20 +2,15 @@
|
|
|
2
2
|
//
|
|
3
3
|
// Default: knowledge only (back-compat, via distillSessions). With
|
|
4
4
|
// `--all-faculties`: mine each transcript ONCE into a superset, then run every
|
|
5
|
-
//
|
|
6
|
-
//
|
|
5
|
+
// faculty module's miner (the Faculty Module registry) over the shared
|
|
6
|
+
// sessions array. Miner hooks are miner-class: fail-soft + time-boxed — a
|
|
7
|
+
// broken or hung miner degrades to 0 proposals, never sinks the others.
|
|
7
8
|
|
|
8
|
-
import { paths } from '../store.mjs';
|
|
9
|
+
import { paths } from '../core/store.mjs';
|
|
9
10
|
import { distillSessions, transcriptsFor, mineHostSession } from '../knowledge/distill.mjs';
|
|
10
|
-
import * as registry from '../
|
|
11
|
-
// Import miner modules so they self-register.
|
|
12
|
-
import '../miners/knowledge.mjs';
|
|
13
|
-
import '../miners/actions.mjs';
|
|
14
|
-
import '../miners/guardrails.mjs';
|
|
15
|
-
import '../miners/instructions.mjs';
|
|
16
|
-
import '../miners/memory.mjs';
|
|
11
|
+
import * as registry from '../faculty/registry.mjs';
|
|
17
12
|
|
|
18
|
-
export function distill(args) {
|
|
13
|
+
export async function distill(args) {
|
|
19
14
|
const scope = args.all ? 'all' : args.session ? null : 'last';
|
|
20
15
|
const pairs = transcriptsFor({ scope: scope ?? 'all', session: args.session || null, cwd: process.cwd() });
|
|
21
16
|
if (!pairs.length) {
|
|
@@ -27,13 +22,17 @@ export function distill(args) {
|
|
|
27
22
|
if (args['all-faculties'] || args.allFaculties) {
|
|
28
23
|
const sessions = pairs.map(mineHostSession).filter(Boolean);
|
|
29
24
|
const hosts = new Set(sessions.map((s) => s.host));
|
|
30
|
-
|
|
25
|
+
const miners = registry.miners();
|
|
26
|
+
console.log(`distilled ${sessions.length} session(s) across ${hosts.size} host(s) and ${miners.length} faculty miner(s):`);
|
|
31
27
|
let total = 0;
|
|
32
|
-
for (const miner of
|
|
33
|
-
const
|
|
34
|
-
const
|
|
28
|
+
for (const miner of miners) {
|
|
29
|
+
const entry = { id: miner.faculty, module: miner };
|
|
30
|
+
const agg = await registry.invokeTimeboxed(entry, 'aggregate', [sessions, {}]);
|
|
31
|
+
const prop = agg.ok ? await registry.invokeTimeboxed(entry, 'propose', [agentDir, agg.value]) : agg;
|
|
32
|
+
const n = prop.ok && Number.isFinite(prop.value) ? prop.value : 0;
|
|
35
33
|
total += n;
|
|
36
|
-
|
|
34
|
+
const note = prop.ok ? '' : ' (miner degraded — see zuzuu doctor)';
|
|
35
|
+
console.log(` ${miner.faculty.padEnd(12)} ${n} proposal(s)${note}`);
|
|
37
36
|
}
|
|
38
37
|
if (total) console.log('next: zuzuu review');
|
|
39
38
|
return;
|
|
@@ -3,16 +3,17 @@
|
|
|
3
3
|
|
|
4
4
|
import { mkdirSync, accessSync, constants } from 'node:fs';
|
|
5
5
|
import { detected } from '../capture/adapters/registry.mjs';
|
|
6
|
-
import { paths, gitInfo } from '../store.mjs';
|
|
6
|
+
import { paths, gitInfo } from '../core/store.mjs';
|
|
7
7
|
import { listLive } from '../live/live-store.mjs';
|
|
8
8
|
import { reconcile } from '../live/reconcile.mjs';
|
|
9
|
-
import { planScaffold, homeExists } from '../scaffold.mjs';
|
|
9
|
+
import { planScaffold, homeExists } from '../home/scaffold.mjs';
|
|
10
|
+
import { facultiesOf, hookFailures } from '../faculty/registry.mjs';
|
|
10
11
|
import { loadRegistry } from '../knowledge/registry.mjs';
|
|
11
12
|
import { allItems } from '../knowledge/items.mjs';
|
|
12
13
|
import { listProposals } from '../knowledge/proposals.mjs';
|
|
13
14
|
import { detectEmbedder } from '../knowledge/embed.mjs';
|
|
14
|
-
import { activeGeneration, readGeneration, snapshotFaculties } from '../faculty/generation.mjs';
|
|
15
|
-
import { sessionStatus } from '../session-git.mjs';
|
|
15
|
+
import { activeGeneration, readGeneration, snapshotFaculties } from '../faculty/generation/read.mjs';
|
|
16
|
+
import { sessionStatus } from '../sessions/session-git.mjs';
|
|
16
17
|
import { leftoverLine } from './session.mjs';
|
|
17
18
|
|
|
18
19
|
/**
|
|
@@ -40,8 +41,8 @@ export function detectDrift(agentDir) {
|
|
|
40
41
|
const pinned = lockfile.faculties || {};
|
|
41
42
|
const drifted = [];
|
|
42
43
|
|
|
43
|
-
// Compare per-faculty item arrays
|
|
44
|
-
for (const faculty of ['knowledge', 'actions', 'memory']) {
|
|
44
|
+
// Compare per-faculty item arrays — all five are envelope-item lists (W24).
|
|
45
|
+
for (const faculty of ['knowledge', 'actions', 'memory', 'guardrails', 'instructions']) {
|
|
45
46
|
const pinnedItems = (pinned[faculty]?.items ?? []);
|
|
46
47
|
const currentItems = (current[faculty]?.items ?? []);
|
|
47
48
|
|
|
@@ -65,19 +66,6 @@ export function detectDrift(agentDir) {
|
|
|
65
66
|
}
|
|
66
67
|
}
|
|
67
68
|
|
|
68
|
-
// Compare single-file faculties (guardrails.rulesHash, instructions.projectHash)
|
|
69
|
-
const singleFile = [
|
|
70
|
-
{ faculty: 'guardrails', field: 'rulesHash' },
|
|
71
|
-
{ faculty: 'instructions', field: 'projectHash' },
|
|
72
|
-
];
|
|
73
|
-
for (const { faculty, field } of singleFile) {
|
|
74
|
-
const pinnedHash = pinned[faculty]?.[field] ?? null;
|
|
75
|
-
const currentHash = current[faculty]?.[field] ?? null;
|
|
76
|
-
if (pinnedHash !== currentHash) {
|
|
77
|
-
drifted.push({ id: field, faculty, reason: 'hash_changed', pinned: pinnedHash, current: currentHash });
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
69
|
// Compare knowledge.registryHash
|
|
82
70
|
const pinnedReg = pinned.knowledge?.registryHash ?? null;
|
|
83
71
|
const currentReg = current.knowledge?.registryHash ?? null;
|
|
@@ -91,6 +79,32 @@ export function detectDrift(agentDir) {
|
|
|
91
79
|
}
|
|
92
80
|
}
|
|
93
81
|
|
|
82
|
+
/**
|
|
83
|
+
* Pure-ish: faculty-module health for doctor — broken manifests + recorded
|
|
84
|
+
* hook failures become warnings (the module degraded to items-only);
|
|
85
|
+
* declarative faculties get an informational note. Fail-open: any error
|
|
86
|
+
* returns empty lists rather than throwing into doctor.
|
|
87
|
+
* @returns {{warnings: string[], notes: string[]}}
|
|
88
|
+
*/
|
|
89
|
+
export function facultyModuleHealth(agentDir) {
|
|
90
|
+
try {
|
|
91
|
+
const warnings = [];
|
|
92
|
+
const notes = [];
|
|
93
|
+
const entries = facultiesOf(agentDir);
|
|
94
|
+
for (const e of entries.filter((x) => x.manifestError)) {
|
|
95
|
+
warnings.push(`faculty '${e.id}' faculty.json unreadable (${e.manifestError}) — module degraded to items-only`);
|
|
96
|
+
}
|
|
97
|
+
const declarative = entries.filter((x) => x.declarative && !x.manifestError);
|
|
98
|
+
if (declarative.length) notes.push(`declarative faculties: ${declarative.map((x) => x.id).join(', ')}`);
|
|
99
|
+
for (const f of hookFailures()) {
|
|
100
|
+
warnings.push(`faculty '${f.faculty}' hook ${f.hook} failed (${f.error}) — degraded, items-only`);
|
|
101
|
+
}
|
|
102
|
+
return { warnings, notes };
|
|
103
|
+
} catch {
|
|
104
|
+
return { warnings: [], notes: [] }; // module health must never break doctor
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
94
108
|
/** The closing line: honest about warnings, never "all good" under them. */
|
|
95
109
|
export function summaryLine(problems, warnings) {
|
|
96
110
|
if (problems) return `\n${problems} problem(s) found`;
|
|
@@ -146,6 +160,14 @@ export async function doctor() {
|
|
|
146
160
|
else ok('faculty home complete (knowledge/ memory/ actions/ instructions/ guardrails/)');
|
|
147
161
|
}
|
|
148
162
|
|
|
163
|
+
// faculty modules (the Faculty Module contract): a broken manifest or a
|
|
164
|
+
// failed hook degrades that faculty to items-only — surface it, never throw.
|
|
165
|
+
if (homeExists(root)) {
|
|
166
|
+
const health = facultyModuleHealth(dir);
|
|
167
|
+
for (const w of health.warnings) warn(w);
|
|
168
|
+
for (const n of health.notes) info(n);
|
|
169
|
+
}
|
|
170
|
+
|
|
149
171
|
// knowledge faculty
|
|
150
172
|
if (homeExists(root)) {
|
|
151
173
|
const reg = loadRegistry(dir);
|