@holoscript/core 7.0.0 → 8.0.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/README.md +2 -2
- package/bin/holoscript.cjs +3 -0
- package/dist/GLTFPipeline-276GE64O.js +16 -0
- package/dist/GLTFPipeline-M7WSSJED.cjs +37 -0
- package/dist/HoloScriptPlusParser-7FBIFUFC.js +693 -0
- package/dist/HoloScriptPlusParser-A2W7OCN2.cjs +698 -0
- package/dist/HoloScriptPlusParser-F2Z56FJR.js +10 -0
- package/dist/HoloScriptPlusParser-WKHRIH6T.cjs +27 -0
- package/dist/HoloScriptRuntime-3URVTKPJ.js +10 -0
- package/dist/HoloScriptRuntime-SXEAEU2N.cjs +19 -0
- package/dist/USDZExporter-3FWJ25JI.cjs +1037 -0
- package/dist/USDZExporter-D2HQLQYK.js +1035 -0
- package/dist/agents/index.cjs +19 -0
- package/dist/agents/index.d.ts +100 -0
- package/dist/agents/index.js +17 -0
- package/dist/chunk-23J755AR.js +1046 -0
- package/dist/chunk-253GBQZY.cjs +627 -0
- package/dist/chunk-25IQCHTO.cjs +781 -0
- package/dist/chunk-2BSMSUCE.js +1941 -0
- package/dist/chunk-2M2DPHKB.js +762 -0
- package/dist/chunk-2YSNA2F2.cjs +1274 -0
- package/dist/chunk-3AO425MZ.cjs +886 -0
- package/dist/chunk-3FOKASKO.cjs +348 -0
- package/dist/chunk-3HYYMEXI.cjs +56578 -0
- package/dist/chunk-3NFFOWGG.js +4287 -0
- package/dist/chunk-3WZEJHUQ.cjs +116 -0
- package/dist/chunk-4C57PR42.js +468 -0
- package/dist/chunk-4N4SXXWF.js +769 -0
- package/dist/chunk-4PDEPEQW.cjs +41 -0
- package/dist/chunk-4R6SBXDB.js +45 -0
- package/dist/chunk-4V2E7U7Q.cjs +2015 -0
- package/dist/chunk-5FSKKMR7.cjs +2092 -0
- package/dist/chunk-5GLCTO44.js +161 -0
- package/dist/chunk-5JEU52DW.js +382 -0
- package/dist/chunk-5S7RKFGR.cjs +446 -0
- package/dist/chunk-5WUNN6ZN.cjs +428 -0
- package/dist/chunk-62FBK3B7.js +70 -0
- package/dist/chunk-6CTRH7HT.cjs +1985 -0
- package/dist/chunk-6DPSFNJB.cjs +847 -0
- package/dist/chunk-6EX3I5P4.cjs +130 -0
- package/dist/chunk-73FELZVJ.cjs +611 -0
- package/dist/chunk-7CUEMLDZ.cjs +6445 -0
- package/dist/chunk-7HIASF7S.cjs +814 -0
- package/dist/chunk-A6KINLZJ.js +236 -0
- package/dist/chunk-AIA52I7T.cjs +543 -0
- package/dist/chunk-ANXZFVY2.js +113 -0
- package/dist/chunk-AYBXB26F.js +2176 -0
- package/dist/chunk-B4TFTDG4.js +449 -0
- package/dist/chunk-BE4UJCQT.js +623 -0
- package/dist/chunk-BRQJKJGT.cjs +20 -0
- package/dist/chunk-C2A5DUMF.cjs +689 -0
- package/dist/chunk-C37BHB7N.cjs +636 -0
- package/dist/chunk-CBJY23VL.js +126 -0
- package/dist/chunk-CIWWXYHZ.cjs +50 -0
- package/dist/chunk-CXFDRBQU.cjs +672 -0
- package/dist/chunk-D54CNIAJ.cjs +413 -0
- package/dist/chunk-DAJXW4KX.js +725 -0
- package/dist/chunk-DTGBOSEM.cjs +319 -0
- package/dist/chunk-E7JP3BS3.cjs +61 -0
- package/dist/chunk-EKBKLK7P.js +1169 -0
- package/dist/chunk-EKYL4PE3.cjs +404 -0
- package/dist/chunk-EUDQTK7N.cjs +4310 -0
- package/dist/chunk-EXKSFGSX.cjs +274 -0
- package/dist/chunk-EXUP2BUM.cjs +1173 -0
- package/dist/chunk-F43YAA34.js +623 -0
- package/dist/chunk-FDSGHPAK.js +130 -0
- package/dist/chunk-FEWUHQNM.cjs +144 -0
- package/dist/chunk-FGGJQRLZ.js +270 -0
- package/dist/chunk-FHP6LXJS.js +415 -0
- package/dist/chunk-FJPADH77.cjs +666 -0
- package/dist/chunk-FYSPZT4V.cjs +169 -0
- package/dist/chunk-GIOYPNTH.js +5575 -0
- package/dist/chunk-GJNCFRJU.cjs +125 -0
- package/dist/chunk-GMP623FG.cjs +1508 -0
- package/dist/chunk-GQHQOPXZ.cjs +5580 -0
- package/dist/chunk-GQT4TYKY.cjs +4381 -0
- package/dist/chunk-GTU2Z2WW.cjs +262 -0
- package/dist/chunk-GYZE55MO.js +2007 -0
- package/dist/chunk-GZG4KA4E.js +529 -0
- package/dist/chunk-H652NHX5.js +600 -0
- package/dist/chunk-HCCQLAA4.cjs +74 -0
- package/dist/chunk-HINXWAOD.cjs +1049 -0
- package/dist/chunk-HYNTS5CP.js +422 -0
- package/dist/chunk-HZSPDCXV.cjs +457 -0
- package/dist/chunk-HZTDET3N.js +1399 -0
- package/dist/chunk-I6XZ5DZF.cjs +488 -0
- package/dist/chunk-ILRBGFVD.cjs +72 -0
- package/dist/chunk-IPWSXCCN.js +1183 -0
- package/dist/chunk-IUTY5WQ2.cjs +424 -0
- package/dist/chunk-IVSZDECV.js +882 -0
- package/dist/chunk-IVY74O6C.js +247 -0
- package/dist/chunk-IZM5VQZD.js +714 -0
- package/dist/chunk-J32ZJZJH.js +554 -0
- package/dist/chunk-J6M4FPK5.js +421 -0
- package/dist/chunk-JC5YBPSF.cjs +984 -0
- package/dist/chunk-JCLBKPMX.js +3813 -0
- package/dist/chunk-JD7CIZ33.js +1949 -0
- package/dist/chunk-JIYN45TV.cjs +2525 -0
- package/dist/chunk-JJBE3TIH.cjs +1189 -0
- package/dist/chunk-JX7YL6ZE.js +2252 -0
- package/dist/chunk-K4VVR7CN.cjs +2433 -0
- package/dist/chunk-KEFNV2WM.cjs +2257 -0
- package/dist/chunk-KH4CNH66.cjs +424 -0
- package/dist/chunk-KJLB4OPV.js +5731 -0
- package/dist/chunk-KKFZ3B6J.cjs +557 -0
- package/dist/chunk-KKP7JKN4.cjs +6002 -0
- package/dist/chunk-KPJL34Y7.cjs +186 -0
- package/dist/chunk-KQCN6AKJ.cjs +3042 -0
- package/dist/chunk-KVRSTFNH.cjs +72 -0
- package/dist/chunk-LICPB5HZ.cjs +1409 -0
- package/dist/chunk-LM2VU56C.cjs +37 -0
- package/dist/chunk-M56JSP4A.js +400 -0
- package/dist/chunk-MBOOR7X4.js +18 -0
- package/dist/chunk-MGE5Z4GS.js +608 -0
- package/dist/chunk-MXFUTKCO.js +56 -0
- package/dist/chunk-MYY4PMWX.cjs +264 -0
- package/dist/chunk-N75IH2HY.js +258 -0
- package/dist/chunk-NBMHU6SW.js +669 -0
- package/dist/chunk-NG77ATEW.cjs +778 -0
- package/dist/chunk-NGKREZ36.js +6384 -0
- package/dist/chunk-NHWSN2SD.cjs +718 -0
- package/dist/chunk-NV4VMVXU.js +421 -0
- package/dist/chunk-NW5G5FBQ.js +215 -0
- package/dist/chunk-NXZFOPVD.cjs +5737 -0
- package/dist/chunk-OBIYPYYS.cjs +1993 -0
- package/dist/chunk-OIQYIIO3.cjs +473 -0
- package/dist/chunk-OL46QLBJ.js +61 -0
- package/dist/chunk-OMXII44L.js +5386 -0
- package/dist/chunk-OR4Q2BGL.cjs +759 -0
- package/dist/chunk-OSYNRVOV.cjs +243 -0
- package/dist/chunk-PGANYCAG.cjs +220 -0
- package/dist/chunk-PHENW4MQ.js +65 -0
- package/dist/chunk-PHVRG4I2.js +844 -0
- package/dist/chunk-Q56TT7IL.js +483 -0
- package/dist/chunk-QPOQ7VPI.js +1491 -0
- package/dist/chunk-QPSKHBJP.js +5963 -0
- package/dist/chunk-QXH7QDSZ.js +1989 -0
- package/dist/chunk-R75BSDH7.cjs +50 -0
- package/dist/chunk-RARB3MBR.js +207 -0
- package/dist/chunk-RVBHAXFG.js +56160 -0
- package/dist/chunk-S3MDHNKB.cjs +490 -0
- package/dist/chunk-S4W6Z2MN.js +2426 -0
- package/dist/chunk-S6YWHCKV.cjs +410 -0
- package/dist/chunk-SIEXCILW.js +229 -0
- package/dist/chunk-SJBGLS25.cjs +2196 -0
- package/dist/chunk-SLU6UPJI.cjs +410 -0
- package/dist/chunk-SMIWS6DE.cjs +212 -0
- package/dist/chunk-T2QCTZMO.js +811 -0
- package/dist/chunk-T5J7ZKP3.cjs +4885 -0
- package/dist/chunk-TDCNJHWO.js +341 -0
- package/dist/chunk-TG7O4WBC.js +406 -0
- package/dist/chunk-THCK6ECW.js +2085 -0
- package/dist/chunk-TJHVSBP2.js +439 -0
- package/dist/chunk-TVHSPJ4N.cjs +606 -0
- package/dist/chunk-U44IKGG7.cjs +5390 -0
- package/dist/chunk-UJXISJBN.js +487 -0
- package/dist/chunk-UM6C3CGK.js +4375 -0
- package/dist/chunk-UMABK6SI.js +686 -0
- package/dist/chunk-UOIGFQXC.cjs +9750 -0
- package/dist/chunk-URG2SJLK.js +2521 -0
- package/dist/chunk-V6MKC2FZ.js +979 -0
- package/dist/chunk-VECQYRXL.js +474 -0
- package/dist/chunk-VJ3L7CHT.cjs +169 -0
- package/dist/chunk-VMLKSV26.js +1216 -0
- package/dist/chunk-VVKVQZI6.js +55 -0
- package/dist/chunk-W6RW64BB.cjs +1219 -0
- package/dist/chunk-W7VDOASB.cjs +639 -0
- package/dist/chunk-WDT3JTGM.cjs +483 -0
- package/dist/chunk-WJIHFLMJ.js +404 -0
- package/dist/chunk-WKX5AMOY.js +309 -0
- package/dist/chunk-WNNE3PO3.js +34 -0
- package/dist/chunk-WRKUDAZJ.js +3038 -0
- package/dist/chunk-WRLUBRKS.cjs +1943 -0
- package/dist/chunk-WRNEH5MO.js +3169 -0
- package/dist/chunk-WRWEX5ZF.js +658 -0
- package/dist/chunk-X3GJPRVK.cjs +3246 -0
- package/dist/chunk-XHIV6326.cjs +793 -0
- package/dist/chunk-XIVIE43A.cjs +729 -0
- package/dist/chunk-XJAN7CZG.cjs +432 -0
- package/dist/chunk-XKTPFXGA.js +164 -0
- package/dist/chunk-XL6INWKT.js +121 -0
- package/dist/chunk-XSFNHP2E.js +632 -0
- package/dist/chunk-XT6JY5W5.js +9684 -0
- package/dist/chunk-XUILI4KB.cjs +430 -0
- package/dist/chunk-XUUVDHIF.cjs +3962 -0
- package/dist/chunk-YF2I3MV3.js +46 -0
- package/dist/chunk-YIMN575O.js +4847 -0
- package/dist/chunk-YIVFJNYV.js +176 -0
- package/dist/chunk-YKGPCZEE.cjs +237 -0
- package/dist/chunk-YN6V7R3L.cjs +327 -0
- package/dist/chunk-YQELFNJV.js +39 -0
- package/dist/chunk-YYXH45E2.js +426 -0
- package/dist/chunk-ZBQXLH2L.js +756 -0
- package/dist/chunk-ZDSYWBIE.cjs +69 -0
- package/dist/chunk-ZU7NIRT6.js +325 -0
- package/dist/chunk-ZZ7RO2UQ.js +1243 -0
- package/dist/chunk-ZZEI7MV4.js +778 -0
- package/dist/cli/holoscript-runner.cjs +2255 -0
- package/dist/cli/holoscript-runner.js +2230 -0
- package/dist/codebase/index.cjs +336 -0
- package/dist/codebase/index.js +331 -0
- package/dist/compiler/agent-inference.cjs +31 -0
- package/dist/compiler/agent-inference.js +8 -0
- package/dist/compiler/android-xr.cjs +24 -0
- package/dist/compiler/android-xr.js +14 -0
- package/dist/compiler/android.cjs +24 -0
- package/dist/compiler/android.js +14 -0
- package/dist/compiler/ar.cjs +23 -0
- package/dist/compiler/ar.js +11 -0
- package/dist/compiler/babylon.cjs +21 -0
- package/dist/compiler/babylon.js +15 -0
- package/dist/compiler/business-quest.cjs +43 -0
- package/dist/compiler/business-quest.js +4 -0
- package/dist/compiler/coco.cjs +27 -0
- package/dist/compiler/coco.js +4 -0
- package/dist/compiler/context.cjs +25 -0
- package/dist/compiler/context.d.ts +28 -0
- package/dist/compiler/context.js +8 -0
- package/dist/compiler/domain-block-utils.cjs +605 -0
- package/dist/compiler/domain-block-utils.js +11 -0
- package/dist/compiler/dtdl.cjs +27 -0
- package/dist/compiler/dtdl.js +11 -0
- package/dist/compiler/gltf-pipeline.cjs +39 -0
- package/dist/compiler/gltf-pipeline.js +4 -0
- package/dist/compiler/godot.cjs +18 -0
- package/dist/compiler/godot.js +12 -0
- package/dist/compiler/incremental.cjs +34 -0
- package/dist/compiler/incremental.js +9 -0
- package/dist/compiler/index.cjs +5860 -0
- package/dist/compiler/index.d.ts +322 -21
- package/dist/compiler/index.js +5525 -0
- package/dist/compiler/ios.cjs +23 -0
- package/dist/compiler/ios.js +13 -0
- package/dist/compiler/llm-provider-capabilities.cjs +25 -0
- package/dist/compiler/llm-provider-capabilities.d.ts +43 -0
- package/dist/compiler/llm-provider-capabilities.js +8 -0
- package/dist/compiler/multi-layer.cjs +24 -0
- package/dist/compiler/multi-layer.js +15 -0
- package/dist/compiler/nodetoy.cjs +23 -0
- package/dist/compiler/nodetoy.js +4 -0
- package/dist/compiler/openxr.cjs +19 -0
- package/dist/compiler/openxr.js +13 -0
- package/dist/compiler/playcanvas.cjs +19 -0
- package/dist/compiler/playcanvas.js +13 -0
- package/dist/compiler/r3f.cjs +38 -0
- package/dist/compiler/r3f.d.ts +22 -0
- package/dist/compiler/r3f.js +16 -0
- package/dist/compiler/remotion.cjs +23 -0
- package/dist/compiler/remotion.js +4 -0
- package/dist/compiler/reproducibility.cjs +39 -0
- package/dist/compiler/reproducibility.js +4 -0
- package/dist/compiler/sdf.cjs +24 -0
- package/dist/compiler/sdf.js +12 -0
- package/dist/compiler/semantic-scene.cjs +31 -0
- package/dist/compiler/semantic-scene.js +4 -0
- package/dist/compiler/state.cjs +21 -0
- package/dist/compiler/state.js +11 -0
- package/dist/compiler/trait-composition.cjs +30 -0
- package/dist/compiler/trait-composition.js +9 -0
- package/dist/compiler/unity.cjs +19 -0
- package/dist/compiler/unity.js +13 -0
- package/dist/compiler/unreal.cjs +23 -0
- package/dist/compiler/unreal.js +13 -0
- package/dist/compiler/urdf.cjs +52 -0
- package/dist/compiler/urdf.js +12 -0
- package/dist/compiler/usd-physics.cjs +26 -0
- package/dist/compiler/usd-physics.js +9 -0
- package/dist/compiler/visionos.cjs +19 -0
- package/dist/compiler/visionos.js +13 -0
- package/dist/compiler/vrchat.cjs +22 -0
- package/dist/compiler/vrchat.js +12 -0
- package/dist/compiler/vrr.cjs +24 -0
- package/dist/compiler/vrr.js +12 -0
- package/dist/compiler/wasm.cjs +36 -0
- package/dist/compiler/wasm.js +12 -0
- package/dist/compiler/webgpu.cjs +18 -0
- package/dist/compiler/webgpu.js +12 -0
- package/dist/coordinators/index.cjs +1266 -0
- package/dist/coordinators/index.d.ts +72 -1
- package/dist/coordinators/index.js +1259 -0
- package/dist/debugger.cjs +24 -0
- package/dist/debugger.js +11 -0
- package/dist/entries/interop.cjs +64 -0
- package/dist/entries/interop.js +7 -0
- package/dist/entries/scripting.cjs +55 -0
- package/dist/entries/scripting.js +10 -0
- package/dist/hololand/index.cjs +146 -0
- package/dist/hololand/index.d.ts +70 -0
- package/dist/hololand/index.js +5 -0
- package/dist/index.cjs +43233 -0
- package/dist/index.d.ts +976 -21
- package/dist/index.js +39995 -0
- package/dist/math/tropical-spmv.cjs +45 -0
- package/dist/math/tropical-spmv.js +4 -0
- package/dist/math/vec3.cjs +57 -0
- package/dist/math/vec3.js +4 -0
- package/dist/ml-dsa-FSKBTE3W.cjs +1265 -0
- package/dist/ml-dsa-Z7JDKW4L.js +1265 -0
- package/dist/paper-0c-spike/index.cjs +150 -0
- package/dist/paper-0c-spike/index.js +141 -0
- package/dist/parser.cjs +61 -0
- package/dist/parser.d.ts +11 -0
- package/dist/parser.js +12 -0
- package/dist/playwright-3AT3AKTV.cjs +98673 -0
- package/dist/playwright-VZPDVUEQ.js +98660 -0
- package/dist/reconstruction/index.cjs +153 -0
- package/dist/reconstruction/index.d.ts +29 -2
- package/dist/reconstruction/index.js +8 -0
- package/dist/runtime.cjs +316 -0
- package/dist/runtime.d.ts +61 -0
- package/dist/runtime.js +31 -0
- package/dist/self-improvement/index.cjs +563 -0
- package/dist/self-improvement/index.js +545 -0
- package/dist/storage/index.cjs +38 -0
- package/dist/storage/index.js +5 -0
- package/dist/testing.cjs +25 -0
- package/dist/testing.d.ts +70 -0
- package/dist/testing.js +4 -0
- package/dist/traitDocs/traitDocs.cjs +33 -0
- package/dist/traitDocs/traitDocs.js +7 -0
- package/dist/traits/botanical-lotus.cjs +41 -0
- package/dist/traits/botanical-lotus.d.ts +172 -0
- package/dist/traits/botanical-lotus.js +4 -0
- package/dist/traits/engines/index.cjs +520 -0
- package/dist/traits/engines/index.js +380 -0
- package/dist/traits/index.cjs +24409 -0
- package/dist/traits/index.d.ts +171 -35
- package/dist/traits/index.js +21634 -0
- package/dist/traits/simulation-solver-factory.cjs +13 -0
- package/dist/traits/simulation-solver-factory.d.ts +23 -0
- package/dist/traits/simulation-solver-factory.js +4 -0
- package/dist/traits/webcam-gaze.cjs +35 -0
- package/dist/traits/webcam-gaze.d.ts +17 -0
- package/dist/traits/webcam-gaze.js +4 -0
- package/dist/type-checker.cjs +19 -0
- package/dist/type-checker.js +6 -0
- package/dist/world/index.cjs +947 -0
- package/dist/world/index.d.ts +147 -0
- package/dist/world/index.js +939 -0
- package/dist/world-model/index.cjs +1446 -0
- package/dist/world-model/index.d.ts +119 -0
- package/dist/world-model/index.js +1414 -0
- package/dist/wot/index.cjs +29 -0
- package/dist/wot/index.js +4 -0
- package/package.json +93 -49
|
@@ -0,0 +1,1993 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkKKP7JKN4_cjs = require('./chunk-KKP7JKN4.cjs');
|
|
4
|
+
var ans = require('@holoscript/core-types/ans');
|
|
5
|
+
|
|
6
|
+
// src/compiler/ContextCompiler.ts
|
|
7
|
+
chunkKKP7JKN4_cjs.init_CompilerBase();
|
|
8
|
+
var BANNED_DEFAULT_PATTERNS = [
|
|
9
|
+
{ pattern: /\bgit\s+add\s+(?:-A|--all|\.)(?=\s|$)/i, rule: "F.001/F.011 - git add -A leaked .env twice" },
|
|
10
|
+
{ pattern: /:\s*any\b|\bas\s+any\b|<any>/i, rule: "global CLAUDE.md - no `any` in TypeScript, use `unknown`" },
|
|
11
|
+
{ pattern: /\bregex\b.+\.(?:hs|hsplus|holo)\b/i, rule: "F.014 - no regex on .hs/.hsplus/.holo, use @holoscript/core" },
|
|
12
|
+
{ pattern: /\bmock\s+(?:the\s+)?(?:db|database)\b/i, rule: "founder-default - real DB in tests, mock-vs-prod divergence" }
|
|
13
|
+
];
|
|
14
|
+
var VENDOR_AS_SUBSTRATE_PATTERNS = [
|
|
15
|
+
{ pattern: /managed_agents_replaces_holomesh/i, rule: "W.GOLD.002 - vendor framework cannot replace HoloMesh" },
|
|
16
|
+
{ pattern: /vector_store_as_source_of_truth/i, rule: "docs/LLM_CAPABILITIES.md hard-don'ts - vendor stores never source-of-truth" },
|
|
17
|
+
{ pattern: /api_keys_as_identity/i, rule: "W.GOLD.004 - wallets are identity, API keys are sessions" }
|
|
18
|
+
];
|
|
19
|
+
var KNOWN_DIAMOND_IDS = /* @__PURE__ */ new Set([
|
|
20
|
+
"W.GOLD.001",
|
|
21
|
+
// Architecture beats alignment
|
|
22
|
+
"P.GOLD.001",
|
|
23
|
+
// Failure knowledge decays slower than success knowledge
|
|
24
|
+
"W.GOLD.188",
|
|
25
|
+
// Algebraic Trust (paired with W.GOLD.189)
|
|
26
|
+
"W.GOLD.189"
|
|
27
|
+
// Algebraic Trust tri-layer (algebra + history + oracle)
|
|
28
|
+
// Add more as graduate.py promotes - verify against D:/GOLD/INDEX.md.
|
|
29
|
+
]);
|
|
30
|
+
var DEFAULT_FLUENT_PROSE_CHARS = 150;
|
|
31
|
+
var ContextCompiler = class extends chunkKKP7JKN4_cjs.CompilerBase {
|
|
32
|
+
constructor(options = {}) {
|
|
33
|
+
super();
|
|
34
|
+
this.compilerName = "ContextCompiler";
|
|
35
|
+
this.options = {
|
|
36
|
+
formats: options.formats ?? ["claude_md"]
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
getRequiredCapability() {
|
|
40
|
+
return ans.ANSCapabilityPath.AGENT_INFERENCE;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Compile a HoloScript context composition to agent-surface formats.
|
|
44
|
+
*
|
|
45
|
+
* Phases:
|
|
46
|
+
* 1. extract - walk the HoloComposition AST, collect all v1 traits
|
|
47
|
+
* into the typed ContextAST shape
|
|
48
|
+
* 2. validate - apply BLOCK rules (Diamond-invariant violations) +
|
|
49
|
+
* WARN rules (soft guidelines). BLOCK rules throw; WARN rules
|
|
50
|
+
* accumulate in diagnostics.
|
|
51
|
+
* 3. emit - dispatch to per-format emitters. Phase 1 ships claude_md
|
|
52
|
+
* and agents_md. cursor_rules + skill_md + anthropic_system_prompt
|
|
53
|
+
* + brain_includes + mcp_context_loader are filed follow-ups.
|
|
54
|
+
*/
|
|
55
|
+
compile(composition, agentToken, outputPath) {
|
|
56
|
+
this.validateCompilerAccess(agentToken, outputPath);
|
|
57
|
+
const ast = this.extractContextAST(composition);
|
|
58
|
+
this.validate(ast);
|
|
59
|
+
const files = {};
|
|
60
|
+
for (const format of this.options.formats) {
|
|
61
|
+
switch (format) {
|
|
62
|
+
case "claude_md":
|
|
63
|
+
files["CLAUDE.md"] = this.emitClaudeMd(ast);
|
|
64
|
+
break;
|
|
65
|
+
case "agents_md":
|
|
66
|
+
files["AGENTS.md"] = this.emitAgentsMd(ast);
|
|
67
|
+
break;
|
|
68
|
+
case "cursor_rules": {
|
|
69
|
+
const cursorFiles = this.emitCursorRules(ast);
|
|
70
|
+
for (const [path, content] of Object.entries(cursorFiles)) {
|
|
71
|
+
files[path] = content;
|
|
72
|
+
}
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
case "skill_md":
|
|
76
|
+
files["SKILL.md"] = this.emitSkillMd(ast);
|
|
77
|
+
break;
|
|
78
|
+
case "anthropic_system_prompt":
|
|
79
|
+
case "brain_includes":
|
|
80
|
+
case "mcp_context_loader":
|
|
81
|
+
throw new Error(
|
|
82
|
+
`Format "${format}" is a Phase 1+ follow-up; not yet emitted. See ai-ecosystem research/2026-05-06_context-as-compile-target.md section Recommended sequence for the rollout order.`
|
|
83
|
+
);
|
|
84
|
+
default: {
|
|
85
|
+
const exhaustive = format;
|
|
86
|
+
throw new Error(`Unknown emit format: ${String(exhaustive)}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return { files, ast, diagnostics: ast.warnings };
|
|
91
|
+
}
|
|
92
|
+
// --- Phase 1: extract -----------------------------------------------
|
|
93
|
+
extractContextAST(composition) {
|
|
94
|
+
const ast = {
|
|
95
|
+
visionPillars: [],
|
|
96
|
+
refusals: [],
|
|
97
|
+
hardDonts: [],
|
|
98
|
+
defaults: [],
|
|
99
|
+
graduatedWisdoms: [],
|
|
100
|
+
feedbacks: [],
|
|
101
|
+
escalations: [],
|
|
102
|
+
verifyTokens: [],
|
|
103
|
+
gapRules: [],
|
|
104
|
+
citationRules: [],
|
|
105
|
+
skills: [],
|
|
106
|
+
includes: [],
|
|
107
|
+
routines: [],
|
|
108
|
+
hardPhysicalGaps: [],
|
|
109
|
+
invocationModes: [],
|
|
110
|
+
dateDisciplines: [],
|
|
111
|
+
domainPreferences: [],
|
|
112
|
+
embodiedProjections: [],
|
|
113
|
+
editorialDefaults: [],
|
|
114
|
+
researchDefaults: [],
|
|
115
|
+
trackBAuthorities: [],
|
|
116
|
+
narrativeOpenings: [],
|
|
117
|
+
triggerPhrases: [],
|
|
118
|
+
proseAfters: [],
|
|
119
|
+
domainDispatches: [],
|
|
120
|
+
corpusMutabilities: [],
|
|
121
|
+
warnings: []
|
|
122
|
+
};
|
|
123
|
+
for (const trait of composition.traits ?? []) {
|
|
124
|
+
this.dispatchTrait(trait, ast);
|
|
125
|
+
}
|
|
126
|
+
for (const obj of composition.objects ?? []) {
|
|
127
|
+
this.extractFromObject(obj, ast);
|
|
128
|
+
}
|
|
129
|
+
return ast;
|
|
130
|
+
}
|
|
131
|
+
extractFromObject(obj, ast) {
|
|
132
|
+
const traits = obj.traits ?? [];
|
|
133
|
+
for (const trait of traits) {
|
|
134
|
+
this.dispatchTrait(trait, ast);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
dispatchTrait(trait, ast) {
|
|
138
|
+
const cfg = trait.config;
|
|
139
|
+
switch (trait.name) {
|
|
140
|
+
case "identity": {
|
|
141
|
+
const allowedToolsList = stringListField(cfg, "allowed_tools");
|
|
142
|
+
ast.identity = {
|
|
143
|
+
name: stringField(cfg, "name", ""),
|
|
144
|
+
role: stringField(cfg, "role", ""),
|
|
145
|
+
domain: stringField(cfg, "domain", ""),
|
|
146
|
+
surface: stringField(cfg, "surface", "any") ?? "any",
|
|
147
|
+
noMonopoly: boolField(cfg, "no_monopoly", false),
|
|
148
|
+
description: stringFieldOrUndef(cfg, "description"),
|
|
149
|
+
allowedTools: allowedToolsList.length > 0 ? allowedToolsList : void 0,
|
|
150
|
+
commandTemplate: stringFieldOrUndef(cfg, "command_template")
|
|
151
|
+
};
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
case "authority_order":
|
|
155
|
+
ast.authorityOrder = { tiers: stringListField(cfg, "tiers") };
|
|
156
|
+
break;
|
|
157
|
+
case "vision_pillar":
|
|
158
|
+
ast.visionPillars.push({
|
|
159
|
+
id: stringField(cfg, "id", ""),
|
|
160
|
+
claim: stringField(cfg, "claim", ""),
|
|
161
|
+
citation: stringFieldOrUndef(cfg, "citation")
|
|
162
|
+
});
|
|
163
|
+
break;
|
|
164
|
+
case "output_shape":
|
|
165
|
+
ast.outputShape = {
|
|
166
|
+
silentTo: stringField(cfg, "silent_to", ""),
|
|
167
|
+
loudTo: stringField(cfg, "loud_to", ""),
|
|
168
|
+
noMetaOutput: boolField(cfg, "no_meta_output", false),
|
|
169
|
+
surfaceHint: stringField(cfg, "surface_hint", "")
|
|
170
|
+
};
|
|
171
|
+
break;
|
|
172
|
+
case "production_rule":
|
|
173
|
+
ast.productionRule = {
|
|
174
|
+
noDevNoMockNoLocalhost: boolField(cfg, "no_dev_no_mock_no_localhost", false),
|
|
175
|
+
exception: stringFieldOrUndef(cfg, "exception")
|
|
176
|
+
};
|
|
177
|
+
break;
|
|
178
|
+
case "refusal":
|
|
179
|
+
ast.refusals.push({
|
|
180
|
+
name: stringField(cfg, "name", ""),
|
|
181
|
+
when: stringField(cfg, "when", ""),
|
|
182
|
+
do: stringField(cfg, "do", ""),
|
|
183
|
+
doNot: stringListField(cfg, "do_not"),
|
|
184
|
+
reason: stringFieldOrUndef(cfg, "reason")
|
|
185
|
+
});
|
|
186
|
+
break;
|
|
187
|
+
case "hard_dont":
|
|
188
|
+
ast.hardDonts.push({
|
|
189
|
+
name: stringField(cfg, "name", ""),
|
|
190
|
+
reason: stringField(cfg, "reason", ""),
|
|
191
|
+
alternative: stringFieldOrUndef(cfg, "alternative"),
|
|
192
|
+
appliesTo: stringListField(cfg, "applies_to")
|
|
193
|
+
});
|
|
194
|
+
break;
|
|
195
|
+
case "default":
|
|
196
|
+
ast.defaults.push({
|
|
197
|
+
name: stringField(cfg, "name", ""),
|
|
198
|
+
when: stringField(cfg, "when", ""),
|
|
199
|
+
do: stringField(cfg, "do", ""),
|
|
200
|
+
reason: stringFieldOrUndef(cfg, "reason")
|
|
201
|
+
});
|
|
202
|
+
break;
|
|
203
|
+
case "graduated_wisdom":
|
|
204
|
+
ast.graduatedWisdoms.push({
|
|
205
|
+
id: stringField(cfg, "id", ""),
|
|
206
|
+
claim: stringField(cfg, "claim", ""),
|
|
207
|
+
tier: stringField(cfg, "tier", "gold")
|
|
208
|
+
});
|
|
209
|
+
break;
|
|
210
|
+
case "feedback":
|
|
211
|
+
ast.feedbacks.push({
|
|
212
|
+
id: stringField(cfg, "id", ""),
|
|
213
|
+
claim: stringField(cfg, "claim", ""),
|
|
214
|
+
source: stringFieldOrUndef(cfg, "source")
|
|
215
|
+
});
|
|
216
|
+
break;
|
|
217
|
+
case "escalation":
|
|
218
|
+
ast.escalations.push({
|
|
219
|
+
trigger: stringField(cfg, "trigger", ""),
|
|
220
|
+
doAction: stringField(cfg, "do_action", ""),
|
|
221
|
+
recipient: stringField(cfg, "recipient", ""),
|
|
222
|
+
refuseToEscalateWhen: stringListField(cfg, "refuse_to_escalate_when")
|
|
223
|
+
});
|
|
224
|
+
break;
|
|
225
|
+
case "verify_token":
|
|
226
|
+
ast.verifyTokens.push({
|
|
227
|
+
meaning: stringField(cfg, "meaning", ""),
|
|
228
|
+
example: stringField(cfg, "example", "")
|
|
229
|
+
});
|
|
230
|
+
break;
|
|
231
|
+
case "gap_rule":
|
|
232
|
+
ast.gapRules.push({
|
|
233
|
+
name: stringField(cfg, "name", ""),
|
|
234
|
+
when: stringField(cfg, "when", ""),
|
|
235
|
+
do: stringListField(cfg, "do"),
|
|
236
|
+
doNot: stringListField(cfg, "do_not"),
|
|
237
|
+
reason: stringFieldOrUndef(cfg, "reason")
|
|
238
|
+
});
|
|
239
|
+
break;
|
|
240
|
+
case "citation_rule":
|
|
241
|
+
ast.citationRules.push({
|
|
242
|
+
fluentProseThresholdChars: numberField(
|
|
243
|
+
cfg,
|
|
244
|
+
"fluent_prose_threshold_chars",
|
|
245
|
+
DEFAULT_FLUENT_PROSE_CHARS
|
|
246
|
+
),
|
|
247
|
+
required: stringListField(cfg, "required"),
|
|
248
|
+
exemption: stringFieldOrUndef(cfg, "exemption"),
|
|
249
|
+
reason: stringFieldOrUndef(cfg, "reason")
|
|
250
|
+
});
|
|
251
|
+
break;
|
|
252
|
+
case "skill":
|
|
253
|
+
ast.skills.push({
|
|
254
|
+
name: stringField(cfg, "name", ""),
|
|
255
|
+
invocableAs: stringField(cfg, "invocable_as", ""),
|
|
256
|
+
authority: stringField(cfg, "authority", ""),
|
|
257
|
+
authoritativeFor: stringListField(cfg, "authoritative_for"),
|
|
258
|
+
refusals: stringListField(cfg, "refusals")
|
|
259
|
+
});
|
|
260
|
+
break;
|
|
261
|
+
case "include":
|
|
262
|
+
ast.includes.push({
|
|
263
|
+
source: stringField(cfg, "source", ""),
|
|
264
|
+
selector: stringFieldOrUndef(cfg, "selector")
|
|
265
|
+
});
|
|
266
|
+
break;
|
|
267
|
+
case "routine":
|
|
268
|
+
ast.routines.push({
|
|
269
|
+
id: stringField(cfg, "id", ""),
|
|
270
|
+
schedule: stringField(cfg, "schedule", ""),
|
|
271
|
+
skill: stringField(cfg, "skill", ""),
|
|
272
|
+
promptRef: stringField(cfg, "prompt_ref", ""),
|
|
273
|
+
sla: stringField(cfg, "sla", ""),
|
|
274
|
+
outputDir: stringFieldOrUndef(cfg, "output_dir"),
|
|
275
|
+
cleanExitScript: stringFieldOrUndef(cfg, "clean_exit_script")
|
|
276
|
+
});
|
|
277
|
+
break;
|
|
278
|
+
case "hard_physical_gap":
|
|
279
|
+
ast.hardPhysicalGaps.push({
|
|
280
|
+
name: stringField(cfg, "name", ""),
|
|
281
|
+
reason: stringField(cfg, "reason", ""),
|
|
282
|
+
appliesTo: stringListField(cfg, "applies_to"),
|
|
283
|
+
alternative: stringFieldOrUndef(cfg, "alternative")
|
|
284
|
+
});
|
|
285
|
+
break;
|
|
286
|
+
case "invocation_mode":
|
|
287
|
+
ast.invocationModes.push({
|
|
288
|
+
mode: stringField(cfg, "mode", "explicit"),
|
|
289
|
+
when: stringField(cfg, "when", ""),
|
|
290
|
+
effect: stringField(cfg, "effect", ""),
|
|
291
|
+
example: stringFieldOrUndef(cfg, "example")
|
|
292
|
+
});
|
|
293
|
+
break;
|
|
294
|
+
case "date_discipline": {
|
|
295
|
+
const crossRefs = stringListField(cfg, "cross_references");
|
|
296
|
+
ast.dateDisciplines.push({
|
|
297
|
+
wisdomId: stringField(cfg, "wisdom_id", ""),
|
|
298
|
+
refusalContract: stringField(cfg, "refusal_contract", ""),
|
|
299
|
+
requiredComponents: stringListField(cfg, "required_components"),
|
|
300
|
+
shapeTemplate: stringField(cfg, "shape_template", ""),
|
|
301
|
+
reason: stringFieldOrUndef(cfg, "reason"),
|
|
302
|
+
crossReferences: crossRefs.length > 0 ? crossRefs : void 0
|
|
303
|
+
});
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
case "domain_preference":
|
|
307
|
+
ast.domainPreferences.push({
|
|
308
|
+
domain: stringField(cfg, "domain", ""),
|
|
309
|
+
skills: stringListField(cfg, "skills"),
|
|
310
|
+
notes: stringFieldOrUndef(cfg, "notes"),
|
|
311
|
+
ceiling: stringFieldOrUndef(cfg, "ceiling")
|
|
312
|
+
});
|
|
313
|
+
break;
|
|
314
|
+
case "authority":
|
|
315
|
+
ast.trackBAuthorities.push({
|
|
316
|
+
target: stringField(cfg, "target", ""),
|
|
317
|
+
actionType: stringField(cfg, "action_type", ""),
|
|
318
|
+
requires: stringListField(cfg, "requires"),
|
|
319
|
+
founderRatificationRequired: boolField(
|
|
320
|
+
cfg,
|
|
321
|
+
"founder_ratification_required",
|
|
322
|
+
false
|
|
323
|
+
),
|
|
324
|
+
notes: stringFieldOrUndef(cfg, "notes")
|
|
325
|
+
});
|
|
326
|
+
break;
|
|
327
|
+
case "embodied_projection":
|
|
328
|
+
ast.embodiedProjections.push({
|
|
329
|
+
surface: stringField(cfg, "surface", ""),
|
|
330
|
+
projectionKind: stringField(cfg, "projection_kind", "read-only"),
|
|
331
|
+
trigger: stringField(cfg, "trigger", ""),
|
|
332
|
+
notes: stringFieldOrUndef(cfg, "notes")
|
|
333
|
+
});
|
|
334
|
+
break;
|
|
335
|
+
case "editorial_default":
|
|
336
|
+
ast.editorialDefaults.push({
|
|
337
|
+
name: stringField(cfg, "name", ""),
|
|
338
|
+
paperId: stringFieldOrUndef(cfg, "paper_id"),
|
|
339
|
+
paperPhase: stringFieldOrUndef(cfg, "paper_phase"),
|
|
340
|
+
when: stringField(cfg, "when", ""),
|
|
341
|
+
do: stringField(cfg, "do", ""),
|
|
342
|
+
reason: stringFieldOrUndef(cfg, "reason")
|
|
343
|
+
});
|
|
344
|
+
break;
|
|
345
|
+
case "research_default":
|
|
346
|
+
ast.researchDefaults.push({
|
|
347
|
+
name: stringField(cfg, "name", ""),
|
|
348
|
+
paperId: stringFieldOrUndef(cfg, "paper_id"),
|
|
349
|
+
paperPhase: stringFieldOrUndef(cfg, "paper_phase"),
|
|
350
|
+
when: stringField(cfg, "when", ""),
|
|
351
|
+
do: stringField(cfg, "do", ""),
|
|
352
|
+
reason: stringFieldOrUndef(cfg, "reason")
|
|
353
|
+
});
|
|
354
|
+
break;
|
|
355
|
+
case "narrative_opening":
|
|
356
|
+
ast.narrativeOpenings.push({
|
|
357
|
+
posture: stringField(cfg, "posture", ""),
|
|
358
|
+
reason: stringFieldOrUndef(cfg, "reason")
|
|
359
|
+
});
|
|
360
|
+
break;
|
|
361
|
+
case "trigger_phrase":
|
|
362
|
+
ast.triggerPhrases.push({
|
|
363
|
+
phrase: stringField(cfg, "phrase", ""),
|
|
364
|
+
context: stringFieldOrUndef(cfg, "context")
|
|
365
|
+
});
|
|
366
|
+
break;
|
|
367
|
+
case "prose_after":
|
|
368
|
+
ast.proseAfters.push({
|
|
369
|
+
trait: stringField(cfg, "trait", ""),
|
|
370
|
+
paragraphs: stringListField(cfg, "paragraphs")
|
|
371
|
+
});
|
|
372
|
+
break;
|
|
373
|
+
case "domain_dispatch":
|
|
374
|
+
ast.domainDispatches.push({
|
|
375
|
+
domain: stringField(cfg, "domain", ""),
|
|
376
|
+
skills: stringListField(cfg, "skills")
|
|
377
|
+
});
|
|
378
|
+
break;
|
|
379
|
+
case "corpus_mutability":
|
|
380
|
+
ast.corpusMutabilities.push({
|
|
381
|
+
policy: stringField(cfg, "policy", ""),
|
|
382
|
+
description: stringField(cfg, "description", "")
|
|
383
|
+
});
|
|
384
|
+
break;
|
|
385
|
+
default:
|
|
386
|
+
ast.warnings.push({
|
|
387
|
+
severity: "warning",
|
|
388
|
+
rule: "unknown-trait",
|
|
389
|
+
message: `Trait "${trait.name}" is not in vocabulary v1. Ignored. Add to vocabulary if load-bearing.`
|
|
390
|
+
});
|
|
391
|
+
break;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
// --- Phase 2: validate (BLOCK rules throw, WARN rules accumulate) --
|
|
395
|
+
validate(ast) {
|
|
396
|
+
for (const def of ast.defaults) {
|
|
397
|
+
for (const banned of BANNED_DEFAULT_PATTERNS) {
|
|
398
|
+
if (banned.pattern.test(def.do)) {
|
|
399
|
+
throw new ContextCompileError(
|
|
400
|
+
`@default "${def.name}" recommends a banned pattern (matches ${banned.pattern}). Rule: ${banned.rule}.`
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
for (const dont of ast.hardDonts) {
|
|
406
|
+
const haystack = `${dont.name} ${dont.reason}`;
|
|
407
|
+
for (const vendorPat of VENDOR_AS_SUBSTRATE_PATTERNS) {
|
|
408
|
+
if (vendorPat.pattern.test(haystack)) {
|
|
409
|
+
throw new ContextCompileError(
|
|
410
|
+
`@hard_dont "${dont.name}" appears to author a vendor-as-substrate pattern. Rule: ${vendorPat.rule}. (A correct hard_dont SAYS "do not adopt vendor as substrate" - this one's framing matches the inverse.)`
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
for (const wisdom of ast.graduatedWisdoms) {
|
|
416
|
+
if (wisdom.tier === "diamond" && !KNOWN_DIAMOND_IDS.has(wisdom.id)) {
|
|
417
|
+
throw new ContextCompileError(
|
|
418
|
+
`@graduated_wisdom "${wisdom.id}" claims tier="diamond" but is not in the compiler's known-Diamond set. Diamond declaration is founder-only (D:/GOLD/INDEX.md). If this is a new Diamond entry, update KNOWN_DIAMOND_IDS in ContextCompiler.ts in the same commit that lands the GOLD entry.`
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
const physicalGapNames = new Set(ast.hardPhysicalGaps.map((g) => g.name));
|
|
423
|
+
for (const skill of ast.skills) {
|
|
424
|
+
for (const claim of skill.authoritativeFor) {
|
|
425
|
+
if (physicalGapNames.has(claim)) {
|
|
426
|
+
throw new ContextCompileError(
|
|
427
|
+
`@skill "${skill.name}" claims authoritative_for="${claim}" but that's a @hard_physical_gap (Trezor/Quest 3/in-person - non-absorbable). Founder skill section "Hard physical gaps the skill never absorbs". Either remove the claim or, if the skill genuinely covers the decision-side (yes/no/when/how-much) without the embodied step, narrow the authoritative_for entry to make the boundary explicit.`
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
for (const wisdom of ast.graduatedWisdoms) {
|
|
433
|
+
if (wisdom.tier !== "diamond" && !/^[WPG]\.GOLD\.\d+$/.test(wisdom.id)) {
|
|
434
|
+
ast.warnings.push({
|
|
435
|
+
severity: "warning",
|
|
436
|
+
rule: "F.023 vault-id-format",
|
|
437
|
+
message: `@graduated_wisdom id "${wisdom.id}" doesn't match expected format (W.GOLD.NNN | P.GOLD.NNN | G.GOLD.NNN). Possible typo or stale citation.`
|
|
438
|
+
});
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
// --- Phase 3: emit -- compile_to_claude_md -------------------------
|
|
443
|
+
emitClaudeMd(ast) {
|
|
444
|
+
const lines = [];
|
|
445
|
+
if (ast.identity) {
|
|
446
|
+
lines.push(`# ${ast.identity.name}`);
|
|
447
|
+
lines.push("");
|
|
448
|
+
lines.push(`> **Role**: ${ast.identity.role}`);
|
|
449
|
+
lines.push(`> **Domain**: ${ast.identity.domain}`);
|
|
450
|
+
lines.push(`> **Surface**: ${ast.identity.surface}`);
|
|
451
|
+
if (ast.identity.noMonopoly) {
|
|
452
|
+
lines.push(
|
|
453
|
+
`> **No-monopoly rule**: this context applies the absorb-as-adapter architectural posture (per docs/LLM_CAPABILITIES.md section Architectural posture).`
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
lines.push("");
|
|
457
|
+
}
|
|
458
|
+
for (const opening of ast.narrativeOpenings) {
|
|
459
|
+
const postureLines = opening.posture.split(/\r?\n/);
|
|
460
|
+
for (const pl of postureLines) {
|
|
461
|
+
lines.push(`> ${pl}`);
|
|
462
|
+
}
|
|
463
|
+
if (opening.reason) {
|
|
464
|
+
const reasonLines = opening.reason.split(/\r?\n/);
|
|
465
|
+
for (const rl of reasonLines) {
|
|
466
|
+
lines.push(`> ${rl}`);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
lines.push("");
|
|
470
|
+
}
|
|
471
|
+
if (ast.authorityOrder && ast.authorityOrder.tiers.length > 0) {
|
|
472
|
+
lines.push(`## Authority order (read top-down; the first match wins)`);
|
|
473
|
+
lines.push("");
|
|
474
|
+
ast.authorityOrder.tiers.forEach((tier, idx) => {
|
|
475
|
+
lines.push(`${idx + 1}. **${tier}**`);
|
|
476
|
+
});
|
|
477
|
+
lines.push("");
|
|
478
|
+
this.appendProseAfter(lines, ast, "authority_order");
|
|
479
|
+
}
|
|
480
|
+
if (ast.visionPillars.length > 0) {
|
|
481
|
+
lines.push(`## Vision pillars (follow; do not drift)`);
|
|
482
|
+
lines.push("");
|
|
483
|
+
ast.visionPillars.forEach((pillar, idx) => {
|
|
484
|
+
const cite = pillar.citation ? ` *(${pillar.citation})*` : "";
|
|
485
|
+
lines.push(`${idx + 1}. **${pillar.claim}**${cite}`);
|
|
486
|
+
});
|
|
487
|
+
lines.push("");
|
|
488
|
+
this.appendProseAfter(lines, ast, "vision_pillar");
|
|
489
|
+
}
|
|
490
|
+
if (ast.refusals.length > 0) {
|
|
491
|
+
lines.push(`## The Four Refusals`);
|
|
492
|
+
lines.push("");
|
|
493
|
+
lines.push(
|
|
494
|
+
`These are not guidelines. They are refusals. If you catch yourself about to do any of the following, stop and reframe before continuing.`
|
|
495
|
+
);
|
|
496
|
+
lines.push("");
|
|
497
|
+
for (const refusal of ast.refusals) {
|
|
498
|
+
lines.push(`### Refuse the ${refusal.name}`);
|
|
499
|
+
lines.push("");
|
|
500
|
+
lines.push(`**When**: ${refusal.when}`);
|
|
501
|
+
lines.push("");
|
|
502
|
+
lines.push(`**Do**: ${refusal.do}`);
|
|
503
|
+
lines.push("");
|
|
504
|
+
if (refusal.doNot.length > 0) {
|
|
505
|
+
lines.push(`**Do not**: ${refusal.doNot.map((d) => `\`${d}\``).join(", ")}`);
|
|
506
|
+
lines.push("");
|
|
507
|
+
}
|
|
508
|
+
if (refusal.reason) {
|
|
509
|
+
lines.push(`**Reason**: ${refusal.reason}`);
|
|
510
|
+
lines.push("");
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
this.appendProseAfter(lines, ast, "refusal");
|
|
514
|
+
}
|
|
515
|
+
if (ast.hardDonts.length > 0) {
|
|
516
|
+
lines.push(`## Hard don'ts (cross-provider red lines)`);
|
|
517
|
+
lines.push("");
|
|
518
|
+
lines.push(`| Name | Reason | Alternative |`);
|
|
519
|
+
lines.push(`|---|---|---|`);
|
|
520
|
+
for (const dont of ast.hardDonts) {
|
|
521
|
+
lines.push(
|
|
522
|
+
`| **${dont.name}** | ${dont.reason} | ${dont.alternative ?? "*(none)*"} |`
|
|
523
|
+
);
|
|
524
|
+
}
|
|
525
|
+
lines.push("");
|
|
526
|
+
this.appendProseAfter(lines, ast, "hard_dont");
|
|
527
|
+
}
|
|
528
|
+
if (ast.defaults.length > 0) {
|
|
529
|
+
lines.push(`## Known founder defaults (answer immediately)`);
|
|
530
|
+
lines.push("");
|
|
531
|
+
lines.push(`| When | Answer | Reason |`);
|
|
532
|
+
lines.push(`|---|---|---|`);
|
|
533
|
+
for (const def of ast.defaults) {
|
|
534
|
+
lines.push(
|
|
535
|
+
`| ${def.when} | **${def.do}** | ${def.reason ?? "*(no citation)*"} |`
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
lines.push("");
|
|
539
|
+
this.appendProseAfter(lines, ast, "default");
|
|
540
|
+
}
|
|
541
|
+
if (ast.domainPreferences.length > 0) {
|
|
542
|
+
lines.push("## Domain preferences (beyond engineering)");
|
|
543
|
+
lines.push("");
|
|
544
|
+
lines.push("| Domain | Skills to delegate to | Notes / ceiling |");
|
|
545
|
+
lines.push("|---|---|---|");
|
|
546
|
+
for (const pref of ast.domainPreferences) {
|
|
547
|
+
const skills = pref.skills.length > 0 ? pref.skills.map((s) => `\`${s}\``).join(", ") : "*(in-skill default)*";
|
|
548
|
+
const notesParts = [];
|
|
549
|
+
if (pref.ceiling) notesParts.push(`Ceiling: ${pref.ceiling}`);
|
|
550
|
+
if (pref.notes) notesParts.push(pref.notes);
|
|
551
|
+
const notes = notesParts.join("; ") || "";
|
|
552
|
+
lines.push(`| **${pref.domain}** | ${skills} | ${notes} |`);
|
|
553
|
+
}
|
|
554
|
+
lines.push("");
|
|
555
|
+
this.appendProseAfter(lines, ast, "domain_preference");
|
|
556
|
+
}
|
|
557
|
+
this.appendTrackBAuthority(lines, ast);
|
|
558
|
+
this.appendProseAfter(lines, ast, "authority");
|
|
559
|
+
this.appendPapersProgramDefaults(lines, ast);
|
|
560
|
+
this.appendProseAfter(lines, ast, "editorial_default");
|
|
561
|
+
this.appendProseAfter(lines, ast, "research_default");
|
|
562
|
+
if (ast.outputShape) {
|
|
563
|
+
lines.push(`## Output shape \u2014 SILENT-TO-JOSEPH, LOUD-TO-THE-AGENT`);
|
|
564
|
+
lines.push("");
|
|
565
|
+
lines.push(`- **Silent to**: ${ast.outputShape.silentTo}`);
|
|
566
|
+
lines.push(`- **Loud to**: ${ast.outputShape.loudTo}`);
|
|
567
|
+
if (ast.outputShape.noMetaOutput) {
|
|
568
|
+
lines.push(`- **No meta-output**: do not narrate the protocol back to the user`);
|
|
569
|
+
}
|
|
570
|
+
if (ast.outputShape.surfaceHint) {
|
|
571
|
+
lines.push(`- **Surface hint**: ${ast.outputShape.surfaceHint}`);
|
|
572
|
+
}
|
|
573
|
+
lines.push("");
|
|
574
|
+
this.appendProseAfter(lines, ast, "output_shape");
|
|
575
|
+
}
|
|
576
|
+
if (ast.productionRule) {
|
|
577
|
+
lines.push(`## Production-only rule (no dev, no mock, no localhost)`);
|
|
578
|
+
lines.push("");
|
|
579
|
+
if (ast.productionRule.noDevNoMockNoLocalhost) {
|
|
580
|
+
lines.push(`No dev. No mock. No localhost. The real service exists - hit it.`);
|
|
581
|
+
}
|
|
582
|
+
if (ast.productionRule.exception) {
|
|
583
|
+
lines.push("");
|
|
584
|
+
lines.push(`**Exception**: ${ast.productionRule.exception}`);
|
|
585
|
+
}
|
|
586
|
+
lines.push("");
|
|
587
|
+
this.appendProseAfter(lines, ast, "production_rule");
|
|
588
|
+
}
|
|
589
|
+
if (ast.hardPhysicalGaps.length > 0) {
|
|
590
|
+
lines.push(`## Hard physical gaps (skill never absorbs)`);
|
|
591
|
+
lines.push("");
|
|
592
|
+
for (const gap of ast.hardPhysicalGaps) {
|
|
593
|
+
lines.push(`- **${gap.name}** - ${gap.reason}`);
|
|
594
|
+
if (gap.alternative) {
|
|
595
|
+
lines.push(` - Alternative: ${gap.alternative}`);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
lines.push("");
|
|
599
|
+
this.appendProseAfter(lines, ast, "hard_physical_gap");
|
|
600
|
+
}
|
|
601
|
+
if (ast.skills.length > 0) {
|
|
602
|
+
lines.push(`## Skills`);
|
|
603
|
+
lines.push("");
|
|
604
|
+
for (const skill of ast.skills) {
|
|
605
|
+
lines.push(`### \`${skill.invocableAs}\` - ${skill.name}`);
|
|
606
|
+
lines.push("");
|
|
607
|
+
lines.push(`**Authority**: ${skill.authority}`);
|
|
608
|
+
lines.push("");
|
|
609
|
+
if (skill.authoritativeFor.length > 0) {
|
|
610
|
+
lines.push(`**Authoritative for**: ${skill.authoritativeFor.join(", ")}`);
|
|
611
|
+
lines.push("");
|
|
612
|
+
}
|
|
613
|
+
if (skill.refusals && skill.refusals.length > 0) {
|
|
614
|
+
lines.push(`**Refusals enforced**: ${skill.refusals.join(", ")}`);
|
|
615
|
+
lines.push("");
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
this.appendProseAfter(lines, ast, "skill");
|
|
619
|
+
}
|
|
620
|
+
if (ast.invocationModes.length > 0) {
|
|
621
|
+
lines.push("## Invocation modes (Track D)");
|
|
622
|
+
lines.push("");
|
|
623
|
+
for (const mode of ast.invocationModes) {
|
|
624
|
+
lines.push(`### ${mode.mode}`);
|
|
625
|
+
lines.push("");
|
|
626
|
+
lines.push(`- **When**: ${mode.when}`);
|
|
627
|
+
lines.push(`- **Effect**: ${mode.effect}`);
|
|
628
|
+
if (mode.example) {
|
|
629
|
+
lines.push(`- **Example**: \`${mode.example}\``);
|
|
630
|
+
}
|
|
631
|
+
lines.push("");
|
|
632
|
+
}
|
|
633
|
+
this.appendProseAfter(lines, ast, "invocation_mode");
|
|
634
|
+
}
|
|
635
|
+
appendEmbodiedProjectionSection(lines, ast.embodiedProjections);
|
|
636
|
+
this.appendProseAfter(lines, ast, "embodied_projection");
|
|
637
|
+
if (ast.routines.length > 0) {
|
|
638
|
+
lines.push(`## Recurring routines (A-00X)`);
|
|
639
|
+
lines.push("");
|
|
640
|
+
lines.push(`| ID | Schedule | Skill | Output |`);
|
|
641
|
+
lines.push(`|---|---|---|---|`);
|
|
642
|
+
for (const routine of ast.routines) {
|
|
643
|
+
lines.push(
|
|
644
|
+
`| ${routine.id} | \`${routine.schedule}\` | ${routine.skill} | ${routine.outputDir ?? "*(varies)*"} |`
|
|
645
|
+
);
|
|
646
|
+
}
|
|
647
|
+
lines.push("");
|
|
648
|
+
this.appendProseAfter(lines, ast, "routine");
|
|
649
|
+
}
|
|
650
|
+
if (ast.escalations.length > 0) {
|
|
651
|
+
lines.push(`## Escape hatch`);
|
|
652
|
+
lines.push("");
|
|
653
|
+
for (const esc of ast.escalations) {
|
|
654
|
+
lines.push(`- **Trigger**: ${esc.trigger}`);
|
|
655
|
+
lines.push(` - **Action**: ${esc.doAction}`);
|
|
656
|
+
lines.push(` - **Recipient**: ${esc.recipient}`);
|
|
657
|
+
if (esc.refuseToEscalateWhen.length > 0) {
|
|
658
|
+
lines.push(
|
|
659
|
+
` - **Refuse to escalate when**: ${esc.refuseToEscalateWhen.join(", ")}`
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
lines.push("");
|
|
664
|
+
this.appendProseAfter(lines, ast, "escalation");
|
|
665
|
+
}
|
|
666
|
+
if (ast.dateDisciplines.length > 0) {
|
|
667
|
+
const firstWisdom = ast.dateDisciplines[0]?.wisdomId;
|
|
668
|
+
const wisdomSuffix = ast.dateDisciplines.length === 1 && firstWisdom ? ` (${firstWisdom})` : "";
|
|
669
|
+
lines.push(`## Date discipline${wisdomSuffix}`);
|
|
670
|
+
lines.push("");
|
|
671
|
+
for (const d of ast.dateDisciplines) {
|
|
672
|
+
const wisdomLabel = d.wisdomId ? ` (${d.wisdomId})` : "";
|
|
673
|
+
lines.push(`### Refusal contract${wisdomLabel}`);
|
|
674
|
+
lines.push("");
|
|
675
|
+
lines.push(`**${d.refusalContract}**`);
|
|
676
|
+
lines.push("");
|
|
677
|
+
if (d.requiredComponents.length > 0) {
|
|
678
|
+
lines.push("**Required components** (all must be present):");
|
|
679
|
+
for (const comp of d.requiredComponents) {
|
|
680
|
+
lines.push(`- ${comp}`);
|
|
681
|
+
}
|
|
682
|
+
lines.push("");
|
|
683
|
+
}
|
|
684
|
+
if (d.shapeTemplate) {
|
|
685
|
+
lines.push("**Output shape**:");
|
|
686
|
+
lines.push("");
|
|
687
|
+
lines.push("```");
|
|
688
|
+
lines.push(d.shapeTemplate);
|
|
689
|
+
lines.push("```");
|
|
690
|
+
lines.push("");
|
|
691
|
+
}
|
|
692
|
+
if (d.reason) {
|
|
693
|
+
lines.push(`**Reason**: ${d.reason}`);
|
|
694
|
+
lines.push("");
|
|
695
|
+
}
|
|
696
|
+
if (d.crossReferences && d.crossReferences.length > 0) {
|
|
697
|
+
lines.push(`**Cross-references**: ${d.crossReferences.join(", ")}`);
|
|
698
|
+
lines.push("");
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
this.appendProseAfter(lines, ast, "date_discipline");
|
|
702
|
+
}
|
|
703
|
+
if (ast.citationRules.length > 0) {
|
|
704
|
+
lines.push(`## Citation discipline`);
|
|
705
|
+
lines.push("");
|
|
706
|
+
for (const rule of ast.citationRules) {
|
|
707
|
+
lines.push(
|
|
708
|
+
`- Fluent prose over **${rule.fluentProseThresholdChars} chars** must include one of: ${rule.required.join(", ")}`
|
|
709
|
+
);
|
|
710
|
+
if (rule.exemption) {
|
|
711
|
+
lines.push(` - Exemption: ${rule.exemption}`);
|
|
712
|
+
}
|
|
713
|
+
if (rule.reason) {
|
|
714
|
+
lines.push(` - Reason: ${rule.reason}`);
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
lines.push("");
|
|
718
|
+
this.appendProseAfter(lines, ast, "citation_rule");
|
|
719
|
+
}
|
|
720
|
+
if (ast.graduatedWisdoms.length > 0 || ast.feedbacks.length > 0) {
|
|
721
|
+
lines.push(`## Authority cross-references`);
|
|
722
|
+
lines.push("");
|
|
723
|
+
if (ast.graduatedWisdoms.length > 0) {
|
|
724
|
+
lines.push(`### GOLD-tier wisdom`);
|
|
725
|
+
lines.push("");
|
|
726
|
+
for (const wisdom of ast.graduatedWisdoms) {
|
|
727
|
+
lines.push(`- **${wisdom.id}** *(${wisdom.tier})* - ${wisdom.claim}`);
|
|
728
|
+
}
|
|
729
|
+
lines.push("");
|
|
730
|
+
}
|
|
731
|
+
if (ast.feedbacks.length > 0) {
|
|
732
|
+
lines.push(`### Feedback memory`);
|
|
733
|
+
lines.push("");
|
|
734
|
+
for (const fb of ast.feedbacks) {
|
|
735
|
+
const src = fb.source ? ` (${fb.source})` : "";
|
|
736
|
+
lines.push(`- **${fb.id}**${src} - ${fb.claim}`);
|
|
737
|
+
}
|
|
738
|
+
lines.push("");
|
|
739
|
+
}
|
|
740
|
+
this.appendProseAfter(lines, ast, "graduated_wisdom");
|
|
741
|
+
this.appendProseAfter(lines, ast, "feedback");
|
|
742
|
+
}
|
|
743
|
+
lines.push("---");
|
|
744
|
+
lines.push("");
|
|
745
|
+
lines.push(
|
|
746
|
+
`*Generated by HoloScript ContextCompiler (compile_to_claude_md). Source: HoloScript composition. Vocabulary: v3 (ratified 2026-05-07).*`
|
|
747
|
+
);
|
|
748
|
+
lines.push("");
|
|
749
|
+
return lines.join("\n");
|
|
750
|
+
}
|
|
751
|
+
// --- Phase 3: emit -- compile_to_agents_md -------------------------
|
|
752
|
+
/**
|
|
753
|
+
* Emit AGENTS.md - cross-tool agent context format. Read by Codex,
|
|
754
|
+
* Copilot, Cursor, Continue, Windsurf, Amp, Devin (any tool that
|
|
755
|
+
* follows the AGENTS.md convention seeded by the Codex docs).
|
|
756
|
+
*
|
|
757
|
+
* Differences from claude_md (per Phase 1 follow-up task spec):
|
|
758
|
+
* - "## Project principles" instead of "## Vision pillars"
|
|
759
|
+
* - "## Hard rules" instead of "## The Refusals" (Codex audience
|
|
760
|
+
* uses non-ritual rule-list framing; refusals + hard donts are
|
|
761
|
+
* merged into one flat ranked list under this single section)
|
|
762
|
+
* - "## Conventions" instead of "## Known defaults"
|
|
763
|
+
* - "## Workflows" instead of "## Skills" (Codex's closer term)
|
|
764
|
+
*
|
|
765
|
+
* Shared sections (authority order, output shape, production rule,
|
|
766
|
+
* hard physical gaps, recurring routines, escalation, citation
|
|
767
|
+
* discipline, authority cross-references) keep the same name across
|
|
768
|
+
* surfaces - those names are universal-context terms, not
|
|
769
|
+
* Claude-specific framings.
|
|
770
|
+
*/
|
|
771
|
+
emitAgentsMd(ast) {
|
|
772
|
+
const lines = [];
|
|
773
|
+
lines.push("# AGENTS.md");
|
|
774
|
+
lines.push("");
|
|
775
|
+
if (ast.identity) {
|
|
776
|
+
lines.push(`> **Role**: ${ast.identity.role}`);
|
|
777
|
+
lines.push(`> **Domain**: ${ast.identity.domain}`);
|
|
778
|
+
lines.push(
|
|
779
|
+
`> **Surface**: ${ast.identity.surface} (cross-tool: read by Codex, Copilot, Cursor, Continue, Windsurf, Amp, Devin)`
|
|
780
|
+
);
|
|
781
|
+
if (ast.identity.noMonopoly) {
|
|
782
|
+
lines.push(
|
|
783
|
+
`> **No-monopoly rule**: this context applies the absorb-as-adapter architectural posture (per docs/LLM_CAPABILITIES.md section Architectural posture).`
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
lines.push("");
|
|
787
|
+
}
|
|
788
|
+
for (const opening of ast.narrativeOpenings) {
|
|
789
|
+
const postureLines = opening.posture.split(/\r?\n/);
|
|
790
|
+
for (const pl of postureLines) {
|
|
791
|
+
lines.push(`> ${pl}`);
|
|
792
|
+
}
|
|
793
|
+
if (opening.reason) {
|
|
794
|
+
const reasonLines = opening.reason.split(/\r?\n/);
|
|
795
|
+
for (const rl of reasonLines) {
|
|
796
|
+
lines.push(`> ${rl}`);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
lines.push("");
|
|
800
|
+
}
|
|
801
|
+
if (ast.authorityOrder && ast.authorityOrder.tiers.length > 0) {
|
|
802
|
+
lines.push("## Authority order (read top-down; first match wins)");
|
|
803
|
+
lines.push("");
|
|
804
|
+
ast.authorityOrder.tiers.forEach((tier, idx) => {
|
|
805
|
+
lines.push(`${idx + 1}. **${tier}**`);
|
|
806
|
+
});
|
|
807
|
+
lines.push("");
|
|
808
|
+
this.appendProseAfter(lines, ast, "authority_order");
|
|
809
|
+
}
|
|
810
|
+
if (ast.visionPillars.length > 0) {
|
|
811
|
+
lines.push("## Project principles (follow; do not drift)");
|
|
812
|
+
lines.push("");
|
|
813
|
+
ast.visionPillars.forEach((pillar, idx) => {
|
|
814
|
+
const cite = pillar.citation ? ` *(${pillar.citation})*` : "";
|
|
815
|
+
lines.push(`${idx + 1}. **${pillar.claim}**${cite}`);
|
|
816
|
+
});
|
|
817
|
+
lines.push("");
|
|
818
|
+
this.appendProseAfter(lines, ast, "vision_pillar");
|
|
819
|
+
}
|
|
820
|
+
if (ast.refusals.length > 0 || ast.hardDonts.length > 0) {
|
|
821
|
+
lines.push("## Hard rules (The Four Refusals + cross-provider red lines)");
|
|
822
|
+
lines.push("");
|
|
823
|
+
lines.push(
|
|
824
|
+
"Rules below are non-negotiable. Each names what to do, what NOT to do, and why."
|
|
825
|
+
);
|
|
826
|
+
lines.push("");
|
|
827
|
+
for (const refusal of ast.refusals) {
|
|
828
|
+
lines.push(`### ${refusal.name}`);
|
|
829
|
+
lines.push("");
|
|
830
|
+
lines.push(`- **When**: ${refusal.when}`);
|
|
831
|
+
lines.push(`- **Do**: ${refusal.do}`);
|
|
832
|
+
if (refusal.doNot.length > 0) {
|
|
833
|
+
lines.push(`- **Do not**: ${refusal.doNot.map((d) => `\`${d}\``).join(", ")}`);
|
|
834
|
+
}
|
|
835
|
+
if (refusal.reason) {
|
|
836
|
+
lines.push(`- **Reason**: ${refusal.reason}`);
|
|
837
|
+
}
|
|
838
|
+
lines.push("");
|
|
839
|
+
}
|
|
840
|
+
for (const dont of ast.hardDonts) {
|
|
841
|
+
lines.push(`### ${dont.name}`);
|
|
842
|
+
lines.push("");
|
|
843
|
+
lines.push(`- **Reason**: ${dont.reason}`);
|
|
844
|
+
if (dont.alternative) {
|
|
845
|
+
lines.push(`- **Alternative**: ${dont.alternative}`);
|
|
846
|
+
}
|
|
847
|
+
if (dont.appliesTo.length > 0) {
|
|
848
|
+
lines.push(`- **Applies to**: ${dont.appliesTo.join(", ")}`);
|
|
849
|
+
}
|
|
850
|
+
lines.push("");
|
|
851
|
+
}
|
|
852
|
+
this.appendProseAfter(lines, ast, "refusal");
|
|
853
|
+
this.appendProseAfter(lines, ast, "hard_dont");
|
|
854
|
+
}
|
|
855
|
+
if (ast.defaults.length > 0) {
|
|
856
|
+
lines.push("## Conventions (answer immediately)");
|
|
857
|
+
lines.push("");
|
|
858
|
+
lines.push("| When | Do | Reason |");
|
|
859
|
+
lines.push("|---|---|---|");
|
|
860
|
+
for (const def of ast.defaults) {
|
|
861
|
+
lines.push(
|
|
862
|
+
`| ${def.when} | **${def.do}** | ${def.reason ?? "*(no citation)*"} |`
|
|
863
|
+
);
|
|
864
|
+
}
|
|
865
|
+
lines.push("");
|
|
866
|
+
this.appendProseAfter(lines, ast, "default");
|
|
867
|
+
}
|
|
868
|
+
if (ast.domainPreferences.length > 0) {
|
|
869
|
+
lines.push("## Domain preferences (beyond engineering)");
|
|
870
|
+
lines.push("");
|
|
871
|
+
lines.push("| Domain | Skills to delegate to | Notes / ceiling |");
|
|
872
|
+
lines.push("|---|---|---|");
|
|
873
|
+
for (const pref of ast.domainPreferences) {
|
|
874
|
+
const skills = pref.skills.length > 0 ? pref.skills.map((s) => `\`${s}\``).join(", ") : "*(in-skill default)*";
|
|
875
|
+
const notesParts = [];
|
|
876
|
+
if (pref.ceiling) notesParts.push(`Ceiling: ${pref.ceiling}`);
|
|
877
|
+
if (pref.notes) notesParts.push(pref.notes);
|
|
878
|
+
const notes = notesParts.join("; ") || "";
|
|
879
|
+
lines.push(`| **${pref.domain}** | ${skills} | ${notes} |`);
|
|
880
|
+
}
|
|
881
|
+
lines.push("");
|
|
882
|
+
this.appendProseAfter(lines, ast, "domain_preference");
|
|
883
|
+
}
|
|
884
|
+
this.appendTrackBAuthority(lines, ast);
|
|
885
|
+
this.appendProseAfter(lines, ast, "authority");
|
|
886
|
+
this.appendPapersProgramDefaults(lines, ast);
|
|
887
|
+
this.appendProseAfter(lines, ast, "editorial_default");
|
|
888
|
+
this.appendProseAfter(lines, ast, "research_default");
|
|
889
|
+
if (ast.outputShape) {
|
|
890
|
+
lines.push("## Output shape \u2014 SILENT-TO-JOSEPH, LOUD-TO-THE-AGENT");
|
|
891
|
+
lines.push("");
|
|
892
|
+
lines.push(`- **Silent to**: ${ast.outputShape.silentTo}`);
|
|
893
|
+
lines.push(`- **Loud to**: ${ast.outputShape.loudTo}`);
|
|
894
|
+
if (ast.outputShape.noMetaOutput) {
|
|
895
|
+
lines.push("- **No meta-output**: do not narrate the protocol back to the user");
|
|
896
|
+
}
|
|
897
|
+
if (ast.outputShape.surfaceHint) {
|
|
898
|
+
lines.push(`- **Surface hint**: ${ast.outputShape.surfaceHint}`);
|
|
899
|
+
}
|
|
900
|
+
lines.push("");
|
|
901
|
+
this.appendProseAfter(lines, ast, "output_shape");
|
|
902
|
+
}
|
|
903
|
+
if (ast.productionRule) {
|
|
904
|
+
lines.push("## Production-only rule (no dev, no mock, no localhost)");
|
|
905
|
+
lines.push("");
|
|
906
|
+
if (ast.productionRule.noDevNoMockNoLocalhost) {
|
|
907
|
+
lines.push("No dev. No mock. No localhost. The real service exists - hit it.");
|
|
908
|
+
}
|
|
909
|
+
if (ast.productionRule.exception) {
|
|
910
|
+
lines.push("");
|
|
911
|
+
lines.push(`**Exception**: ${ast.productionRule.exception}`);
|
|
912
|
+
}
|
|
913
|
+
lines.push("");
|
|
914
|
+
this.appendProseAfter(lines, ast, "production_rule");
|
|
915
|
+
}
|
|
916
|
+
if (ast.hardPhysicalGaps.length > 0) {
|
|
917
|
+
lines.push("## Hard physical gaps (never absorb)");
|
|
918
|
+
lines.push("");
|
|
919
|
+
for (const gap of ast.hardPhysicalGaps) {
|
|
920
|
+
lines.push(`- **${gap.name}** - ${gap.reason}`);
|
|
921
|
+
if (gap.alternative) {
|
|
922
|
+
lines.push(` - Alternative: ${gap.alternative}`);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
lines.push("");
|
|
926
|
+
this.appendProseAfter(lines, ast, "hard_physical_gap");
|
|
927
|
+
}
|
|
928
|
+
if (ast.skills.length > 0) {
|
|
929
|
+
lines.push("## Workflows");
|
|
930
|
+
lines.push("");
|
|
931
|
+
for (const skill of ast.skills) {
|
|
932
|
+
lines.push(`### ${skill.name} (\`${skill.invocableAs}\`)`);
|
|
933
|
+
lines.push("");
|
|
934
|
+
lines.push(`- **Authority**: ${skill.authority}`);
|
|
935
|
+
if (skill.authoritativeFor.length > 0) {
|
|
936
|
+
lines.push(`- **Authoritative for**: ${skill.authoritativeFor.join(", ")}`);
|
|
937
|
+
}
|
|
938
|
+
if (skill.refusals && skill.refusals.length > 0) {
|
|
939
|
+
lines.push(`- **Enforces rules**: ${skill.refusals.join(", ")}`);
|
|
940
|
+
}
|
|
941
|
+
lines.push("");
|
|
942
|
+
}
|
|
943
|
+
this.appendProseAfter(lines, ast, "skill");
|
|
944
|
+
}
|
|
945
|
+
if (ast.invocationModes.length > 0) {
|
|
946
|
+
lines.push("## Invocation modes (Track D)");
|
|
947
|
+
lines.push("");
|
|
948
|
+
for (const mode of ast.invocationModes) {
|
|
949
|
+
lines.push(`### ${mode.mode}`);
|
|
950
|
+
lines.push("");
|
|
951
|
+
lines.push(`- **When**: ${mode.when}`);
|
|
952
|
+
lines.push(`- **Effect**: ${mode.effect}`);
|
|
953
|
+
if (mode.example) {
|
|
954
|
+
lines.push(`- **Example**: \`${mode.example}\``);
|
|
955
|
+
}
|
|
956
|
+
lines.push("");
|
|
957
|
+
}
|
|
958
|
+
this.appendProseAfter(lines, ast, "invocation_mode");
|
|
959
|
+
}
|
|
960
|
+
appendEmbodiedProjectionSection(lines, ast.embodiedProjections);
|
|
961
|
+
this.appendProseAfter(lines, ast, "embodied_projection");
|
|
962
|
+
if (ast.routines.length > 0) {
|
|
963
|
+
lines.push("## Recurring routines (A-00X)");
|
|
964
|
+
lines.push("");
|
|
965
|
+
lines.push("| ID | Schedule | Skill | Output |");
|
|
966
|
+
lines.push("|---|---|---|---|");
|
|
967
|
+
for (const routine of ast.routines) {
|
|
968
|
+
lines.push(
|
|
969
|
+
`| ${routine.id} | \`${routine.schedule}\` | ${routine.skill} | ${routine.outputDir ?? "*(varies)*"} |`
|
|
970
|
+
);
|
|
971
|
+
}
|
|
972
|
+
lines.push("");
|
|
973
|
+
this.appendProseAfter(lines, ast, "routine");
|
|
974
|
+
}
|
|
975
|
+
if (ast.escalations.length > 0) {
|
|
976
|
+
lines.push("## Escape hatch");
|
|
977
|
+
lines.push("");
|
|
978
|
+
for (const esc of ast.escalations) {
|
|
979
|
+
lines.push(`- **Trigger**: ${esc.trigger}`);
|
|
980
|
+
lines.push(` - **Action**: ${esc.doAction}`);
|
|
981
|
+
lines.push(` - **Recipient**: ${esc.recipient}`);
|
|
982
|
+
if (esc.refuseToEscalateWhen.length > 0) {
|
|
983
|
+
lines.push(
|
|
984
|
+
` - **Refuse to escalate when**: ${esc.refuseToEscalateWhen.join(", ")}`
|
|
985
|
+
);
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
lines.push("");
|
|
989
|
+
this.appendProseAfter(lines, ast, "escalation");
|
|
990
|
+
}
|
|
991
|
+
if (ast.dateDisciplines.length > 0) {
|
|
992
|
+
const firstWisdom = ast.dateDisciplines[0]?.wisdomId;
|
|
993
|
+
const wisdomSuffix = ast.dateDisciplines.length === 1 && firstWisdom ? ` (${firstWisdom})` : "";
|
|
994
|
+
lines.push(`## Date discipline${wisdomSuffix}`);
|
|
995
|
+
lines.push("");
|
|
996
|
+
for (const d of ast.dateDisciplines) {
|
|
997
|
+
const wisdomLabel = d.wisdomId ? ` (${d.wisdomId})` : "";
|
|
998
|
+
lines.push(`### Refusal contract${wisdomLabel}`);
|
|
999
|
+
lines.push("");
|
|
1000
|
+
lines.push(`**${d.refusalContract}**`);
|
|
1001
|
+
lines.push("");
|
|
1002
|
+
if (d.requiredComponents.length > 0) {
|
|
1003
|
+
lines.push("**Required components** (all must be present):");
|
|
1004
|
+
for (const comp of d.requiredComponents) {
|
|
1005
|
+
lines.push(`- ${comp}`);
|
|
1006
|
+
}
|
|
1007
|
+
lines.push("");
|
|
1008
|
+
}
|
|
1009
|
+
if (d.shapeTemplate) {
|
|
1010
|
+
lines.push("**Output shape**:");
|
|
1011
|
+
lines.push("");
|
|
1012
|
+
lines.push("```");
|
|
1013
|
+
lines.push(d.shapeTemplate);
|
|
1014
|
+
lines.push("```");
|
|
1015
|
+
lines.push("");
|
|
1016
|
+
}
|
|
1017
|
+
if (d.reason) {
|
|
1018
|
+
lines.push(`**Reason**: ${d.reason}`);
|
|
1019
|
+
lines.push("");
|
|
1020
|
+
}
|
|
1021
|
+
if (d.crossReferences && d.crossReferences.length > 0) {
|
|
1022
|
+
lines.push(`**Cross-references**: ${d.crossReferences.join(", ")}`);
|
|
1023
|
+
lines.push("");
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
this.appendProseAfter(lines, ast, "date_discipline");
|
|
1027
|
+
}
|
|
1028
|
+
if (ast.citationRules.length > 0) {
|
|
1029
|
+
lines.push("## Citation discipline");
|
|
1030
|
+
lines.push("");
|
|
1031
|
+
for (const rule of ast.citationRules) {
|
|
1032
|
+
lines.push(
|
|
1033
|
+
`- Fluent prose over **${rule.fluentProseThresholdChars} chars** must include one of: ${rule.required.join(", ")}`
|
|
1034
|
+
);
|
|
1035
|
+
if (rule.exemption) {
|
|
1036
|
+
lines.push(` - Exemption: ${rule.exemption}`);
|
|
1037
|
+
}
|
|
1038
|
+
if (rule.reason) {
|
|
1039
|
+
lines.push(` - Reason: ${rule.reason}`);
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
lines.push("");
|
|
1043
|
+
this.appendProseAfter(lines, ast, "citation_rule");
|
|
1044
|
+
}
|
|
1045
|
+
if (ast.graduatedWisdoms.length > 0 || ast.feedbacks.length > 0) {
|
|
1046
|
+
lines.push("## Authority cross-references");
|
|
1047
|
+
lines.push("");
|
|
1048
|
+
if (ast.graduatedWisdoms.length > 0) {
|
|
1049
|
+
lines.push("### GOLD-tier wisdom");
|
|
1050
|
+
lines.push("");
|
|
1051
|
+
for (const wisdom of ast.graduatedWisdoms) {
|
|
1052
|
+
lines.push(`- **${wisdom.id}** *(${wisdom.tier})* - ${wisdom.claim}`);
|
|
1053
|
+
}
|
|
1054
|
+
lines.push("");
|
|
1055
|
+
}
|
|
1056
|
+
if (ast.feedbacks.length > 0) {
|
|
1057
|
+
lines.push("### Feedback memory");
|
|
1058
|
+
lines.push("");
|
|
1059
|
+
for (const fb of ast.feedbacks) {
|
|
1060
|
+
const src = fb.source ? ` (${fb.source})` : "";
|
|
1061
|
+
lines.push(`- **${fb.id}**${src} - ${fb.claim}`);
|
|
1062
|
+
}
|
|
1063
|
+
lines.push("");
|
|
1064
|
+
}
|
|
1065
|
+
this.appendProseAfter(lines, ast, "graduated_wisdom");
|
|
1066
|
+
this.appendProseAfter(lines, ast, "feedback");
|
|
1067
|
+
}
|
|
1068
|
+
lines.push("---");
|
|
1069
|
+
lines.push("");
|
|
1070
|
+
lines.push(
|
|
1071
|
+
`*Generated by HoloScript ContextCompiler (compile_to_agents_md). Source: HoloScript composition. Vocabulary: v3 (ratified 2026-05-07). Cross-tool: Codex, Copilot, Cursor, Continue, Windsurf, Amp, Devin.*`
|
|
1072
|
+
);
|
|
1073
|
+
lines.push("");
|
|
1074
|
+
return lines.join("\n");
|
|
1075
|
+
}
|
|
1076
|
+
// --- Phase 3: emit -- compile_to_cursor_rules ----------------------
|
|
1077
|
+
/**
|
|
1078
|
+
* Emit Cursor `.cursor/rules/*.mdc` files. Different output shape from
|
|
1079
|
+
* claude_md / agents_md - one file per rule rather than a single big
|
|
1080
|
+
* file (Cursor's idiom). Per spec:
|
|
1081
|
+
* research/2026-05-06_cursor-mdc-spec.md.
|
|
1082
|
+
*
|
|
1083
|
+
* Layout:
|
|
1084
|
+
* .cursor/rules/refusal-<name>.mdc (one per @refusal)
|
|
1085
|
+
* .cursor/rules/hard-dont-<name>.mdc (one per @hard_dont)
|
|
1086
|
+
* .cursor/rules/default-<name>.mdc (one per @default)
|
|
1087
|
+
* .cursor/rules/_ecosystem-context.mdc (top-level blocks: identity,
|
|
1088
|
+
* authority order, vision
|
|
1089
|
+
* pillars, production rule,
|
|
1090
|
+
* output shape, gaps, routines,
|
|
1091
|
+
* skill registry, cross-refs)
|
|
1092
|
+
*
|
|
1093
|
+
* Frontmatter v1: every file emits with `alwaysApply: true` and empty
|
|
1094
|
+
* `globs:`. Glob mapping from `applies_to` -> file patterns is deferred
|
|
1095
|
+
* to v2 (see spec memo § "What the emitter does NOT do (v1 scope)").
|
|
1096
|
+
*
|
|
1097
|
+
* Returns Record<string, string> with full repo-relative paths as keys
|
|
1098
|
+
* (e.g. ".cursor/rules/refusal-bandaid.mdc"). The consumer writes each
|
|
1099
|
+
* entry to disk at exactly that path.
|
|
1100
|
+
*/
|
|
1101
|
+
emitCursorRules(ast) {
|
|
1102
|
+
const out = {};
|
|
1103
|
+
for (const refusal of ast.refusals) {
|
|
1104
|
+
const slug = toCursorSlug(refusal.name);
|
|
1105
|
+
const filename = `.cursor/rules/refusal-${slug}.mdc`;
|
|
1106
|
+
const description = oneLine(
|
|
1107
|
+
`Refusal: ${refusal.name} - ${refusal.reason ?? refusal.when}`
|
|
1108
|
+
);
|
|
1109
|
+
const body = [];
|
|
1110
|
+
body.push(`# Refusal: ${refusal.name}`);
|
|
1111
|
+
body.push("");
|
|
1112
|
+
body.push(`**When**: ${refusal.when}`);
|
|
1113
|
+
body.push("");
|
|
1114
|
+
body.push(`**Do**: ${refusal.do}`);
|
|
1115
|
+
body.push("");
|
|
1116
|
+
if (refusal.doNot.length > 0) {
|
|
1117
|
+
body.push(`**Do not**: ${refusal.doNot.map((d) => `\`${d}\``).join(", ")}`);
|
|
1118
|
+
body.push("");
|
|
1119
|
+
}
|
|
1120
|
+
if (refusal.reason) {
|
|
1121
|
+
body.push(`**Reason**: ${refusal.reason}`);
|
|
1122
|
+
body.push("");
|
|
1123
|
+
}
|
|
1124
|
+
out[filename] = wrapMdc(description, body);
|
|
1125
|
+
}
|
|
1126
|
+
for (const dont of ast.hardDonts) {
|
|
1127
|
+
const slug = toCursorSlug(dont.name);
|
|
1128
|
+
const filename = `.cursor/rules/hard-dont-${slug}.mdc`;
|
|
1129
|
+
const description = oneLine(`Hard don't: ${dont.name} - ${dont.reason}`);
|
|
1130
|
+
const body = [];
|
|
1131
|
+
body.push(`# Hard don't: ${dont.name}`);
|
|
1132
|
+
body.push("");
|
|
1133
|
+
body.push(`**Reason**: ${dont.reason}`);
|
|
1134
|
+
body.push("");
|
|
1135
|
+
if (dont.alternative) {
|
|
1136
|
+
body.push(`**Alternative**: ${dont.alternative}`);
|
|
1137
|
+
body.push("");
|
|
1138
|
+
}
|
|
1139
|
+
if (dont.appliesTo.length > 0) {
|
|
1140
|
+
body.push(`**Applies to**: ${dont.appliesTo.join(", ")}`);
|
|
1141
|
+
body.push("");
|
|
1142
|
+
}
|
|
1143
|
+
out[filename] = wrapMdc(description, body);
|
|
1144
|
+
}
|
|
1145
|
+
for (const def of ast.defaults) {
|
|
1146
|
+
const slug = toCursorSlug(def.name);
|
|
1147
|
+
const filename = `.cursor/rules/default-${slug}.mdc`;
|
|
1148
|
+
const description = oneLine(`Default: ${def.name} - ${def.when}`);
|
|
1149
|
+
const body = [];
|
|
1150
|
+
body.push(`# Default: ${def.name}`);
|
|
1151
|
+
body.push("");
|
|
1152
|
+
body.push(`**When**: ${def.when}`);
|
|
1153
|
+
body.push("");
|
|
1154
|
+
body.push(`**Do**: ${def.do}`);
|
|
1155
|
+
body.push("");
|
|
1156
|
+
if (def.reason) {
|
|
1157
|
+
body.push(`**Reason**: ${def.reason}`);
|
|
1158
|
+
body.push("");
|
|
1159
|
+
}
|
|
1160
|
+
out[filename] = wrapMdc(description, body);
|
|
1161
|
+
}
|
|
1162
|
+
const indexFilename = ".cursor/rules/_ecosystem-context.mdc";
|
|
1163
|
+
const indexDescription = ast.identity ? oneLine(`Ecosystem context for ${ast.identity.name} (${ast.identity.role})`) : "Ecosystem context (HoloScript-generated)";
|
|
1164
|
+
const idx = [];
|
|
1165
|
+
if (ast.identity) {
|
|
1166
|
+
idx.push(`# ${ast.identity.name}`);
|
|
1167
|
+
idx.push("");
|
|
1168
|
+
idx.push(`**Role**: ${ast.identity.role}`);
|
|
1169
|
+
idx.push(`**Domain**: ${ast.identity.domain}`);
|
|
1170
|
+
idx.push(`**Surface**: ${ast.identity.surface}`);
|
|
1171
|
+
if (ast.identity.noMonopoly) {
|
|
1172
|
+
idx.push("");
|
|
1173
|
+
idx.push(
|
|
1174
|
+
"No-monopoly rule: this context applies the absorb-as-adapter architectural posture (per docs/LLM_CAPABILITIES.md)."
|
|
1175
|
+
);
|
|
1176
|
+
}
|
|
1177
|
+
idx.push("");
|
|
1178
|
+
} else {
|
|
1179
|
+
idx.push("# Ecosystem context");
|
|
1180
|
+
idx.push("");
|
|
1181
|
+
}
|
|
1182
|
+
for (const opening of ast.narrativeOpenings) {
|
|
1183
|
+
const postureLines = opening.posture.split(/\r?\n/);
|
|
1184
|
+
for (const pl of postureLines) {
|
|
1185
|
+
idx.push(`> ${pl}`);
|
|
1186
|
+
}
|
|
1187
|
+
if (opening.reason) {
|
|
1188
|
+
const reasonLines = opening.reason.split(/\r?\n/);
|
|
1189
|
+
for (const rl of reasonLines) {
|
|
1190
|
+
idx.push(`> ${rl}`);
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
idx.push("");
|
|
1194
|
+
}
|
|
1195
|
+
if (ast.authorityOrder && ast.authorityOrder.tiers.length > 0) {
|
|
1196
|
+
idx.push("## Authority order (read top-down; first match wins)");
|
|
1197
|
+
idx.push("");
|
|
1198
|
+
ast.authorityOrder.tiers.forEach((tier, i) => {
|
|
1199
|
+
idx.push(`${i + 1}. **${tier}**`);
|
|
1200
|
+
});
|
|
1201
|
+
idx.push("");
|
|
1202
|
+
this.appendProseAfter(idx, ast, "authority_order");
|
|
1203
|
+
}
|
|
1204
|
+
if (ast.visionPillars.length > 0) {
|
|
1205
|
+
idx.push("## Vision pillars (follow; do not drift)");
|
|
1206
|
+
idx.push("");
|
|
1207
|
+
ast.visionPillars.forEach((pillar, i) => {
|
|
1208
|
+
const cite = pillar.citation ? ` *(${pillar.citation})*` : "";
|
|
1209
|
+
idx.push(`${i + 1}. **${pillar.claim}**${cite}`);
|
|
1210
|
+
});
|
|
1211
|
+
idx.push("");
|
|
1212
|
+
this.appendProseAfter(idx, ast, "vision_pillar");
|
|
1213
|
+
}
|
|
1214
|
+
if (ast.domainPreferences.length > 0) {
|
|
1215
|
+
idx.push("## Domain preferences (beyond engineering)");
|
|
1216
|
+
idx.push("");
|
|
1217
|
+
idx.push("| Domain | Skills to delegate to | Notes / ceiling |");
|
|
1218
|
+
idx.push("|---|---|---|");
|
|
1219
|
+
for (const pref of ast.domainPreferences) {
|
|
1220
|
+
const skills = pref.skills.length > 0 ? pref.skills.map((s) => `\`${s}\``).join(", ") : "*(in-skill default)*";
|
|
1221
|
+
const notesParts = [];
|
|
1222
|
+
if (pref.ceiling) notesParts.push(`Ceiling: ${pref.ceiling}`);
|
|
1223
|
+
if (pref.notes) notesParts.push(pref.notes);
|
|
1224
|
+
const notes = notesParts.join("; ") || "";
|
|
1225
|
+
idx.push(`| **${pref.domain}** | ${skills} | ${notes} |`);
|
|
1226
|
+
}
|
|
1227
|
+
idx.push("");
|
|
1228
|
+
this.appendProseAfter(idx, ast, "domain_preference");
|
|
1229
|
+
}
|
|
1230
|
+
this.appendTrackBAuthority(idx, ast);
|
|
1231
|
+
this.appendProseAfter(idx, ast, "authority");
|
|
1232
|
+
this.appendPapersProgramDefaults(idx, ast);
|
|
1233
|
+
this.appendProseAfter(idx, ast, "editorial_default");
|
|
1234
|
+
this.appendProseAfter(idx, ast, "research_default");
|
|
1235
|
+
if (ast.outputShape) {
|
|
1236
|
+
idx.push("## Output shape \u2014 SILENT-TO-JOSEPH, LOUD-TO-THE-AGENT");
|
|
1237
|
+
idx.push("");
|
|
1238
|
+
idx.push(`- **Silent to**: ${ast.outputShape.silentTo}`);
|
|
1239
|
+
idx.push(`- **Loud to**: ${ast.outputShape.loudTo}`);
|
|
1240
|
+
if (ast.outputShape.noMetaOutput) {
|
|
1241
|
+
idx.push("- **No meta-output**: do not narrate the protocol back to the user");
|
|
1242
|
+
}
|
|
1243
|
+
if (ast.outputShape.surfaceHint) {
|
|
1244
|
+
idx.push(`- **Surface hint**: ${ast.outputShape.surfaceHint}`);
|
|
1245
|
+
}
|
|
1246
|
+
idx.push("");
|
|
1247
|
+
this.appendProseAfter(idx, ast, "output_shape");
|
|
1248
|
+
}
|
|
1249
|
+
if (ast.productionRule) {
|
|
1250
|
+
idx.push("## Production-only rule (no dev, no mock, no localhost)");
|
|
1251
|
+
idx.push("");
|
|
1252
|
+
if (ast.productionRule.noDevNoMockNoLocalhost) {
|
|
1253
|
+
idx.push("No dev. No mock. No localhost. The real service exists - hit it.");
|
|
1254
|
+
}
|
|
1255
|
+
if (ast.productionRule.exception) {
|
|
1256
|
+
idx.push("");
|
|
1257
|
+
idx.push(`**Exception**: ${ast.productionRule.exception}`);
|
|
1258
|
+
}
|
|
1259
|
+
idx.push("");
|
|
1260
|
+
this.appendProseAfter(idx, ast, "production_rule");
|
|
1261
|
+
}
|
|
1262
|
+
if (ast.hardPhysicalGaps.length > 0) {
|
|
1263
|
+
idx.push("## Hard physical gaps (skill never absorbs)");
|
|
1264
|
+
idx.push("");
|
|
1265
|
+
for (const gap of ast.hardPhysicalGaps) {
|
|
1266
|
+
idx.push(`- **${gap.name}** - ${gap.reason}`);
|
|
1267
|
+
if (gap.alternative) {
|
|
1268
|
+
idx.push(` - Alternative: ${gap.alternative}`);
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
idx.push("");
|
|
1272
|
+
this.appendProseAfter(idx, ast, "hard_physical_gap");
|
|
1273
|
+
}
|
|
1274
|
+
if (ast.skills.length > 0) {
|
|
1275
|
+
idx.push("## Skill registry");
|
|
1276
|
+
idx.push("");
|
|
1277
|
+
for (const skill of ast.skills) {
|
|
1278
|
+
idx.push(`- **${skill.invocableAs}** (${skill.name}) - ${skill.authority}`);
|
|
1279
|
+
}
|
|
1280
|
+
idx.push("");
|
|
1281
|
+
this.appendProseAfter(idx, ast, "skill");
|
|
1282
|
+
}
|
|
1283
|
+
if (ast.invocationModes.length > 0) {
|
|
1284
|
+
idx.push("## Invocation modes (Track D)");
|
|
1285
|
+
idx.push("");
|
|
1286
|
+
for (const mode of ast.invocationModes) {
|
|
1287
|
+
idx.push(`### ${mode.mode}`);
|
|
1288
|
+
idx.push("");
|
|
1289
|
+
idx.push(`- **When**: ${mode.when}`);
|
|
1290
|
+
idx.push(`- **Effect**: ${mode.effect}`);
|
|
1291
|
+
if (mode.example) {
|
|
1292
|
+
idx.push(`- **Example**: \`${mode.example}\``);
|
|
1293
|
+
}
|
|
1294
|
+
idx.push("");
|
|
1295
|
+
}
|
|
1296
|
+
this.appendProseAfter(idx, ast, "invocation_mode");
|
|
1297
|
+
}
|
|
1298
|
+
appendEmbodiedProjectionSection(idx, ast.embodiedProjections);
|
|
1299
|
+
this.appendProseAfter(idx, ast, "embodied_projection");
|
|
1300
|
+
if (ast.routines.length > 0) {
|
|
1301
|
+
idx.push("## Recurring routines (A-00X)");
|
|
1302
|
+
idx.push("");
|
|
1303
|
+
idx.push("| ID | Schedule | Skill | Output |");
|
|
1304
|
+
idx.push("|---|---|---|---|");
|
|
1305
|
+
for (const routine of ast.routines) {
|
|
1306
|
+
idx.push(
|
|
1307
|
+
`| ${routine.id} | \`${routine.schedule}\` | ${routine.skill} | ${routine.outputDir ?? "*(varies)*"} |`
|
|
1308
|
+
);
|
|
1309
|
+
}
|
|
1310
|
+
idx.push("");
|
|
1311
|
+
this.appendProseAfter(idx, ast, "routine");
|
|
1312
|
+
}
|
|
1313
|
+
if (ast.escalations.length > 0) {
|
|
1314
|
+
idx.push("## Escape hatch");
|
|
1315
|
+
idx.push("");
|
|
1316
|
+
for (const esc of ast.escalations) {
|
|
1317
|
+
idx.push(`- **Trigger**: ${esc.trigger}`);
|
|
1318
|
+
idx.push(` - **Action**: ${esc.doAction}`);
|
|
1319
|
+
idx.push(` - **Recipient**: ${esc.recipient}`);
|
|
1320
|
+
if (esc.refuseToEscalateWhen.length > 0) {
|
|
1321
|
+
idx.push(
|
|
1322
|
+
` - **Refuse to escalate when**: ${esc.refuseToEscalateWhen.join(", ")}`
|
|
1323
|
+
);
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
idx.push("");
|
|
1327
|
+
this.appendProseAfter(idx, ast, "escalation");
|
|
1328
|
+
}
|
|
1329
|
+
if (ast.dateDisciplines.length > 0) {
|
|
1330
|
+
const firstWisdom = ast.dateDisciplines[0]?.wisdomId;
|
|
1331
|
+
const wisdomSuffix = ast.dateDisciplines.length === 1 && firstWisdom ? ` (${firstWisdom})` : "";
|
|
1332
|
+
idx.push(`## Date discipline${wisdomSuffix}`);
|
|
1333
|
+
idx.push("");
|
|
1334
|
+
for (const d of ast.dateDisciplines) {
|
|
1335
|
+
const wisdomLabel = d.wisdomId ? ` (${d.wisdomId})` : "";
|
|
1336
|
+
idx.push(`### Refusal contract${wisdomLabel}`);
|
|
1337
|
+
idx.push("");
|
|
1338
|
+
idx.push(`**${d.refusalContract}**`);
|
|
1339
|
+
idx.push("");
|
|
1340
|
+
if (d.requiredComponents.length > 0) {
|
|
1341
|
+
idx.push("**Required components** (all must be present):");
|
|
1342
|
+
for (const comp of d.requiredComponents) {
|
|
1343
|
+
idx.push(`- ${comp}`);
|
|
1344
|
+
}
|
|
1345
|
+
idx.push("");
|
|
1346
|
+
}
|
|
1347
|
+
if (d.shapeTemplate) {
|
|
1348
|
+
idx.push("**Output shape**:");
|
|
1349
|
+
idx.push("");
|
|
1350
|
+
idx.push("```");
|
|
1351
|
+
idx.push(d.shapeTemplate);
|
|
1352
|
+
idx.push("```");
|
|
1353
|
+
idx.push("");
|
|
1354
|
+
}
|
|
1355
|
+
if (d.reason) {
|
|
1356
|
+
idx.push(`**Reason**: ${d.reason}`);
|
|
1357
|
+
idx.push("");
|
|
1358
|
+
}
|
|
1359
|
+
if (d.crossReferences && d.crossReferences.length > 0) {
|
|
1360
|
+
idx.push(`**Cross-references**: ${d.crossReferences.join(", ")}`);
|
|
1361
|
+
idx.push("");
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
this.appendProseAfter(idx, ast, "date_discipline");
|
|
1365
|
+
}
|
|
1366
|
+
if (ast.citationRules.length > 0) {
|
|
1367
|
+
idx.push("## Citation discipline");
|
|
1368
|
+
idx.push("");
|
|
1369
|
+
for (const rule of ast.citationRules) {
|
|
1370
|
+
idx.push(
|
|
1371
|
+
`- Fluent prose over **${rule.fluentProseThresholdChars} chars** must include one of: ${rule.required.join(", ")}`
|
|
1372
|
+
);
|
|
1373
|
+
if (rule.exemption) {
|
|
1374
|
+
idx.push(` - Exemption: ${rule.exemption}`);
|
|
1375
|
+
}
|
|
1376
|
+
if (rule.reason) {
|
|
1377
|
+
idx.push(` - Reason: ${rule.reason}`);
|
|
1378
|
+
}
|
|
1379
|
+
}
|
|
1380
|
+
idx.push("");
|
|
1381
|
+
this.appendProseAfter(idx, ast, "citation_rule");
|
|
1382
|
+
}
|
|
1383
|
+
if (ast.graduatedWisdoms.length > 0 || ast.feedbacks.length > 0) {
|
|
1384
|
+
idx.push("## Authority cross-references");
|
|
1385
|
+
idx.push("");
|
|
1386
|
+
if (ast.graduatedWisdoms.length > 0) {
|
|
1387
|
+
idx.push("### GOLD-tier wisdom");
|
|
1388
|
+
idx.push("");
|
|
1389
|
+
for (const wisdom of ast.graduatedWisdoms) {
|
|
1390
|
+
idx.push(`- **${wisdom.id}** *(${wisdom.tier})* - ${wisdom.claim}`);
|
|
1391
|
+
}
|
|
1392
|
+
idx.push("");
|
|
1393
|
+
}
|
|
1394
|
+
if (ast.feedbacks.length > 0) {
|
|
1395
|
+
idx.push("### Feedback memory");
|
|
1396
|
+
idx.push("");
|
|
1397
|
+
for (const fb of ast.feedbacks) {
|
|
1398
|
+
const src = fb.source ? ` (${fb.source})` : "";
|
|
1399
|
+
idx.push(`- **${fb.id}**${src} - ${fb.claim}`);
|
|
1400
|
+
}
|
|
1401
|
+
idx.push("");
|
|
1402
|
+
}
|
|
1403
|
+
this.appendProseAfter(idx, ast, "graduated_wisdom");
|
|
1404
|
+
this.appendProseAfter(idx, ast, "feedback");
|
|
1405
|
+
}
|
|
1406
|
+
idx.push("---");
|
|
1407
|
+
idx.push("");
|
|
1408
|
+
idx.push(
|
|
1409
|
+
"*Generated by HoloScript ContextCompiler (compile_to_cursor_rules). Source: HoloScript composition. Vocabulary: v3 (ratified 2026-05-07). Per-rule files emit alongside this index under .cursor/rules/.*"
|
|
1410
|
+
);
|
|
1411
|
+
idx.push("");
|
|
1412
|
+
out[indexFilename] = wrapMdc(indexDescription, idx);
|
|
1413
|
+
return out;
|
|
1414
|
+
}
|
|
1415
|
+
// --- Phase 3: emit -- compile_to_skill_md --------------------------
|
|
1416
|
+
/**
|
|
1417
|
+
* Emit SKILL.md - Claude Code skill format. Read by Claude Code's
|
|
1418
|
+
* skill discovery system at `~/.claude/skills/<name>/SKILL.md` and
|
|
1419
|
+
* `<repo>/.claude/skills/<name>/SKILL.md` (per-window per-repo
|
|
1420
|
+
* skills are loaded into the available-skills block at session start).
|
|
1421
|
+
*
|
|
1422
|
+
* Format differs from claude_md / agents_md / cursor_rules: Claude
|
|
1423
|
+
* Code parses a YAML frontmatter block at the top of the file
|
|
1424
|
+
* (`name:`, `description:`, `allowed-tools:`) for skill registration,
|
|
1425
|
+
* THEN reads the markdown body as the skill prompt. The frontmatter
|
|
1426
|
+
* is what makes a SKILL.md invocable as `/<name>`.
|
|
1427
|
+
*
|
|
1428
|
+
* Phase 2(a) target: this emitter is the dependency for self-hosting
|
|
1429
|
+
* the founder skill - `compositions/founder.hs` becomes source-of-
|
|
1430
|
+
* truth, `~/.claude/skills/founder/SKILL.md` becomes the emitted
|
|
1431
|
+
* artifact. Round-trip parity is the validation gate.
|
|
1432
|
+
*
|
|
1433
|
+
* Source fields:
|
|
1434
|
+
* - frontmatter `name:` <- ContextIdentity.name
|
|
1435
|
+
* - frontmatter `description:` <- ContextIdentity.description (required
|
|
1436
|
+
* for skill discovery; emitter throws if missing - Claude Code
|
|
1437
|
+
* refuses to register a skill without one)
|
|
1438
|
+
* - frontmatter `allowed-tools:` <- ContextIdentity.allowedTools
|
|
1439
|
+
* (defaults to a sensible cross-tool set if omitted)
|
|
1440
|
+
*
|
|
1441
|
+
* Body sections mirror agents_md / claude_md - same vocabulary, same
|
|
1442
|
+
* authority order, same refusals, etc. - so the agent's operational
|
|
1443
|
+
* behavior is consistent across surfaces.
|
|
1444
|
+
*/
|
|
1445
|
+
emitSkillMd(ast) {
|
|
1446
|
+
if (!ast.identity) {
|
|
1447
|
+
throw new ContextCompileError(
|
|
1448
|
+
`compile_to_skill_md requires an @identity trait. Claude Code's skill discovery reads the YAML frontmatter \`name:\` field, which comes from ContextIdentity.name. Add an @identity block to the composition.`
|
|
1449
|
+
);
|
|
1450
|
+
}
|
|
1451
|
+
if (!ast.identity.description) {
|
|
1452
|
+
throw new ContextCompileError(
|
|
1453
|
+
`compile_to_skill_md requires @identity.description. Claude Code refuses to register a skill without a description (skill discovery gate). Add a 'description' field to the @identity trait.`
|
|
1454
|
+
);
|
|
1455
|
+
}
|
|
1456
|
+
const lines = [];
|
|
1457
|
+
lines.push("---");
|
|
1458
|
+
lines.push(`name: ${yamlScalar(ast.identity.name)}`);
|
|
1459
|
+
let enrichedDescription = ast.identity.description;
|
|
1460
|
+
if (ast.triggerPhrases.length > 0) {
|
|
1461
|
+
enrichedDescription += "\n\nTrigger phrases:";
|
|
1462
|
+
for (const tp of ast.triggerPhrases) {
|
|
1463
|
+
enrichedDescription += `
|
|
1464
|
+
- "${tp.phrase}"${tp.context ? ` (${tp.context})` : ""}`;
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
lines.push(formatYamlDescription(enrichedDescription));
|
|
1468
|
+
const tools = ast.identity.allowedTools && ast.identity.allowedTools.length > 0 ? ast.identity.allowedTools : ["Bash", "Read", "Write", "Edit", "Grep", "Glob", "WebFetch"];
|
|
1469
|
+
lines.push(`allowed-tools: ${tools.join(", ")}`);
|
|
1470
|
+
lines.push("---");
|
|
1471
|
+
lines.push("");
|
|
1472
|
+
lines.push(`# ${ast.identity.name}`);
|
|
1473
|
+
lines.push("");
|
|
1474
|
+
lines.push(`> **Role**: ${ast.identity.role}`);
|
|
1475
|
+
lines.push(`> **Domain**: ${ast.identity.domain}`);
|
|
1476
|
+
lines.push(`> **Surface**: ${ast.identity.surface}`);
|
|
1477
|
+
if (ast.identity.noMonopoly) {
|
|
1478
|
+
lines.push(
|
|
1479
|
+
`> **No-monopoly rule**: this skill applies the absorb-as-adapter architectural posture (per docs/LLM_CAPABILITIES.md section Architectural posture).`
|
|
1480
|
+
);
|
|
1481
|
+
}
|
|
1482
|
+
lines.push("");
|
|
1483
|
+
if (ast.identity.commandTemplate) {
|
|
1484
|
+
lines.push(`**Command**: ${ast.identity.commandTemplate}`);
|
|
1485
|
+
lines.push("");
|
|
1486
|
+
}
|
|
1487
|
+
for (const opening of ast.narrativeOpenings) {
|
|
1488
|
+
const postureLines = opening.posture.split(/\r?\n/);
|
|
1489
|
+
for (const pl of postureLines) {
|
|
1490
|
+
lines.push(`> ${pl}`);
|
|
1491
|
+
}
|
|
1492
|
+
if (opening.reason) {
|
|
1493
|
+
const reasonLines = opening.reason.split(/\r?\n/);
|
|
1494
|
+
for (const rl of reasonLines) {
|
|
1495
|
+
lines.push(`> ${rl}`);
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
lines.push("");
|
|
1499
|
+
}
|
|
1500
|
+
if (ast.authorityOrder && ast.authorityOrder.tiers.length > 0) {
|
|
1501
|
+
lines.push("## Authority order (read top-down; first match wins)");
|
|
1502
|
+
lines.push("");
|
|
1503
|
+
ast.authorityOrder.tiers.forEach((tier, idx) => {
|
|
1504
|
+
lines.push(`${idx + 1}. **${tier}**`);
|
|
1505
|
+
});
|
|
1506
|
+
lines.push("");
|
|
1507
|
+
this.appendProseAfter(lines, ast, "authority_order");
|
|
1508
|
+
}
|
|
1509
|
+
if (ast.visionPillars.length > 0) {
|
|
1510
|
+
lines.push("## Vision pillars (follow; do not drift)");
|
|
1511
|
+
lines.push("");
|
|
1512
|
+
ast.visionPillars.forEach((pillar, idx) => {
|
|
1513
|
+
const cite = pillar.citation ? ` *(${pillar.citation})*` : "";
|
|
1514
|
+
lines.push(`${idx + 1}. **${pillar.claim}**${cite}`);
|
|
1515
|
+
});
|
|
1516
|
+
lines.push("");
|
|
1517
|
+
this.appendProseAfter(lines, ast, "vision_pillar");
|
|
1518
|
+
}
|
|
1519
|
+
if (ast.refusals.length > 0) {
|
|
1520
|
+
lines.push("## The Four Refusals");
|
|
1521
|
+
lines.push("");
|
|
1522
|
+
lines.push(
|
|
1523
|
+
"These are not guidelines. They are refusals. If you catch yourself about to do any of the following, stop and reframe before continuing."
|
|
1524
|
+
);
|
|
1525
|
+
lines.push("");
|
|
1526
|
+
for (const refusal of ast.refusals) {
|
|
1527
|
+
lines.push(`### Refuse the ${refusal.name}`);
|
|
1528
|
+
lines.push("");
|
|
1529
|
+
lines.push(`**When**: ${refusal.when}`);
|
|
1530
|
+
lines.push("");
|
|
1531
|
+
lines.push(`**Do**: ${refusal.do}`);
|
|
1532
|
+
lines.push("");
|
|
1533
|
+
if (refusal.doNot.length > 0) {
|
|
1534
|
+
lines.push(`**Do not**: ${refusal.doNot.map((d) => `\`${d}\``).join(", ")}`);
|
|
1535
|
+
lines.push("");
|
|
1536
|
+
}
|
|
1537
|
+
if (refusal.reason) {
|
|
1538
|
+
lines.push(`**Reason**: ${refusal.reason}`);
|
|
1539
|
+
lines.push("");
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
this.appendProseAfter(lines, ast, "refusal");
|
|
1543
|
+
}
|
|
1544
|
+
if (ast.hardDonts.length > 0) {
|
|
1545
|
+
lines.push("## Hard don'ts (cross-provider red lines)");
|
|
1546
|
+
lines.push("");
|
|
1547
|
+
lines.push(`| Name | Reason | Alternative |`);
|
|
1548
|
+
lines.push(`|---|---|---|`);
|
|
1549
|
+
for (const dont of ast.hardDonts) {
|
|
1550
|
+
lines.push(
|
|
1551
|
+
`| **${dont.name}** | ${dont.reason} | ${dont.alternative ?? "*(none)*"} |`
|
|
1552
|
+
);
|
|
1553
|
+
}
|
|
1554
|
+
lines.push("");
|
|
1555
|
+
this.appendProseAfter(lines, ast, "hard_dont");
|
|
1556
|
+
}
|
|
1557
|
+
if (ast.defaults.length > 0) {
|
|
1558
|
+
lines.push("## Known founder defaults (answer immediately)");
|
|
1559
|
+
lines.push("");
|
|
1560
|
+
lines.push(`| When | Answer | Reason |`);
|
|
1561
|
+
lines.push(`|---|---|---|`);
|
|
1562
|
+
for (const def of ast.defaults) {
|
|
1563
|
+
lines.push(
|
|
1564
|
+
`| ${def.when} | **${def.do}** | ${def.reason ?? "*(no citation)*"} |`
|
|
1565
|
+
);
|
|
1566
|
+
}
|
|
1567
|
+
lines.push("");
|
|
1568
|
+
this.appendProseAfter(lines, ast, "default");
|
|
1569
|
+
}
|
|
1570
|
+
if (ast.domainPreferences.length > 0) {
|
|
1571
|
+
lines.push("## Domain preferences (beyond engineering)");
|
|
1572
|
+
lines.push("");
|
|
1573
|
+
lines.push("| Domain | Skills to delegate to | Notes / ceiling |");
|
|
1574
|
+
lines.push("|---|---|---|");
|
|
1575
|
+
for (const pref of ast.domainPreferences) {
|
|
1576
|
+
const skills = pref.skills.length > 0 ? pref.skills.map((s) => `\`${s}\``).join(", ") : "*(in-skill default)*";
|
|
1577
|
+
const notesParts = [];
|
|
1578
|
+
if (pref.ceiling) notesParts.push(`Ceiling: ${pref.ceiling}`);
|
|
1579
|
+
if (pref.notes) notesParts.push(pref.notes);
|
|
1580
|
+
const notes = notesParts.join("; ") || "";
|
|
1581
|
+
lines.push(`| **${pref.domain}** | ${skills} | ${notes} |`);
|
|
1582
|
+
}
|
|
1583
|
+
lines.push("");
|
|
1584
|
+
this.appendProseAfter(lines, ast, "domain_preference");
|
|
1585
|
+
}
|
|
1586
|
+
this.appendTrackBAuthority(lines, ast);
|
|
1587
|
+
this.appendProseAfter(lines, ast, "authority");
|
|
1588
|
+
this.appendPapersProgramDefaults(lines, ast);
|
|
1589
|
+
this.appendProseAfter(lines, ast, "editorial_default");
|
|
1590
|
+
this.appendProseAfter(lines, ast, "research_default");
|
|
1591
|
+
if (ast.outputShape) {
|
|
1592
|
+
lines.push("## Output shape \u2014 SILENT-TO-JOSEPH, LOUD-TO-THE-AGENT");
|
|
1593
|
+
lines.push("");
|
|
1594
|
+
lines.push(`- **Silent to**: ${ast.outputShape.silentTo}`);
|
|
1595
|
+
lines.push(`- **Loud to**: ${ast.outputShape.loudTo}`);
|
|
1596
|
+
if (ast.outputShape.noMetaOutput) {
|
|
1597
|
+
lines.push("- **No meta-output**: do not narrate the protocol back to the user");
|
|
1598
|
+
}
|
|
1599
|
+
if (ast.outputShape.surfaceHint) {
|
|
1600
|
+
lines.push(`- **Surface hint**: ${ast.outputShape.surfaceHint}`);
|
|
1601
|
+
}
|
|
1602
|
+
lines.push("");
|
|
1603
|
+
this.appendProseAfter(lines, ast, "output_shape");
|
|
1604
|
+
}
|
|
1605
|
+
if (ast.productionRule) {
|
|
1606
|
+
lines.push("## Production-only rule (no dev, no mock, no localhost)");
|
|
1607
|
+
lines.push("");
|
|
1608
|
+
if (ast.productionRule.noDevNoMockNoLocalhost) {
|
|
1609
|
+
lines.push("No dev. No mock. No localhost. The real service exists - hit it.");
|
|
1610
|
+
}
|
|
1611
|
+
if (ast.productionRule.exception) {
|
|
1612
|
+
lines.push("");
|
|
1613
|
+
lines.push(`**Exception**: ${ast.productionRule.exception}`);
|
|
1614
|
+
}
|
|
1615
|
+
lines.push("");
|
|
1616
|
+
this.appendProseAfter(lines, ast, "production_rule");
|
|
1617
|
+
}
|
|
1618
|
+
if (ast.hardPhysicalGaps.length > 0) {
|
|
1619
|
+
lines.push("## Hard physical gaps (skill never absorbs)");
|
|
1620
|
+
lines.push("");
|
|
1621
|
+
for (const gap of ast.hardPhysicalGaps) {
|
|
1622
|
+
lines.push(`- **${gap.name}** - ${gap.reason}`);
|
|
1623
|
+
if (gap.alternative) {
|
|
1624
|
+
lines.push(` - Alternative: ${gap.alternative}`);
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
lines.push("");
|
|
1628
|
+
this.appendProseAfter(lines, ast, "hard_physical_gap");
|
|
1629
|
+
}
|
|
1630
|
+
if (ast.skills.length > 0) {
|
|
1631
|
+
lines.push("## Skills this skill cross-references");
|
|
1632
|
+
lines.push("");
|
|
1633
|
+
for (const skill of ast.skills) {
|
|
1634
|
+
lines.push(`### \`${skill.invocableAs}\` - ${skill.name}`);
|
|
1635
|
+
lines.push("");
|
|
1636
|
+
lines.push(`**Authority**: ${skill.authority}`);
|
|
1637
|
+
lines.push("");
|
|
1638
|
+
if (skill.authoritativeFor.length > 0) {
|
|
1639
|
+
lines.push(`**Authoritative for**: ${skill.authoritativeFor.join(", ")}`);
|
|
1640
|
+
lines.push("");
|
|
1641
|
+
}
|
|
1642
|
+
if (skill.refusals && skill.refusals.length > 0) {
|
|
1643
|
+
lines.push(`**Refusals enforced**: ${skill.refusals.join(", ")}`);
|
|
1644
|
+
lines.push("");
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
this.appendProseAfter(lines, ast, "skill");
|
|
1648
|
+
}
|
|
1649
|
+
if (ast.invocationModes.length > 0) {
|
|
1650
|
+
lines.push("## Invocation modes (Track D)");
|
|
1651
|
+
lines.push("");
|
|
1652
|
+
for (const mode of ast.invocationModes) {
|
|
1653
|
+
lines.push(`### ${mode.mode}`);
|
|
1654
|
+
lines.push("");
|
|
1655
|
+
lines.push(`- **When**: ${mode.when}`);
|
|
1656
|
+
lines.push(`- **Effect**: ${mode.effect}`);
|
|
1657
|
+
if (mode.example) {
|
|
1658
|
+
lines.push(`- **Example**: \`${mode.example}\``);
|
|
1659
|
+
}
|
|
1660
|
+
lines.push("");
|
|
1661
|
+
}
|
|
1662
|
+
this.appendProseAfter(lines, ast, "invocation_mode");
|
|
1663
|
+
}
|
|
1664
|
+
appendEmbodiedProjectionSection(lines, ast.embodiedProjections);
|
|
1665
|
+
this.appendProseAfter(lines, ast, "embodied_projection");
|
|
1666
|
+
if (ast.routines.length > 0) {
|
|
1667
|
+
lines.push("## Recurring routines (A-00X)");
|
|
1668
|
+
lines.push("");
|
|
1669
|
+
lines.push(`| ID | Schedule | Skill | Output |`);
|
|
1670
|
+
lines.push(`|---|---|---|---|`);
|
|
1671
|
+
for (const routine of ast.routines) {
|
|
1672
|
+
lines.push(
|
|
1673
|
+
`| ${routine.id} | \`${routine.schedule}\` | ${routine.skill} | ${routine.outputDir ?? "*(varies)*"} |`
|
|
1674
|
+
);
|
|
1675
|
+
}
|
|
1676
|
+
lines.push("");
|
|
1677
|
+
this.appendProseAfter(lines, ast, "routine");
|
|
1678
|
+
}
|
|
1679
|
+
if (ast.escalations.length > 0) {
|
|
1680
|
+
lines.push("## Escape hatch");
|
|
1681
|
+
lines.push("");
|
|
1682
|
+
for (const esc of ast.escalations) {
|
|
1683
|
+
lines.push(`- **Trigger**: ${esc.trigger}`);
|
|
1684
|
+
lines.push(` - **Action**: ${esc.doAction}`);
|
|
1685
|
+
lines.push(` - **Recipient**: ${esc.recipient}`);
|
|
1686
|
+
if (esc.refuseToEscalateWhen.length > 0) {
|
|
1687
|
+
lines.push(
|
|
1688
|
+
` - **Refuse to escalate when**: ${esc.refuseToEscalateWhen.join(", ")}`
|
|
1689
|
+
);
|
|
1690
|
+
}
|
|
1691
|
+
}
|
|
1692
|
+
lines.push("");
|
|
1693
|
+
this.appendProseAfter(lines, ast, "escalation");
|
|
1694
|
+
}
|
|
1695
|
+
if (ast.dateDisciplines.length > 0) {
|
|
1696
|
+
const firstWisdom = ast.dateDisciplines[0]?.wisdomId;
|
|
1697
|
+
const wisdomSuffix = ast.dateDisciplines.length === 1 && firstWisdom ? ` (${firstWisdom})` : "";
|
|
1698
|
+
lines.push(`## Date discipline${wisdomSuffix}`);
|
|
1699
|
+
lines.push("");
|
|
1700
|
+
for (const d of ast.dateDisciplines) {
|
|
1701
|
+
const wisdomLabel = d.wisdomId ? ` (${d.wisdomId})` : "";
|
|
1702
|
+
lines.push(`### Refusal contract${wisdomLabel}`);
|
|
1703
|
+
lines.push("");
|
|
1704
|
+
lines.push(`**${d.refusalContract}**`);
|
|
1705
|
+
lines.push("");
|
|
1706
|
+
if (d.requiredComponents.length > 0) {
|
|
1707
|
+
lines.push("**Required components** (all must be present):");
|
|
1708
|
+
for (const comp of d.requiredComponents) {
|
|
1709
|
+
lines.push(`- ${comp}`);
|
|
1710
|
+
}
|
|
1711
|
+
lines.push("");
|
|
1712
|
+
}
|
|
1713
|
+
if (d.shapeTemplate) {
|
|
1714
|
+
lines.push("**Output shape**:");
|
|
1715
|
+
lines.push("");
|
|
1716
|
+
lines.push("```");
|
|
1717
|
+
lines.push(d.shapeTemplate);
|
|
1718
|
+
lines.push("```");
|
|
1719
|
+
lines.push("");
|
|
1720
|
+
}
|
|
1721
|
+
if (d.reason) {
|
|
1722
|
+
lines.push(`**Reason**: ${d.reason}`);
|
|
1723
|
+
lines.push("");
|
|
1724
|
+
}
|
|
1725
|
+
if (d.crossReferences && d.crossReferences.length > 0) {
|
|
1726
|
+
lines.push(`**Cross-references**: ${d.crossReferences.join(", ")}`);
|
|
1727
|
+
lines.push("");
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
this.appendProseAfter(lines, ast, "date_discipline");
|
|
1731
|
+
}
|
|
1732
|
+
if (ast.citationRules.length > 0) {
|
|
1733
|
+
lines.push("## Citation discipline");
|
|
1734
|
+
lines.push("");
|
|
1735
|
+
for (const rule of ast.citationRules) {
|
|
1736
|
+
lines.push(
|
|
1737
|
+
`- Fluent prose over **${rule.fluentProseThresholdChars} chars** must include one of: ${rule.required.join(", ")}`
|
|
1738
|
+
);
|
|
1739
|
+
if (rule.exemption) {
|
|
1740
|
+
lines.push(` - Exemption: ${rule.exemption}`);
|
|
1741
|
+
}
|
|
1742
|
+
if (rule.reason) {
|
|
1743
|
+
lines.push(` - Reason: ${rule.reason}`);
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
lines.push("");
|
|
1747
|
+
this.appendProseAfter(lines, ast, "citation_rule");
|
|
1748
|
+
}
|
|
1749
|
+
if (ast.graduatedWisdoms.length > 0 || ast.feedbacks.length > 0) {
|
|
1750
|
+
lines.push("## Authority cross-references");
|
|
1751
|
+
lines.push("");
|
|
1752
|
+
if (ast.graduatedWisdoms.length > 0) {
|
|
1753
|
+
lines.push("### GOLD-tier wisdom");
|
|
1754
|
+
lines.push("");
|
|
1755
|
+
for (const wisdom of ast.graduatedWisdoms) {
|
|
1756
|
+
lines.push(`- **${wisdom.id}** *(${wisdom.tier})* - ${wisdom.claim}`);
|
|
1757
|
+
}
|
|
1758
|
+
lines.push("");
|
|
1759
|
+
}
|
|
1760
|
+
if (ast.feedbacks.length > 0) {
|
|
1761
|
+
lines.push("### Feedback memory");
|
|
1762
|
+
lines.push("");
|
|
1763
|
+
for (const fb of ast.feedbacks) {
|
|
1764
|
+
const src = fb.source ? ` (${fb.source})` : "";
|
|
1765
|
+
lines.push(`- **${fb.id}**${src} - ${fb.claim}`);
|
|
1766
|
+
}
|
|
1767
|
+
lines.push("");
|
|
1768
|
+
}
|
|
1769
|
+
this.appendProseAfter(lines, ast, "graduated_wisdom");
|
|
1770
|
+
this.appendProseAfter(lines, ast, "feedback");
|
|
1771
|
+
}
|
|
1772
|
+
if (ast.domainDispatches.length > 0) {
|
|
1773
|
+
lines.push("## Domain \u2192 execution skill dispatch");
|
|
1774
|
+
lines.push("");
|
|
1775
|
+
lines.push(
|
|
1776
|
+
"The engine rules with founder defaults, then delegates execution to the right skill:"
|
|
1777
|
+
);
|
|
1778
|
+
lines.push("");
|
|
1779
|
+
lines.push("| Domain | Existing skills |");
|
|
1780
|
+
lines.push("|---|---|");
|
|
1781
|
+
for (const d of ast.domainDispatches) {
|
|
1782
|
+
const skills = d.skills.length > 0 ? d.skills.map((s) => `\`${s}\``).join(", ") : "*(in-skill default)*";
|
|
1783
|
+
lines.push(`| ${d.domain} | ${skills} |`);
|
|
1784
|
+
}
|
|
1785
|
+
lines.push("");
|
|
1786
|
+
this.appendProseAfter(lines, ast, "domain_dispatch");
|
|
1787
|
+
}
|
|
1788
|
+
if (ast.corpusMutabilities.length > 0) {
|
|
1789
|
+
lines.push("## Corpus mutability");
|
|
1790
|
+
lines.push("");
|
|
1791
|
+
for (const c of ast.corpusMutabilities) {
|
|
1792
|
+
lines.push(`- **${c.policy}**: ${c.description}`);
|
|
1793
|
+
}
|
|
1794
|
+
lines.push("");
|
|
1795
|
+
this.appendProseAfter(lines, ast, "corpus_mutability");
|
|
1796
|
+
}
|
|
1797
|
+
lines.push("---");
|
|
1798
|
+
lines.push("");
|
|
1799
|
+
lines.push(
|
|
1800
|
+
`*Generated by HoloScript ContextCompiler (compile_to_skill_md). Source: HoloScript composition. Vocabulary: v4 (2026-05-22). Phase 2(a) self-host target.*`
|
|
1801
|
+
);
|
|
1802
|
+
lines.push("");
|
|
1803
|
+
return lines.join("\n");
|
|
1804
|
+
}
|
|
1805
|
+
appendTrackBAuthority(lines, ast) {
|
|
1806
|
+
if (ast.trackBAuthorities.length === 0) {
|
|
1807
|
+
return;
|
|
1808
|
+
}
|
|
1809
|
+
const renderRows = (heading, rows) => {
|
|
1810
|
+
if (rows.length === 0) return;
|
|
1811
|
+
lines.push(`### ${heading}`);
|
|
1812
|
+
lines.push("");
|
|
1813
|
+
lines.push("| Target | Action type | Requires | Founder ratification | Notes |");
|
|
1814
|
+
lines.push("|---|---|---|---|---|");
|
|
1815
|
+
for (const row of rows) {
|
|
1816
|
+
const actionType = row.actionType ? `\`${mdTableCell(row.actionType)}\`` : "*(unspecified)*";
|
|
1817
|
+
const requires = row.requires.length > 0 ? row.requires.map((r) => mdTableCell(r)).join("<br>") : "*(none)*";
|
|
1818
|
+
const notes = row.notes ? mdTableCell(row.notes) : "";
|
|
1819
|
+
lines.push(
|
|
1820
|
+
`| ${mdTableCell(row.target)} | ${actionType} | ${requires} | ${row.founderRatificationRequired ? "Yes" : "No"} | ${notes} |`
|
|
1821
|
+
);
|
|
1822
|
+
}
|
|
1823
|
+
lines.push("");
|
|
1824
|
+
};
|
|
1825
|
+
const mutableTargets = ast.trackBAuthorities.filter(
|
|
1826
|
+
(row) => !row.founderRatificationRequired
|
|
1827
|
+
);
|
|
1828
|
+
const founderRatifiedTargets = ast.trackBAuthorities.filter(
|
|
1829
|
+
(row) => row.founderRatificationRequired
|
|
1830
|
+
);
|
|
1831
|
+
lines.push("## Self-edit + tier-write authority (Track B)");
|
|
1832
|
+
lines.push("");
|
|
1833
|
+
lines.push(
|
|
1834
|
+
"Every mutation requires backup-before-write, normal Edit/Write mutation, and append-only audit logging with a cited reason."
|
|
1835
|
+
);
|
|
1836
|
+
lines.push("");
|
|
1837
|
+
renderRows("Mutable targets", mutableTargets);
|
|
1838
|
+
renderRows("Founder-ratification-required targets", founderRatifiedTargets);
|
|
1839
|
+
}
|
|
1840
|
+
appendPapersProgramDefaults(lines, ast) {
|
|
1841
|
+
if (ast.editorialDefaults.length === 0 && ast.researchDefaults.length === 0) {
|
|
1842
|
+
return;
|
|
1843
|
+
}
|
|
1844
|
+
lines.push("## Papers program defaults");
|
|
1845
|
+
lines.push("");
|
|
1846
|
+
if (ast.editorialDefaults.length > 0) {
|
|
1847
|
+
lines.push("### Editorial defaults");
|
|
1848
|
+
lines.push("");
|
|
1849
|
+
lines.push("| Scope | Question | Answer | Reason |");
|
|
1850
|
+
lines.push("|---|---|---|---|");
|
|
1851
|
+
for (const def of ast.editorialDefaults) {
|
|
1852
|
+
lines.push(
|
|
1853
|
+
`| ${this.formatPaperDefaultScope(def)} | ${def.when} | **${def.do}** | ${def.reason ?? "*(no citation)*"} |`
|
|
1854
|
+
);
|
|
1855
|
+
}
|
|
1856
|
+
lines.push("");
|
|
1857
|
+
}
|
|
1858
|
+
if (ast.researchDefaults.length > 0) {
|
|
1859
|
+
lines.push("### Research-decision defaults");
|
|
1860
|
+
lines.push("");
|
|
1861
|
+
lines.push("| Scope | Question | Answer | Reason |");
|
|
1862
|
+
lines.push("|---|---|---|---|");
|
|
1863
|
+
for (const def of ast.researchDefaults) {
|
|
1864
|
+
lines.push(
|
|
1865
|
+
`| ${this.formatPaperDefaultScope(def)} | ${def.when} | **${def.do}** | ${def.reason ?? "*(no citation)*"} |`
|
|
1866
|
+
);
|
|
1867
|
+
}
|
|
1868
|
+
lines.push("");
|
|
1869
|
+
}
|
|
1870
|
+
}
|
|
1871
|
+
formatPaperDefaultScope(def) {
|
|
1872
|
+
const paperId = def.paperId?.trim();
|
|
1873
|
+
const paperPhase = def.paperPhase?.trim();
|
|
1874
|
+
if (paperId && paperPhase) return `${paperId} / ${paperPhase}`;
|
|
1875
|
+
if (paperId) return paperId;
|
|
1876
|
+
if (paperPhase) return paperPhase;
|
|
1877
|
+
return "program-wide";
|
|
1878
|
+
}
|
|
1879
|
+
/**
|
|
1880
|
+
* Emit @prose_after paragraphs for a given canonical trait name.
|
|
1881
|
+
* Called after the structured rendering of each section so prose
|
|
1882
|
+
* appears immediately after its target section in all emitters.
|
|
1883
|
+
*/
|
|
1884
|
+
appendProseAfter(lines, ast, traitName) {
|
|
1885
|
+
const prose = ast.proseAfters.filter((p) => p.trait === traitName);
|
|
1886
|
+
for (const entry of prose) {
|
|
1887
|
+
for (const paragraph of entry.paragraphs) {
|
|
1888
|
+
lines.push(paragraph);
|
|
1889
|
+
}
|
|
1890
|
+
lines.push("");
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
};
|
|
1894
|
+
var ContextCompileError = class extends Error {
|
|
1895
|
+
constructor(message) {
|
|
1896
|
+
super(message);
|
|
1897
|
+
this.name = "ContextCompileError";
|
|
1898
|
+
}
|
|
1899
|
+
};
|
|
1900
|
+
function createContextCompiler(options) {
|
|
1901
|
+
return new ContextCompiler(options);
|
|
1902
|
+
}
|
|
1903
|
+
function stringField(cfg, key, fallback) {
|
|
1904
|
+
const v = cfg[key];
|
|
1905
|
+
if (typeof v === "string") return v;
|
|
1906
|
+
return fallback;
|
|
1907
|
+
}
|
|
1908
|
+
function stringFieldOrUndef(cfg, key) {
|
|
1909
|
+
const v = cfg[key];
|
|
1910
|
+
return typeof v === "string" ? v : void 0;
|
|
1911
|
+
}
|
|
1912
|
+
function numberField(cfg, key, fallback) {
|
|
1913
|
+
const v = cfg[key];
|
|
1914
|
+
return typeof v === "number" && Number.isFinite(v) ? v : fallback;
|
|
1915
|
+
}
|
|
1916
|
+
function boolField(cfg, key, fallback) {
|
|
1917
|
+
const v = cfg[key];
|
|
1918
|
+
return typeof v === "boolean" ? v : fallback;
|
|
1919
|
+
}
|
|
1920
|
+
function mdTableCell(value) {
|
|
1921
|
+
return value.replace(/\|/g, "\\|").replace(/[\r\n]+/g, "<br>");
|
|
1922
|
+
}
|
|
1923
|
+
function yamlScalar(s) {
|
|
1924
|
+
if (/^[A-Za-z][A-Za-z0-9_-]*$/.test(s) && !YAML_RESERVED.has(s.toLowerCase())) {
|
|
1925
|
+
return s;
|
|
1926
|
+
}
|
|
1927
|
+
return JSON.stringify(s);
|
|
1928
|
+
}
|
|
1929
|
+
function formatYamlDescription(description) {
|
|
1930
|
+
if (!description.includes("\n")) {
|
|
1931
|
+
return `description: ${JSON.stringify(description)}`;
|
|
1932
|
+
}
|
|
1933
|
+
const lines = description.split("\n").map((line) => ` ${line}`);
|
|
1934
|
+
return `description: >
|
|
1935
|
+
${lines.join("\n")}`;
|
|
1936
|
+
}
|
|
1937
|
+
var YAML_RESERVED = /* @__PURE__ */ new Set([
|
|
1938
|
+
"yes",
|
|
1939
|
+
"no",
|
|
1940
|
+
"true",
|
|
1941
|
+
"false",
|
|
1942
|
+
"on",
|
|
1943
|
+
"off",
|
|
1944
|
+
"null",
|
|
1945
|
+
"~"
|
|
1946
|
+
]);
|
|
1947
|
+
function stringListField(cfg, key) {
|
|
1948
|
+
const v = cfg[key];
|
|
1949
|
+
if (!Array.isArray(v)) return [];
|
|
1950
|
+
return v.filter((x) => typeof x === "string");
|
|
1951
|
+
}
|
|
1952
|
+
function appendEmbodiedProjectionSection(lines, projections) {
|
|
1953
|
+
if (projections.length === 0) return;
|
|
1954
|
+
lines.push("## Embodied projections");
|
|
1955
|
+
lines.push("");
|
|
1956
|
+
for (const projection of projections) {
|
|
1957
|
+
const surface = projection.surface || "unspecified-surface";
|
|
1958
|
+
const kind = projection.projectionKind || "read-only";
|
|
1959
|
+
lines.push(`### ${surface} / ${kind}`);
|
|
1960
|
+
lines.push("");
|
|
1961
|
+
lines.push(`- **Surface**: ${surface}`);
|
|
1962
|
+
lines.push(`- **Projection kind**: ${kind}`);
|
|
1963
|
+
if (projection.trigger) {
|
|
1964
|
+
lines.push(`- **Trigger**: ${projection.trigger}`);
|
|
1965
|
+
}
|
|
1966
|
+
if (projection.notes) {
|
|
1967
|
+
lines.push(`- **Notes**: ${projection.notes}`);
|
|
1968
|
+
}
|
|
1969
|
+
lines.push("");
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
function wrapMdc(description, bodyLines) {
|
|
1973
|
+
const front = ["---", `description: ${description}`, "globs:", "alwaysApply: true", "---", ""];
|
|
1974
|
+
return front.concat(bodyLines).join("\n");
|
|
1975
|
+
}
|
|
1976
|
+
function oneLine(s) {
|
|
1977
|
+
return s.replace(/[\r\n]+/g, " ").replace(/\s+/g, " ").trim();
|
|
1978
|
+
}
|
|
1979
|
+
function toCursorSlug(name) {
|
|
1980
|
+
const base = name.toLowerCase().replace(/[_\s]+/g, "-").replace(/[^a-z0-9-]+/g, "").replace(/-{2,}/g, "-").replace(/^-+|-+$/g, "");
|
|
1981
|
+
if (base.length > 0) return base;
|
|
1982
|
+
let h = 0;
|
|
1983
|
+
for (let i = 0; i < name.length; i += 1) {
|
|
1984
|
+
h = (h + name.charCodeAt(i)) % 1e6;
|
|
1985
|
+
}
|
|
1986
|
+
return `rule-${h.toString(36).padStart(4, "0")}`;
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
exports.ContextCompileError = ContextCompileError;
|
|
1990
|
+
exports.ContextCompiler = ContextCompiler;
|
|
1991
|
+
exports.createContextCompiler = createContextCompiler;
|
|
1992
|
+
//# sourceMappingURL=chunk-OBIYPYYS.cjs.map
|
|
1993
|
+
//# sourceMappingURL=chunk-OBIYPYYS.cjs.map
|