@mistralys/persona-builder 2.1.2 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/engine/partials.ts","../src/engine/conditionals.ts","../src/engine/variables.ts","../src/engine/postProcessor.ts","../src/engine/serializer.ts","../src/loaders/partials-loader.ts","../src/plugins/runner.ts","../src/builders/frontmatter.ts","../src/builders/persona-builder.ts","../src/cli.ts"],"names":["readdir","path","readFile","existsSync","yaml","mkdir","writeFile","createRequire","require","pathToFileURL"],"mappings":";;;;;;;;;;;;;;;;;AA4BO,SAAS,eAAA,CACd,IAAA,EACA,WAAA,EACA,KAAA,GAAQ,CAAA,EACA;AACR,EAAA,IAAI,KAAA,IAAS,GAAG,OAAO,IAAA;AACvB,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,qBAAA,EAAuB,CAAC,OAAO,IAAA,KAAiB;AAClE,IAAA,IAAI,EAAE,QAAQ,WAAA,CAAA,EAAc;AAC1B,MAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,0BAAA,EAA6B,KAAK,CAAA,CAAE,CAAA;AACjD,MAAA,OAAO,KAAA;AAAA,IACT;AAGA,IAAA,OAAO,eAAA,CAAgB,YAAY,IAAI,CAAA,EAAG,aAAa,KAAA,GAAQ,CAAC,EAAE,OAAA,EAAQ;AAAA,EAC5E,CAAC,CAAA;AACH;;;ACVO,SAAS,mBAAA,CACd,MACA,OAAA,EACQ;AACR,EAAA,OAAO,IAAA,CAAK,OAAA;AAAA,IACV,2EAAA;AAAA,IACA,CACE,MAAA,EACA,IAAA,EACA,KAAA,EACA,SAAA,KACG;AACH,MAAA,IAAI,OAAA,CAAQ,IAAI,CAAA,EAAG;AAEjB,QAAA,OAAO,IAAA,GAAO,MAAM,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA,CAAE,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA,GAAI,IAAA;AAAA,MAChE;AACA,MAAA,IAAI,cAAc,MAAA,EAAW;AAE3B,QAAA,OAAO,IAAA,GAAO,UAAU,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA,CAAE,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA,GAAI,IAAA;AAAA,MACpE;AAEA,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,GACF;AACF;;;AClCO,SAAS,gBAAA,CACd,IAAA,EACA,OAAA,EACA,QAAA,EACQ;AACR,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,gBAAA,EAAkB,CAAC,OAAO,OAAA,KAAoB;AAChE,IAAA,IAAI,OAAA,IAAW,OAAA,IAAW,OAAA,CAAQ,OAAO,MAAM,MAAA,EAAW;AACxD,MAAA,OAAO,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAC,CAAA;AAAA,IAChC;AACA,IAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,4BAAA,EAA+B,KAAK,CAAA,IAAA,EAAO,QAAQ,CAAA,CAAE,CAAA;AAClE,IAAA,OAAO,KAAA;AAAA,EACT,CAAC,CAAA;AACH;;;AClBO,SAAS,mBAAmB,IAAA,EAAsB;AACvD,EAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,SAAA,EAAW,QAAQ,CAAA;AACzC;AAaO,SAAS,8BAA8B,IAAA,EAAsB;AAElE,EAAA,IAAI,MAAA,GAAS,IAAA,CAAK,OAAA,CAAQ,qBAAA,EAAuB,UAAU,CAAA;AAE3D,EAAA,MAAA,GAAS,MAAA,CAAO,OAAA,CAAQ,mBAAA,EAAqB,YAAY,CAAA;AAEzD,EAAA,MAAA,GAAS,MAAA,CAAO,OAAA,CAAQ,mBAAA,EAAqB,YAAY,CAAA;AACzD,EAAA,OAAO,MAAA;AACT;AAUO,SAAS,kBAAkB,IAAA,EAAsB;AACtD,EAAA,OAAO,KAAK,OAAA,CAAQ,OAAA,EAAS,IAAI,CAAA,CAAE,OAAA,CAAQ,OAAO,IAAI,CAAA;AACxD;;;AChCO,SAAS,eAAe,KAAA,EAAyB;AACtD,EAAA,OAAO,GAAA,GAAM,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAA,EAAI,CAAC,CAAA,CAAA,CAAG,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA,GAAI,GAAA;AACvD;AAeO,SAAS,mBAAmB,KAAA,EAAyB;AAC1D,EAAA,OAAO,KAAA,CAAM,IAAI,CAAC,CAAA,KAAM,IAAI,CAAC,CAAA,CAAA,CAAG,CAAA,CAAE,IAAA,CAAK,IAAI,CAAA;AAC7C;ACLA,eAAsB,aAAa,GAAA,EAA8C;AAC/E,EAAA,MAAM,UAAU,MAAMA,gBAAA,CAAQ,KAAK,EAAE,aAAA,EAAe,MAAM,CAAA;AAE1D,EAAA,MAAM,UAAU,OAAA,CAAQ,MAAA;AAAA,IACtB,CAAC,UAAU,KAAA,CAAM,MAAA,MAAY,KAAA,CAAM,IAAA,CAAK,SAAS,KAAK;AAAA,GACxD;AAEA,EAAA,MAAM,KAAA,GAAQ,MAAM,OAAA,CAAQ,GAAA;AAAA,IAC1B,OAAA,CAAQ,GAAA,CAAI,OAAO,KAAA,KAAU;AAC3B,MAAA,MAAM,OAAO,KAAA,CAAM,IAAA,CAAK,MAAM,CAAA,EAAG,CAAC,MAAM,MAAM,CAAA;AAC9C,MAAA,MAAM,QAAA,GAAWC,sBAAA,CAAK,IAAA,CAAK,GAAA,EAAK,MAAM,IAAI,CAAA;AAC1C,MAAA,MAAM,OAAA,GAAU,MAAMC,iBAAA,CAAS,QAAA,EAAU,MAAM,CAAA;AAC/C,MAAA,OAAO,CAAC,MAAM,OAAO,CAAA;AAAA,IACvB,CAAC;AAAA,GACH;AAEA,EAAA,OAAO,MAAA,CAAO,YAAY,KAAK,CAAA;AACjC;;;ACVO,SAAS,YAAA,CACd,OAAA,EACA,KAAA,EACA,UAAA,EACM;AACN,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,IAAI,OAAO,MAAA,CAAO,WAAA,KAAgB,UAAA,EAAY;AAC5C,MAAA,MAAA,CAAO,WAAA,CAAY,OAAO,UAAU,CAAA;AAAA,IACtC;AAAA,EACF;AACF;AAoBO,SAAS,eAAA,CACd,OAAA,EACA,GAAA,EACA,OAAA,EACA,KAAA,EACyB;AACzB,EAAA,IAAI,WAAA,GAAc,GAAA;AAClB,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,IAAI,OAAO,MAAA,CAAO,cAAA,KAAmB,UAAA,EAAY;AAC/C,MAAA,WAAA,GAAc,MAAA,CAAO,cAAA,CAAe,WAAA,EAAa,OAAA,EAAS,KAAK,CAAA;AAAA,IACjE;AAAA,EACF;AACA,EAAA,OAAO,WAAA;AACT;AAoBO,SAAS,aAAA,CACd,OAAA,EACA,QAAA,EACA,OAAA,EACA,MAAA,EACQ;AACR,EAAA,IAAI,MAAA,GAAS,QAAA;AACb,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,IAAI,OAAO,MAAA,CAAO,YAAA,KAAiB,UAAA,EAAY;AAC7C,MAAA,MAAA,GAAS,MAAA,CAAO,YAAA,CAAa,MAAA,EAAQ,OAAA,EAAS,MAAM,CAAA;AAAA,IACtD;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAmBO,SAAS,WAAA,CACd,OAAA,EACA,OAAA,EACA,KAAA,EACA,MAAA,EACoB;AACpB,EAAA,MAAM,UAA8B,EAAC;AACrC,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,IAAI,OAAO,MAAA,CAAO,UAAA,KAAe,UAAA,EAAY;AAC3C,MAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,UAAA,CAAW,OAAA,EAAS,OAAO,MAAM,CAAA;AAC9D,MAAA,OAAA,CAAQ,IAAA,CAAK,GAAG,aAAa,CAAA;AAAA,IAC/B;AAAA,EACF;AACA,EAAA,OAAO,OAAA;AACT;;;ACvHO,IAAM,0BAAA,GAA6B,CAAA;AAAA;AAAA;AAAA;AAAA,GAAA,CAAA;AAYnC,IAAM,+BAAA,GAAkC,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,GAAA,CAAA;AA4BxC,SAAS,0BAAA,CACd,MAAA,EACA,OAAA,EACA,eAAA,EACQ;AAGR,EAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,IAAA,IAAI,MAAA,CAAO,oBAAA,IAAwB,MAAA,IAAU,MAAA,CAAO,oBAAA,EAAsB;AACxE,MAAA,MAAM,GAAA,GAAM,MAAA,CAAO,oBAAA,CAAqB,MAAM,CAAA;AAC9C,MAAA,IAAI,GAAA,KAAQ,QAAW,OAAO,GAAA;AAAA,IAChC;AAAA,EACF;AAGA,EAAA,IAAI,eAAA,IAAmB,UAAU,eAAA,EAAiB;AAChD,IAAA,MAAM,GAAA,GAAM,gBAAgB,MAAM,CAAA;AAClC,IAAA,IAAI,GAAA,KAAQ,QAAW,OAAO,GAAA;AAAA,EAChC;AAGA,EAAA,OAAO,MAAA,KAAW,WAAW,0BAAA,GAA6B,+BAAA;AAC5D;AAkBO,SAAS,iBAAA,CACd,QAAA,EACA,OAAA,EACA,QAAA,EACQ;AACR,EAAA,IAAI,QAAA,GAAW,mBAAA,CAAoB,QAAA,EAAU,OAAO,CAAA;AACpD,EAAA,QAAA,GAAW,gBAAA,CAAiB,QAAA,EAAU,OAAA,EAAS,QAAQ,CAAA;AACvD,EAAA,OAAO,QAAA;AACT;;;AC1DA,eAAe,0BAA0B,WAAA,EAA6C;AACpF,EAAA,MAAM,UAAA,GAAa,YAAY,UAAA,IAAc,MAAA;AAC7C,EAAA,MAAM,OAAA,GAAUD,sBAAAA,CAAK,IAAA,CAAK,WAAA,CAAY,QAAQ,UAAU,CAAA;AAExD,EAAA,MAAM,UAAU,MAAMD,gBAAAA,CAAQ,SAAS,EAAE,aAAA,EAAe,MAAM,CAAA;AAE9D,EAAA,OAAO,OAAA,CACJ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,MAAA,EAAO,IAAK,CAAA,CAAE,IAAA,CAAK,QAAA,CAAS,OAAO,CAAA,IAAK,CAAC,CAAA,CAAE,IAAA,CAAK,UAAA,CAAW,GAAG,CAAC,CAAA,CAC/E,GAAA,CAAI,CAAC,CAAA,KAAMC,sBAAAA,CAAK,IAAA,CAAK,OAAA,EAAS,CAAA,CAAE,IAAI,CAAC,EACrC,IAAA,EAAK;AACV;AAUA,eAAe,YAAY,QAAA,EAAoD;AAC7E,EAAA,IAAI,CAACE,aAAA,CAAW,QAAQ,CAAA,SAAU,EAAC;AACnC,EAAA,MAAM,GAAA,GAAM,MAAMD,iBAAAA,CAAS,QAAA,EAAU,MAAM,CAAA;AAC3C,EAAA,MAAM,MAAA,GAAkBE,qBAAA,CAAK,IAAA,CAAK,GAAG,CAAA;AACrC,EAAA,IAAI,MAAA,KAAW,IAAA,IAAQ,MAAA,KAAW,MAAA,SAAkB,EAAC;AACrD,EAAA,IAAI,OAAO,WAAW,QAAA,IAAY,KAAA,CAAM,QAAQ,MAAM,CAAA,SAAU,EAAC;AACjE,EAAA,OAAO,MAAA;AACT;AASA,eAAe,gBAAgB,QAAA,EAAoD;AACjF,EAAA,MAAM,GAAA,GAAM,MAAMF,iBAAAA,CAAS,QAAA,EAAU,MAAM,CAAA;AAC3C,EAAA,MAAM,MAAA,GAAkBE,qBAAA,CAAK,IAAA,CAAK,GAAG,CAAA;AAErC,EAAA,IAAI,MAAA,KAAW,IAAA,IAAQ,MAAA,KAAW,MAAA,IAAa,OAAO,WAAW,QAAA,IAAY,KAAA,CAAM,OAAA,CAAQ,MAAM,CAAA,EAAG;AAClG,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yCAAA,EAA4C,QAAQ,CAAA,CAAA,CAAG,CAAA;AAAA,EACzE;AAEA,EAAA,MAAM,MAAA,GAAS,MAAA;AAGf,EAAA,IAAI,CAAC,MAAA,CAAO,MAAM,CAAA,EAAG;AACnB,IAAA,MAAA,CAAO,MAAM,CAAA,GAAIH,sBAAAA,CAAK,QAAA,CAAS,UAAU,OAAO,CAAA;AAAA,EAClD;AAEA,EAAA,OAAO,MAAA;AACT;AAgBA,eAAe,kBACb,MAAA,EACiC;AACjC,EAAA,MAAM,WAAmC,EAAC;AAE1C,EAAA,KAAA,MAAW,GAAG,WAAW,CAAA,IAAK,OAAO,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAA,EAAG;AAC3D,IAAA,MAAM,UAAA,GAAa,YAAY,UAAA,IAAc,MAAA;AAC7C,IAAA,MAAM,iBAAiBA,sBAAAA,CAAK,IAAA,CAAK,WAAA,CAAY,MAAA,EAAQ,YAAY,cAAc,CAAA;AAC/E,IAAA,MAAM,UAAA,GAAa,MAAM,WAAA,CAAY,cAAc,CAAA;AACnD,IAAA,MAAM,cAAA,GACJ,OAAO,UAAA,CAAW,iBAAiB,MAAM,QAAA,GACrC,UAAA,CAAW,iBAAiB,CAAA,GAC5B,OAAA;AAEN,IAAA,MAAM,YAAA,GAAe,MAAM,yBAAA,CAA0B,WAAW,CAAA;AAEhE,IAAA,KAAA,MAAW,YAAY,YAAA,EAAc;AACnC,MAAA,MAAM,OAAA,GAAU,MAAM,eAAA,CAAgB,QAAQ,CAAA;AAE9C,MAAA,MAAM,IAAA,GACJ,OAAO,OAAA,CAAQ,MAAM,CAAA,KAAM,QAAA,GACvB,OAAA,CAAQ,MAAM,CAAA,GACdA,sBAAAA,CAAK,QAAA,CAAS,QAAA,EAAU,OAAO,CAAA;AAErC,MAAA,MAAM,IAAA,GACJ,OAAO,OAAA,CAAQ,MAAM,MAAM,QAAA,GACvB,OAAA,CAAQ,MAAM,CAAA,GACd,IAAA;AAEN,MAAA,MAAM,OAAA,GACJ,OAAO,OAAA,CAAQ,SAAS,MAAM,QAAA,GAC1B,OAAA,CAAQ,SAAS,CAAA,GACjB,cAAA;AAEN,MAAA,MAAM,MAAM,CAAA,MAAA,EAAS,IAAA,CAAK,OAAA,CAAQ,IAAA,EAAM,GAAG,CAAC,CAAA,CAAA;AAC5C,MAAA,QAAA,CAAS,GAAG,CAAA,GAAI,CAAA,EAAG,IAAI,KAAK,OAAO,CAAA,CAAA;AAAA,IACrC;AAAA,EACF;AAEA,EAAA,OAAO,QAAA;AACT;AAgBA,SAAS,YAAA,CACP,WAAA,EACA,UAAA,EACA,QAAA,GAAmC,EAAC,EACX;AACzB,EAAA,MAAM,UACJ,OAAO,WAAA,CAAY,SAAS,CAAA,KAAM,WAC9B,WAAA,CAAY,SAAS,CAAA,GACrB,OAAO,WAAW,iBAAiB,CAAA,KAAM,QAAA,GACvC,UAAA,CAAW,iBAAiB,CAAA,GAC5B,OAAA;AAGR,EAAA,MAAM,MAAA,GAAkC;AAAA,IACtC,GAAG,UAAA;AAAA,IACH,GAAG,WAAA;AAAA,IACH;AAAA,GACF;AAIA,EAAA,MAAM,KAAA,GAAQ,KAAA,CAAM,OAAA,CAAQ,MAAA,CAAO,OAAO,CAAC,CAAA,GAAK,MAAA,CAAO,OAAO,CAAA,GAAiB,EAAC;AAChF,EAAA,IAAI,EAAE,gBAAgB,MAAA,CAAA,EAAS;AAC7B,IAAA,MAAA,CAAO,YAAY,CAAA,GAAI,kBAAA,CAAmB,KAAK,CAAA;AAAA,EACjD;AACA,EAAA,IAAI,EAAE,gBAAgB,MAAA,CAAA,EAAS;AAC7B,IAAA,MAAA,CAAO,YAAY,CAAA,GAAI,cAAA,CAAe,KAAK,CAAA;AAAA,EAC7C;AAGA,EAAA,MAAM,OAAA,GAAU,MAAM,OAAA,CAAQ,MAAA,CAAO,UAAU,CAAC,CAAA,GAAK,MAAA,CAAO,UAAU,CAAA,GAAiB,KAAA;AACvF,EAAA,IAAI,EAAE,mBAAmB,MAAA,CAAA,EAAS;AAChC,IAAA,MAAA,CAAO,eAAe,CAAA,GAAI,kBAAA,CAAmB,OAAO,CAAA;AAAA,EACtD;AACA,EAAA,IAAI,EAAE,mBAAmB,MAAA,CAAA,EAAS;AAChC,IAAA,MAAA,CAAO,eAAe,CAAA,GAAI,cAAA,CAAe,OAAO,CAAA;AAAA,EAClD;AAGA,EAAA,IAAI,EAAE,mBAAA,IAAuB,MAAA,CAAA,IAAW,OAAO,MAAA,CAAO,cAAc,MAAM,QAAA,EAAU;AAClF,IAAA,MAAM,UAAA,GAAa,OAAO,cAAc,CAAA;AACxC,IAAA,MAAA,CAAO,mBAAmB,CAAA,GAAI,UAAA,CAAW,OAAA,CAAQ,SAAS,EAAE,CAAA;AAAA,EAC9D;AAGA,EAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,QAAQ,CAAA,EAAG;AACnD,IAAA,IAAI,EAAE,OAAO,MAAA,CAAA,EAAS;AACpB,MAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAAA,IAChB;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAiCA,eAAsB,YAAA,CACpB,eAAA,EACA,SAAA,EACA,WAAA,EACA,UAAA,EACA,WAAA,EACA,MAAA,EACA,OAAA,EACA,MAAA,EACA,QAAA,GAAmC,EAAC,EACd;AAEtB,EAAA,MAAM,WAAA,GAAc,MAAM,eAAA,CAAgB,eAAe,CAAA;AAGzD,EAAA,IAAI,OAAA,GAAU,YAAA,CAAa,WAAA,EAAa,UAAA,EAAY,QAAQ,CAAA;AAK5D,EAAA,MAAM,gBAAA,GAAmB,WAAA;AACzB,EAAA,OAAA,GAAU,eAAA,CAAgB,OAAA,EAAS,OAAA,EAAS,gBAAA,EAAkB,WAAW,CAAA;AAGzE,EAAA,MAAM,UAAA,GAAa,0BAAA,CAA2B,MAAA,EAAQ,OAAA,EAAS,OAAO,WAAW,CAAA;AACjF,EAAA,MAAM,eAAA,GAAkBA,sBAAAA,CAAK,QAAA,CAAS,eAAA,EAAiB,OAAO,CAAA,GAAI,KAAA;AAClE,EAAA,MAAM,WAAA,GAAc,iBAAA,CAAkB,UAAA,EAAY,OAAA,EAAS,eAAe,CAAA;AAG1E,EAAA,MAAM,aAAA,GAAgB,YAAY,aAAA,IAAiB,SAAA;AACnD,EAAA,MAAM,cAAcA,sBAAAA,CAAK,IAAA,CAAK,WAAA,CAAY,MAAA,EAAQ,eAAe,eAAe,CAAA;AAChF,EAAA,MAAM,eAAe,iBAAA,CAAkB,MAAMC,iBAAAA,CAAS,WAAA,EAAa,MAAM,CAAC,CAAA;AAG1E,EAAA,IAAI,IAAA,GAAO,eAAA,CAAgB,YAAA,EAAc,WAAW,CAAA;AACpD,EAAA,IAAA,GAAO,mBAAA,CAAoB,MAAM,OAAO,CAAA;AACxC,EAAA,IAAA,GAAO,gBAAA,CAAiB,IAAA,EAAM,OAAA,EAAS,eAAe,CAAA;AACtD,EAAA,IAAA,GAAO,mBAAmB,IAAI,CAAA;AAC9B,EAAA,IAAA,GAAO,8BAA8B,IAAI,CAAA;AACzC,EAAA,IAAA,GAAO,KAAK,OAAA,EAAQ;AAGpB,EAAA,IAAI,MAAA,GAAS,iBAAA,CAAkB,CAAA,EAAG,WAAW;;AAAA,EAAO,IAAI;AAAA,CAAI,CAAA;AAG5D,EAAA,MAAA,GAAS,aAAA,CAAc,OAAA,EAAS,MAAA,EAAQ,gBAAA,EAAkB,MAAM,CAAA;AAGhE,EAAA,MAAM,iBAAA,GAAwC,WAAA,CAAY,OAAA,EAAS,gBAAA,EAAkB,aAAa,MAAM,CAAA;AAGxG,EAAA,MAAM,SAAA,GAAY,MAAA,KAAW,QAAA,GAAW,WAAA,CAAY,YAAY,WAAA,CAAY,aAAA;AAG5E,EAAA,IAAI,cAAA;AACJ,EAAA,IAAI,WAAW,QAAA,IAAY,OAAO,OAAA,CAAQ,cAAc,MAAM,QAAA,EAAU;AACtE,IAAA,cAAA,GAAiB,QAAQ,cAAc,CAAA;AAAA,EACzC,WAAW,MAAA,KAAW,aAAA,IAAiB,OAAO,OAAA,CAAQ,cAAc,MAAM,QAAA,EAAU;AAClF,IAAA,cAAA,GAAiB,QAAQ,cAAc,CAAA;AAAA,EACzC,CAAA,MAAO;AACL,IAAA,cAAA,GAAiB,eAAA;AAAA,EACnB;AACA,EAAA,MAAM,UAAA,GAAaD,sBAAAA,CAAK,IAAA,CAAK,SAAA,EAAW,cAAc,CAAA;AAGtD,EAAA,MAAM,KAAA,GAAQ,OAAO,KAAA,IAAS,KAAA;AAC9B,EAAA,IAAI,OAAA,GAAU,KAAA;AAEd,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,MAAMI,cAAA,CAAM,SAAA,EAAW,EAAE,SAAA,EAAW,MAAM,CAAA;AAC1C,IAAA,MAAMC,kBAAA,CAAU,UAAA,EAAY,MAAA,EAAQ,MAAM,CAAA;AAC1C,IAAA,OAAA,GAAU,IAAA;AAAA,EACZ;AAEA,EAAA,OAAO;AAAA,IACL,KAAA,EAAO,SAAA;AAAA,IACP,MAAA;AAAA,IACA,eAAA;AAAA,IACA,UAAA;AAAA,IACA,OAAA,EAAS,MAAA;AAAA,IACT,iBAAA;AAAA,IACA;AAAA,GACF;AACF;AAuBA,eAAsB,UAAA,CACpB,WACA,WAAA,EACA,MAAA,EACA,SACA,MAAA,EACA,QAAA,GAAmC,EAAC,EACZ;AAExB,EAAA,MAAM,UAAA,GAAa,YAAY,UAAA,IAAc,MAAA;AAC7C,EAAA,MAAM,iBAAiBL,sBAAAA,CAAK,IAAA,CAAK,WAAA,CAAY,MAAA,EAAQ,YAAY,cAAc,CAAA;AAC/E,EAAA,MAAM,UAAA,GAAa,MAAM,WAAA,CAAY,cAAc,CAAA;AAGnD,EAAA,IAAI,cAAsC,EAAC;AAE3C,EAAA,IAAI,MAAA,CAAO,iBAAA,IAAqBE,aAAA,CAAW,MAAA,CAAO,iBAAiB,CAAA,EAAG;AACpE,IAAA,WAAA,GAAc,EAAE,GAAG,WAAA,EAAa,GAAI,MAAM,YAAA,CAAa,MAAA,CAAO,iBAAiB,CAAA,EAAG;AAAA,EACpF;AAEA,EAAA,MAAM,cAAA,GAAiB,YAAY,cAAA,IAAkB,UAAA;AACrD,EAAA,MAAM,gBAAA,GAAmBF,sBAAAA,CAAK,IAAA,CAAK,WAAA,CAAY,QAAQ,cAAc,CAAA;AACrE,EAAA,IAAIE,aAAA,CAAW,gBAAgB,CAAA,EAAG;AAChC,IAAA,WAAA,GAAc,EAAE,GAAG,WAAA,EAAa,GAAI,MAAM,YAAA,CAAa,gBAAgB,CAAA,EAAG;AAAA,EAC5E;AAGA,EAAA,YAAA,CAAa,OAAA,EAAS,aAAa,UAAU,CAAA;AAG7C,EAAA,MAAM,gBAAA,GAAmB,MAAM,yBAAA,CAA0B,WAAW,CAAA;AAGpE,EAAA,MAAM,UAAyB,EAAC;AAChC,EAAA,KAAA,MAAW,YAAY,gBAAA,EAAkB;AACvC,IAAA,MAAM,SAAS,MAAM,YAAA;AAAA,MACnB,QAAA;AAAA,MACA,SAAA;AAAA,MACA,WAAA;AAAA,MACA,UAAA;AAAA,MACA,WAAA;AAAA,MACA,MAAA;AAAA,MACA,OAAA;AAAA,MACA,MAAA;AAAA,MACA;AAAA,KACF;AACA,IAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AAAA,EACrB;AAEA,EAAA,OAAO,OAAA;AACT;AAyBA,eAAsB,MAAM,MAAA,EAA4C;AACtE,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,IAAW,EAAC;AACnC,EAAA,MAAM,OAAA,GAAU,MAAA,CAAO,OAAA,IAAW,CAAC,UAAU,aAAa,CAAA;AAC1D,EAAA,MAAM,aAA4B,EAAC;AAGnC,EAAA,MAAM,QAAA,GAAW,MAAM,iBAAA,CAAkB,MAAM,CAAA;AAE/C,EAAA,KAAA,MAAW,CAAC,WAAW,WAAW,CAAA,IAAK,OAAO,OAAA,CAAQ,MAAA,CAAO,MAAM,CAAA,EAAG;AACpE,IAAA,KAAA,MAAW,UAAU,OAAA,EAAS;AAC5B,MAAA,MAAM,YAAA,GAAe,MAAM,UAAA,CAAW,SAAA,EAAW,aAAa,MAAA,EAAQ,OAAA,EAAS,QAAQ,QAAQ,CAAA;AAC/F,MAAA,UAAA,CAAW,IAAA,CAAK,GAAG,YAAY,CAAA;AAAA,IACjC;AAAA,EACF;AAGA,EAAA,MAAM,cAAA,GAAqC,MAAA,CAAO,MAAA,GAC9C,UAAA,CAAW,OAAA;AAAA,IAAQ,CAAC,CAAA,KAClB,CAAA,CAAE,iBAAA,CAAkB,MAAA;AAAA,MAClB,CAAC,CAAA,KAAM,CAAA,CAAE,QAAA,KAAa,OAAA,IAAW,EAAE,QAAA,KAAa;AAAA;AAClD,MAEF,EAAC;AAEL,EAAA,MAAM,OAAA,GAAU,CAAC,MAAA,CAAO,MAAA,IAAU,eAAe,MAAA,KAAW,CAAA;AAE5D,EAAA,MAAM,OAAA,GAAwB;AAAA,IAC5B,OAAA;AAAA,IACA,OAAA,EAAS,UAAA;AAAA,IACT,cAAA;AAAA,IACA,YAAY,UAAA,CAAW,MAAA;AAAA,IACvB,cAAc,UAAA,CAAW,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,OAAO,CAAA,CAAE;AAAA,GACpD;AAEA,EAAA,IAAI,MAAA,CAAO,MAAA,IAAU,CAAC,OAAA,EAAS;AAC7B,IAAA,MAAM,QAAA,GAAW,cAAA,CAAe,GAAA,CAAI,CAAC,MAAM,CAAA,CAAA,EAAI,CAAA,CAAE,QAAQ,CAAA,EAAA,EAAK,CAAA,CAAE,OAAO,CAAA,CAAE,CAAA,CAAE,KAAK,IAAI,CAAA;AACpF,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,mCAAA,EAAiC,eAAe,MAAM,CAAA;AAAA,EAA0B,QAAQ,CAAA;AAAA,KAC1F;AAAA,EACF;AAEA,EAAA,OAAO,OAAA;AACT;;;AC9cA,IAAM,WAAA,GAAcI,sBAAA,CAAc,yPAAe,CAAA;AACjD,IAAM,OAAA,GAAW,WAAA,CAAY,iBAAiB,CAAA,CAA0B,OAAA;AAMxE,IAAM,KAAA,GAAQ;AAAA,4BAAA,EACgB,OAAO;;AAAA;;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA,CAyBnC,IAAA,EAAK;AAcP,SAAS,UAAU,IAAA,EAA4B;AAC7C,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA;AAEzB,EAAA,MAAM,MAAA,GAAqB;AAAA,IACzB,UAAA,EAAY,MAAA;AAAA,IACZ,KAAA,EAAO,KAAA;AAAA,IACP,MAAA,EAAQ,KAAA;AAAA,IACR,IAAA,EAAM,KAAA;AAAA,IACN,OAAA,EAAS;AAAA,GACX;AAEA,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,OAAO,CAAA,GAAI,KAAK,MAAA,EAAQ;AACtB,IAAA,MAAM,GAAA,GAAM,KAAK,CAAC,CAAA;AAClB,IAAA,QAAQ,GAAA;AAAK,MACX,KAAK,QAAA;AAAA,MACL,KAAK,IAAA;AACH,QAAA,MAAA,CAAO,IAAA,GAAO,IAAA;AACd,QAAA;AAAA,MACF,KAAK,WAAA;AAAA,MACL,KAAK,IAAA;AACH,QAAA,MAAA,CAAO,OAAA,GAAU,IAAA;AACjB,QAAA;AAAA,MACF,KAAK,SAAA;AACH,QAAA,MAAA,CAAO,KAAA,GAAQ,IAAA;AACf,QAAA;AAAA,MACF,KAAK,UAAA;AACH,QAAA,MAAA,CAAO,MAAA,GAAS,IAAA;AAChB,QAAA;AAAA,MACF,KAAK,UAAA,EAAY;AACf,QAAA,MAAM,IAAA,GAAO,IAAA,CAAK,CAAA,GAAI,CAAC,CAAA;AACvB,QAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,CAAK,UAAA,CAAW,IAAI,CAAA,EAAG;AAClC,UAAA,OAAA,CAAQ,MAAM,2CAA2C,CAAA;AACzD,UAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,QAChB;AACA,QAAA,MAAA,CAAO,UAAA,GAAa,IAAA;AACpB,QAAA,CAAA,EAAA;AACA,QAAA;AAAA,MACF;AAAA,MACA;AAEE,QAAA,IAAI,GAAA,CAAI,UAAA,CAAW,IAAI,CAAA,EAAG;AACxB,UAAA,OAAA,CAAQ,IAAA,CAAK,CAAA,uBAAA,EAA0B,GAAG,CAAA,iBAAA,CAAc,CAAA;AAAA,QAC1D;AAAA;AAEJ,IAAA,CAAA,EAAA;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAeA,SAAS,kBAAkB,QAAA,EAA2B;AACpD,EAAA,IAAI,QAAA,EAAU;AACZ,IAAA,MAAM,QAAA,GAAWN,sBAAAA,CAAK,OAAA,CAAQ,QAAQ,CAAA;AACtC,IAAA,IAAI,CAACE,aAAAA,CAAW,QAAQ,CAAA,EAAG;AACzB,MAAA,OAAA,CAAQ,KAAA,CAAM,CAAA,8BAAA,EAAiC,QAAQ,CAAA,CAAE,CAAA;AACzD,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,IAChB;AACA,IAAA,OAAO,QAAA;AAAA,EACT;AAEA,EAAA,MAAM,UAAA,GAAa;AAAA,IACjB,yBAAA;AAAA,IACA,0BAAA;AAAA,IACA;AAAA,GACF;AAEA,EAAA,KAAA,MAAW,QAAQ,UAAA,EAAY;AAC7B,IAAA,MAAM,SAAA,GAAYF,sBAAAA,CAAK,OAAA,CAAQ,IAAI,CAAA;AACnC,IAAA,IAAIE,aAAAA,CAAW,SAAS,CAAA,EAAG,OAAO,SAAA;AAAA,EACpC;AAEA,EAAA,OAAA,CAAQ,KAAA;AAAA,IACN;AAAA,GAEF;AACA,EAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAChB;AAaA,eAAe,WAAW,UAAA,EAA0C;AAClE,EAAA,MAAM,GAAA,GAAMF,sBAAAA,CAAK,OAAA,CAAQ,UAAU,EAAE,WAAA,EAAY;AAEjD,EAAA,IAAI,SAAA;AAEJ,EAAA,IAAI,GAAA,KAAQ,MAAA,IAAU,GAAA,KAAQ,OAAA,EAAS;AACrC,IAAA,MAAMO,QAAAA,GAAUD,sBAAA,CAAc,yPAAe,CAAA;AAC7C,IAAA,SAAA,GAAYC,SAAQ,UAAU,CAAA;AAAA,EAChC,CAAA,MAAO;AAEL,IAAA,MAAM,OAAA,GAAUC,iBAAA,CAAc,UAAU,CAAA,CAAE,IAAA;AAC1C,IAAA,MAAM,GAAA,GAAM,MAAM,OAAO,OAAA,CAAA;AACzB,IAAA,SAAA,GAAY,IAAI,OAAA,IAAW,GAAA;AAAA,EAC7B;AAEA,EAAA,IAAI,CAAC,aAAa,OAAO,SAAA,KAAc,YAAY,KAAA,CAAM,OAAA,CAAQ,SAAS,CAAA,EAAG;AAC3E,IAAA,OAAA,CAAQ,KAAA;AAAA,MACN,uBAAuB,UAAU,CAAA,2CAAA;AAAA,KACnC;AACA,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAEA,EAAA,MAAM,MAAA,GAAS,SAAA;AAEf,EAAA,IAAI,CAAC,MAAA,CAAO,MAAA,IAAU,OAAO,MAAA,CAAO,WAAW,QAAA,EAAU;AACvD,IAAA,OAAA,CAAQ,KAAA;AAAA,MACN,uBAAuB,UAAU,CAAA,0DAAA;AAAA,KACnC;AACA,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAEA,EAAA,OAAO,MAAA;AACT;AAMA,SAAS,YAAA,CAAa,SAAuB,KAAA,EAAsB;AACjE,EAAA,MAAM,IAAA,GAAO,QAAQ,uCAAA,GAAqC,EAAA;AAC1D,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,OAAA,GAAU,wBAAA,GAAsB,qBAAA;AACvD,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,MAAM,CAAA,EAAG,IAAI,CAAA,CAAE,CAAA;AAC9B,EAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,uBAAA,EAA0B,OAAA,CAAQ,UAAU,CAAA,CAAE,CAAA;AAC1D,EAAA,IAAI,CAAC,KAAA,EAAO;AACV,IAAA,OAAA,CAAQ,GAAA,CAAI,CAAA,uBAAA,EAA0B,OAAA,CAAQ,YAAY,CAAA,CAAE,CAAA;AAAA,EAC9D;AACA,EAAA,IAAI,OAAA,CAAQ,cAAA,CAAe,MAAA,GAAS,CAAA,EAAG;AACrC,IAAA,OAAA,CAAQ,GAAA,CAAI;AAAA,uBAAA,EAA4B,OAAA,CAAQ,cAAA,CAAe,MAAM,CAAA,EAAA,CAAI,CAAA;AACzE,IAAA,KAAA,MAAW,CAAA,IAAK,QAAQ,cAAA,EAAgB;AACtC,MAAA,OAAA,CAAQ,IAAI,CAAA,KAAA,EAAQ,CAAA,CAAE,QAAQ,CAAA,EAAA,EAAK,CAAA,CAAE,OAAO,CAAA,CAAE,CAAA;AAAA,IAChD;AAAA,EACF;AACF;AAMA,eAAe,IAAA,GAAsB;AACnC,EAAA,MAAM,IAAA,GAAO,SAAA,CAAU,OAAA,CAAQ,IAAI,CAAA;AAGnC,EAAA,IAAI,KAAK,IAAA,EAAM;AACb,IAAA,OAAA,CAAQ,IAAI,KAAK,CAAA;AACjB,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAEA,EAAA,IAAI,KAAK,OAAA,EAAS;AAChB,IAAA,OAAA,CAAQ,IAAI,OAAO,CAAA;AACnB,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAGA,EAAA,MAAM,UAAA,GAAa,iBAAA,CAAkB,IAAA,CAAK,UAAU,CAAA;AACpD,EAAA,IAAI,MAAA;AAEJ,EAAA,IAAI;AACF,IAAA,MAAA,GAAS,MAAM,WAAW,UAAU,CAAA;AAAA,EACtC,SAAS,GAAA,EAAK;AACZ,IAAA,OAAA,CAAQ,KAAA,CAAM,yBAAyB,GAAA,YAAe,KAAA,GAAQ,IAAI,OAAA,GAAU,MAAA,CAAO,GAAG,CAAC,CAAA,CAAE,CAAA;AACzF,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAGA,EAAA,IAAI,IAAA,CAAK,KAAA,EAAO,MAAA,CAAO,KAAA,GAAQ,IAAA;AAC/B,EAAA,IAAI,IAAA,CAAK,MAAA,EAAQ,MAAA,CAAO,MAAA,GAAS,IAAA;AAGjC,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI;AACF,IAAA,OAAA,GAAU,MAAM,MAAM,MAAM,CAAA;AAAA,EAC9B,SAAS,GAAA,EAAK;AAEZ,IAAA,IAAI,eAAe,KAAA,EAAO;AACxB,MAAA,OAAA,CAAQ,KAAA,CAAM;AAAA,EAAK,GAAA,CAAI,OAAO,CAAA,CAAE,CAAA;AAAA,IAClC,CAAA,MAAO;AACL,MAAA,OAAA,CAAQ,KAAA,CAAM,0CAA0C,GAAG,CAAA;AAAA,IAC7D;AACA,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAGA,EAAA,YAAA,CAAa,OAAA,EAAS,MAAA,CAAO,KAAA,IAAS,KAAK,CAAA;AAG3C,EAAA,IAAI,CAAC,QAAQ,OAAA,EAAS;AACpB,IAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,EAChB;AAEA,EAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAChB;AAEA,IAAA,EAAK,CAAE,KAAA,CAAM,CAAC,GAAA,KAAQ;AACpB,EAAA,OAAA,CAAQ,KAAA,CAAM,qBAAqB,GAAG,CAAA;AACtC,EAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AAChB,CAAC,CAAA","file":"cli.cjs","sourcesContent":["/**\r\n * partials.ts\r\n *\r\n * Pure template-engine function for resolving partial inclusions.\r\n * Supports {{> name}} syntax with up to depth-2 recursion to handle\r\n * partials-within-partials. No file-system I/O.\r\n */\r\n\r\n/**\r\n * Resolve partial inclusions in a template string.\r\n *\r\n * Replaces `{{> name}}` markers with the content from `partialsMap`.\r\n * Recursion is capped at depth 2 so that:\r\n * - depth 0 → 1: outer partials are expanded\r\n * - depth 1 → 2: one level of nested partials are expanded\r\n * - depth 2: recursion stops, marker is left as-is\r\n *\r\n * Each resolved partial is `trimEnd()`-ed to prevent trailing blank lines\r\n * from causing double-blank-line artefacts during concatenation.\r\n *\r\n * If a partial name is not found in `partialsMap`, the original marker is\r\n * preserved and a warning is emitted via `console.warn`.\r\n *\r\n * @param text - Template string potentially containing {{> name}} markers\r\n * @param partialsMap - Map of partial name → partial content\r\n * @param depth - Current recursion depth (callers should omit; defaults to 0)\r\n * @returns The template string with partial markers replaced\r\n */\r\nexport function resolvePartials(\r\n text: string,\r\n partialsMap: Record<string, string>,\r\n depth = 0,\r\n): string {\r\n if (depth >= 2) return text;\r\n return text.replace(/\\{\\{> ([\\w-]+)\\}\\}/g, (match, name: string) => {\r\n if (!(name in partialsMap)) {\r\n console.warn(`[WARN] Partial not found: ${match}`);\r\n return match;\r\n }\r\n // Recursively resolve nested partials (depth + 1).\r\n // trimEnd() strips trailing whitespace to avoid extra blank lines.\r\n return resolvePartials(partialsMap[name], partialsMap, depth + 1).trimEnd();\r\n });\r\n}\r\n","/**\r\n * conditionals.ts\r\n *\r\n * Pure template-engine function for resolving conditional blocks.\r\n * Handles {{#if flag}}…{{/if}} and {{#if flag}}…{{else}}…{{/if}} syntax.\r\n * No file-system I/O.\r\n */\r\n\r\n/**\r\n * Resolve conditional blocks in a template string.\r\n *\r\n * Syntax:\r\n * `{{#if flag}}content{{/if}}`\r\n * `{{#if flag}}truthy-content{{else}}falsy-content{{/if}}`\r\n *\r\n * Behaviour:\r\n * - When `context[flag]` is truthy: the delimiters are stripped and the\r\n * content before `{{else}}` (or the entire inner block if no `{{else}}`)\r\n * is kept, surrounded by single `\\n` delimiters.\r\n * - When `context[flag]` is falsy and a `{{else}}` branch exists: the\r\n * content after `{{else}}` is kept, surrounded by single `\\n` delimiters.\r\n * - When `context[flag]` is falsy and no `{{else}}` branch exists: the\r\n * entire block (including surrounding newlines) is removed, leaving a\r\n * single `\\n`.\r\n * - Unknown flags (absent from context) are treated as falsy.\r\n *\r\n * Leading and trailing newlines within the kept content are trimmed so the\r\n * output does not accumulate extra blank lines.\r\n *\r\n * @param text - Template string potentially containing {{#if}} blocks\r\n * @param context - Key-value map used to evaluate flag truthiness\r\n * @returns The template string with conditional blocks resolved\r\n */\r\nexport function resolveConditionals(\r\n text: string,\r\n context: Record<string, unknown>,\r\n): string {\r\n return text.replace(\r\n /\\n*\\{\\{#if (\\w+)\\}\\}([\\s\\S]*?)(?:\\{\\{else\\}\\}([\\s\\S]*?))?\\{\\{\\/if\\}\\}\\n*/g,\r\n (\r\n _match: string,\r\n flag: string,\r\n inner: string,\r\n elseInner: string | undefined,\r\n ) => {\r\n if (context[flag]) {\r\n // Truthy: keep content before {{else}} (or entire inner if no {{else}})\r\n return '\\n' + inner.replace(/^\\n+/, '').replace(/\\n+$/, '') + '\\n';\r\n }\r\n if (elseInner !== undefined) {\r\n // Falsy with {{else}}: keep content after {{else}}\r\n return '\\n' + elseInner.replace(/^\\n+/, '').replace(/\\n+$/, '') + '\\n';\r\n }\r\n // Falsy without {{else}}: remove entire block\r\n return '\\n';\r\n },\r\n );\r\n}\r\n","/**\r\n * variables.ts\r\n *\r\n * Pure template-engine function for resolving variable substitutions.\r\n * Handles {{varName}} syntax. No file-system I/O.\r\n */\r\n\r\n/**\r\n * Resolve variable substitutions in a template string.\r\n *\r\n * Replaces `{{varName}}` markers with `String(context[varName])`.\r\n * If a variable is not found in `context` (or its value is `undefined`),\r\n * the original marker is preserved and a warning is emitted via\r\n * `console.warn`, identifying the file by `filename` for easier debugging.\r\n *\r\n * Note: this step must run AFTER `resolvePartials` and `resolveConditionals`\r\n * so that only plain variable markers remain.\r\n *\r\n * @param text - Template string potentially containing {{varName}} markers\r\n * @param context - Key-value map of variable name → value\r\n * @param filename - Identifier used in warning messages (e.g. persona file path)\r\n * @returns The template string with variable markers substituted\r\n */\r\nexport function resolveVariables(\r\n text: string,\r\n context: Record<string, unknown>,\r\n filename: string,\r\n): string {\r\n return text.replace(/\\{\\{(\\w+)\\}\\}/g, (match, varName: string) => {\r\n if (varName in context && context[varName] !== undefined) {\r\n return String(context[varName]);\r\n }\r\n console.warn(`[WARN] Unresolved variable: ${match} in ${filename}`);\r\n return match;\r\n });\r\n}\r\n","/**\r\n * postProcessor.ts\r\n *\r\n * Pure post-processing functions for cleaning up rendered persona output.\r\n * All functions are side-effect-free and operate only on strings.\r\n * No file-system I/O.\r\n */\r\n\r\n/**\r\n * Collapse 3 or more consecutive blank lines into 2 blank lines.\r\n *\r\n * Specifically converts 4 or more consecutive `\\n` characters into `\\n\\n\\n`\r\n * (which equals 2 blank lines between paragraphs).\r\n *\r\n * @param text - Rendered output string\r\n * @returns String with excessive blank lines collapsed\r\n */\r\nexport function collapseBlankLines(text: string): string {\r\n return text.replace(/\\n{4,}/g, '\\n\\n\\n');\r\n}\r\n\r\n/**\r\n * Ensure every Markdown heading has a blank line immediately before it.\r\n *\r\n * Also ensures horizontal rules (`---`) have a blank line before and after\r\n * them. This corrects spacing gaps caused by partial concatenation where\r\n * `trimEnd()` strips trailing newlines and conditionals add only a single\r\n * `\\n` delimiter.\r\n *\r\n * @param text - Rendered output string\r\n * @returns String with blank lines inserted before headings and rules\r\n */\r\nexport function ensureBlankLineBeforeHeadings(text: string): string {\r\n // Blank line before headings\r\n let result = text.replace(/([^\\n])\\n(#{1,6} )/g, '$1\\n\\n$2');\r\n // Blank line before horizontal rules (---)\r\n result = result.replace(/([^\\n])\\n(---)\\n/g, '$1\\n\\n$2\\n');\r\n // Blank line after horizontal rules (---)\r\n result = result.replace(/\\n(---)\\n([^\\n])/g, '\\n$1\\n\\n$2');\r\n return result;\r\n}\r\n\r\n/**\r\n * Normalize line endings to LF (`\\n`) for OS-agnostic output.\r\n *\r\n * Converts CRLF (`\\r\\n`) first, then strips any remaining stray CR (`\\r`).\r\n *\r\n * @param text - String potentially containing CRLF or CR line endings\r\n * @returns String with all line endings normalized to LF\r\n */\r\nexport function normalizeNewlines(text: string): string {\r\n return text.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\r\n}\r\n","/**\r\n * serializer.ts\r\n *\r\n * Pure serializer functions for converting tool lists to YAML-compatible\r\n * string representations. No file-system I/O.\r\n */\r\n\r\n/**\r\n * Serialize a tools array in YAML single-quote flow format WITH outer brackets.\r\n *\r\n * Output format: `['tool1', 'tool2', 'tool3']`\r\n * Used by the ledger suite to preserve byte-identical frontmatter output.\r\n *\r\n * @param tools - Array of tool name strings\r\n * @returns YAML flow-sequence string including outer brackets\r\n *\r\n * @example\r\n * serializeTools(['Bash', 'Read']) // => \"['Bash', 'Read']\"\r\n * serializeTools([]) // => \"[]\"\r\n */\r\nexport function serializeTools(tools: string[]): string {\r\n return '[' + tools.map((t) => `'${t}'`).join(', ') + ']';\r\n}\r\n\r\n/**\r\n * Serialize a tools array in YAML single-quote flow format WITHOUT outer brackets.\r\n *\r\n * Output format: `'tool1', 'tool2', 'tool3'`\r\n * Used inside standalone frontmatter templates which supply the surrounding `[ ]`.\r\n *\r\n * @param tools - Array of tool name strings\r\n * @returns Comma-separated quoted tool names (no outer brackets)\r\n *\r\n * @example\r\n * serializeToolsList(['Bash', 'Read']) // => \"'Bash', 'Read'\"\r\n * serializeToolsList([]) // => \"\"\r\n */\r\nexport function serializeToolsList(tools: string[]): string {\r\n return tools.map((t) => `'${t}'`).join(', ');\r\n}\r\n","/**\r\n * src/loaders/partials-loader.ts\r\n *\r\n * File-system loader for Handlebars-style partial snippets.\r\n *\r\n * Reads every `.md` file in `dir`, keys each entry by the filename stem\r\n * (i.e. the portion before the final `.md` extension), and returns the\r\n * map. Callers that need a two-layer (shared → suite-local override)\r\n * setup should call `loadPartials` twice and merge the results themselves,\r\n * with the suite-local result spreading last.\r\n *\r\n * All file reads are performed asynchronously. Path construction uses\r\n * `path.join` and `path.posix`-compatible operations so no path-separator\r\n * assumptions are baked in.\r\n */\r\n\r\nimport { readdir, readFile } from 'node:fs/promises';\r\nimport path from 'node:path';\r\n\r\n/**\r\n * Load all `.md` files in `dir` and return them as a `Record<string, string>`\r\n * keyed by filename stem.\r\n *\r\n * Files whose names do not end in `.md` are silently ignored.\r\n * The directory must exist; a missing directory throws an `ENOENT` error from\r\n * the underlying `readdir` call (let callers decide how to handle absence).\r\n *\r\n * @param dir Absolute (or relative) path to the directory to scan.\r\n * @returns A map from filename stem → file content string.\r\n *\r\n * @example\r\n * const partials = await loadPartials('/project/partials');\r\n * // { greeting: 'Hello, {{name}}!', footer: '---\\nEnd of file' }\r\n */\r\nexport async function loadPartials(dir: string): Promise<Record<string, string>> {\r\n const entries = await readdir(dir, { withFileTypes: true });\r\n\r\n const mdFiles = entries.filter(\r\n (entry) => entry.isFile() && entry.name.endsWith('.md'),\r\n );\r\n\r\n const pairs = await Promise.all(\r\n mdFiles.map(async (entry) => {\r\n const stem = entry.name.slice(0, -'.md'.length); // strip trailing \".md\"\r\n const filePath = path.join(dir, entry.name);\r\n const content = await readFile(filePath, 'utf8');\r\n return [stem, content] as [string, string];\r\n }),\r\n );\r\n\r\n return Object.fromEntries(pairs);\r\n}\r\n","/**\r\n * src/plugins/runner.ts\r\n *\r\n * Plugin runner — responsible for invoking plugin hooks in registration order.\r\n *\r\n * Each exported function corresponds to one lifecycle hook defined in\r\n * PersonaBuildPlugin. The runner:\r\n * - Skips plugins that do not implement the requested hook (hook is optional)\r\n * - Invokes hooks in the order plugins are registered (first-in first-called)\r\n * - For accumulating hooks (onBuildContext, onPostRender), each plugin\r\n * receives the output of the previous plugin as its first argument\r\n * - For collecting hooks (onValidate), results are concatenated into a\r\n * flat array\r\n *\r\n * No file-system I/O. No async operations.\r\n */\r\n\r\nimport type {\r\n PersonaBuildPlugin,\r\n PersonaMetadata,\r\n SuiteConfig,\r\n TargetType,\r\n ValidationResult,\r\n} from './types.js';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Suite-level hook\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Invoke the `onSuiteInit` hook on every registered plugin.\r\n *\r\n * Each plugin may optionally implement this hook. Plugins are called in\r\n * registration order. The hook receives the suite config and a mutable\r\n * `sharedMeta` object — plugins may mutate `sharedMeta` in place; the\r\n * same reference is passed to every subsequent plugin.\r\n *\r\n * @param plugins Ordered list of registered plugins\r\n * @param suite The suite configuration object\r\n * @param sharedMeta Mutable shared metadata object (mutated in place by plugins)\r\n */\r\nexport function runSuiteInit(\r\n plugins: PersonaBuildPlugin[],\r\n suite: SuiteConfig,\r\n sharedMeta: Record<string, unknown>,\r\n): void {\r\n for (const plugin of plugins) {\r\n if (typeof plugin.onSuiteInit === 'function') {\r\n plugin.onSuiteInit(suite, sharedMeta);\r\n }\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Per-persona context accumulation\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Invoke the `onBuildContext` hook on every registered plugin, accumulating\r\n * context mutations sequentially.\r\n *\r\n * Each plugin receives the context returned by the previous plugin. If a\r\n * plugin does not implement `onBuildContext`, the context passes through\r\n * unchanged. The final accumulated context is returned.\r\n *\r\n * @param plugins Ordered list of registered plugins\r\n * @param ctx Initial rendering context for this persona\r\n * @param persona Typed metadata for the persona being built\r\n * @param suite The suite configuration object\r\n * @returns Accumulated rendering context after all plugins have run\r\n */\r\nexport function runBuildContext(\r\n plugins: PersonaBuildPlugin[],\r\n ctx: Record<string, unknown>,\r\n persona: PersonaMetadata,\r\n suite: SuiteConfig,\r\n): Record<string, unknown> {\r\n let accumulated = ctx;\r\n for (const plugin of plugins) {\r\n if (typeof plugin.onBuildContext === 'function') {\r\n accumulated = plugin.onBuildContext(accumulated, persona, suite);\r\n }\r\n }\r\n return accumulated;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Per-persona post-render chain\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Invoke the `onPostRender` hook on every registered plugin, chaining the\r\n * output string sequentially.\r\n *\r\n * Each plugin receives the string returned by the previous plugin. If a\r\n * plugin does not implement `onPostRender`, the string passes through\r\n * unchanged. The final string is returned.\r\n *\r\n * @param plugins Ordered list of registered plugins\r\n * @param rendered Initial rendered output string\r\n * @param persona Typed metadata for the persona being built\r\n * @param target The current build target\r\n * @returns Final output string after all plugins have run\r\n */\r\nexport function runPostRender(\r\n plugins: PersonaBuildPlugin[],\r\n rendered: string,\r\n persona: PersonaMetadata,\r\n target: TargetType,\r\n): string {\r\n let output = rendered;\r\n for (const plugin of plugins) {\r\n if (typeof plugin.onPostRender === 'function') {\r\n output = plugin.onPostRender(output, persona, target);\r\n }\r\n }\r\n return output;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Per-persona validation collection\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Invoke the `onValidate` hook on every registered plugin and collect all\r\n * returned ValidationResult objects into a single flat array.\r\n *\r\n * Plugins that do not implement `onValidate` contribute nothing to the result.\r\n * The return value is always an array (never null/undefined).\r\n *\r\n * @param plugins Ordered list of registered plugins\r\n * @param persona Typed metadata for the persona being built\r\n * @param suite The suite configuration object\r\n * @param target The current build target (optional — forwarded to each plugin)\r\n * @returns Flat array of all ValidationResult objects from all plugins\r\n */\r\nexport function runValidate(\r\n plugins: PersonaBuildPlugin[],\r\n persona: PersonaMetadata,\r\n suite: SuiteConfig,\r\n target?: TargetType,\r\n): ValidationResult[] {\r\n const results: ValidationResult[] = [];\r\n for (const plugin of plugins) {\r\n if (typeof plugin.onValidate === 'function') {\r\n const pluginResults = plugin.onValidate(persona, suite, target);\r\n results.push(...pluginResults);\r\n }\r\n }\r\n return results;\r\n}\r\n","/**\r\n * src/builders/frontmatter.ts\r\n *\r\n * Frontmatter template registry for @mistralys/persona-builder.\r\n *\r\n * Ships two minimal default templates — one per target — that work for the\r\n * \"standalone\" persona mode (simple personas without numbered workflows or\r\n * MCP server blocks). Projects needing richer frontmatter register custom\r\n * templates via the `PersonaBuildPlugin.frontmatterTemplates` property.\r\n *\r\n * Template rendering follows the same two-step sequence as body rendering:\r\n * 1. resolveConditionals() — resolve {{#if flag}} blocks\r\n * 2. resolveVariables() — substitute {{varName}} markers\r\n *\r\n * No partials in frontmatter — frontmatter is kept deliberately simple.\r\n */\r\n\r\nimport { resolveConditionals } from '../engine/conditionals.js';\r\nimport { resolveVariables } from '../engine/variables.js';\r\nimport type { PersonaBuildPlugin } from '../plugins/types.js';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Built-in default templates\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Default VS Code frontmatter template.\r\n *\r\n * Minimal fields that work for standalone personas. Projects using numbered\r\n * workflows (e.g. ledger) should inject a richer template via a plugin.\r\n */\r\nexport const DEFAULT_FRONTMATTER_VSCODE = `---\r\nname: '{{name}} v{{version}}'\r\ndescription: '{{description}}'\r\ntools: [{{tools_list}}]\r\n---`;\r\n\r\n/**\r\n * Default Claude Code frontmatter template.\r\n *\r\n * Minimal fields that work for standalone personas. Projects using numbered\r\n * workflows should inject a richer template via a plugin.\r\n */\r\nexport const DEFAULT_FRONTMATTER_CLAUDE_CODE = `---\r\nname: {{cc_file_name_stem}}\r\npermissionMode: {{cc_permission_mode}}\r\nmodel: {{cc_model}}\r\nmemory: {{cc_memory}}\r\nallowedTools: [{{cc_tools_list}}]\r\n---`;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Template resolution\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Resolve frontmatter template precedence.\r\n *\r\n * Precedence order (highest wins):\r\n * 1. Plugin `frontmatterTemplates` — the last plugin with a matching key\r\n * wins (plugins are applied in reverse-registration order so the\r\n * *first* registered plugin with a template takes precedence over later\r\n * ones, matching the general plugin-chain contract).\r\n * 2. `configTemplates` — templates passed via `BuildConfig.frontmatter`\r\n * 3. Library defaults (`DEFAULT_FRONTMATTER_VSCODE` / `DEFAULT_FRONTMATTER_CLAUDE_CODE`)\r\n *\r\n * @param target The build target ('vscode' | 'claude-code')\r\n * @param plugins Registered plugins (searched in order; first match wins)\r\n * @param configTemplates Optional caller-supplied overrides from BuildConfig\r\n * @returns The resolved template string\r\n */\r\nexport function resolveFrontmatterTemplate(\r\n target: 'vscode' | 'claude-code',\r\n plugins: PersonaBuildPlugin[],\r\n configTemplates?: Partial<Record<'vscode' | 'claude-code', string>>,\r\n): string {\r\n // Check plugins in registration order — first plugin with a matching\r\n // frontmatterTemplates entry wins.\r\n for (const plugin of plugins) {\r\n if (plugin.frontmatterTemplates && target in plugin.frontmatterTemplates) {\r\n const tpl = plugin.frontmatterTemplates[target];\r\n if (tpl !== undefined) return tpl;\r\n }\r\n }\r\n\r\n // Caller-supplied config templates\r\n if (configTemplates && target in configTemplates) {\r\n const tpl = configTemplates[target];\r\n if (tpl !== undefined) return tpl;\r\n }\r\n\r\n // Library defaults\r\n return target === 'vscode' ? DEFAULT_FRONTMATTER_VSCODE : DEFAULT_FRONTMATTER_CLAUDE_CODE;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Frontmatter rendering\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Render a frontmatter template string against the given context.\r\n *\r\n * Applies the standard two-step template resolution:\r\n * 1. `resolveConditionals` — `{{#if flag}}` blocks\r\n * 2. `resolveVariables` — `{{varName}}` substitution\r\n *\r\n * @param template The raw frontmatter template string (may contain markers)\r\n * @param context Key-value context for variable substitution\r\n * @param filename Source filename used in warning messages\r\n * @returns Rendered frontmatter string (ready to prepend to body)\r\n */\r\nexport function renderFrontmatter(\r\n template: string,\r\n context: Record<string, unknown>,\r\n filename: string,\r\n): string {\r\n let rendered = resolveConditionals(template, context);\r\n rendered = resolveVariables(rendered, context, filename);\r\n return rendered;\r\n}\r\n","/**\r\n * src/builders/persona-builder.ts\r\n *\r\n * Core build orchestrator for @mistralys/persona-builder.\r\n *\r\n * Exports three public functions:\r\n *\r\n * 1. buildPersona(personaYamlPath, suiteName, suiteConfig, sharedMeta,\r\n * partialsMap, config, plugins, target, agentMap?)\r\n * — Builds a single persona for a single target. Returns a BuildResult.\r\n *\r\n * 2. buildSuite(suiteName, suiteConfig, config, plugins, target, agentMap?)\r\n * — Discovers all persona YAMLs for a suite, fires onSuiteInit, maps\r\n * buildPersona() over each, and returns BuildResult[].\r\n *\r\n * 3. build(config)\r\n * — Top-level entry point. Pre-scans all suites to build a cross-suite\r\n * agent name map, then iterates all suites × targets, calls\r\n * buildSuite() for each combination, and returns a BuildSummary.\r\n * Respects --check (no writes) and --strict (fail on warnings/errors).\r\n */\r\n\r\nimport { readdir, readFile, mkdir, writeFile } from 'node:fs/promises';\r\nimport { existsSync } from 'node:fs';\r\nimport path from 'node:path';\r\nimport yaml from 'js-yaml';\r\n\r\nimport { resolvePartials } from '../engine/partials.js';\r\nimport { resolveConditionals } from '../engine/conditionals.js';\r\nimport { resolveVariables } from '../engine/variables.js';\r\nimport {\r\n collapseBlankLines,\r\n ensureBlankLineBeforeHeadings,\r\n normalizeNewlines,\r\n} from '../engine/postProcessor.js';\r\nimport { serializeTools, serializeToolsList } from '../engine/serializer.js';\r\nimport { loadPartials } from '../loaders/partials-loader.js';\r\nimport {\r\n runSuiteInit,\r\n runBuildContext,\r\n runPostRender,\r\n runValidate,\r\n} from '../plugins/runner.js';\r\n\r\nimport { resolveFrontmatterTemplate, renderFrontmatter } from './frontmatter.js';\r\nimport type { BuildConfig, BuildResult, BuildSummary } from './types.js';\r\nimport type { PersonaBuildPlugin, PersonaMetadata, SuiteConfig, ValidationResult } from '../plugins/types.js';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Discover all persona YAML files in the `meta/` subdirectory of a suite.\r\n *\r\n * Excludes files whose names start with `_` (shared metadata files such as\r\n * `_shared.yaml`). Results are sorted lexicographically.\r\n *\r\n * @param suiteConfig Suite configuration (used to locate `metaSubdir`)\r\n * @returns Absolute paths to each persona YAML file, sorted.\r\n */\r\nasync function discoverSuitePersonaYamls(suiteConfig: SuiteConfig): Promise<string[]> {\r\n const metaSubdir = suiteConfig.metaSubdir ?? 'meta';\r\n const metaDir = path.join(suiteConfig.srcDir, metaSubdir);\r\n\r\n const entries = await readdir(metaDir, { withFileTypes: true });\r\n\r\n return entries\r\n .filter((e) => e.isFile() && e.name.endsWith('.yaml') && !e.name.startsWith('_'))\r\n .map((e) => path.join(metaDir, e.name))\r\n .sort();\r\n}\r\n\r\n/**\r\n * Load and parse a raw YAML file into a plain object.\r\n * Used for `_shared.yaml` which does not conform to PersonaMetadata's\r\n * `name` requirement.\r\n *\r\n * @param filePath Absolute path to the YAML file\r\n * @returns Parsed object, or {} when the file is empty/absent\r\n */\r\nasync function loadRawYaml(filePath: string): Promise<Record<string, unknown>> {\r\n if (!existsSync(filePath)) return {};\r\n const raw = await readFile(filePath, 'utf8');\r\n const parsed: unknown = yaml.load(raw);\r\n if (parsed === null || parsed === undefined) return {};\r\n if (typeof parsed !== 'object' || Array.isArray(parsed)) return {};\r\n return parsed as Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Load a persona YAML file and return it as a plain metadata record.\r\n * The `name` field is derived from the filename stem when absent.\r\n *\r\n * @param yamlPath Absolute path to the persona YAML file\r\n * @returns Merged metadata record ready for context building\r\n */\r\nasync function loadPersonaYaml(yamlPath: string): Promise<Record<string, unknown>> {\r\n const raw = await readFile(yamlPath, 'utf8');\r\n const parsed: unknown = yaml.load(raw);\r\n\r\n if (parsed === null || parsed === undefined || typeof parsed !== 'object' || Array.isArray(parsed)) {\r\n throw new Error(`buildPersona: expected a YAML object in \"${yamlPath}\"`);\r\n }\r\n\r\n const record = parsed as Record<string, unknown>;\r\n\r\n // Derive name from filename stem if not present in YAML\r\n if (!record['name']) {\r\n record['name'] = path.basename(yamlPath, '.yaml');\r\n }\r\n\r\n return record;\r\n}\r\n\r\n/**\r\n * Pre-scan all suites and build a cross-suite agent name map.\r\n *\r\n * For each persona across all configured suites, creates a context variable:\r\n * key: `agent_` + slug (hyphens → underscores)\r\n * value: `\"<name> v<version>\"`\r\n *\r\n * Slug is taken from the persona YAML's `slug` field, falling back to the\r\n * filename stem. Version falls back to the suite's `default_version`, then\r\n * to `'0.0.0'`.\r\n *\r\n * @param config Top-level BuildConfig with all suite definitions\r\n * @returns Map of agent variable keys to display strings\r\n */\r\nasync function buildAgentNameMap(\r\n config: BuildConfig,\r\n): Promise<Record<string, string>> {\r\n const agentMap: Record<string, string> = {};\r\n\r\n for (const [, suiteConfig] of Object.entries(config.suites)) {\r\n const metaSubdir = suiteConfig.metaSubdir ?? 'meta';\r\n const sharedYamlPath = path.join(suiteConfig.srcDir, metaSubdir, '_shared.yaml');\r\n const sharedMeta = await loadRawYaml(sharedYamlPath);\r\n const defaultVersion =\r\n typeof sharedMeta['default_version'] === 'string'\r\n ? sharedMeta['default_version']\r\n : '0.0.0';\r\n\r\n const personaYamls = await discoverSuitePersonaYamls(suiteConfig);\r\n\r\n for (const yamlPath of personaYamls) {\r\n const persona = await loadPersonaYaml(yamlPath);\r\n\r\n const slug =\r\n typeof persona['slug'] === 'string'\r\n ? persona['slug']\r\n : path.basename(yamlPath, '.yaml');\r\n\r\n const name =\r\n typeof persona['name'] === 'string'\r\n ? persona['name']\r\n : slug;\r\n\r\n const version =\r\n typeof persona['version'] === 'string'\r\n ? persona['version']\r\n : defaultVersion;\r\n\r\n const key = `agent_${slug.replace(/-/g, '_')}`;\r\n agentMap[key] = `${name} v${version}`;\r\n }\r\n }\r\n\r\n return agentMap;\r\n}\r\n\r\n/**\r\n * Build the merged template context for a single persona.\r\n *\r\n * Merge order (later values win):\r\n * 1. sharedMeta (suite-level defaults)\r\n * 2. per-persona YAML fields\r\n * 3. derived/computed fields (version fallback, etc.)\r\n * 4. agentMap entries (only for keys not already present)\r\n *\r\n * @param personaMeta Per-persona YAML as a plain record\r\n * @param sharedMeta Parsed `_shared.yaml` fields\r\n * @param agentMap Cross-suite agent name map (injected by build())\r\n * @returns Merged rendering context\r\n */\r\nfunction buildContext(\r\n personaMeta: Record<string, unknown>,\r\n sharedMeta: Record<string, unknown>,\r\n agentMap: Record<string, string> = {},\r\n): Record<string, unknown> {\r\n const version =\r\n typeof personaMeta['version'] === 'string'\r\n ? personaMeta['version']\r\n : typeof sharedMeta['default_version'] === 'string'\r\n ? sharedMeta['default_version']\r\n : '0.0.0';\r\n\r\n // Merge base: shared first, persona overrides\r\n const merged: Record<string, unknown> = {\r\n ...sharedMeta,\r\n ...personaMeta,\r\n version,\r\n };\r\n\r\n // ── Derived convenience fields (only set when not already provided) ───────\r\n // tools_list / tools_json — serialized from the `tools` array if present\r\n const tools = Array.isArray(merged['tools']) ? (merged['tools'] as string[]) : [];\r\n if (!('tools_list' in merged)) {\r\n merged['tools_list'] = serializeToolsList(tools);\r\n }\r\n if (!('tools_json' in merged)) {\r\n merged['tools_json'] = serializeTools(tools);\r\n }\r\n\r\n // cc_tools_list / cc_tools_json — from `cc_tools` or fall back to `tools`\r\n const ccTools = Array.isArray(merged['cc_tools']) ? (merged['cc_tools'] as string[]) : tools;\r\n if (!('cc_tools_list' in merged)) {\r\n merged['cc_tools_list'] = serializeToolsList(ccTools);\r\n }\r\n if (!('cc_tools_json' in merged)) {\r\n merged['cc_tools_json'] = serializeTools(ccTools);\r\n }\r\n\r\n // cc_file_name_stem — stem of cc_file_name (for default CC frontmatter template)\r\n if (!('cc_file_name_stem' in merged) && typeof merged['cc_file_name'] === 'string') {\r\n const ccFileName = merged['cc_file_name'] as string;\r\n merged['cc_file_name_stem'] = ccFileName.replace(/\\.md$/, '');\r\n }\r\n\r\n // ── Cross-suite agent name variables ──────────────────────────────────────\r\n for (const [key, value] of Object.entries(agentMap)) {\r\n if (!(key in merged)) {\r\n merged[key] = value;\r\n }\r\n }\r\n\r\n return merged;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// buildPersona — single persona × single target\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Build a single persona for a single output target.\r\n *\r\n * Pipeline:\r\n * 1. Load sharedMeta + personaMeta (callers supply pre-loaded values)\r\n * 2. Build merged context\r\n * 3. Run onBuildContext plugin hooks (context accumulation)\r\n * 4. Resolve frontmatter template → render frontmatter\r\n * 5. Load content template\r\n * 6. Render body: partials → conditionals → variables → post-process\r\n * 7. Assemble final output (frontmatter + body)\r\n * 8. Run onPostRender plugin hooks (output chain)\r\n * 9. Run onValidate plugin hooks (validation collection)\r\n * 10. Determine output file path\r\n * 11. Write output file (unless check mode)\r\n * 12. Return BuildResult\r\n *\r\n * @param personaYamlPath Absolute path to the persona YAML source file\r\n * @param suiteName Identifier for the suite this persona belongs to\r\n * @param suiteConfig Suite configuration object\r\n * @param sharedMeta Pre-loaded `_shared.yaml` contents\r\n * @param partialsMap Pre-loaded partials map (shared + suite-local merged)\r\n * @param config Top-level BuildConfig\r\n * @param plugins Registered plugins\r\n * @param target Target output format\r\n * @returns BuildResult for this persona × target combination\r\n */\r\nexport async function buildPersona(\r\n personaYamlPath: string,\r\n suiteName: string,\r\n suiteConfig: SuiteConfig,\r\n sharedMeta: Record<string, unknown>,\r\n partialsMap: Record<string, string>,\r\n config: BuildConfig,\r\n plugins: PersonaBuildPlugin[],\r\n target: 'vscode' | 'claude-code',\r\n agentMap: Record<string, string> = {},\r\n): Promise<BuildResult> {\r\n // ── 1. Load persona metadata ──────────────────────────────────────────────\r\n const personaMeta = await loadPersonaYaml(personaYamlPath);\r\n\r\n // ── 2. Build merged context ───────────────────────────────────────────────\r\n let context = buildContext(personaMeta, sharedMeta, agentMap);\r\n\r\n // ── 3. Plugin onBuildContext ──────────────────────────────────────────────\r\n // Cast context to PersonaMetadata for the plugin runner (it requires a\r\n // name field which is guaranteed by loadPersonaYaml above).\r\n const personaMetaTyped = personaMeta as PersonaMetadata;\r\n context = runBuildContext(plugins, context, personaMetaTyped, suiteConfig);\r\n\r\n // ── 4. Render frontmatter ─────────────────────────────────────────────────\r\n const fmTemplate = resolveFrontmatterTemplate(target, plugins, config.frontmatter);\r\n const contentBasename = path.basename(personaYamlPath, '.yaml') + '.md';\r\n const frontmatter = renderFrontmatter(fmTemplate, context, contentBasename);\r\n\r\n // ── 5. Load content template ──────────────────────────────────────────────\r\n const contentSubdir = suiteConfig.contentSubdir ?? 'content';\r\n const contentPath = path.join(suiteConfig.srcDir, contentSubdir, contentBasename);\r\n const bodyTemplate = normalizeNewlines(await readFile(contentPath, 'utf8'));\r\n\r\n // ── 6. Render body ────────────────────────────────────────────────────────\r\n let body = resolvePartials(bodyTemplate, partialsMap);\r\n body = resolveConditionals(body, context);\r\n body = resolveVariables(body, context, contentBasename);\r\n body = collapseBlankLines(body);\r\n body = ensureBlankLineBeforeHeadings(body);\r\n body = body.trimEnd();\r\n\r\n // ── 7. Assemble output ────────────────────────────────────────────────────\r\n let output = normalizeNewlines(`${frontmatter}\\n\\n${body}\\n`);\r\n\r\n // ── 8. Plugin onPostRender ────────────────────────────────────────────────\r\n output = runPostRender(plugins, output, personaMetaTyped, target);\r\n\r\n // ── 9. Plugin onValidate ──────────────────────────────────────────────────\r\n const validationResults: ValidationResult[] = runValidate(plugins, personaMetaTyped, suiteConfig, target);\r\n\r\n // ── 10. Determine output file path ────────────────────────────────────────\r\n const outputDir = target === 'vscode' ? suiteConfig.outVscode : suiteConfig.outClaudeCode;\r\n // Use declared output filename fields when present (vs_file_name / cc_file_name),\r\n // falling back to the content basename.\r\n let outputBasename: string;\r\n if (target === 'vscode' && typeof context['vs_file_name'] === 'string') {\r\n outputBasename = context['vs_file_name'];\r\n } else if (target === 'claude-code' && typeof context['cc_file_name'] === 'string') {\r\n outputBasename = context['cc_file_name'];\r\n } else {\r\n outputBasename = contentBasename;\r\n }\r\n const outputPath = path.join(outputDir, outputBasename);\r\n\r\n // ── 11. Write (unless check mode) ─────────────────────────────────────────\r\n const check = config.check ?? false;\r\n let written = false;\r\n\r\n if (!check) {\r\n await mkdir(outputDir, { recursive: true });\r\n await writeFile(outputPath, output, 'utf8');\r\n written = true;\r\n }\r\n\r\n return {\r\n suite: suiteName,\r\n target,\r\n personaYamlPath,\r\n outputPath,\r\n content: output,\r\n validationResults,\r\n written,\r\n };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// buildSuite — all personas in one suite × one target\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Build all personas in a suite for a single output target.\r\n *\r\n * Pipeline:\r\n * 1. Load `_shared.yaml` for the suite\r\n * 2. Load merged partials (shared → suite-local)\r\n * 3. Run `onSuiteInit` on all plugins\r\n * 4. Discover all persona YAML files\r\n * 5. Call `buildPersona()` for each\r\n *\r\n * @param suiteName Identifier for this suite\r\n * @param suiteConfig Suite configuration\r\n * @param config Top-level BuildConfig\r\n * @param plugins Registered plugins\r\n * @param target Target output format\r\n * @returns Array of BuildResult objects, one per persona\r\n */\r\nexport async function buildSuite(\r\n suiteName: string,\r\n suiteConfig: SuiteConfig,\r\n config: BuildConfig,\r\n plugins: PersonaBuildPlugin[],\r\n target: 'vscode' | 'claude-code',\r\n agentMap: Record<string, string> = {},\r\n): Promise<BuildResult[]> {\r\n // ── 1. Load shared metadata ───────────────────────────────────────────────\r\n const metaSubdir = suiteConfig.metaSubdir ?? 'meta';\r\n const sharedYamlPath = path.join(suiteConfig.srcDir, metaSubdir, '_shared.yaml');\r\n const sharedMeta = await loadRawYaml(sharedYamlPath);\r\n\r\n // ── 2. Load partials (two-layer: shared base → suite-local override) ──────\r\n let partialsMap: Record<string, string> = {};\r\n\r\n if (config.sharedPartialsDir && existsSync(config.sharedPartialsDir)) {\r\n partialsMap = { ...partialsMap, ...(await loadPartials(config.sharedPartialsDir)) };\r\n }\r\n\r\n const partialsSubdir = suiteConfig.partialsSubdir ?? 'partials';\r\n const suitePartialsDir = path.join(suiteConfig.srcDir, partialsSubdir);\r\n if (existsSync(suitePartialsDir)) {\r\n partialsMap = { ...partialsMap, ...(await loadPartials(suitePartialsDir)) };\r\n }\r\n\r\n // ── 3. Plugin onSuiteInit ─────────────────────────────────────────────────\r\n runSuiteInit(plugins, suiteConfig, sharedMeta);\r\n\r\n // ── 4. Discover persona YAML files ────────────────────────────────────────\r\n const personaYamlPaths = await discoverSuitePersonaYamls(suiteConfig);\r\n\r\n // ── 5. Build each persona ─────────────────────────────────────────────────\r\n const results: BuildResult[] = [];\r\n for (const yamlPath of personaYamlPaths) {\r\n const result = await buildPersona(\r\n yamlPath,\r\n suiteName,\r\n suiteConfig,\r\n sharedMeta,\r\n partialsMap,\r\n config,\r\n plugins,\r\n target,\r\n agentMap,\r\n );\r\n results.push(result);\r\n }\r\n\r\n return results;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// build — top-level entry point\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Top-level build orchestrator.\r\n *\r\n * Iterates all `config.suites × config.targets` combinations, calls\r\n * `buildSuite()` for each, and aggregates the results into a `BuildSummary`.\r\n *\r\n * Modes:\r\n * - Normal: renders and writes all personas.\r\n * - `check: true`: renders without writing; useful for CI staleness checks.\r\n * - `strict: true`: throws when any ValidationResult has severity `'error'`\r\n * or `'warning'`. All suites are processed before the throw, so output\r\n * files **will** be written to disk even when the build ultimately fails.\r\n * **For CI usage, combine `strict: true` with `check: true`** to avoid\r\n * leaving partial artefacts on disk when validation fails.\r\n *\r\n * @param config Typed build configuration\r\n * @returns Aggregated BuildSummary\r\n * @throws `Error` when `strict: true` and validation failures exist\r\n */\r\nexport async function build(config: BuildConfig): Promise<BuildSummary> {\r\n const plugins = config.plugins ?? [];\r\n const targets = config.targets ?? ['vscode', 'claude-code'];\r\n const allResults: BuildResult[] = [];\r\n\r\n // Pre-scan: build cross-suite agent name map\r\n const agentMap = await buildAgentNameMap(config);\r\n\r\n for (const [suiteName, suiteConfig] of Object.entries(config.suites)) {\r\n for (const target of targets) {\r\n const suiteResults = await buildSuite(suiteName, suiteConfig, config, plugins, target, agentMap);\r\n allResults.push(...suiteResults);\r\n }\r\n }\r\n\r\n // Collect strict failures (error + warning severity)\r\n const strictFailures: ValidationResult[] = config.strict\r\n ? allResults.flatMap((r) =>\r\n r.validationResults.filter(\r\n (v) => v.severity === 'error' || v.severity === 'warning',\r\n ),\r\n )\r\n : [];\r\n\r\n const success = !config.strict || strictFailures.length === 0;\r\n\r\n const summary: BuildSummary = {\r\n success,\r\n results: allResults,\r\n strictFailures,\r\n totalBuilt: allResults.length,\r\n totalWritten: allResults.filter((r) => r.written).length,\r\n };\r\n\r\n if (config.strict && !success) {\r\n const messages = strictFailures.map((f) => `[${f.severity}] ${f.message}`).join('\\n');\r\n throw new Error(\r\n `Build failed in strict mode — ${strictFailures.length} validation issue(s):\\n${messages}`,\r\n );\r\n }\r\n\r\n return summary;\r\n}\r\n","#!/usr/bin/env node\r\n/**\r\n * src/cli.ts — @mistralys/persona-builder CLI entry point\r\n *\r\n * Flags:\r\n * --config <path> Path to config file (JS/CJS/JSON). Default: persona-build.config.js\r\n * --check Run the build pipeline but do not write output files.\r\n * Always exits 0 unless combined with --strict, which causes\r\n * exit 1 when any ValidationResult has severity 'error' or\r\n * 'warning'.\r\n * --strict Fail (exit 1) if any ValidationResult has severity\r\n * 'error' or 'warning'.\r\n * --help Print usage and exit 0.\r\n * --version Print package version and exit 0.\r\n *\r\n * No heavy CLI framework — args are parsed with a hand-rolled loop.\r\n */\r\n\r\nimport { createRequire } from 'node:module';\r\nimport path from 'node:path';\r\nimport { existsSync } from 'node:fs';\r\nimport { pathToFileURL } from 'node:url';\r\n\r\nimport { build } from './builders/persona-builder.js';\r\nimport type { BuildConfig, BuildSummary } from './builders/types.js';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Version — sourced from package.json (single source of truth).\r\n// createRequire is already imported above for config loading; reuse it here.\r\n// ---------------------------------------------------------------------------\r\n\r\nconst _pkgRequire = createRequire(import.meta.url);\r\nconst VERSION = (_pkgRequire('../package.json') as { version: string }).version;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Usage / help text\r\n// ---------------------------------------------------------------------------\r\n\r\nconst USAGE = `\r\n@mistralys/persona-builder v${VERSION}\r\n\r\nBuild AI persona documents from YAML metadata and Markdown content templates.\r\n\r\nUSAGE\r\n persona-build [options]\r\n\r\nOPTIONS\r\n --config <path> Path to the build config file.\r\n Supports .js (ESM), .cjs, and .json formats.\r\n Default: persona-build.config.js in the current directory.\r\n --check Render personas but skip writing output files.\r\n Always exits 0 on its own. Combine with --strict to\r\n exit 1 when validators report errors or warnings.\r\n --strict Exit 1 if any validation result has severity 'error'\r\n or 'warning'.\r\n --help Show this help message and exit.\r\n --version Print the package version and exit.\r\n\r\nEXAMPLES\r\n persona-build # Build with default config\r\n persona-build --config ./my-config.js # Build with a custom config\r\n persona-build --check # CI staleness check (no file writes)\r\n persona-build --strict # Fail on warnings or errors\r\n persona-build --check --strict # Safe CI check — no writes + strict\r\n`.trim();\r\n\r\n// ---------------------------------------------------------------------------\r\n// Arg parsing\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface ParsedArgs {\r\n configPath?: string;\r\n check: boolean;\r\n strict: boolean;\r\n help: boolean;\r\n version: boolean;\r\n}\r\n\r\nfunction parseArgs(argv: string[]): ParsedArgs {\r\n const args = argv.slice(2); // strip 'node' + script path\r\n\r\n const result: ParsedArgs = {\r\n configPath: undefined,\r\n check: false,\r\n strict: false,\r\n help: false,\r\n version: false,\r\n };\r\n\r\n let i = 0;\r\n while (i < args.length) {\r\n const arg = args[i];\r\n switch (arg) {\r\n case '--help':\r\n case '-h':\r\n result.help = true;\r\n break;\r\n case '--version':\r\n case '-v':\r\n result.version = true;\r\n break;\r\n case '--check':\r\n result.check = true;\r\n break;\r\n case '--strict':\r\n result.strict = true;\r\n break;\r\n case '--config': {\r\n const next = args[i + 1];\r\n if (!next || next.startsWith('--')) {\r\n console.error('Error: --config requires a path argument.');\r\n process.exit(1);\r\n }\r\n result.configPath = next;\r\n i++; // consume the value\r\n break;\r\n }\r\n default:\r\n // Unknown flag — warn but do not exit so older configs stay forward-compatible\r\n if (arg.startsWith('--')) {\r\n console.warn(`Warning: Unknown flag \"${arg}\" — ignored.`);\r\n }\r\n }\r\n i++;\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Config loading\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Resolve the config file path from the user-supplied value or the default\r\n * discovery chain.\r\n *\r\n * Discovery order (when --config is not supplied):\r\n * 1. persona-build.config.js (ESM)\r\n * 2. persona-build.config.cjs (CJS)\r\n * 3. persona-build.config.json (JSON)\r\n */\r\nfunction resolveConfigPath(cliValue?: string): string {\r\n if (cliValue) {\r\n const resolved = path.resolve(cliValue);\r\n if (!existsSync(resolved)) {\r\n console.error(`Error: Config file not found: ${resolved}`);\r\n process.exit(1);\r\n }\r\n return resolved;\r\n }\r\n\r\n const candidates = [\r\n 'persona-build.config.js',\r\n 'persona-build.config.cjs',\r\n 'persona-build.config.json',\r\n ];\r\n\r\n for (const name of candidates) {\r\n const candidate = path.resolve(name);\r\n if (existsSync(candidate)) return candidate;\r\n }\r\n\r\n console.error(\r\n 'Error: No config file found. ' +\r\n 'Create persona-build.config.js in the current directory or pass --config <path>.',\r\n );\r\n process.exit(1);\r\n}\r\n\r\n/**\r\n * Load and validate the config file.\r\n *\r\n * Supports:\r\n * - ESM .js → dynamic import()\r\n * - CJS .cjs → createRequire()\r\n * - JSON .json → createRequire()\r\n *\r\n * The config module must export a default export (or be a plain JSON object)\r\n * that conforms to BuildConfig.\r\n */\r\nasync function loadConfig(configPath: string): Promise<BuildConfig> {\r\n const ext = path.extname(configPath).toLowerCase();\r\n\r\n let rawConfig: unknown;\r\n\r\n if (ext === '.cjs' || ext === '.json') {\r\n const require = createRequire(import.meta.url);\r\n rawConfig = require(configPath);\r\n } else {\r\n // ESM default — use dynamic import with a file URL\r\n const fileUrl = pathToFileURL(configPath).href;\r\n const mod = await import(fileUrl);\r\n rawConfig = mod.default ?? mod;\r\n }\r\n\r\n if (!rawConfig || typeof rawConfig !== 'object' || Array.isArray(rawConfig)) {\r\n console.error(\r\n `Error: Config file \"${configPath}\" must export a plain object (BuildConfig).`,\r\n );\r\n process.exit(1);\r\n }\r\n\r\n const config = rawConfig as BuildConfig;\r\n\r\n if (!config.suites || typeof config.suites !== 'object') {\r\n console.error(\r\n `Error: Config file \"${configPath}\" must have a \"suites\" property (record of suite configs).`,\r\n );\r\n process.exit(1);\r\n }\r\n\r\n return config;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Output formatting\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction printSummary(summary: BuildSummary, check: boolean): void {\r\n const mode = check ? ' [check mode — no files written]' : '';\r\n const status = summary.success ? '✓ Build succeeded' : '✗ Build failed';\r\n console.log(`${status}${mode}`);\r\n console.log(` Personas processed : ${summary.totalBuilt}`);\r\n if (!check) {\r\n console.log(` Files written : ${summary.totalWritten}`);\r\n }\r\n if (summary.strictFailures.length > 0) {\r\n console.log(`\\n Validation failures (${summary.strictFailures.length}):`);\r\n for (const f of summary.strictFailures) {\r\n console.log(` [${f.severity}] ${f.message}`);\r\n }\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Main entry point\r\n// ---------------------------------------------------------------------------\r\n\r\nasync function main(): Promise<void> {\r\n const args = parseArgs(process.argv);\r\n\r\n // Short-circuit flags\r\n if (args.help) {\r\n console.log(USAGE);\r\n process.exit(0);\r\n }\r\n\r\n if (args.version) {\r\n console.log(VERSION);\r\n process.exit(0);\r\n }\r\n\r\n // Resolve and load config\r\n const configPath = resolveConfigPath(args.configPath);\r\n let config: BuildConfig;\r\n\r\n try {\r\n config = await loadConfig(configPath);\r\n } catch (err) {\r\n console.error(`Error loading config: ${err instanceof Error ? err.message : String(err)}`);\r\n process.exit(1);\r\n }\r\n\r\n // Apply CLI flag overrides (CLI flags take precedence over config-file values)\r\n if (args.check) config.check = true;\r\n if (args.strict) config.strict = true;\r\n\r\n // Run the build\r\n let summary: BuildSummary;\r\n try {\r\n summary = await build(config);\r\n } catch (err) {\r\n // build() throws in strict mode when there are validation failures\r\n if (err instanceof Error) {\r\n console.error(`\\n${err.message}`);\r\n } else {\r\n console.error('Build failed with an unexpected error:', err);\r\n }\r\n process.exit(1);\r\n }\r\n\r\n // Print results\r\n printSummary(summary, config.check ?? false);\r\n\r\n // Exit code\r\n if (!summary.success) {\r\n process.exit(1);\r\n }\r\n\r\n process.exit(0);\r\n}\r\n\r\nmain().catch((err) => {\r\n console.error('Unexpected error:', err);\r\n process.exit(1);\r\n});\r\n"]}
1
+ {"version":3,"sources":["../src/engine/partials.ts","../src/engine/conditionals.ts","../src/engine/variables.ts","../src/engine/postProcessor.ts","../src/engine/serializer.ts","../src/loaders/partials-loader.ts","../src/plugins/runner.ts","../src/targets/types.ts","../src/builders/frontmatter.ts","../src/targets/registry.ts","../src/targets/built-in.ts","../src/builders/persona-builder.ts","../src/cli.ts"],"names":["readdir","path","readFile","existsSync","yaml","mkdir","writeFile","createRequire","require","pathToFileURL"],"mappings":"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","file":"cli.cjs","sourcesContent":["/**\r\n * partials.ts\r\n *\r\n * Pure template-engine function for resolving partial inclusions.\r\n * Supports {{> name}} syntax with up to depth-2 recursion to handle\r\n * partials-within-partials. No file-system I/O.\r\n */\r\n\r\n/**\r\n * Resolve partial inclusions in a template string.\r\n *\r\n * Replaces `{{> name}}` markers with the content from `partialsMap`.\r\n * Recursion is capped at depth 2 so that:\r\n * - depth 0 → 1: outer partials are expanded\r\n * - depth 1 → 2: one level of nested partials are expanded\r\n * - depth 2: recursion stops, marker is left as-is\r\n *\r\n * Each resolved partial is `trimEnd()`-ed to prevent trailing blank lines\r\n * from causing double-blank-line artefacts during concatenation.\r\n *\r\n * If a partial name is not found in `partialsMap`, the original marker is\r\n * preserved and a warning is emitted via `console.warn`.\r\n *\r\n * @param text - Template string potentially containing {{> name}} markers\r\n * @param partialsMap - Map of partial name → partial content\r\n * @param depth - Current recursion depth (callers should omit; defaults to 0)\r\n * @returns The template string with partial markers replaced\r\n */\r\nexport function resolvePartials(\r\n text: string,\r\n partialsMap: Record<string, string>,\r\n depth = 0,\r\n): string {\r\n if (depth >= 2) return text;\r\n return text.replace(/\\{\\{> ([\\w-]+)\\}\\}/g, (match, name: string) => {\r\n if (!(name in partialsMap)) {\r\n console.warn(`[WARN] Partial not found: ${match}`);\r\n return match;\r\n }\r\n // Recursively resolve nested partials (depth + 1).\r\n // trimEnd() strips trailing whitespace to avoid extra blank lines.\r\n return resolvePartials(partialsMap[name], partialsMap, depth + 1).trimEnd();\r\n });\r\n}\r\n","/**\r\n * conditionals.ts\r\n *\r\n * Pure template-engine function for resolving conditional blocks.\r\n * Handles {{#if flag}}…{{/if}} and {{#if flag}}…{{else}}…{{/if}} syntax,\r\n * including nested {{#if}} blocks inside {{else}} branches.\r\n * No file-system I/O.\r\n */\r\n\r\n/**\r\n * Resolve conditional blocks in a template string.\r\n *\r\n * Syntax:\r\n * `{{#if flag}}content{{/if}}`\r\n * `{{#if flag}}truthy-content{{else}}falsy-content{{/if}}`\r\n *\r\n * Nested conditionals inside `{{else}}` branches are supported:\r\n * `{{#if a}}A{{else}}{{#if b}}B{{else}}C{{/if}}{{/if}}`\r\n *\r\n * Behaviour:\r\n * - When `context[flag]` is truthy: the delimiters are stripped and the\r\n * content before `{{else}}` (or the entire inner block if no `{{else}}`)\r\n * is kept, surrounded by single `\\n` delimiters.\r\n * - When `context[flag]` is falsy and a `{{else}}` branch exists: the\r\n * content after `{{else}}` is kept, surrounded by single `\\n` delimiters.\r\n * - When `context[flag]` is falsy and no `{{else}}` branch exists: the\r\n * entire block (including surrounding newlines) is removed, leaving a\r\n * single `\\n`.\r\n * - Unknown flags (absent from context) are treated as falsy.\r\n *\r\n * Leading and trailing newlines within the kept content are trimmed so the\r\n * output does not accumulate extra blank lines.\r\n *\r\n * Nesting algorithm: the regex matches only *innermost* blocks — those\r\n * whose content contains no further `{{#if` markers. The replacement loop\r\n * repeats until the output stabilises, resolving each nesting level in\r\n * depth-first (innermost-first) order. This avoids the closing `{{/if}}`\r\n * ambiguity that arises with non-greedy single-pass matching.\r\n *\r\n * @param text - Template string potentially containing {{#if}} blocks\r\n * @param context - Key-value map used to evaluate flag truthiness\r\n * @returns The template string with conditional blocks resolved\r\n */\r\nexport function resolveConditionals(\r\n text: string,\r\n context: Record<string, unknown>,\r\n): string {\r\n // Match only innermost conditional blocks — those whose truthy and falsy\r\n // content contains no nested `{{#if`. The negative lookahead\r\n // `(?!\\{\\{#if\\b)` ensures the quantifier stops before any nested opener,\r\n // so each pass resolves one depth level. Subsequent passes bubble outward\r\n // until the output stabilises (no more `{{#if` markers remain).\r\n const noNestedIf = String.raw`(?:(?!\\{\\{#if\\b)[\\s\\S])*?`;\r\n const pattern = new RegExp(\r\n String.raw`\\n*\\{\\{#if (\\w+)\\}\\}(${noNestedIf})` +\r\n String.raw`(?:\\{\\{else\\}\\}(${noNestedIf}))?\\{\\{\\/if\\}\\}\\n*`,\r\n 'g',\r\n );\r\n\r\n const resolve = (\r\n _match: string,\r\n flag: string,\r\n inner: string,\r\n elseInner: string | undefined,\r\n ): string => {\r\n if (context[flag]) {\r\n // Truthy: keep content before {{else}} (or entire inner if no {{else}})\r\n return '\\n' + inner.replace(/^\\n+/, '').replace(/\\n+$/, '') + '\\n';\r\n }\r\n if (elseInner !== undefined) {\r\n // Falsy with {{else}}: keep content after {{else}}\r\n return '\\n' + elseInner.replace(/^\\n+/, '').replace(/\\n+$/, '') + '\\n';\r\n }\r\n // Falsy without {{else}}: remove entire block\r\n return '\\n';\r\n };\r\n\r\n let result = text;\r\n let prev: string;\r\n do {\r\n prev = result;\r\n result = result.replace(pattern, resolve);\r\n } while (result !== prev);\r\n return result;\r\n}\r\n","/**\r\n * variables.ts\r\n *\r\n * Pure template-engine function for resolving variable substitutions.\r\n * Handles {{varName}} syntax. No file-system I/O.\r\n */\r\n\r\n/**\r\n * Resolve variable substitutions in a template string.\r\n *\r\n * Replaces `{{varName}}` markers with `String(context[varName])`.\r\n * If a variable is not found in `context` (or its value is `undefined`),\r\n * the original marker is preserved and a warning is emitted via\r\n * `console.warn`, identifying the file by `filename` for easier debugging.\r\n *\r\n * Note: this step must run AFTER `resolvePartials` and `resolveConditionals`\r\n * so that only plain variable markers remain.\r\n *\r\n * @param text - Template string potentially containing {{varName}} markers\r\n * @param context - Key-value map of variable name → value\r\n * @param filename - Identifier used in warning messages (e.g. persona file path)\r\n * @returns The template string with variable markers substituted\r\n */\r\nexport function resolveVariables(\r\n text: string,\r\n context: Record<string, unknown>,\r\n filename: string,\r\n): string {\r\n return text.replace(/\\{\\{(\\w+)\\}\\}/g, (match, varName: string) => {\r\n if (varName in context && context[varName] !== undefined) {\r\n return String(context[varName]);\r\n }\r\n console.warn(`[WARN] Unresolved variable: ${match} in ${filename}`);\r\n return match;\r\n });\r\n}\r\n","/**\r\n * postProcessor.ts\r\n *\r\n * Pure post-processing functions for cleaning up rendered persona output.\r\n * All functions are side-effect-free and operate only on strings.\r\n * No file-system I/O.\r\n */\r\n\r\n/**\r\n * Collapse 3 or more consecutive blank lines into 2 blank lines.\r\n *\r\n * Specifically converts 4 or more consecutive `\\n` characters into `\\n\\n\\n`\r\n * (which equals 2 blank lines between paragraphs).\r\n *\r\n * @param text - Rendered output string\r\n * @returns String with excessive blank lines collapsed\r\n */\r\nexport function collapseBlankLines(text: string): string {\r\n return text.replace(/\\n{4,}/g, '\\n\\n\\n');\r\n}\r\n\r\n/**\r\n * Ensure every Markdown heading has a blank line immediately before it.\r\n *\r\n * Also ensures horizontal rules (`---`) have a blank line before and after\r\n * them. This corrects spacing gaps caused by partial concatenation where\r\n * `trimEnd()` strips trailing newlines and conditionals add only a single\r\n * `\\n` delimiter.\r\n *\r\n * @param text - Rendered output string\r\n * @returns String with blank lines inserted before headings and rules\r\n */\r\nexport function ensureBlankLineBeforeHeadings(text: string): string {\r\n // Blank line before headings\r\n let result = text.replace(/([^\\n])\\n(#{1,6} )/g, '$1\\n\\n$2');\r\n // Blank line before horizontal rules (---)\r\n result = result.replace(/([^\\n])\\n(---)\\n/g, '$1\\n\\n$2\\n');\r\n // Blank line after horizontal rules (---)\r\n result = result.replace(/\\n(---)\\n([^\\n])/g, '\\n$1\\n\\n$2');\r\n return result;\r\n}\r\n\r\n/**\r\n * Normalize line endings to LF (`\\n`) for OS-agnostic output.\r\n *\r\n * Converts CRLF (`\\r\\n`) first, then strips any remaining stray CR (`\\r`).\r\n *\r\n * @param text - String potentially containing CRLF or CR line endings\r\n * @returns String with all line endings normalized to LF\r\n */\r\nexport function normalizeNewlines(text: string): string {\r\n return text.replace(/\\r\\n/g, '\\n').replace(/\\r/g, '\\n');\r\n}\r\n","/**\r\n * serializer.ts\r\n *\r\n * Pure serializer functions for converting tool lists to YAML-compatible\r\n * string representations. No file-system I/O.\r\n */\r\n\r\n/**\r\n * Serialize a tools array in YAML single-quote flow format WITH outer brackets.\r\n *\r\n * Output format: `['tool1', 'tool2', 'tool3']`\r\n * Used by the ledger suite to preserve byte-identical frontmatter output.\r\n *\r\n * @param tools - Array of tool name strings\r\n * @returns YAML flow-sequence string including outer brackets\r\n *\r\n * @example\r\n * serializeTools(['Bash', 'Read']) // => \"['Bash', 'Read']\"\r\n * serializeTools([]) // => \"[]\"\r\n */\r\nexport function serializeTools(tools: string[]): string {\r\n return '[' + tools.map((t) => `'${t}'`).join(', ') + ']';\r\n}\r\n\r\n/**\r\n * Serialize a tools array in YAML single-quote flow format WITHOUT outer brackets.\r\n *\r\n * Output format: `'tool1', 'tool2', 'tool3'`\r\n * Used inside standalone frontmatter templates which supply the surrounding `[ ]`.\r\n *\r\n * @param tools - Array of tool name strings\r\n * @returns Comma-separated quoted tool names (no outer brackets)\r\n *\r\n * @example\r\n * serializeToolsList(['Bash', 'Read']) // => \"'Bash', 'Read'\"\r\n * serializeToolsList([]) // => \"\"\r\n */\r\nexport function serializeToolsList(tools: string[]): string {\r\n return tools.map((t) => `'${t}'`).join(', ');\r\n}\r\n","/**\r\n * src/loaders/partials-loader.ts\r\n *\r\n * File-system loader for Handlebars-style partial snippets.\r\n *\r\n * Reads every `.md` file in `dir`, keys each entry by the filename stem\r\n * (i.e. the portion before the final `.md` extension), and returns the\r\n * map. Callers that need a two-layer (shared → suite-local override)\r\n * setup should call `loadPartials` twice and merge the results themselves,\r\n * with the suite-local result spreading last.\r\n *\r\n * All file reads are performed asynchronously. Path construction uses\r\n * `path.join` and `path.posix`-compatible operations so no path-separator\r\n * assumptions are baked in.\r\n */\r\n\r\nimport { readdir, readFile } from 'node:fs/promises';\r\nimport path from 'node:path';\r\n\r\n/**\r\n * Load all `.md` files in `dir` and return them as a `Record<string, string>`\r\n * keyed by filename stem.\r\n *\r\n * Files whose names do not end in `.md` are silently ignored.\r\n * The directory must exist; a missing directory throws an `ENOENT` error from\r\n * the underlying `readdir` call (let callers decide how to handle absence).\r\n *\r\n * @param dir Absolute (or relative) path to the directory to scan.\r\n * @returns A map from filename stem → file content string.\r\n *\r\n * @example\r\n * const partials = await loadPartials('/project/partials');\r\n * // { greeting: 'Hello, {{name}}!', footer: '---\\nEnd of file' }\r\n */\r\nexport async function loadPartials(dir: string): Promise<Record<string, string>> {\r\n const entries = await readdir(dir, { withFileTypes: true });\r\n\r\n const mdFiles = entries.filter(\r\n (entry) => entry.isFile() && entry.name.endsWith('.md'),\r\n );\r\n\r\n const pairs = await Promise.all(\r\n mdFiles.map(async (entry) => {\r\n const stem = entry.name.slice(0, -'.md'.length); // strip trailing \".md\"\r\n const filePath = path.join(dir, entry.name);\r\n const content = await readFile(filePath, 'utf8');\r\n return [stem, content] as [string, string];\r\n }),\r\n );\r\n\r\n return Object.fromEntries(pairs);\r\n}\r\n","/**\r\n * src/plugins/runner.ts\r\n *\r\n * Plugin runner — responsible for invoking plugin hooks in registration order.\r\n *\r\n * Each exported function corresponds to one lifecycle hook defined in\r\n * PersonaBuildPlugin. The runner:\r\n * - Skips plugins that do not implement the requested hook (hook is optional)\r\n * - Invokes hooks in the order plugins are registered (first-in first-called)\r\n * - For accumulating hooks (onBuildContext, onPostRender), each plugin\r\n * receives the output of the previous plugin as its first argument\r\n * - For collecting hooks (onValidate), results are concatenated into a\r\n * flat array\r\n *\r\n * No file-system I/O. No async operations.\r\n */\r\n\r\nimport type {\r\n PersonaBuildPlugin,\r\n PersonaMetadata,\r\n SuiteConfig,\r\n TargetType,\r\n ValidationResult,\r\n} from './types.js';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Suite-level hook\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Invoke the `onSuiteInit` hook on every registered plugin.\r\n *\r\n * Each plugin may optionally implement this hook. Plugins are called in\r\n * registration order. The hook receives the suite config and a mutable\r\n * `sharedMeta` object — plugins may mutate `sharedMeta` in place; the\r\n * same reference is passed to every subsequent plugin.\r\n *\r\n * @param plugins Ordered list of registered plugins\r\n * @param suite The suite configuration object\r\n * @param sharedMeta Mutable shared metadata object (mutated in place by plugins)\r\n */\r\nexport function runSuiteInit(\r\n plugins: PersonaBuildPlugin[],\r\n suite: SuiteConfig,\r\n sharedMeta: Record<string, unknown>,\r\n): void {\r\n for (const plugin of plugins) {\r\n if (typeof plugin.onSuiteInit === 'function') {\r\n plugin.onSuiteInit(suite, sharedMeta);\r\n }\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Per-persona context accumulation\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Invoke the `onBuildContext` hook on every registered plugin, accumulating\r\n * context mutations sequentially.\r\n *\r\n * Each plugin receives the context returned by the previous plugin. If a\r\n * plugin does not implement `onBuildContext`, the context passes through\r\n * unchanged. The final accumulated context is returned.\r\n *\r\n * @param plugins Ordered list of registered plugins\r\n * @param ctx Initial rendering context for this persona\r\n * @param persona Typed metadata for the persona being built\r\n * @param suite The suite configuration object\r\n * @param target The current build target (optional — forwarded to each plugin)\r\n * @returns Accumulated rendering context after all plugins have run\r\n */\r\nexport function runBuildContext(\r\n plugins: PersonaBuildPlugin[],\r\n ctx: Record<string, unknown>,\r\n persona: PersonaMetadata,\r\n suite: SuiteConfig,\r\n target?: TargetType,\r\n): Record<string, unknown> {\r\n let accumulated = ctx;\r\n for (const plugin of plugins) {\r\n if (typeof plugin.onBuildContext === 'function') {\r\n accumulated = plugin.onBuildContext(accumulated, persona, suite, target);\r\n }\r\n }\r\n return accumulated;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Per-persona post-render chain\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Invoke the `onPostRender` hook on every registered plugin, chaining the\r\n * output string sequentially.\r\n *\r\n * Each plugin receives the string returned by the previous plugin. If a\r\n * plugin does not implement `onPostRender`, the string passes through\r\n * unchanged. The final string is returned.\r\n *\r\n * @param plugins Ordered list of registered plugins\r\n * @param rendered Initial rendered output string\r\n * @param persona Typed metadata for the persona being built\r\n * @param target The current build target\r\n * @returns Final output string after all plugins have run\r\n */\r\nexport function runPostRender(\r\n plugins: PersonaBuildPlugin[],\r\n rendered: string,\r\n persona: PersonaMetadata,\r\n target: TargetType,\r\n): string {\r\n let output = rendered;\r\n for (const plugin of plugins) {\r\n if (typeof plugin.onPostRender === 'function') {\r\n output = plugin.onPostRender(output, persona, target);\r\n }\r\n }\r\n return output;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Per-persona validation collection\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Invoke the `onValidate` hook on every registered plugin and collect all\r\n * returned ValidationResult objects into a single flat array.\r\n *\r\n * Plugins that do not implement `onValidate` contribute nothing to the result.\r\n * The return value is always an array (never null/undefined).\r\n *\r\n * @param plugins Ordered list of registered plugins\r\n * @param persona Typed metadata for the persona being built\r\n * @param suite The suite configuration object\r\n * @param target The current build target (optional — forwarded to each plugin)\r\n * @returns Flat array of all ValidationResult objects from all plugins\r\n */\r\nexport function runValidate(\r\n plugins: PersonaBuildPlugin[],\r\n persona: PersonaMetadata,\r\n suite: SuiteConfig,\r\n target?: TargetType,\r\n): ValidationResult[] {\r\n const results: ValidationResult[] = [];\r\n for (const plugin of plugins) {\r\n if (typeof plugin.onValidate === 'function') {\r\n const pluginResults = plugin.onValidate(persona, suite, target);\r\n results.push(...pluginResults);\r\n }\r\n }\r\n return results;\r\n}\r\n","/**\r\n * src/targets/types.ts\r\n *\r\n * Target type definitions for @mistralys/persona-builder.\r\n *\r\n * Defines the TargetDefinition interface and well-known target name constants.\r\n */\r\n\r\n// ---------------------------------------------------------------------------\r\n// TargetDefinition interface\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Describes a build target — maps a target name to its output directory key,\r\n * filename context key, default frontmatter template, and optional\r\n * auto-injected context flags.\r\n */\r\nexport interface TargetDefinition {\r\n /** Unique target identifier (e.g. 'vscode', 'claude-code'). */\r\n name: string;\r\n\r\n /**\r\n * Key used to look up the output directory in the suite's output dir map.\r\n * For built-in targets this matches the target name.\r\n */\r\n outputDirKey: string;\r\n\r\n /**\r\n * Context field name that holds a custom output filename for this target.\r\n * When present and non-empty in the rendered context, it overrides the\r\n * default filename derived from the persona name.\r\n */\r\n filenameContextKey?: string;\r\n\r\n /**\r\n * Default frontmatter template string for this target.\r\n * Used when neither a plugin nor a BuildConfig template is provided.\r\n */\r\n defaultFrontmatter: string;\r\n\r\n /**\r\n * Declarative context flags merged into the build context when this target\r\n * is rendered. Useful for `{{#if target_vscode}}` guards.\r\n *\r\n * All entries are spread into the context by `buildContext()` via a\r\n * registry lookup — `registry.get(target).contextFlags`. The fallback path\r\n * (for targets absent from the registry) injects a single boolean flag\r\n * derived from the target name: `target_${name.replace(/-/g, '_')} = true`.\r\n */\r\n contextFlags?: Record<string, unknown>;\r\n\r\n /**\r\n * Whether this target is included in the default build when no explicit\r\n * `targets` array is configured. Defaults to `true` when omitted.\r\n *\r\n * Set to `false` for opt-in targets (e.g. `'deep-agents'`) that should\r\n * only be built when explicitly requested via `config.targets`.\r\n */\r\n defaultEnabled?: boolean;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Well-known target name constants\r\n// ---------------------------------------------------------------------------\r\n\r\n/** Well-known name constant for the VS Code target. */\r\nexport const TARGET_VSCODE = 'vscode' as const;\r\n\r\n/** Well-known name constant for the Claude Code target. */\r\nexport const TARGET_CLAUDE_CODE = 'claude-code' as const;\r\n\r\n/** Well-known name constant for the Deep Agents target. */\r\nexport const TARGET_DEEP_AGENTS = 'deep-agents' as const;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Default frontmatter templates (owned by the targets layer)\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Default VS Code frontmatter template.\r\n *\r\n * Minimal fields that work for standalone personas. Projects using numbered\r\n * workflows (e.g. ledger) should inject a richer template via a plugin.\r\n */\r\nexport const DEFAULT_FRONTMATTER_VSCODE = `---\r\nname: '{{name}} v{{version}}'\r\ndescription: '{{description}}'\r\ntools: [{{tools_list}}]\r\n---`;\r\n\r\n/**\r\n * Default Claude Code frontmatter template.\r\n *\r\n * Minimal fields that work for standalone personas. Projects using numbered\r\n * workflows should inject a richer template via a plugin.\r\n */\r\nexport const DEFAULT_FRONTMATTER_CLAUDE_CODE = `---\r\nname: {{cc_file_name_stem}}\r\npermissionMode: {{cc_permission_mode}}\r\nmodel: {{cc_model}}\r\nmemory: {{cc_memory}}\r\nallowedTools: [{{cc_tools_list}}]\r\n---`;\r\n\r\n/**\r\n * Default Deep Agents frontmatter template.\r\n *\r\n * Minimal fields — no IDE-specific properties. Suitable for headless\r\n * LangGraph / Deep Agents pipeline executors that consume persona files\r\n * without an IDE host.\r\n */\r\nexport const DEFAULT_FRONTMATTER_DEEP_AGENTS = `---\r\nname: {{name}}\r\ndescription: {{description}}\r\n---`;\r\n","/**\r\n * src/builders/frontmatter.ts\r\n *\r\n * Frontmatter template registry for @mistralys/persona-builder.\r\n *\r\n * Ships three minimal default templates — one per built-in target — that work for the\r\n * \"standalone\" persona mode (simple personas without numbered workflows or\r\n * MCP server blocks). Projects needing richer frontmatter register custom\r\n * templates via the `PersonaBuildPlugin.frontmatterTemplates` property.\r\n *\r\n * Template rendering follows the same two-step sequence as body rendering:\r\n * 1. resolveConditionals() — resolve {{#if flag}} blocks\r\n * 2. resolveVariables() — substitute {{varName}} markers\r\n *\r\n * No partials in frontmatter — frontmatter is kept deliberately simple.\r\n */\r\n\r\nimport { resolveConditionals } from '../engine/conditionals.js';\r\nimport { resolveVariables } from '../engine/variables.js';\r\nimport type { PersonaBuildPlugin } from '../plugins/types.js';\r\nimport type { TargetRegistry } from '../targets/registry.js';\r\n\r\n// Default templates are owned by the targets layer; re-exported here so\r\n// the public API surface (src/builders/index.ts) is unchanged.\r\nimport {\r\n DEFAULT_FRONTMATTER_VSCODE,\r\n DEFAULT_FRONTMATTER_CLAUDE_CODE,\r\n DEFAULT_FRONTMATTER_DEEP_AGENTS,\r\n} from '../targets/types.js';\r\nexport { DEFAULT_FRONTMATTER_VSCODE, DEFAULT_FRONTMATTER_CLAUDE_CODE, DEFAULT_FRONTMATTER_DEEP_AGENTS };\r\n\r\n// ---------------------------------------------------------------------------\r\n// Template resolution\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Resolve frontmatter template precedence.\r\n *\r\n * Precedence order (highest wins):\r\n * 1. Plugin `frontmatterTemplates` — plugins are checked in registration\r\n * order; the first plugin with a matching key wins.\r\n * 2. `configTemplates` — templates passed via `BuildConfig.frontmatter`\r\n * 3. Registry default — `TargetDefinition.defaultFrontmatter` for the target\r\n * 4. Library default (`DEFAULT_FRONTMATTER_VSCODE`) — safety fallback only\r\n *\r\n * @param target The build target name (e.g. `'vscode'`, `'claude-code'`, or a custom target)\r\n * @param plugins Registered plugins (searched in order; first match wins)\r\n * @param configTemplates Optional caller-supplied overrides from BuildConfig\r\n * @param registry Optional TargetRegistry for resolving the built-in default template\r\n * @returns The resolved template string\r\n */\r\nexport function resolveFrontmatterTemplate(\r\n target: string,\r\n plugins: PersonaBuildPlugin[],\r\n configTemplates?: Record<string, string>,\r\n registry?: TargetRegistry,\r\n): string {\r\n // Check plugins in registration order — first plugin with a matching\r\n // frontmatterTemplates entry wins.\r\n for (const plugin of plugins) {\r\n if (plugin.frontmatterTemplates && target in plugin.frontmatterTemplates) {\r\n const tpl = plugin.frontmatterTemplates[target];\r\n if (tpl !== undefined) return tpl;\r\n }\r\n }\r\n\r\n // Caller-supplied config templates\r\n if (configTemplates && target in configTemplates) {\r\n const tpl = configTemplates[target];\r\n if (tpl !== undefined) return tpl;\r\n }\r\n\r\n // Registry default (covers all registered targets, including custom ones)\r\n if (registry && registry.has(target)) {\r\n return registry.get(target).defaultFrontmatter;\r\n }\r\n\r\n // Absolute fallback — should not be reached in normal usage\r\n return DEFAULT_FRONTMATTER_VSCODE;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Frontmatter rendering\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Render a frontmatter template string against the given context.\r\n *\r\n * Applies the standard two-step template resolution:\r\n * 1. `resolveConditionals` — `{{#if flag}}` blocks\r\n * 2. `resolveVariables` — `{{varName}}` substitution\r\n *\r\n * @param template The raw frontmatter template string (may contain markers)\r\n * @param context Key-value context for variable substitution\r\n * @param filename Source filename used in warning messages\r\n * @returns Rendered frontmatter string (ready to prepend to body)\r\n */\r\nexport function renderFrontmatter(\r\n template: string,\r\n context: Record<string, unknown>,\r\n filename: string,\r\n): string {\r\n let rendered = resolveConditionals(template, context);\r\n rendered = resolveVariables(rendered, context, filename);\r\n return rendered;\r\n}\r\n","/**\r\n * src/targets/registry.ts\r\n *\r\n * TargetRegistry — holds TargetDefinition entries and allows consumers to\r\n * register custom build targets alongside (or instead of) the built-in ones.\r\n */\r\n\r\nimport type { TargetDefinition } from './types.js';\r\n\r\n// ---------------------------------------------------------------------------\r\n// TargetRegistry class\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Registry that maps target names to their TargetDefinition objects.\r\n *\r\n * Consumers can extend the default build system by calling `register()` with\r\n * a custom TargetDefinition before invoking `build()`.\r\n *\r\n * @example\r\n * ```ts\r\n * import { defaultRegistry } from '@mistralys/persona-builder';\r\n *\r\n * defaultRegistry.register({\r\n * name: 'my-target',\r\n * outputDirKey: 'my-target',\r\n * defaultFrontmatter: '---\\nmy: frontmatter\\n---',\r\n * contextFlags: { target_my_target: true },\r\n * });\r\n * ```\r\n */\r\nexport class TargetRegistry {\r\n // Map preserves insertion order — names() and allDefinitions() are\r\n // therefore deterministic and match registration sequence. This is\r\n // intentional: the built-in registry guarantees ['vscode', 'claude-code']\r\n // ordering for the default targets (AC-2).\r\n private readonly _definitions = new Map<string, TargetDefinition>();\r\n\r\n /**\r\n * Register a new target definition.\r\n *\r\n * @param definition The target descriptor to register.\r\n * @throws {Error} If a target with the same `name` is already registered.\r\n */\r\n register(definition: TargetDefinition): void {\r\n if (this._definitions.has(definition.name)) {\r\n throw new Error(\r\n `TargetRegistry: target \"${definition.name}\" is already registered. ` +\r\n `Use a unique name or remove the existing registration first.`,\r\n );\r\n }\r\n this._definitions.set(definition.name, definition);\r\n }\r\n\r\n /**\r\n * Retrieve a registered target definition by name.\r\n *\r\n * Returns a shallow copy — mutating the returned object does not affect\r\n * the registry's internal state.\r\n *\r\n * @param name The target name to look up.\r\n * @returns A shallow copy of the matching TargetDefinition.\r\n * @throws {Error} If no target with the given name is registered.\r\n */\r\n get(name: string): TargetDefinition {\r\n const def = this._definitions.get(name);\r\n if (!def) {\r\n const known = this.names().join(', ') || '(none)';\r\n throw new Error(\r\n `TargetRegistry: target \"${name}\" is not registered. ` +\r\n `Registered targets: ${known}.`,\r\n );\r\n }\r\n return { ...def };\r\n }\r\n\r\n /**\r\n * Returns `true` if a target with the given name is registered.\r\n *\r\n * @param name The target name to check.\r\n */\r\n has(name: string): boolean {\r\n return this._definitions.has(name);\r\n }\r\n\r\n /**\r\n * Returns the names of all registered targets, in registration order.\r\n */\r\n names(): string[] {\r\n return Array.from(this._definitions.keys());\r\n }\r\n\r\n /**\r\n * Returns all registered TargetDefinition objects, in registration order.\r\n *\r\n * Returns shallow copies — mutating a returned definition does not affect\r\n * the registry's internal state.\r\n */\r\n allDefinitions(): TargetDefinition[] {\r\n return Array.from(this._definitions.values()).map(def => ({ ...def }));\r\n }\r\n\r\n /**\r\n * Returns a new TargetRegistry pre-populated with the same definitions.\r\n *\r\n * Useful for test isolation: clone the `defaultRegistry` to get an\r\n * independent copy that can be mutated without affecting the singleton.\r\n */\r\n clone(): TargetRegistry {\r\n const copy = new TargetRegistry();\r\n for (const def of this._definitions.values()) {\r\n copy.register({ ...def });\r\n }\r\n return copy;\r\n }\r\n}\r\n","/**\r\n * src/targets/built-in.ts\r\n *\r\n * Creates and exports the defaultRegistry — a TargetRegistry pre-populated\r\n * with the three built-in targets: 'vscode', 'claude-code', and 'deep-agents'.\r\n *\r\n * Consumers import defaultRegistry when they need to register additional\r\n * custom targets or query the built-in target definitions.\r\n */\r\n\r\nimport { TargetRegistry } from './registry.js';\r\nimport {\r\n DEFAULT_FRONTMATTER_CLAUDE_CODE,\r\n DEFAULT_FRONTMATTER_DEEP_AGENTS,\r\n DEFAULT_FRONTMATTER_VSCODE,\r\n TARGET_CLAUDE_CODE,\r\n TARGET_DEEP_AGENTS,\r\n TARGET_VSCODE,\r\n} from './types.js';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Default registry\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Singleton TargetRegistry pre-populated with the three built-in targets:\r\n * `'vscode'`, `'claude-code'`, and `'deep-agents'`.\r\n *\r\n * Import and call `register()` on this instance to add custom targets before\r\n * invoking `build()`.\r\n *\r\n * **Warning:** This is a module-level singleton. Calling `register()` on it\r\n * in tests mutates shared state that persists across test cases. Use\r\n * `defaultRegistry.clone()` to obtain an isolated copy for test scenarios\r\n * that need to register additional targets.\r\n */\r\nexport const defaultRegistry = new TargetRegistry();\r\n\r\ndefaultRegistry.register({\r\n name: TARGET_VSCODE,\r\n outputDirKey: 'vscode',\r\n filenameContextKey: 'vs_file_name',\r\n defaultFrontmatter: DEFAULT_FRONTMATTER_VSCODE,\r\n contextFlags: { target_vscode: true },\r\n defaultEnabled: true,\r\n});\r\n\r\ndefaultRegistry.register({\r\n name: TARGET_CLAUDE_CODE,\r\n outputDirKey: 'claude-code',\r\n filenameContextKey: 'cc_file_name',\r\n defaultFrontmatter: DEFAULT_FRONTMATTER_CLAUDE_CODE,\r\n contextFlags: { target_claude_code: true },\r\n defaultEnabled: true,\r\n});\r\n\r\ndefaultRegistry.register({\r\n name: TARGET_DEEP_AGENTS,\r\n outputDirKey: 'deep-agents',\r\n filenameContextKey: 'da_file_name',\r\n defaultFrontmatter: DEFAULT_FRONTMATTER_DEEP_AGENTS,\r\n contextFlags: { target_deep_agents: true },\r\n defaultEnabled: false,\r\n});\r\n","/**\r\n * src/builders/persona-builder.ts\r\n *\r\n * Core build orchestrator for @mistralys/persona-builder.\r\n *\r\n * Exports three public functions:\r\n *\r\n * 1. buildPersona(personaYamlPath, suiteName, suiteConfig, sharedMeta,\r\n * partialsMap, config, plugins, target, agentMap?)\r\n * — Builds a single persona for a single target. Returns a BuildResult.\r\n *\r\n * 2. buildSuite(suiteName, suiteConfig, config, plugins, target, agentMap?)\r\n * — Discovers all persona YAMLs for a suite, fires onSuiteInit, maps\r\n * buildPersona() over each, and returns BuildResult[].\r\n *\r\n * 3. build(config)\r\n * — Top-level entry point. Pre-scans all suites to build a cross-suite\r\n * agent name map, then iterates all suites × targets, calls\r\n * buildSuite() for each combination, and returns a BuildSummary.\r\n * Respects --check (no writes) and --strict (fail on warnings/errors).\r\n */\r\n\r\nimport { readdir, readFile, mkdir, writeFile } from 'node:fs/promises';\r\nimport { existsSync } from 'node:fs';\r\nimport path from 'node:path';\r\nimport yaml from 'js-yaml';\r\n\r\nimport { resolvePartials } from '../engine/partials.js';\r\nimport { resolveConditionals } from '../engine/conditionals.js';\r\nimport { resolveVariables } from '../engine/variables.js';\r\nimport {\r\n collapseBlankLines,\r\n ensureBlankLineBeforeHeadings,\r\n normalizeNewlines,\r\n} from '../engine/postProcessor.js';\r\nimport { serializeTools, serializeToolsList } from '../engine/serializer.js';\r\nimport { loadPartials } from '../loaders/partials-loader.js';\r\nimport {\r\n runSuiteInit,\r\n runBuildContext,\r\n runPostRender,\r\n runValidate,\r\n} from '../plugins/runner.js';\r\n\r\nimport { resolveFrontmatterTemplate, renderFrontmatter } from './frontmatter.js';\r\nimport type { BuildConfig, BuildResult, BuildSummary } from './types.js';\r\nimport type { PersonaBuildPlugin, PersonaMetadata, SuiteConfig, TargetType, ValidationResult } from '../plugins/types.js';\r\nimport { defaultRegistry } from '../targets/built-in.js';\r\nimport type { TargetDefinition } from '../targets/types.js';\r\nimport type { TargetRegistry } from '../targets/registry.js';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Internal helpers\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Discover all persona YAML files in the `meta/` subdirectory of a suite.\r\n *\r\n * Excludes files whose names start with `_` (shared metadata files such as\r\n * `_shared.yaml`). Results are sorted lexicographically.\r\n *\r\n * @param suiteConfig Suite configuration (used to locate `metaSubdir`)\r\n * @returns Absolute paths to each persona YAML file, sorted.\r\n */\r\nasync function discoverSuitePersonaYamls(suiteConfig: SuiteConfig): Promise<string[]> {\r\n const metaSubdir = suiteConfig.metaSubdir ?? 'meta';\r\n const metaDir = path.join(suiteConfig.srcDir, metaSubdir);\r\n\r\n const entries = await readdir(metaDir, { withFileTypes: true });\r\n\r\n return entries\r\n .filter((e) => e.isFile() && e.name.endsWith('.yaml') && !e.name.startsWith('_'))\r\n .map((e) => path.join(metaDir, e.name))\r\n .sort();\r\n}\r\n\r\n/**\r\n * Load and parse a raw YAML file into a plain object.\r\n * Used for `_shared.yaml` which does not conform to PersonaMetadata's\r\n * `name` requirement.\r\n *\r\n * @param filePath Absolute path to the YAML file\r\n * @returns Parsed object, or {} when the file is empty/absent\r\n */\r\nasync function loadRawYaml(filePath: string): Promise<Record<string, unknown>> {\r\n if (!existsSync(filePath)) return {};\r\n const raw = await readFile(filePath, 'utf8');\r\n const parsed: unknown = yaml.load(raw);\r\n if (parsed === null || parsed === undefined) return {};\r\n if (typeof parsed !== 'object' || Array.isArray(parsed)) return {};\r\n return parsed as Record<string, unknown>;\r\n}\r\n\r\n/**\r\n * Load a persona YAML file and return it as a plain metadata record.\r\n * The `name` field is derived from the filename stem when absent.\r\n *\r\n * @param yamlPath Absolute path to the persona YAML file\r\n * @returns Merged metadata record ready for context building\r\n */\r\nasync function loadPersonaYaml(yamlPath: string): Promise<Record<string, unknown>> {\r\n const raw = await readFile(yamlPath, 'utf8');\r\n const parsed: unknown = yaml.load(raw);\r\n\r\n if (parsed === null || parsed === undefined || typeof parsed !== 'object' || Array.isArray(parsed)) {\r\n throw new Error(`buildPersona: expected a YAML object in \"${yamlPath}\"`);\r\n }\r\n\r\n const record = parsed as Record<string, unknown>;\r\n\r\n // Derive name from filename stem if not present in YAML\r\n if (!record['name']) {\r\n record['name'] = path.basename(yamlPath, '.yaml');\r\n }\r\n\r\n return record;\r\n}\r\n\r\n/**\r\n * Resolve the output directory for a given target from a suite configuration.\r\n *\r\n * Resolution order (first match wins):\r\n * 1. `suiteConfig.outputDirs[definition.outputDirKey]` — generic map, takes precedence.\r\n * 2. `suiteConfig.outVscode` — deprecated fallback for the built-in 'vscode' key.\r\n * 3. `suiteConfig.outClaudeCode` — deprecated fallback for the built-in 'claude-code' key.\r\n *\r\n * The lookup key is `definition.outputDirKey` when a registry definition is\r\n * provided, falling back to the raw `target` name for unregistered targets\r\n * (where `outputDirKey` equals the name by convention).\r\n *\r\n * @param target The build target name.\r\n * @param suiteConfig The suite configuration to resolve from.\r\n * @param definition Optional registry definition for the target. When present,\r\n * `definition.outputDirKey` is used as the output dir map key.\r\n * @returns Resolved output directory path.\r\n * @throws {Error} When no output directory is configured for the target.\r\n */\r\nfunction resolveOutputDir(\r\n target: string,\r\n suiteConfig: SuiteConfig,\r\n definition?: TargetDefinition,\r\n): string {\r\n // Build a merged map: deprecated named fields provide the base, outputDirs overrides.\r\n const merged: Record<string, string> = {};\r\n if (suiteConfig.outVscode) merged['vscode'] = suiteConfig.outVscode;\r\n if (suiteConfig.outClaudeCode) merged['claude-code'] = suiteConfig.outClaudeCode;\r\n if (suiteConfig.outputDirs) Object.assign(merged, suiteConfig.outputDirs);\r\n\r\n // Use outputDirKey from the registry definition when available, falling back\r\n // to the target name for unregistered targets where outputDirKey === name.\r\n const lookupKey = definition?.outputDirKey ?? target;\r\n const dir = merged[lookupKey];\r\n if (dir) return dir;\r\n\r\n throw new Error(\r\n `buildPersona: no output directory configured for target \"${target}\". ` +\r\n `Add outputDirs['${lookupKey}'] to the suite config, or, for the built-in ` +\r\n `targets, provide the outVscode / outClaudeCode fields.`,\r\n );\r\n}\r\n\r\n/**\r\n * Pre-scan all suites and build a cross-suite agent name map.\r\n *\r\n * For each persona across all configured suites, creates a context variable:\r\n * key: `agent_` + slug (hyphens → underscores)\r\n * value: `\"<name> v<version>\"`\r\n *\r\n * Slug is taken from the persona YAML's `slug` field, falling back to the\r\n * filename stem. Version falls back to the suite's `default_version`, then\r\n * to `'0.0.0'`.\r\n *\r\n * @param config Top-level BuildConfig with all suite definitions\r\n * @returns Map of agent variable keys to display strings\r\n */\r\nasync function buildAgentNameMap(\r\n config: BuildConfig,\r\n): Promise<Record<string, string>> {\r\n const agentMap: Record<string, string> = {};\r\n\r\n for (const [, suiteConfig] of Object.entries(config.suites)) {\r\n const metaSubdir = suiteConfig.metaSubdir ?? 'meta';\r\n const sharedYamlPath = path.join(suiteConfig.srcDir, metaSubdir, '_shared.yaml');\r\n const sharedMeta = await loadRawYaml(sharedYamlPath);\r\n const defaultVersion =\r\n typeof sharedMeta['default_version'] === 'string'\r\n ? sharedMeta['default_version']\r\n : '0.0.0';\r\n\r\n const personaYamls = await discoverSuitePersonaYamls(suiteConfig);\r\n\r\n for (const yamlPath of personaYamls) {\r\n const persona = await loadPersonaYaml(yamlPath);\r\n\r\n const slug =\r\n typeof persona['slug'] === 'string'\r\n ? persona['slug']\r\n : path.basename(yamlPath, '.yaml');\r\n\r\n const name =\r\n typeof persona['name'] === 'string'\r\n ? persona['name']\r\n : slug;\r\n\r\n const version =\r\n typeof persona['version'] === 'string'\r\n ? persona['version']\r\n : defaultVersion;\r\n\r\n const underscoredSlug = slug.replace(/-/g, '_');\r\n const key = `agent_${underscoredSlug}`;\r\n agentMap[key] = `${name} v${version}`;\r\n\r\n const slugKey = `agent_slug_${underscoredSlug}`;\r\n agentMap[slugKey] = slug;\r\n }\r\n }\r\n\r\n return agentMap;\r\n}\r\n\r\n/**\r\n * Build the merged template context for a single persona.\r\n *\r\n * Merge order (later values win):\r\n * 1. sharedMeta (suite-level defaults)\r\n * 2. per-persona YAML fields\r\n * 3. derived/computed fields (version fallback, etc.)\r\n * 4. agentMap entries (only for keys not already present)\r\n *\r\n * @param personaMeta Per-persona YAML as a plain record\r\n * @param sharedMeta Parsed `_shared.yaml` fields\r\n * @param agentMap Cross-suite agent name map (injected by build())\r\n * @returns Merged rendering context\r\n */\r\nfunction buildContext(\r\n personaMeta: Record<string, unknown>,\r\n sharedMeta: Record<string, unknown>,\r\n agentMap: Record<string, string> = {},\r\n target?: TargetType,\r\n registry?: TargetRegistry,\r\n): Record<string, unknown> {\r\n const version =\r\n typeof personaMeta['version'] === 'string'\r\n ? personaMeta['version']\r\n : typeof sharedMeta['default_version'] === 'string'\r\n ? sharedMeta['default_version']\r\n : '0.0.0';\r\n\r\n // Merge base: shared first, persona overrides\r\n const merged: Record<string, unknown> = {\r\n ...sharedMeta,\r\n ...personaMeta,\r\n version,\r\n };\r\n\r\n // ── Derived convenience fields (only set when not already provided) ───────\r\n // tools_list / tools_json — serialized from the `tools` array if present\r\n const tools = Array.isArray(merged['tools']) ? (merged['tools'] as string[]) : [];\r\n if (!('tools_list' in merged)) {\r\n merged['tools_list'] = serializeToolsList(tools);\r\n }\r\n if (!('tools_json' in merged)) {\r\n merged['tools_json'] = serializeTools(tools);\r\n }\r\n\r\n // cc_tools_list / cc_tools_json — from `cc_tools` or fall back to `tools`\r\n const ccTools = Array.isArray(merged['cc_tools']) ? (merged['cc_tools'] as string[]) : tools;\r\n if (!('cc_tools_list' in merged)) {\r\n merged['cc_tools_list'] = serializeToolsList(ccTools);\r\n }\r\n if (!('cc_tools_json' in merged)) {\r\n merged['cc_tools_json'] = serializeTools(ccTools);\r\n }\r\n\r\n // cc_file_name_stem — stem of cc_file_name (for default CC frontmatter template)\r\n if (!('cc_file_name_stem' in merged) && typeof merged['cc_file_name'] === 'string') {\r\n const ccFileName = merged['cc_file_name'] as string;\r\n merged['cc_file_name_stem'] = ccFileName.replace(/\\.md$/, '');\r\n }\r\n\r\n // da_file_name_stem — stem of da_file_name (for deep-agents output)\r\n if (!('da_file_name_stem' in merged) && typeof merged['da_file_name'] === 'string') {\r\n const daFileName = merged['da_file_name'] as string;\r\n merged['da_file_name_stem'] = daFileName.replace(/\\.md$/, '');\r\n }\r\n\r\n // da_tools_list / da_tools_json — from `da_tools` or fall back to `tools`\r\n // Intentionally gated on da_file_name: unlike cc_tools_list/cc_tools_json (always emitted for\r\n // every persona), da_* fields are absent when the persona has no deep-agents output file (AC-4).\r\n if (typeof merged['da_file_name'] === 'string') {\r\n const daTools = Array.isArray(merged['da_tools']) ? (merged['da_tools'] as string[]) : tools;\r\n if (!('da_tools_list' in merged)) {\r\n merged['da_tools_list'] = serializeToolsList(daTools);\r\n }\r\n if (!('da_tools_json' in merged)) {\r\n merged['da_tools_json'] = serializeTools(daTools);\r\n }\r\n }\r\n\r\n // ── Cross-suite agent name variables ──────────────────────────────────────\r\n for (const [key, value] of Object.entries(agentMap)) {\r\n if (!(key in merged)) {\r\n merged[key] = value;\r\n }\r\n }\r\n\r\n // ── Target flag injection ─────────────────────────────────────────────────\r\n if (target !== undefined) {\r\n if (registry && registry.has(target)) {\r\n // Inject all contextFlags declared in the target's registry definition.\r\n const flags = registry.get(target).contextFlags ?? {};\r\n for (const [key, value] of Object.entries(flags)) {\r\n merged[key] = value;\r\n }\r\n } else {\r\n // Fallback for targets not present in the registry.\r\n merged[`target_${target.replace(/-/g, '_')}`] = true;\r\n }\r\n }\r\n\r\n return merged;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// buildPersona — single persona × single target\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Build a single persona for a single output target.\r\n *\r\n * Pipeline:\r\n * 1. Load sharedMeta + personaMeta (callers supply pre-loaded values)\r\n * 2. Build merged context\r\n * 3. Run onBuildContext plugin hooks (context accumulation)\r\n * 4. Resolve frontmatter template → render frontmatter\r\n * 5. Load content template\r\n * 6. Render body: partials → conditionals → variables → post-process\r\n * 7. Assemble final output (frontmatter + body)\r\n * 8. Run onPostRender plugin hooks (output chain)\r\n * 9. Run onValidate plugin hooks (validation collection)\r\n * 10. Determine output file path\r\n * 11. Write output file (unless check mode)\r\n * 12. Return BuildResult\r\n *\r\n * @param personaYamlPath Absolute path to the persona YAML source file\r\n * @param suiteName Identifier for the suite this persona belongs to\r\n * @param suiteConfig Suite configuration object\r\n * @param sharedMeta Pre-loaded `_shared.yaml` contents\r\n * @param partialsMap Pre-loaded partials map (shared + suite-local merged)\r\n * @param config Top-level BuildConfig\r\n * @param plugins Registered plugins\r\n * @param target Target output format\r\n * @param agentMap Pre-built cross-suite agent name map\r\n * @param registry Target registry to use. Defaults to `defaultRegistry`.\r\n * **Two-registry limitation:** If you pass a custom `TargetRegistry` only\r\n * to `build()` (via `config.targetRegistry`) and call `buildPersona()`\r\n * directly without also passing that registry here, your custom targets\r\n * will not be visible — `defaultRegistry` will be used instead. Either\r\n * pass the same registry instance explicitly, or call `build()` to have\r\n * the registry forwarded automatically.\r\n * @returns BuildResult for this persona × target combination\r\n */\r\nexport async function buildPersona(\r\n personaYamlPath: string,\r\n suiteName: string,\r\n suiteConfig: SuiteConfig,\r\n sharedMeta: Record<string, unknown>,\r\n partialsMap: Record<string, string>,\r\n config: BuildConfig,\r\n plugins: PersonaBuildPlugin[],\r\n target: string,\r\n agentMap: Record<string, string> = {},\r\n registry: TargetRegistry = defaultRegistry,\r\n): Promise<BuildResult> {\r\n // ── 1. Load persona metadata ──────────────────────────────────────────────\r\n const personaMeta = await loadPersonaYaml(personaYamlPath);\r\n\r\n // ── 2. Build merged context ───────────────────────────────────────────────\r\n let context = buildContext(personaMeta, sharedMeta, agentMap, target, registry);\r\n\r\n // ── 3. Plugin onBuildContext ──────────────────────────────────────────────\r\n // Cast context to PersonaMetadata for the plugin runner (it requires a\r\n // name field which is guaranteed by loadPersonaYaml above).\r\n const personaMetaTyped = personaMeta as PersonaMetadata;\r\n context = runBuildContext(plugins, context, personaMetaTyped, suiteConfig, target);\r\n\r\n // ── 4. Render frontmatter ─────────────────────────────────────────────────\r\n const fmTemplate = resolveFrontmatterTemplate(target, plugins, config.frontmatter, registry);\r\n const contentBasename = path.basename(personaYamlPath, '.yaml') + '.md';\r\n const frontmatter = renderFrontmatter(fmTemplate, context, contentBasename);\r\n\r\n // ── 5. Load content template ──────────────────────────────────────────────\r\n const contentSubdir = suiteConfig.contentSubdir ?? 'content';\r\n const contentPath = path.join(suiteConfig.srcDir, contentSubdir, contentBasename);\r\n const bodyTemplate = normalizeNewlines(await readFile(contentPath, 'utf8'));\r\n\r\n // ── 6. Render body ────────────────────────────────────────────────────────\r\n let body = resolvePartials(bodyTemplate, partialsMap);\r\n body = resolveConditionals(body, context);\r\n body = resolveVariables(body, context, contentBasename);\r\n body = collapseBlankLines(body);\r\n body = ensureBlankLineBeforeHeadings(body);\r\n body = body.trimEnd();\r\n\r\n // ── 7. Assemble output ────────────────────────────────────────────────────\r\n let output = normalizeNewlines(`${frontmatter}\\n\\n${body}\\n`);\r\n\r\n // ── 8. Plugin onPostRender ────────────────────────────────────────────────\r\n output = runPostRender(plugins, output, personaMetaTyped, target);\r\n\r\n // ── 9. Plugin onValidate ──────────────────────────────────────────────────\r\n const validationResults: ValidationResult[] = runValidate(plugins, personaMetaTyped, suiteConfig, target);\r\n\r\n // ── 10. Determine output file path ────────────────────────────────────────\r\n // Resolve the registry definition once — used for both outputDirKey (map\r\n // lookup) and filenameContextKey (output filename override).\r\n const def = registry.has(target) ? registry.get(target) : undefined;\r\n const outputDir = resolveOutputDir(target, suiteConfig, def);\r\n // Use the filename context key declared in the target's registry definition,\r\n // falling back to the content basename when absent or unset in context.\r\n const fnKey = def?.filenameContextKey;\r\n const outputBasename =\r\n fnKey && typeof context[fnKey] === 'string'\r\n ? (context[fnKey] as string)\r\n : contentBasename;\r\n const outputPath = path.join(outputDir, outputBasename);\r\n\r\n // ── 11. Write (unless check mode) ─────────────────────────────────────────\r\n const check = config.check ?? false;\r\n let written = false;\r\n\r\n if (!check) {\r\n await mkdir(outputDir, { recursive: true });\r\n await writeFile(outputPath, output, 'utf8');\r\n written = true;\r\n }\r\n\r\n return {\r\n suite: suiteName,\r\n target,\r\n personaYamlPath,\r\n outputPath,\r\n content: output,\r\n validationResults,\r\n written,\r\n };\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// buildSuite — all personas in one suite × one target\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Build all personas in a suite for a single output target.\r\n *\r\n * Pipeline:\r\n * 1. Load `_shared.yaml` for the suite\r\n * 2. Load merged partials (shared → suite-local)\r\n * 3. Run `onSuiteInit` on all plugins\r\n * 4. Discover all persona YAML files\r\n * 5. Call `buildPersona()` for each\r\n *\r\n * @param suiteName Identifier for this suite\r\n * @param suiteConfig Suite configuration\r\n * @param config Top-level BuildConfig\r\n * @param plugins Registered plugins\r\n * @param target Target output format\r\n * @param agentMap Pre-built cross-suite agent name map\r\n * @param registry Target registry to use. Defaults to `defaultRegistry`.\r\n * **Two-registry limitation:** If you pass a custom `TargetRegistry` only\r\n * to `build()` (via `config.targetRegistry`) and call `buildSuite()`\r\n * directly without also passing that registry here, your custom targets\r\n * will not be visible — `defaultRegistry` will be used instead. Either\r\n * pass the same registry instance explicitly, or call `build()` to have\r\n * the registry forwarded automatically.\r\n * @returns Array of BuildResult objects, one per persona\r\n */\r\nexport async function buildSuite(\r\n suiteName: string,\r\n suiteConfig: SuiteConfig,\r\n config: BuildConfig,\r\n plugins: PersonaBuildPlugin[],\r\n target: string,\r\n agentMap: Record<string, string> = {},\r\n registry: TargetRegistry = defaultRegistry,\r\n): Promise<BuildResult[]> {\r\n // ── 1. Load shared metadata ───────────────────────────────────────────────\r\n const metaSubdir = suiteConfig.metaSubdir ?? 'meta';\r\n const sharedYamlPath = path.join(suiteConfig.srcDir, metaSubdir, '_shared.yaml');\r\n const sharedMeta = await loadRawYaml(sharedYamlPath);\r\n\r\n // ── 2. Load partials (two-layer: shared base → suite-local override) ──────\r\n let partialsMap: Record<string, string> = {};\r\n\r\n if (config.sharedPartialsDir && existsSync(config.sharedPartialsDir)) {\r\n partialsMap = { ...partialsMap, ...(await loadPartials(config.sharedPartialsDir)) };\r\n }\r\n\r\n const partialsSubdir = suiteConfig.partialsSubdir ?? 'partials';\r\n const suitePartialsDir = path.join(suiteConfig.srcDir, partialsSubdir);\r\n if (existsSync(suitePartialsDir)) {\r\n partialsMap = { ...partialsMap, ...(await loadPartials(suitePartialsDir)) };\r\n }\r\n\r\n // ── 3. Plugin onSuiteInit ─────────────────────────────────────────────────\r\n runSuiteInit(plugins, suiteConfig, sharedMeta);\r\n\r\n // ── 4. Discover persona YAML files ────────────────────────────────────────\r\n const personaYamlPaths = await discoverSuitePersonaYamls(suiteConfig);\r\n\r\n // ── 5. Build each persona ─────────────────────────────────────────────────\r\n const results: BuildResult[] = [];\r\n for (const yamlPath of personaYamlPaths) {\r\n const result = await buildPersona(\r\n yamlPath,\r\n suiteName,\r\n suiteConfig,\r\n sharedMeta,\r\n partialsMap,\r\n config,\r\n plugins,\r\n target,\r\n agentMap,\r\n registry,\r\n );\r\n results.push(result);\r\n }\r\n\r\n return results;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// build — top-level entry point\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Top-level build orchestrator.\r\n *\r\n * Iterates all `config.suites × config.targets` combinations, calls\r\n * `buildSuite()` for each, and aggregates the results into a `BuildSummary`.\r\n *\r\n * Modes:\r\n * - Normal: renders and writes all personas.\r\n * - `check: true`: renders without writing; useful for CI staleness checks.\r\n * - `strict: true`: throws when any ValidationResult has severity `'error'`\r\n * or `'warning'`. All suites are processed before the throw, so output\r\n * files **will** be written to disk even when the build ultimately fails.\r\n * **For CI usage, combine `strict: true` with `check: true`** to avoid\r\n * leaving partial artefacts on disk when validation fails.\r\n *\r\n * @param config Typed build configuration\r\n * @returns Aggregated BuildSummary\r\n * @throws `Error` when `strict: true` and validation failures exist\r\n */\r\nexport async function build(config: BuildConfig): Promise<BuildSummary> {\r\n const plugins = config.plugins ?? [];\r\n const registry = config.targetRegistry ?? defaultRegistry;\r\n // When a custom registry is supplied and targets are not explicit, build all\r\n // registered targets. When using the default registry without an explicit\r\n // targets list, build only targets with defaultEnabled !== false. This\r\n // preserves the historical two-target default (vscode + claude-code) for\r\n // existing suite configs that do not configure deep-agents output.\r\n const targets = config.targets ?? registry.names().filter(n => registry.get(n).defaultEnabled !== false);\r\n const allResults: BuildResult[] = [];\r\n\r\n // Pre-scan: build cross-suite agent name map\r\n const agentMap = await buildAgentNameMap(config);\r\n\r\n for (const [suiteName, suiteConfig] of Object.entries(config.suites)) {\r\n for (const target of targets) {\r\n const suiteResults = await buildSuite(suiteName, suiteConfig, config, plugins, target, agentMap, registry);\r\n allResults.push(...suiteResults);\r\n }\r\n }\r\n\r\n // Collect strict failures (error + warning severity)\r\n const strictFailures: ValidationResult[] = config.strict\r\n ? allResults.flatMap((r) =>\r\n r.validationResults.filter(\r\n (v) => v.severity === 'error' || v.severity === 'warning',\r\n ),\r\n )\r\n : [];\r\n\r\n const success = !config.strict || strictFailures.length === 0;\r\n\r\n const summary: BuildSummary = {\r\n success,\r\n results: allResults,\r\n strictFailures,\r\n totalBuilt: allResults.length,\r\n totalWritten: allResults.filter((r) => r.written).length,\r\n };\r\n\r\n if (config.strict && !success) {\r\n const messages = strictFailures.map((f) => `[${f.severity}] ${f.message}`).join('\\n');\r\n throw new Error(\r\n `Build failed in strict mode — ${strictFailures.length} validation issue(s):\\n${messages}`,\r\n );\r\n }\r\n\r\n return summary;\r\n}\r\n","#!/usr/bin/env node\r\n/**\r\n * src/cli.ts — @mistralys/persona-builder CLI entry point\r\n *\r\n * Flags:\r\n * --config <path> Path to config file (JS/CJS/JSON). Default: persona-build.config.js\r\n * --check Run the build pipeline but do not write output files.\r\n * Always exits 0 unless combined with --strict, which causes\r\n * exit 1 when any ValidationResult has severity 'error' or\r\n * 'warning'.\r\n * --strict Fail (exit 1) if any ValidationResult has severity\r\n * 'error' or 'warning'.\r\n * --help Print usage and exit 0.\r\n * --version Print package version and exit 0.\r\n *\r\n * No heavy CLI framework — args are parsed with a hand-rolled loop.\r\n */\r\n\r\nimport { createRequire } from 'node:module';\r\nimport path from 'node:path';\r\nimport { existsSync } from 'node:fs';\r\nimport { pathToFileURL } from 'node:url';\r\n\r\nimport { build } from './builders/persona-builder.js';\r\nimport type { BuildConfig, BuildSummary } from './builders/types.js';\r\n\r\n// ---------------------------------------------------------------------------\r\n// Version — sourced from package.json (single source of truth).\r\n// createRequire is already imported above for config loading; reuse it here.\r\n// ---------------------------------------------------------------------------\r\n\r\nconst _pkgRequire = createRequire(import.meta.url);\r\nconst VERSION = (_pkgRequire('../package.json') as { version: string }).version;\r\n\r\n// ---------------------------------------------------------------------------\r\n// Usage / help text\r\n// ---------------------------------------------------------------------------\r\n\r\nconst USAGE = `\r\n@mistralys/persona-builder v${VERSION}\r\n\r\nBuild AI persona documents from YAML metadata and Markdown content templates.\r\n\r\nUSAGE\r\n persona-build [options]\r\n\r\nOPTIONS\r\n --config <path> Path to the build config file.\r\n Supports .js (ESM), .cjs, and .json formats.\r\n Default: persona-build.config.js in the current directory.\r\n --check Render personas but skip writing output files.\r\n Always exits 0 on its own. Combine with --strict to\r\n exit 1 when validators report errors or warnings.\r\n --strict Exit 1 if any validation result has severity 'error'\r\n or 'warning'.\r\n --help Show this help message and exit.\r\n --version Print the package version and exit.\r\n\r\nEXAMPLES\r\n persona-build # Build with default config\r\n persona-build --config ./my-config.js # Build with a custom config\r\n persona-build --check # CI staleness check (no file writes)\r\n persona-build --strict # Fail on warnings or errors\r\n persona-build --check --strict # Safe CI check — no writes + strict\r\n`.trim();\r\n\r\n// ---------------------------------------------------------------------------\r\n// Arg parsing\r\n// ---------------------------------------------------------------------------\r\n\r\ninterface ParsedArgs {\r\n configPath?: string;\r\n check: boolean;\r\n strict: boolean;\r\n help: boolean;\r\n version: boolean;\r\n}\r\n\r\nfunction parseArgs(argv: string[]): ParsedArgs {\r\n const args = argv.slice(2); // strip 'node' + script path\r\n\r\n const result: ParsedArgs = {\r\n configPath: undefined,\r\n check: false,\r\n strict: false,\r\n help: false,\r\n version: false,\r\n };\r\n\r\n let i = 0;\r\n while (i < args.length) {\r\n const arg = args[i];\r\n switch (arg) {\r\n case '--help':\r\n case '-h':\r\n result.help = true;\r\n break;\r\n case '--version':\r\n case '-v':\r\n result.version = true;\r\n break;\r\n case '--check':\r\n result.check = true;\r\n break;\r\n case '--strict':\r\n result.strict = true;\r\n break;\r\n case '--config': {\r\n const next = args[i + 1];\r\n if (!next || next.startsWith('--')) {\r\n console.error('Error: --config requires a path argument.');\r\n process.exit(1);\r\n }\r\n result.configPath = next;\r\n i++; // consume the value\r\n break;\r\n }\r\n default:\r\n // Unknown flag — warn but do not exit so older configs stay forward-compatible\r\n if (arg.startsWith('--')) {\r\n console.warn(`Warning: Unknown flag \"${arg}\" — ignored.`);\r\n }\r\n }\r\n i++;\r\n }\r\n\r\n return result;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Config loading\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Resolve the config file path from the user-supplied value or the default\r\n * discovery chain.\r\n *\r\n * Discovery order (when --config is not supplied):\r\n * 1. persona-build.config.js (ESM)\r\n * 2. persona-build.config.cjs (CJS)\r\n * 3. persona-build.config.json (JSON)\r\n */\r\nfunction resolveConfigPath(cliValue?: string): string {\r\n if (cliValue) {\r\n const resolved = path.resolve(cliValue);\r\n if (!existsSync(resolved)) {\r\n console.error(`Error: Config file not found: ${resolved}`);\r\n process.exit(1);\r\n }\r\n return resolved;\r\n }\r\n\r\n const candidates = [\r\n 'persona-build.config.js',\r\n 'persona-build.config.cjs',\r\n 'persona-build.config.json',\r\n ];\r\n\r\n for (const name of candidates) {\r\n const candidate = path.resolve(name);\r\n if (existsSync(candidate)) return candidate;\r\n }\r\n\r\n console.error(\r\n 'Error: No config file found. ' +\r\n 'Create persona-build.config.js in the current directory or pass --config <path>.',\r\n );\r\n process.exit(1);\r\n}\r\n\r\n/**\r\n * Load and validate the config file.\r\n *\r\n * Supports:\r\n * - ESM .js → dynamic import()\r\n * - CJS .cjs → createRequire()\r\n * - JSON .json → createRequire()\r\n *\r\n * The config module must export a default export (or be a plain JSON object)\r\n * that conforms to BuildConfig.\r\n */\r\nasync function loadConfig(configPath: string): Promise<BuildConfig> {\r\n const ext = path.extname(configPath).toLowerCase();\r\n\r\n let rawConfig: unknown;\r\n\r\n if (ext === '.cjs' || ext === '.json') {\r\n const require = createRequire(import.meta.url);\r\n rawConfig = require(configPath);\r\n } else {\r\n // ESM default — use dynamic import with a file URL\r\n const fileUrl = pathToFileURL(configPath).href;\r\n const mod = await import(fileUrl);\r\n rawConfig = mod.default ?? mod;\r\n }\r\n\r\n if (!rawConfig || typeof rawConfig !== 'object' || Array.isArray(rawConfig)) {\r\n console.error(\r\n `Error: Config file \"${configPath}\" must export a plain object (BuildConfig).`,\r\n );\r\n process.exit(1);\r\n }\r\n\r\n const config = rawConfig as BuildConfig;\r\n\r\n if (!config.suites || typeof config.suites !== 'object') {\r\n console.error(\r\n `Error: Config file \"${configPath}\" must have a \"suites\" property (record of suite configs).`,\r\n );\r\n process.exit(1);\r\n }\r\n\r\n return config;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Output formatting\r\n// ---------------------------------------------------------------------------\r\n\r\nfunction printSummary(summary: BuildSummary, check: boolean): void {\r\n const mode = check ? ' [check mode — no files written]' : '';\r\n const status = summary.success ? '✓ Build succeeded' : '✗ Build failed';\r\n console.log(`${status}${mode}`);\r\n console.log(` Personas processed : ${summary.totalBuilt}`);\r\n if (!check) {\r\n console.log(` Files written : ${summary.totalWritten}`);\r\n }\r\n if (summary.strictFailures.length > 0) {\r\n console.log(`\\n Validation failures (${summary.strictFailures.length}):`);\r\n for (const f of summary.strictFailures) {\r\n console.log(` [${f.severity}] ${f.message}`);\r\n }\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Main entry point\r\n// ---------------------------------------------------------------------------\r\n\r\nasync function main(): Promise<void> {\r\n const args = parseArgs(process.argv);\r\n\r\n // Short-circuit flags\r\n if (args.help) {\r\n console.log(USAGE);\r\n process.exit(0);\r\n }\r\n\r\n if (args.version) {\r\n console.log(VERSION);\r\n process.exit(0);\r\n }\r\n\r\n // Resolve and load config\r\n const configPath = resolveConfigPath(args.configPath);\r\n let config: BuildConfig;\r\n\r\n try {\r\n config = await loadConfig(configPath);\r\n } catch (err) {\r\n console.error(`Error loading config: ${err instanceof Error ? err.message : String(err)}`);\r\n process.exit(1);\r\n }\r\n\r\n // Apply CLI flag overrides (CLI flags take precedence over config-file values)\r\n if (args.check) config.check = true;\r\n if (args.strict) config.strict = true;\r\n\r\n // Run the build\r\n let summary: BuildSummary;\r\n try {\r\n summary = await build(config);\r\n } catch (err) {\r\n // build() throws in strict mode when there are validation failures\r\n if (err instanceof Error) {\r\n console.error(`\\n${err.message}`);\r\n } else {\r\n console.error('Build failed with an unexpected error:', err);\r\n }\r\n process.exit(1);\r\n }\r\n\r\n // Print results\r\n printSummary(summary, config.check ?? false);\r\n\r\n // Exit code\r\n if (!summary.success) {\r\n process.exit(1);\r\n }\r\n\r\n process.exit(0);\r\n}\r\n\r\nmain().catch((err) => {\r\n console.error('Unexpected error:', err);\r\n process.exit(1);\r\n});\r\n"]}