@ashx-j/lunr 0.2.16 → 0.2.18
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/CHANGELOG.md +25 -1
- package/README.md +2 -1
- package/dist/builtin-extensions/ashxj-thinking.d.ts +1 -0
- package/dist/builtin-extensions/ashxj-thinking.d.ts.map +1 -1
- package/dist/builtin-extensions/ashxj-thinking.js +44 -19
- package/dist/builtin-extensions/ashxj-thinking.js.map +1 -1
- package/dist/builtin-extensions/ashxj-tui.d.ts +2 -2
- package/dist/builtin-extensions/ashxj-tui.d.ts.map +1 -1
- package/dist/builtin-extensions/ashxj-tui.js +8 -11
- package/dist/builtin-extensions/ashxj-tui.js.map +1 -1
- package/dist/builtin-extensions/index.d.ts.map +1 -1
- package/dist/builtin-extensions/index.js +2 -1
- package/dist/builtin-extensions/index.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/index.d.ts +4 -0
- package/dist/builtin-extensions/pi-lsp-extension/src/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/index.js +172 -171
- package/dist/builtin-extensions/pi-lsp-extension/src/index.js.map +1 -1
- package/dist/builtin-extensions/pi-lsp-extension/src/runtime.d.ts +50 -0
- package/dist/builtin-extensions/pi-lsp-extension/src/runtime.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-lsp-extension/src/runtime.js +131 -0
- package/dist/builtin-extensions/pi-lsp-extension/src/runtime.js.map +1 -0
- package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.d.ts +7 -0
- package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.js +211 -0
- package/dist/builtin-extensions/pi-mcp-adapter/direct-tool-executor.js.map +1 -0
- package/dist/builtin-extensions/pi-mcp-adapter/direct-tools.d.ts +0 -5
- package/dist/builtin-extensions/pi-mcp-adapter/direct-tools.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/direct-tools.js +0 -202
- package/dist/builtin-extensions/pi-mcp-adapter/direct-tools.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/index.js +276 -109
- package/dist/builtin-extensions/pi-mcp-adapter/index.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/init.d.ts +4 -1
- package/dist/builtin-extensions/pi-mcp-adapter/init.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/init.js +10 -3
- package/dist/builtin-extensions/pi-mcp-adapter/init.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/metadata-cache.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/metadata-cache.js +6 -1
- package/dist/builtin-extensions/pi-mcp-adapter/metadata-cache.js.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/server-manager.d.ts +6 -1
- package/dist/builtin-extensions/pi-mcp-adapter/server-manager.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-mcp-adapter/server-manager.js +33 -8
- package/dist/builtin-extensions/pi-mcp-adapter/server-manager.js.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.js +2 -1
- package/dist/builtin-extensions/pi-prompt-template-model/prompt-loader.js.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.d.ts +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.js +1 -1
- package/dist/builtin-extensions/pi-prompt-template-model/tool-manager.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/index.js +68 -15
- package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js +6 -2
- package/dist/builtin-extensions/pi-subagents/src/extension/schemas.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js +5 -2
- package/dist/builtin-extensions/pi-subagents/src/runs/background/wait-tool.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/request-params.d.ts +10 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/request-params.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/request-params.js +38 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/request-params.js.map +1 -0
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js +3 -16
- package/dist/builtin-extensions/pi-subagents/src/runs/foreground/subagent-executor.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/fork-context.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/fork-context.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/shared/fork-context.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js +1 -1
- package/dist/builtin-extensions/pi-subagents/src/slash/slash-commands.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +2 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/tui/render.js +72 -31
- package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/review.d.ts +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/review.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/review.js +2 -1
- package/dist/builtin-extensions/pi-subagents/src/watchdog/review.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/extract.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/extract.js +105 -54
- package/dist/builtin-extensions/pi-web-access/extract.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/gemini-search.d.ts +1 -1
- package/dist/builtin-extensions/pi-web-access/gemini-search.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/gemini-search.js +82 -65
- package/dist/builtin-extensions/pi-web-access/gemini-search.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/github-extract.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/github-extract.js +2 -0
- package/dist/builtin-extensions/pi-web-access/github-extract.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/index.d.ts.map +1 -1
- package/dist/builtin-extensions/pi-web-access/index.js +259 -168
- package/dist/builtin-extensions/pi-web-access/index.js.map +1 -1
- package/dist/builtin-extensions/pi-web-access/lazy.d.ts +18 -0
- package/dist/builtin-extensions/pi-web-access/lazy.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-web-access/lazy.js +19 -0
- package/dist/builtin-extensions/pi-web-access/lazy.js.map +1 -0
- package/dist/builtin-extensions/pi-web-access/session-cleanup.d.ts +6 -0
- package/dist/builtin-extensions/pi-web-access/session-cleanup.d.ts.map +1 -0
- package/dist/builtin-extensions/pi-web-access/session-cleanup.js +17 -0
- package/dist/builtin-extensions/pi-web-access/session-cleanup.js.map +1 -0
- package/dist/cli-runtime.d.ts +3 -0
- package/dist/cli-runtime.d.ts.map +1 -0
- package/dist/cli-runtime.js +72 -0
- package/dist/cli-runtime.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +11 -60
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +6 -3
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/host-static.d.ts.map +1 -1
- package/dist/core/extensions/host-static.js +34 -12
- package/dist/core/extensions/host-static.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +1 -2
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +10 -64
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/keybindings.d.ts +2 -2
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +2 -2
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +1 -1
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/sdk.d.ts +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +1 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/timings.d.ts +2 -1
- package/dist/core/timings.d.ts.map +1 -1
- package/dist/core/timings.js +17 -2
- package/dist/core/timings.js.map +1 -1
- package/dist/gateway/agent-bridge.d.ts +6 -1
- package/dist/gateway/agent-bridge.d.ts.map +1 -1
- package/dist/gateway/agent-bridge.js +23 -6
- package/dist/gateway/agent-bridge.js.map +1 -1
- package/dist/gateway/cron.d.ts +1 -1
- package/dist/gateway/cron.d.ts.map +1 -1
- package/dist/gateway/cron.js +3 -1
- package/dist/gateway/cron.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +20 -14
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/injected-context.d.ts +2 -0
- package/dist/modes/interactive/injected-context.d.ts.map +1 -0
- package/dist/modes/interactive/injected-context.js +7 -0
- package/dist/modes/interactive/injected-context.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +2 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +32 -8
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/thinking-level-slash.d.ts +4 -0
- package/dist/modes/interactive/thinking-level-slash.d.ts.map +1 -0
- package/dist/modes/interactive/thinking-level-slash.js +23 -0
- package/dist/modes/interactive/thinking-level-slash.js.map +1 -0
- package/dist/node-runtime/agent-session-services-35WNVGMR.js +36 -0
- package/dist/node-runtime/benchmark-request-UC7PD3V3.js +57 -0
- package/dist/node-runtime/brave-UWDA3I22.js +143 -0
- package/dist/node-runtime/builtin-extensions-QATGXENO.js +28 -0
- package/dist/node-runtime/chunk-2SJB2AWP.js +47 -0
- package/dist/node-runtime/chunk-3NMWLTPV.js +64 -0
- package/dist/node-runtime/chunk-3WFAEVKS.js +115 -0
- package/dist/node-runtime/chunk-3X3KZKMI.js +49 -0
- package/dist/node-runtime/chunk-4CSFRBCN.js +7558 -0
- package/dist/node-runtime/chunk-4DJ6HEGH.js +296 -0
- package/dist/node-runtime/chunk-4HXHDDCF.js +16 -0
- package/dist/node-runtime/chunk-4I23VTC4.js +429 -0
- package/dist/node-runtime/chunk-4TLO4PO2.js +3427 -0
- package/dist/node-runtime/chunk-4ZWGEEAS.js +69 -0
- package/dist/node-runtime/chunk-53YJI7JU.js +137 -0
- package/dist/node-runtime/chunk-5EFIU3OM.js +295 -0
- package/dist/node-runtime/chunk-6BEIBLQ3.js +53 -0
- package/dist/node-runtime/chunk-6KDIOJL3.js +72 -0
- package/dist/node-runtime/chunk-7N3YHTYF.js +26 -0
- package/dist/node-runtime/chunk-7NBZ5P7I.js +24 -0
- package/dist/node-runtime/chunk-AD6VXAO7.js +342 -0
- package/dist/node-runtime/chunk-ARC4KOTI.js +11178 -0
- package/dist/node-runtime/chunk-AROOY4BB.js +173 -0
- package/dist/node-runtime/chunk-ATGA2WLC.js +5646 -0
- package/dist/node-runtime/chunk-AUXVGBO4.js +19 -0
- package/dist/node-runtime/chunk-AY6CAJSL.js +30 -0
- package/dist/node-runtime/chunk-BHO7O6E5.js +296 -0
- package/dist/node-runtime/chunk-BI3DHYCN.js +8845 -0
- package/dist/node-runtime/chunk-BOHIDQT4.js +21 -0
- package/dist/node-runtime/chunk-BRJX2PRC.js +53 -0
- package/dist/node-runtime/chunk-CBGB57XT.js +20211 -0
- package/dist/node-runtime/chunk-CCZJ3PYY.js +17 -0
- package/dist/node-runtime/chunk-CGBXPL3E.js +1171 -0
- package/dist/node-runtime/chunk-CJECDQKP.js +19 -0
- package/dist/node-runtime/chunk-CSFI6YXL.js +130 -0
- package/dist/node-runtime/chunk-DAPBPCBP.js +53 -0
- package/dist/node-runtime/chunk-DDWHZ633.js +37 -0
- package/dist/node-runtime/chunk-DMMTJQMQ.js +43 -0
- package/dist/node-runtime/chunk-DVGWF6A2.js +1180 -0
- package/dist/node-runtime/chunk-EBF6COVM.js +1734 -0
- package/dist/node-runtime/chunk-FQMM2EZ2.js +248 -0
- package/dist/node-runtime/chunk-FVDOXRUD.js +96 -0
- package/dist/node-runtime/chunk-G4P75AIS.js +9471 -0
- package/dist/node-runtime/chunk-G6LRAP36.js +105 -0
- package/dist/node-runtime/chunk-GKLEQ3I4.js +860 -0
- package/dist/node-runtime/chunk-H2EOZYMP.js +57 -0
- package/dist/node-runtime/chunk-HQCKFM2O.js +56 -0
- package/dist/node-runtime/chunk-HYHJIRDW.js +19 -0
- package/dist/node-runtime/chunk-I6R76AG7.js +22 -0
- package/dist/node-runtime/chunk-IRPJXI6U.js +1269 -0
- package/dist/node-runtime/chunk-J26TSGDL.js +633 -0
- package/dist/node-runtime/chunk-JZQ7F36T.js +610 -0
- package/dist/node-runtime/chunk-KBKMCJDU.js +126 -0
- package/dist/node-runtime/chunk-KWA4OC2J.js +100 -0
- package/dist/node-runtime/chunk-M3LZLQW2.js +98 -0
- package/dist/node-runtime/chunk-MCUNIRD5.js +8388 -0
- package/dist/node-runtime/chunk-NI6OTSBH.js +966 -0
- package/dist/node-runtime/chunk-NUIFPZWX.js +209 -0
- package/dist/node-runtime/chunk-OBMWP3I5.js +68 -0
- package/dist/node-runtime/chunk-OCVIXVTZ.js +88 -0
- package/dist/node-runtime/chunk-OPEK5RRY.js +466 -0
- package/dist/node-runtime/chunk-OR4L3IB2.js +42 -0
- package/dist/node-runtime/chunk-PL6JKXWI.js +3622 -0
- package/dist/node-runtime/chunk-PNJSG3IZ.js +807 -0
- package/dist/node-runtime/chunk-PVCDKGR6.js +55 -0
- package/dist/node-runtime/chunk-Q4Q6D4IY.js +364 -0
- package/dist/node-runtime/chunk-Q5ZU2VRT.js +83 -0
- package/dist/node-runtime/chunk-QFWG2RVL.js +5477 -0
- package/dist/node-runtime/chunk-QZMODZQ2.js +305 -0
- package/dist/node-runtime/chunk-R5EDISSV.js +375 -0
- package/dist/node-runtime/chunk-RNBHABBA.js +986 -0
- package/dist/node-runtime/chunk-RQ2Q5IYR.js +72 -0
- package/dist/node-runtime/chunk-RRIZE6QQ.js +17 -0
- package/dist/node-runtime/chunk-SN6G4OU6.js +4753 -0
- package/dist/node-runtime/chunk-STERBGUB.js +949 -0
- package/dist/node-runtime/chunk-UWQYRSYQ.js +8973 -0
- package/dist/node-runtime/chunk-VRB2IYGG.js +53 -0
- package/dist/node-runtime/chunk-VSELYKWU.js +772 -0
- package/dist/node-runtime/chunk-W3CVH5RX.js +62 -0
- package/dist/node-runtime/chunk-WJVFOIB5.js +24921 -0
- package/dist/node-runtime/chunk-WKDK4C5P.js +2834 -0
- package/dist/node-runtime/chunk-XATUM2HK.js +46 -0
- package/dist/node-runtime/chunk-XBWPBZBN.js +125 -0
- package/dist/node-runtime/chunk-XTHQ7XR7.js +509 -0
- package/dist/node-runtime/chunk-ZBV7FAHG.js +1345 -0
- package/dist/node-runtime/cli-runtime.js +80 -0
- package/dist/node-runtime/clipboard-OZ63BBC6.js +12 -0
- package/dist/node-runtime/clipboard-image-7QR6GXVA.js +13 -0
- package/dist/node-runtime/command-AAV3YRR5.js +13 -0
- package/dist/node-runtime/commands-MV5KOZ64.js +291 -0
- package/dist/node-runtime/config-QDD5PUE2.js +73 -0
- package/dist/node-runtime/curator-server-XCM43VEF.js +3816 -0
- package/dist/node-runtime/customize-XEXL2DGQ.js +12 -0
- package/dist/node-runtime/direct-tool-executor-BK7CLEBX.js +188 -0
- package/dist/node-runtime/exa-LL64QZR2.js +329 -0
- package/dist/node-runtime/export-html-TEXVV5RP.js +150 -0
- package/dist/node-runtime/extension-input-O4HSAEM4.js +14 -0
- package/dist/node-runtime/extension-selector-X5FCX43D.js +14 -0
- package/dist/node-runtime/extract-XLQSJN4V.js +17 -0
- package/dist/node-runtime/file-sync-HCOP2QVF.js +117 -0
- package/dist/node-runtime/gateway-OAC4OBBL.js +2137 -0
- package/dist/node-runtime/gemini-api-QE7ANVDZ.js +29 -0
- package/dist/node-runtime/gemini-search-U7SUMPQA.js +330 -0
- package/dist/node-runtime/gemini-url-context-PXWCBQHK.js +103 -0
- package/dist/node-runtime/gemini-web-MM446SEH.js +14 -0
- package/dist/node-runtime/github-extract-F64RZOEA.js +619 -0
- package/dist/node-runtime/goal-NJEE5CTU.js +1831 -0
- package/dist/node-runtime/index.js +859 -0
- package/dist/node-runtime/init-3C7Z24OI.js +28 -0
- package/dist/node-runtime/install-cli-EXMJQESX.js +308 -0
- package/dist/node-runtime/interactive-mode-2SZUO53H.js +56 -0
- package/dist/node-runtime/interactive-view-S6J3QHEF.js +247 -0
- package/dist/node-runtime/lsp-manager-3ASUSO4T.js +1104 -0
- package/dist/node-runtime/lunr-cron-AUUYP4N4.js +272 -0
- package/dist/node-runtime/main.js +54 -0
- package/dist/node-runtime/mcp-auth-flow-QIXHW6QN.js +32 -0
- package/dist/node-runtime/mcp-panel-IIGMXQGP.js +501 -0
- package/dist/node-runtime/mcp-setup-panel-FEK7663I.js +355 -0
- package/dist/node-runtime/memory-cap-3S4XRLNP.js +20 -0
- package/dist/node-runtime/model-tiers-NJLHUEGK.js +20 -0
- package/dist/node-runtime/openai-search-B3MSNCQA.js +288 -0
- package/dist/node-runtime/package-manager-cli-7RKSZGEN.js +749 -0
- package/dist/node-runtime/parallel-AI2MNSCU.js +265 -0
- package/dist/node-runtime/parser-manager-TQHWYDH7.js +152 -0
- package/dist/node-runtime/pdf-extract-IPE6H4HP.js +57 -0
- package/dist/node-runtime/perplexity-QVJW3I35.js +12 -0
- package/dist/node-runtime/pi-intercom-EEMBGQID.js +2215 -0
- package/dist/node-runtime/pi-mcp-adapter-GUFZWW54.js +428 -0
- package/dist/node-runtime/pi-ollama-cloud-2F3Y2QNM.js +1440 -0
- package/dist/node-runtime/pi-prompt-template-model-QWTCGLJU.js +3946 -0
- package/dist/node-runtime/pi-subagents-7YJ3I4VE.js +6048 -0
- package/dist/node-runtime/pi-web-access-2CQGFLT2.js +1867 -0
- package/dist/node-runtime/print-mode-XSFM26EL.js +12 -0
- package/dist/node-runtime/proxy-modes-V6YVFH3C.js +685 -0
- package/dist/node-runtime/rpc-entry.js +62 -0
- package/dist/node-runtime/rpc-mode-W5ZTLTMZ.js +13 -0
- package/dist/node-runtime/runtime-bridges-3RKBDLNA.js +14 -0
- package/dist/node-runtime/session-manager-E7AREDTV.js +33 -0
- package/dist/node-runtime/session-selector-FJ7M2AIX.js +14 -0
- package/dist/node-runtime/settings-manager-GHPTUN7R.js +21 -0
- package/dist/node-runtime/src-BPQFJR76.js +2427 -0
- package/dist/node-runtime/subagent-executor-5Q5A4HJ2.js +8499 -0
- package/dist/node-runtime/summary-review-YSMXKITO.js +228 -0
- package/dist/node-runtime/tavily-WEZFVFP7.js +154 -0
- package/dist/node-runtime/timings-UAD5BEAS.js +16 -0
- package/dist/node-runtime/tool-renderer-MV5O452K.js +204 -0
- package/dist/node-runtime/update-cli-L3JIBH2U.js +70 -0
- package/dist/node-runtime/v4-5MNC3H7G.js +424 -0
- package/dist/node-runtime/video-extract-OYT5WKS5.js +304 -0
- package/dist/node-runtime/workspace-index-6DBXSTJ6.js +163 -0
- package/dist/node-runtime/youtube-extract-TQYKGFGS.js +264 -0
- package/dist/rpc.d.ts +3 -0
- package/dist/rpc.d.ts.map +1 -0
- package/dist/rpc.js +18 -0
- package/dist/rpc.js.map +1 -0
- package/dist/startup/benchmark-request.d.ts +3 -0
- package/dist/startup/benchmark-request.d.ts.map +1 -0
- package/dist/startup/benchmark-request.js +65 -0
- package/dist/startup/benchmark-request.js.map +1 -0
- package/dist/startup/interactive-view.d.ts.map +1 -1
- package/dist/startup/interactive-view.js +1 -2
- package/dist/startup/interactive-view.js.map +1 -1
- package/dist/startup/startup-milestones.d.ts +1 -1
- package/dist/startup/startup-milestones.d.ts.map +1 -1
- package/dist/startup/startup-milestones.js.map +1 -1
- package/dist/utils/await-with-abort.d.ts +2 -0
- package/dist/utils/await-with-abort.d.ts.map +1 -0
- package/dist/utils/await-with-abort.js +19 -0
- package/dist/utils/await-with-abort.js.map +1 -0
- package/docs/development.md +5 -1
- package/docs/features.md +2 -2
- package/docs/interactive-startup.md +95 -48
- package/docs/keybindings.md +2 -2
- package/docs/terminal-setup.md +1 -1
- package/docs/usage.md +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/hidden-thinking-label.ts +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/package.json +8 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt-loader.d.ts","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-prompt-template-model/prompt-loader.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAKnE,eAAO,MAAM,sBAAsB,aAgCjC,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,CAAC;AAE9C,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,GAAG,YAAY,CAAC;AAEpF,MAAM,MAAM,sBAAsB,GAC/B;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAEpD,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEtD,MAAM,WAAW,iBAAiB;IACjC,SAAS,EAAE,sBAAsB,CAAC;IAClC,OAAO,EAAE,oBAAoB,CAAC;IAC9B,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,gBAAgB,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,QAAQ,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACjC,SAAS,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACnC,YAAY,CAAC,EAAE,oBAAoB,CAAC;IACpC,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,YAAY,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,0BAA0B;IAC1C,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACtC,WAAW,EAAE,sBAAsB,EAAE,CAAC;CACtC;AA8hCD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG7D;AA+3BD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,mBAAmB,UAAQ,GAAG,0BAA0B,CAkDzG;AAMD,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CA4B7E;AA+BD,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAgBnF;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAG1D","sourcesContent":["// @ts-nocheck\nimport { existsSync, readdirSync, readFileSync, realpathSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { minimatch } from \"minimatch\";\nimport type { ThinkingLevel } from \"@ashx-j/lunr-agent\";\nimport { CONFIG_DIR_NAME, getAgentDir, parseFrontmatter } from \"@ashx-j/lunr\";\nimport { parseChainDeclaration } from \"./chain-parser.ts\";\n\nconst VALID_THINKING_LEVELS = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\"] as const;\nexport const RESERVED_COMMAND_NAMES = new Set([\n\t\"chain-prompts\",\n\t\"prompt-tool\",\n\t\"settings\",\n\t\"model\",\n\t\"scoped-models\",\n\t\"export\",\n\t\"share\",\n\t\"copy\",\n\t\"name\",\n\t\"session\",\n\t\"hotkeys\",\n\t\"fork\",\n\t\"tree\",\n\t\"login\",\n\t\"logout\",\n\t// lunr: /auth and /deauth aliases of /login and /logout\n\t\"auth\",\n\t\"deauth\",\n\t\"new\",\n\t\"compact\",\n\t\"resume\",\n\t\"reload\",\n\t\"quit\",\n\t// lunr: /exit alias of /quit\n\t\"exit\",\n\t\"mode\",\n\t\"manual\",\n\t\"yolo\",\n\t\"auto\",\n\t\"processes\",\n\t\"rollback\",\n]);\n\nexport type PromptSource = \"user\" | \"project\";\n\nexport interface DelegationLineupSlot {\n\tagent: string;\n\tmodel?: string;\n\ttask?: string;\n\ttaskSuffix?: string;\n\tcwd?: string;\n\tcount?: number;\n}\n\nexport type DeterministicHandoff = \"always\" | \"never\" | \"on-success\" | \"on-failure\";\n\nexport type DeterministicExecution =\n\t| { kind: \"run\"; command: string }\n\t| { kind: \"command\"; command: string; args: string[]; shell: boolean }\n\t| { kind: \"script\"; path: string; args: string[] };\n\nexport type DeterministicEnv = Record<string, string>;\n\nexport interface DeterministicStep {\n\texecution: DeterministicExecution;\n\thandoff: DeterministicHandoff;\n\tnonInteractive: boolean;\n\ttimeoutMs?: number;\n\tcwd?: string;\n\tenv?: DeterministicEnv;\n}\n\nexport interface PromptWithModel {\n\tname: string;\n\tdescription: string;\n\tcontent: string;\n\tmodels: string[];\n\tchain?: string;\n\tchainContext?: \"summary\";\n\trestore: boolean;\n\tskill?: string;\n\tthinking?: ThinkingLevel;\n\tthinkingLevels?: ThinkingLevel[];\n\trotate?: boolean;\n\tfresh?: boolean;\n\tloop?: number | null;\n\tconverge?: boolean;\n\tboomerang?: boolean;\n\tparallel?: number;\n\tworktree?: boolean;\n\tdeterministic?: DeterministicStep;\n\tsubagent?: true | string;\n\tinheritContext?: boolean;\n\tcwd?: string;\n\tworkers?: DelegationLineupSlot[];\n\treviewers?: DelegationLineupSlot[];\n\tfinalApplier?: DelegationLineupSlot;\n\tsource: PromptSource;\n\tsubdir?: string;\n\tfilePath: string;\n}\n\nexport interface PromptLoaderDiagnostic {\n\tcode: string;\n\tmessage: string;\n\tfilePath: string;\n\tsource: PromptSource;\n\tkey: string;\n}\n\nexport interface LoadPromptsWithModelResult {\n\tprompts: Map<string, PromptWithModel>;\n\tdiagnostics: PromptLoaderDiagnostic[];\n}\n\nfunction createDiagnostic(\n\tcode: string,\n\tfilePath: string,\n\tsource: PromptSource,\n\tmessage: string,\n): PromptLoaderDiagnostic {\n\treturn {\n\t\tcode,\n\t\tmessage,\n\t\tfilePath,\n\t\tsource,\n\t\tkey: `${code}:${filePath}:${message}`,\n\t};\n}\n\nfunction lexicalCompare(a: string, b: string): number {\n\tif (a < b) return -1;\n\tif (a > b) return 1;\n\treturn 0;\n}\n\nfunction normalizeStringField(\n\tfield: string,\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): string | undefined {\n\tif (value === undefined) return undefined;\n\tif (typeof value !== \"string\") {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t`invalid-${field}`,\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: expected a string.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst normalized = value.trim();\n\treturn normalized.length > 0 ? normalized : undefined;\n}\n\nfunction isValidModelSelectionSpec(spec: string): boolean {\n\tif (!spec || spec.includes(\"*\") || /\\s/.test(spec)) return false;\n\n\tconst slashIndex = spec.indexOf(\"/\");\n\tif (slashIndex === -1) return true;\n\tif (slashIndex === 0) return false;\n\tconst modelId = spec.slice(slashIndex + 1);\n\tif (modelId.length === 0) return false;\n\tif (modelId.split(\"/\").some((segment) => segment.length === 0)) return false;\n\treturn true;\n}\n\nfunction normalizeFrontmatterRecord(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): Record<string, unknown> | undefined {\n\tif (value && typeof value === \"object\" && !Array.isArray(value)) {\n\t\treturn value as Record<string, unknown>;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-frontmatter\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Skipping prompt template at ${filePath}: frontmatter must be a key-value object.`,\n\t\t),\n\t);\n\treturn undefined;\n}\n\nfunction normalizeModelSpecs(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): string[] | undefined {\n\tif (value === undefined) return undefined;\n\tif (typeof value !== \"string\") {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-model\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Skipping prompt template at ${filePath}: frontmatter field \"model\" must be a string.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst models = value\n\t\t.split(\",\")\n\t\t.map((item) => item.trim())\n\t\t.filter(Boolean);\n\n\tif (models.length === 0) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"empty-model\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Skipping prompt template at ${filePath}: frontmatter field \"model\" is empty.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst invalidSpec = models.find((model) => !isValidModelSelectionSpec(model));\n\tif (invalidSpec) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-model-spec\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Skipping prompt template at ${filePath}: invalid model spec ${JSON.stringify(invalidSpec)} in frontmatter field \"model\".`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\treturn models;\n}\n\nfunction normalizeRestore(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): boolean {\n\tif (value === undefined) return true;\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"true\") return true;\n\t\tif (normalized === \"false\") return false;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-restore\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Using default restore=true for ${filePath}: frontmatter field \"restore\" must be true or false.`,\n\t\t),\n\t);\n\treturn true;\n}\n\nfunction normalizeFresh(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): boolean {\n\tif (value === undefined) return false;\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"true\") return true;\n\t\tif (normalized === \"false\") return false;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-fresh\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Using default fresh=false for ${filePath}: frontmatter field \"fresh\" must be true or false.`,\n\t\t),\n\t);\n\treturn false;\n}\n\nfunction normalizeRotate(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): boolean {\n\tif (value === undefined) return false;\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"true\") return true;\n\t\tif (normalized === \"false\") return false;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-rotate\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Using default rotate=false for ${filePath}: frontmatter field \"rotate\" must be true or false.`,\n\t\t),\n\t);\n\treturn false;\n}\n\nfunction normalizeBoomerang(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): boolean {\n\tif (value === undefined) return false;\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"true\") return true;\n\t\tif (normalized === \"false\") return false;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-boomerang\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Using default boomerang=false for ${filePath}: frontmatter field \"boomerang\" must be true or false.`,\n\t\t),\n\t);\n\treturn false;\n}\n\nfunction normalizeLoop(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): number | null | undefined {\n\tif (value === undefined) return undefined;\n\n\tif (value === true || (typeof value === \"string\" && value.trim().toLowerCase() === \"unlimited\")) {\n\t\treturn null;\n\t}\n\n\tlet normalizedValue: number | undefined;\n\tif (typeof value === \"number\") {\n\t\tnormalizedValue = value;\n\t} else if (typeof value === \"string\" && /^\\d+$/.test(value.trim())) {\n\t\tnormalizedValue = parseInt(value.trim(), 10);\n\t}\n\n\tif (normalizedValue !== undefined && Number.isInteger(normalizedValue) && normalizedValue >= 1 && normalizedValue <= 999) {\n\t\treturn normalizedValue;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-loop\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Ignoring invalid loop value in ${filePath}: frontmatter field \"loop\" must be an integer between 1 and 999, true, or \"unlimited\".`,\n\t\t),\n\t);\n\treturn undefined;\n}\n\nfunction normalizeParallel(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): number | undefined {\n\tif (value === undefined) return undefined;\n\n\tlet normalizedValue: number | undefined;\n\tif (typeof value === \"number\") {\n\t\tnormalizedValue = value;\n\t} else if (typeof value === \"string\" && /^\\d+$/.test(value.trim())) {\n\t\tnormalizedValue = parseInt(value.trim(), 10);\n\t}\n\n\tif (normalizedValue !== undefined && Number.isInteger(normalizedValue) && normalizedValue >= 2) {\n\t\treturn normalizedValue;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-parallel\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Ignoring invalid parallel value in ${filePath}: frontmatter field \"parallel\" must be an integer greater than or equal to 2.`,\n\t\t),\n\t);\n\treturn undefined;\n}\n\nfunction normalizeStringArrayField(\n\tfield: string,\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): string[] | undefined {\n\tif (value === undefined) return [];\n\tif (!Array.isArray(value)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t`invalid-${field}`,\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: expected an array of strings.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst args: string[] = [];\n\tfor (const entry of value) {\n\t\tif (typeof entry !== \"string\") {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t`invalid-${field}`,\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: expected an array of strings.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\targs.push(entry);\n\t}\n\treturn args;\n}\n\nfunction normalizeDeterministicHandoff(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): DeterministicHandoff {\n\tif (value === undefined) return \"always\";\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"always\" || normalized === \"never\" || normalized === \"on-success\" || normalized === \"on-failure\") {\n\t\t\treturn normalized;\n\t\t}\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-deterministic-handoff\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Using default deterministic handoff=always for ${filePath}: expected \"always\", \"never\", \"on-success\", or \"on-failure\".`,\n\t\t),\n\t);\n\treturn \"always\";\n}\n\nfunction normalizeTimeoutMs(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): number | undefined {\n\tif (value === undefined) return undefined;\n\tlet timeoutMs: number | undefined;\n\tif (typeof value === \"number\") timeoutMs = value;\n\tif (typeof value === \"string\" && /^\\d+$/.test(value.trim())) timeoutMs = parseInt(value.trim(), 10);\n\tif (timeoutMs !== undefined && Number.isInteger(timeoutMs) && timeoutMs >= 1) return timeoutMs;\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-deterministic-timeout\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Ignoring invalid deterministic timeout in ${filePath}: expected an integer greater than or equal to 1 (milliseconds).`,\n\t\t),\n\t);\n\treturn undefined;\n}\n\nfunction normalizeDeterministicEnv(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): DeterministicEnv | undefined {\n\tif (value === undefined) return undefined;\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic-env\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid deterministic env in ${filePath}: expected an object with string/number/boolean values.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst env: DeterministicEnv = {};\n\tfor (const [key, raw] of Object.entries(value as Record<string, unknown>)) {\n\t\tif (!key.trim()) {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\"invalid-deterministic-env\",\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid deterministic env in ${filePath}: env keys must be non-empty strings.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\tif (typeof raw !== \"string\" && typeof raw !== \"number\" && typeof raw !== \"boolean\") {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\"invalid-deterministic-env\",\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid deterministic env in ${filePath}: env value for ${JSON.stringify(key)} must be a string, number, or boolean.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\tenv[key] = String(raw);\n\t}\n\n\treturn Object.keys(env).length > 0 ? env : undefined;\n}\n\nfunction normalizeDeterministicNonInteractive(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): boolean {\n\tif (value === undefined) return true;\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"true\") return true;\n\t\tif (normalized === \"false\") return false;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-deterministic-non-interactive\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Using default deterministic nonInteractive=true for ${filePath}: expected true or false.`,\n\t\t),\n\t);\n\treturn true;\n}\n\nfunction normalizeDeterministicRunValue(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): DeterministicExecution | undefined {\n\tif (typeof value === \"string\") {\n\t\tconst command = value.trim();\n\t\tif (command) return { kind: \"run\", command };\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic-run\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid deterministic run value in ${filePath}: expected a non-empty string or an object with command/args.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic-run\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid deterministic run value in ${filePath}: expected a non-empty string or an object with command/args.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst record = value as Record<string, unknown>;\n\tconst command = normalizeStringField(\"deterministic.run.command\", record.command, filePath, source, diagnostics);\n\tif (!command) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic-run\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid deterministic run value in ${filePath}: expected object field \"command\" to be a non-empty string.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\tconst args = normalizeStringArrayField(\"deterministic.run.args\", record.args, filePath, source, diagnostics);\n\tif (!args) return undefined;\n\tlet shell = false;\n\tif (record.shell !== undefined) {\n\t\tif (typeof record.shell === \"boolean\") {\n\t\t\tshell = record.shell;\n\t\t} else {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\"invalid-deterministic-run\",\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid deterministic run value in ${filePath}: object field \"shell\" must be true or false.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t}\n\treturn { kind: \"command\", command, args, shell };\n}\n\nfunction normalizeDeterministicScriptValue(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): DeterministicExecution | undefined {\n\tif (typeof value === \"string\") {\n\t\tconst path = value.trim();\n\t\tif (path) return { kind: \"script\", path, args: [] };\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic-script\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid deterministic script value in ${filePath}: expected a non-empty string or an object with path/args.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic-script\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid deterministic script value in ${filePath}: expected a non-empty string or an object with path/args.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst record = value as Record<string, unknown>;\n\tconst path = normalizeStringField(\"deterministic.script.path\", record.path, filePath, source, diagnostics);\n\tif (!path) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic-script\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid deterministic script value in ${filePath}: expected object field \"path\" to be a non-empty string.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\tconst args = normalizeStringArrayField(\"deterministic.script.args\", record.args, filePath, source, diagnostics);\n\tif (!args) return undefined;\n\treturn { kind: \"script\", path, args };\n}\n\nfunction normalizeDeterministic(\n\tfrontmatter: Record<string, unknown>,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): DeterministicStep | undefined {\n\tconst hasNested = Object.hasOwn(frontmatter, \"deterministic\");\n\tconst hasRun = Object.hasOwn(frontmatter, \"run\");\n\tconst hasScript = Object.hasOwn(frontmatter, \"script\");\n\tconst hasHandoff = Object.hasOwn(frontmatter, \"handoff\");\n\tconst hasTimeout = Object.hasOwn(frontmatter, \"timeout\");\n\tconst hasEnv = Object.hasOwn(frontmatter, \"env\");\n\tconst hasNonInteractive = Object.hasOwn(frontmatter, \"nonInteractive\");\n\tif (!hasNested && !hasRun && !hasScript && !hasHandoff && !hasTimeout && !hasEnv && !hasNonInteractive) return undefined;\n\n\tif (hasNested && (hasRun || hasScript || hasHandoff || hasTimeout || hasEnv || hasNonInteractive)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic-mixed-shorthand\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring top-level deterministic shorthand in ${filePath}: use either \"deterministic\" or top-level run/script/handoff/timeout/env/nonInteractive, not both.`,\n\t\t\t),\n\t\t);\n\t}\n\n\tlet record: Record<string, unknown>;\n\tif (hasNested) {\n\t\tconst raw = frontmatter.deterministic;\n\t\tif (!raw || typeof raw !== \"object\" || Array.isArray(raw)) {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\"invalid-deterministic\",\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid deterministic config in ${filePath}: frontmatter field \"deterministic\" must be an object.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\trecord = raw as Record<string, unknown>;\n\t} else {\n\t\trecord = {\n\t\t\trun: frontmatter.run,\n\t\t\tscript: frontmatter.script,\n\t\t\thandoff: frontmatter.handoff,\n\t\t\ttimeout: frontmatter.timeout,\n\t\t\tenv: frontmatter.env,\n\t\t\tnonInteractive: frontmatter.nonInteractive,\n\t\t};\n\t}\n\n\tconst runValue = Object.hasOwn(record, \"run\") ? record.run : undefined;\n\tconst scriptValue = Object.hasOwn(record, \"script\") ? record.script : undefined;\n\tif (runValue !== undefined && scriptValue !== undefined) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring deterministic config in ${filePath}: \"run\" and \"script\" cannot be declared together.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst execution = runValue !== undefined\n\t\t? normalizeDeterministicRunValue(runValue, filePath, source, diagnostics)\n\t\t: scriptValue !== undefined\n\t\t\t? normalizeDeterministicScriptValue(scriptValue, filePath, source, diagnostics)\n\t\t\t: undefined;\n\tif (!execution) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring deterministic config in ${filePath}: expected either \"run\" or \"script\".`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst handoff = normalizeDeterministicHandoff(record.handoff, filePath, source, diagnostics);\n\tconst timeoutMs = normalizeTimeoutMs(record.timeout, filePath, source, diagnostics);\n\tconst cwd = normalizeCwd(record.cwd, filePath, source, diagnostics);\n\tconst env = normalizeDeterministicEnv(record.env, filePath, source, diagnostics);\n\tconst nonInteractive = normalizeDeterministicNonInteractive(record.nonInteractive, filePath, source, diagnostics);\n\treturn {\n\t\texecution,\n\t\thandoff,\n\t\tnonInteractive,\n\t\t...(timeoutMs !== undefined ? { timeoutMs } : {}),\n\t\t...(cwd ? { cwd } : {}),\n\t\t...(env ? { env } : {}),\n\t};\n}\n\nfunction normalizeLineupSlot(\n\tvalue: unknown,\n\tfield: \"workers\" | \"reviewers\" | \"finalApplier\",\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n\tindex: number,\n): DelegationLineupSlot | undefined {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t`invalid-${field}`,\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} must be an object.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst slot = value as Record<string, unknown>;\n\tif (slot.agent !== undefined && slot.subagent !== undefined) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t`invalid-${field}`,\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} cannot combine \"agent\" and \"subagent\".`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tlet agent: string | undefined;\n\tif (typeof slot.agent === \"string\" && slot.agent.trim()) {\n\t\tagent = slot.agent.trim();\n\t} else if (slot.agent !== undefined) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t`invalid-${field}`,\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} requires a non-empty string \"agent\".`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tif (!agent && slot.subagent !== undefined) {\n\t\tif (slot.subagent === true) {\n\t\t\tagent = field === \"reviewers\" ? \"reviewer\" : \"delegate\";\n\t\t} else if (typeof slot.subagent === \"string\" && slot.subagent.trim()) {\n\t\t\tagent = slot.subagent.trim();\n\t\t} else {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t`invalid-${field}`,\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} requires \"subagent\" to be true or a non-empty string.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tif (!agent) {\n\t\tagent = field === \"reviewers\" ? \"reviewer\" : \"delegate\";\n\t}\n\n\tconst normalized: DelegationLineupSlot = {\n\t\tagent,\n\t};\n\n\tif (slot.model !== undefined) {\n\t\tif (typeof slot.model !== \"string\" || !slot.model.trim()) {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t`invalid-${field}`,\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} has an invalid \"model\".`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\tconst modelSpec = slot.model.trim();\n\t\tif (!isValidModelSelectionSpec(modelSpec)) {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t`invalid-${field}`,\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} has invalid model spec ${JSON.stringify(modelSpec)}.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\tnormalized.model = modelSpec;\n\t}\n\n\tif (slot.task !== undefined) {\n\t\tif (typeof slot.task !== \"string\") {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t`invalid-${field}`,\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} has a non-string \"task\".`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\tconst task = slot.task.trim();\n\t\tif (task) normalized.task = task;\n\t}\n\n\tif (slot.taskSuffix !== undefined) {\n\t\tif (typeof slot.taskSuffix !== \"string\") {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t`invalid-${field}`,\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} has a non-string \"taskSuffix\".`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\tconst taskSuffix = slot.taskSuffix.trim();\n\t\tif (taskSuffix) normalized.taskSuffix = taskSuffix;\n\t}\n\n\tif (slot.cwd !== undefined) {\n\t\tif (typeof slot.cwd !== \"string\") {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t`invalid-${field}`,\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} has a non-string \"cwd\".`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\tconst cwdRaw = slot.cwd.trim();\n\t\tif (cwdRaw) {\n\t\t\tconst expanded = expandCwdPath(cwdRaw);\n\t\t\tif (!expanded) {\n\t\t\t\tdiagnostics.push(\n\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t`invalid-${field}`,\n\t\t\t\t\t\tfilePath,\n\t\t\t\t\t\tsource,\n\t\t\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} \"cwd\" must be an absolute path.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tnormalized.cwd = expanded;\n\t\t}\n\t}\n\n\tif (slot.count !== undefined) {\n\t\tlet count: number | undefined;\n\t\tif (typeof slot.count === \"number\") {\n\t\t\tcount = slot.count;\n\t\t} else if (typeof slot.count === \"string\" && /^\\d+$/.test(slot.count.trim())) {\n\t\t\tcount = parseInt(slot.count.trim(), 10);\n\t\t}\n\t\tif (count === undefined || !Number.isInteger(count) || count < 1) {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t`invalid-${field}`,\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} \"count\" must be an integer greater than or equal to 1.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\tnormalized.count = count;\n\t}\n\n\treturn normalized;\n}\n\nfunction normalizeLineup(\n\tvalue: unknown,\n\tfield: \"workers\" | \"reviewers\",\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): DelegationLineupSlot[] | undefined {\n\tif (value === undefined) return undefined;\n\tif (!Array.isArray(value)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t`invalid-${field}`,\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: expected an array of slot objects.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\tif (value.length === 0) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t`invalid-${field}`,\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: expected at least one slot.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst slots: DelegationLineupSlot[] = [];\n\tfor (let i = 0; i < value.length; i++) {\n\t\tconst normalized = normalizeLineupSlot(value[i], field, filePath, source, diagnostics, i);\n\t\tif (!normalized) return undefined;\n\t\tslots.push(normalized);\n\t}\n\treturn slots;\n}\n\nfunction normalizeFinalApplier(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): DelegationLineupSlot | undefined {\n\tif (value === undefined) return undefined;\n\tconst normalized = normalizeLineupSlot(value, \"finalApplier\", filePath, source, diagnostics, 0);\n\tif (!normalized) return undefined;\n\tconst slot = value as Record<string, unknown>;\n\tif (Object.hasOwn(slot, \"count\")) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-final-applier\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid finalApplier value in ${filePath}: slot 1 \"count\" is not supported.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\tif (Object.hasOwn(slot, \"cwd\")) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-final-applier\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid finalApplier value in ${filePath}: slot 1 \"cwd\" is not supported.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\treturn normalized;\n}\n\nfunction normalizeBestOfN(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): Record<string, unknown> | undefined {\n\tif (value === undefined) return undefined;\n\tif (value && typeof value === \"object\" && !Array.isArray(value)) {\n\t\treturn value as Record<string, unknown>;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-best-of-n\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Ignoring invalid bestOfN value in ${filePath}: frontmatter field \"bestOfN\" must be an object.`,\n\t\t),\n\t);\n\treturn undefined;\n}\n\nfunction pushLegacyCompareFieldDiagnostic(\n\tfield: \"workers\" | \"reviewers\" | \"finalApplier\",\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n) {\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t`invalid-${field}`,\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Ignoring top-level ${field} in ${filePath}: compare template authoring moved to \"bestOfN.${field}\".`,\n\t\t),\n\t);\n}\n\nfunction normalizeConverge(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): boolean {\n\tif (value === undefined) return true;\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"true\") return true;\n\t\tif (normalized === \"false\") return false;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-converge\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Using default converge=true for ${filePath}: frontmatter field \"converge\" must be true or false.`,\n\t\t),\n\t);\n\treturn true;\n}\n\nfunction normalizeWorktree(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): boolean {\n\tif (value === undefined) return false;\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"true\") return true;\n\t\tif (normalized === \"false\") return false;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-worktree\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Using default worktree=false for ${filePath}: frontmatter field \"worktree\" must be true or false.`,\n\t\t),\n\t);\n\treturn false;\n}\n\nfunction normalizeSubagent(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): true | string | undefined {\n\tif (value === undefined) return undefined;\n\tif (value === true) return true;\n\tif (value === false) return undefined;\n\tif (typeof value !== \"string\") {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-subagent\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid subagent value in ${filePath}: frontmatter field \"subagent\" must be true or a non-empty string.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst normalized = value.trim();\n\tif (!normalized) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-subagent\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid subagent value in ${filePath}: frontmatter field \"subagent\" must be true or a non-empty string.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\treturn normalized;\n}\n\nexport function expandCwdPath(raw: string): string | undefined {\n\tconst expanded = raw.startsWith(\"~/\") ? join(homedir(), raw.slice(2)) : raw;\n\treturn isAbsolute(expanded) ? expanded : undefined;\n}\n\nfunction normalizeCwd(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): string | undefined {\n\tif (value === undefined) return undefined;\n\tif (typeof value !== \"string\") {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-cwd\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid cwd in ${filePath}: expected a string.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst trimmed = value.trim();\n\tif (!trimmed) return undefined;\n\tconst expanded = expandCwdPath(trimmed);\n\tif (!expanded) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-cwd\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring cwd in ${filePath}: must be an absolute path.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\treturn expanded;\n}\n\nfunction normalizeInheritContext(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): boolean {\n\tif (value === undefined) return false;\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"true\") return true;\n\t\tif (normalized === \"false\") return false;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-inherit-context\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Using default inheritContext=false for ${filePath}: frontmatter field \"inheritContext\" must be true or false.`,\n\t\t),\n\t);\n\treturn false;\n}\n\nfunction normalizeChain(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): string | undefined {\n\tif (value === undefined) return undefined;\n\tif (typeof value !== \"string\") {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-chain\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid chain value in ${filePath}: frontmatter field \"chain\" must be a string.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst normalized = value.trim();\n\tif (normalized.length > 0) return normalized;\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"empty-chain\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Ignoring invalid chain value in ${filePath}: frontmatter field \"chain\" must be a non-empty string.`,\n\t\t),\n\t);\n\treturn undefined;\n}\n\nfunction normalizeChainContext(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): \"summary\" | undefined {\n\tif (value === undefined) return undefined;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"summary\") return \"summary\";\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-chain-context\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Ignoring invalid chainContext value in ${filePath}: frontmatter field \"chainContext\" must be \"summary\".`,\n\t\t),\n\t);\n\treturn undefined;\n}\n\nfunction normalizeThinking(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): ThinkingLevel | undefined {\n\tconst thinking = normalizeStringField(\"thinking\", value, filePath, source, diagnostics);\n\tif (thinking === undefined) return undefined;\n\n\tconst normalized = thinking.toLowerCase();\n\tif ((VALID_THINKING_LEVELS as readonly string[]).includes(normalized)) {\n\t\treturn normalized as ThinkingLevel;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-thinking\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Ignoring invalid thinking level in ${filePath}: ${JSON.stringify(thinking)}.`,\n\t\t),\n\t);\n\treturn undefined;\n}\n\nfunction normalizeThinkingLevels(\n\tvalue: unknown,\n\tmodelCount: number,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): ThinkingLevel[] | undefined {\n\tif (typeof value !== \"string\") return undefined;\n\n\tconst levels = value\n\t\t.split(\",\")\n\t\t.map((item) => item.trim())\n\t\t.filter(Boolean);\n\n\tconst invalidLevel = levels.find((level) => !(VALID_THINKING_LEVELS as readonly string[]).includes(level.toLowerCase()));\n\tif (invalidLevel) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-thinking-levels\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid thinking level in ${filePath}: ${JSON.stringify(invalidLevel)}.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tif (levels.length !== modelCount) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-thinking-level-count\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring comma-separated thinking levels in ${filePath}: expected ${modelCount} entries to match frontmatter field \"model\".`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\treturn levels.map((level) => level.toLowerCase() as ThinkingLevel);\n}\n\ninterface ConfiguredPromptPath {\n\trawPath: string;\n\tresolvedPath: string;\n\tsettingsPath: string;\n\tsource: PromptSource;\n\tbaseDir: string;\n\tpatterns: string[];\n}\n\ninterface ConfiguredPromptPaths {\n\tpaths: ConfiguredPromptPath[];\n\tpatterns: string[];\n}\n\nfunction expandConfiguredPromptPath(rawPath: string, baseDir: string): string {\n\tconst trimmed = rawPath.trim();\n\tconst expanded = trimmed === \"~\" ? homedir() : trimmed.startsWith(\"~/\") ? join(homedir(), trimmed.slice(2)) : trimmed;\n\treturn isAbsolute(expanded) ? resolve(expanded) : resolve(baseDir, expanded);\n}\n\nfunction isSettingsPromptPattern(value: string): boolean {\n\treturn value.startsWith(\"!\") || value.startsWith(\"+\") || value.startsWith(\"-\") || value.includes(\"*\") || value.includes(\"?\");\n}\n\nfunction isSettingsPromptOverridePattern(value: string): boolean {\n\treturn value.startsWith(\"!\") || value.startsWith(\"+\") || value.startsWith(\"-\");\n}\n\nfunction toPosixPath(path: string): string {\n\treturn path.replace(/\\\\/g, \"/\");\n}\n\nfunction normalizeExactPromptPattern(pattern: string): string {\n\tconst normalized = pattern.startsWith(\"./\") || pattern.startsWith(\".\\\\\") ? pattern.slice(2) : pattern;\n\treturn toPosixPath(normalized);\n}\n\nfunction matchesPromptPattern(filePath: string, pattern: string, baseDir: string): boolean {\n\tconst normalizedPattern = toPosixPath(pattern);\n\tconst rel = toPosixPath(relative(baseDir, filePath));\n\tconst name = basename(filePath);\n\tconst filePathPosix = toPosixPath(filePath);\n\treturn [rel, name, filePathPosix].some((candidate) => minimatch(candidate, normalizedPattern));\n}\n\nfunction matchesExactPromptPattern(filePath: string, pattern: string, baseDir: string): boolean {\n\tconst normalizedPattern = normalizeExactPromptPattern(pattern);\n\tconst rel = toPosixPath(relative(baseDir, filePath));\n\tconst filePathPosix = toPosixPath(filePath);\n\treturn normalizedPattern === rel || normalizedPattern === filePathPosix;\n}\n\nfunction shouldLoadPromptFile(filePath: string, patterns: string[], baseDir: string): boolean {\n\tconst includes: string[] = [];\n\tconst excludes: string[] = [];\n\tconst forceIncludes: string[] = [];\n\tconst forceExcludes: string[] = [];\n\n\tfor (const pattern of patterns) {\n\t\tif (pattern.startsWith(\"+\")) {\n\t\t\tforceIncludes.push(pattern.slice(1));\n\t\t} else if (pattern.startsWith(\"-\")) {\n\t\t\tforceExcludes.push(pattern.slice(1));\n\t\t} else if (pattern.startsWith(\"!\")) {\n\t\t\texcludes.push(pattern.slice(1));\n\t\t} else {\n\t\t\tincludes.push(pattern);\n\t\t}\n\t}\n\n\tlet enabled = includes.length === 0 || includes.some((pattern) => matchesPromptPattern(filePath, pattern, baseDir));\n\tif (excludes.some((pattern) => matchesPromptPattern(filePath, pattern, baseDir))) enabled = false;\n\tif (forceIncludes.some((pattern) => matchesExactPromptPattern(filePath, pattern, baseDir))) enabled = true;\n\tif (forceExcludes.some((pattern) => matchesExactPromptPattern(filePath, pattern, baseDir))) enabled = false;\n\treturn enabled;\n}\n\nfunction createPromptFileFilter(patterns: string[], baseDir: string): ((filePath: string) => boolean) | undefined {\n\treturn patterns.length === 0 ? undefined : (filePath) => shouldLoadPromptFile(filePath, patterns, baseDir);\n}\n\nfunction loadConfiguredPromptPaths(\n\tsettingsPath: string,\n\tsource: PromptSource,\n\tbaseDir: string,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): ConfiguredPromptPaths {\n\tif (!existsSync(settingsPath)) return { paths: [], patterns: [] };\n\n\tlet rawSettings: string;\n\ttry {\n\t\trawSettings = readFileSync(settingsPath, \"utf-8\");\n\t} catch (error) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"unreadable-settings\",\n\t\t\t\tsettingsPath,\n\t\t\t\tsource,\n\t\t\t\t`Skipping prompt settings at ${settingsPath}: ${error instanceof Error ? error.message : String(error)}.`,\n\t\t\t),\n\t\t);\n\t\treturn { paths: [], patterns: [] };\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(rawSettings);\n\t} catch (error) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-settings-json\",\n\t\t\t\tsettingsPath,\n\t\t\t\tsource,\n\t\t\t\t`Skipping prompt settings at ${settingsPath}: ${error instanceof Error ? error.message : String(error)}.`,\n\t\t\t),\n\t\t);\n\t\treturn { paths: [], patterns: [] };\n\t}\n\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-settings\",\n\t\t\t\tsettingsPath,\n\t\t\t\tsource,\n\t\t\t\t`Skipping prompt settings at ${settingsPath}: settings must be a JSON object.`,\n\t\t\t),\n\t\t);\n\t\treturn { paths: [], patterns: [] };\n\t}\n\n\tconst prompts = (parsed as Record<string, unknown>).prompts;\n\tif (prompts === undefined) return { paths: [], patterns: [] };\n\tif (!Array.isArray(prompts)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-settings-prompts\",\n\t\t\t\tsettingsPath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring prompts in ${settingsPath}: expected \"prompts\" to be an array of strings.`,\n\t\t\t),\n\t\t);\n\t\treturn { paths: [], patterns: [] };\n\t}\n\n\tconst configuredPaths: Omit<ConfiguredPromptPath, \"patterns\">[] = [];\n\tconst patterns: string[] = [];\n\tfor (let index = 0; index < prompts.length; index++) {\n\t\tconst rawPath = prompts[index];\n\t\tif (typeof rawPath !== \"string\" || rawPath.trim().length === 0) {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\"invalid-settings-prompt-entry\",\n\t\t\t\t\tsettingsPath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring prompts[${index}] in ${settingsPath}: expected a non-empty string.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst trimmed = rawPath.trim();\n\t\tif (isSettingsPromptPattern(trimmed)) {\n\t\t\tpatterns.push(trimmed);\n\t\t\tcontinue;\n\t\t}\n\t\tconfiguredPaths.push({\n\t\t\trawPath: trimmed,\n\t\t\tresolvedPath: expandConfiguredPromptPath(trimmed, baseDir),\n\t\t\tsettingsPath,\n\t\t\tsource,\n\t\t\tbaseDir,\n\t\t});\n\t}\n\n\treturn { paths: configuredPaths.map((path) => ({ ...path, patterns })), patterns };\n}\n\nfunction canonicalizePromptFile(filePath: string): string {\n\ttry {\n\t\treturn realpathSync(filePath);\n\t} catch {\n\t\treturn resolve(filePath);\n\t}\n}\n\nfunction loadPromptsWithModelFromDir(\n\tdir: string,\n\tsource: PromptSource,\n\tincludePlainPrompts: boolean,\n\tsubdir = \"\",\n\tvisitedDirectories = new Set<string>(),\n\tonlyFileName?: string,\n\tseenFiles?: Set<string>,\n\tshouldLoadFile?: (filePath: string) => boolean,\n): { prompts: PromptWithModel[]; diagnostics: PromptLoaderDiagnostic[] } {\n\tconst prompts: PromptWithModel[] = [];\n\tconst diagnostics: PromptLoaderDiagnostic[] = [];\n\n\tif (!existsSync(dir)) {\n\t\treturn { prompts, diagnostics };\n\t}\n\n\tlet canonicalDir: string;\n\ttry {\n\t\tcanonicalDir = realpathSync(dir);\n\t} catch (error) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"unreadable-directory\",\n\t\t\t\tdir,\n\t\t\t\tsource,\n\t\t\t\t`Skipping prompt directory ${dir}: ${error instanceof Error ? error.message : String(error)}.`,\n\t\t\t),\n\t\t);\n\t\treturn { prompts, diagnostics };\n\t}\n\n\tif (visitedDirectories.has(canonicalDir)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"directory-cycle\",\n\t\t\t\tdir,\n\t\t\t\tsource,\n\t\t\t\t`Skipping already visited prompt directory at ${dir}.`,\n\t\t\t),\n\t\t);\n\t\treturn { prompts, diagnostics };\n\t}\n\n\tvisitedDirectories.add(canonicalDir);\n\n\ttry {\n\t\tconst entries = readdirSync(dir, { withFileTypes: true }).sort((a, b) => lexicalCompare(a.name, b.name));\n\n\t\tfor (const entry of entries) {\n\t\t\tif (onlyFileName && entry.name !== onlyFileName) continue;\n\t\t\tconst fullPath = join(dir, entry.name);\n\n\t\t\tlet isFile = entry.isFile();\n\t\t\tlet isDirectory = entry.isDirectory();\n\t\t\tif (entry.isSymbolicLink()) {\n\t\t\t\ttry {\n\t\t\t\t\tconst stats = statSync(fullPath);\n\t\t\t\t\tisFile = stats.isFile();\n\t\t\t\t\tisDirectory = stats.isDirectory();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"unreadable-symlink\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Skipping unreadable symlink at ${fullPath}: ${error instanceof Error ? error.message : String(error)}.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (isDirectory) {\n\t\t\t\tif (onlyFileName) continue;\n\t\t\t\tconst nextSubdir = subdir ? `${subdir}:${entry.name}` : entry.name;\n\t\t\t\tconst nested = loadPromptsWithModelFromDir(fullPath, source, includePlainPrompts, nextSubdir, visitedDirectories, undefined, seenFiles, shouldLoadFile);\n\t\t\t\tprompts.push(...nested.prompts);\n\t\t\t\tdiagnostics.push(...nested.diagnostics);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!isFile || !entry.name.endsWith(\".md\")) continue;\n\t\t\tif (shouldLoadFile && !shouldLoadFile(fullPath)) continue;\n\t\t\tconst canonicalFile = canonicalizePromptFile(fullPath);\n\t\t\tif (seenFiles?.has(canonicalFile)) continue;\n\t\t\tseenFiles?.add(canonicalFile);\n\n\t\t\ttry {\n\t\t\t\tconst rawContent = readFileSync(fullPath, \"utf-8\");\n\t\t\t\tconst parsed = parseFrontmatter<Record<string, unknown>>(rawContent);\n\t\t\t\tconst frontmatter = normalizeFrontmatterRecord(parsed.frontmatter, fullPath, source, diagnostics);\n\t\t\t\tif (!frontmatter) continue;\n\t\t\t\tconst { body } = parsed;\n\t\t\t\tconst chain = normalizeChain(frontmatter.chain, fullPath, source, diagnostics);\n\t\t\t\tlet parsedChainDeclarationResult:\n\t\t\t\t\t| ReturnType<typeof parseChainDeclaration>\n\t\t\t\t\t| undefined;\n\t\t\t\tconst chainContext = chain ? normalizeChainContext(frontmatter.chainContext, fullPath, source, diagnostics) : undefined;\n\t\t\t\tif (chain && /\\bparallel\\s*\\(/.test(chain)) {\n\t\t\t\t\tparsedChainDeclarationResult = parseChainDeclaration(chain);\n\t\t\t\t\tif (parsedChainDeclarationResult.invalidSegments.length > 0 || parsedChainDeclarationResult.steps.length === 0) {\n\t\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\t\"invalid-chain-declaration\",\n\t\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t\t`Skipping prompt template at ${fullPath}: invalid chain declaration segment ${JSON.stringify(parsedChainDeclarationResult.invalidSegments[0] ?? chain)}.`,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlet subagent = normalizeSubagent(frontmatter.subagent, fullPath, source, diagnostics);\n\t\t\t\tconst cwd = normalizeCwd(frontmatter.cwd, fullPath, source, diagnostics);\n\t\t\t\tconst inheritContext = normalizeInheritContext(frontmatter.inheritContext, fullPath, source, diagnostics);\n\t\t\t\tconst parallel = normalizeParallel(frontmatter.parallel, fullPath, source, diagnostics);\n\t\t\t\tconst hasBestOfN = Object.hasOwn(frontmatter, \"bestOfN\");\n\t\t\t\tconst bestOfN = normalizeBestOfN(frontmatter.bestOfN, fullPath, source, diagnostics);\n\t\t\t\tlet deterministic = normalizeDeterministic(frontmatter, fullPath, source, diagnostics);\n\t\t\t\tconst hasLegacyWorkers = Object.hasOwn(frontmatter, \"workers\");\n\t\t\t\tconst hasLegacyReviewers = Object.hasOwn(frontmatter, \"reviewers\");\n\t\t\t\tconst hasLegacyFinalApplier = Object.hasOwn(frontmatter, \"finalApplier\");\n\t\t\t\tconst hasLegacyCompareFields = hasLegacyWorkers || hasLegacyReviewers || hasLegacyFinalApplier;\n\t\t\t\tif (hasLegacyWorkers) {\n\t\t\t\t\tpushLegacyCompareFieldDiagnostic(\"workers\", fullPath, source, diagnostics);\n\t\t\t\t}\n\t\t\t\tif (hasLegacyReviewers) {\n\t\t\t\t\tpushLegacyCompareFieldDiagnostic(\"reviewers\", fullPath, source, diagnostics);\n\t\t\t\t}\n\t\t\t\tif (hasLegacyFinalApplier) {\n\t\t\t\t\tpushLegacyCompareFieldDiagnostic(\"finalApplier\", fullPath, source, diagnostics);\n\t\t\t\t}\n\t\t\t\tif (hasBestOfN && Object.hasOwn(frontmatter, \"worktree\")) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-worktree\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring top-level worktree in ${fullPath}: use \"bestOfN.worktree\" for compare template authoring.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst workers = normalizeLineup(hasBestOfN ? bestOfN?.workers : undefined, \"workers\", fullPath, source, diagnostics);\n\t\t\t\tconst reviewers = normalizeLineup(hasBestOfN ? bestOfN?.reviewers : undefined, \"reviewers\", fullPath, source, diagnostics);\n\t\t\t\tconst finalApplier = normalizeFinalApplier(hasBestOfN ? bestOfN?.finalApplier : undefined, fullPath, source, diagnostics);\n\t\t\t\tlet safeWorkers = workers;\n\t\t\t\tlet safeReviewers = reviewers;\n\t\t\t\tlet safeFinalApplier = finalApplier;\n\t\t\t\tif (chain && subagent !== undefined) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-subagent-chain\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring subagent in ${fullPath}: frontmatter fields \"chain\" and \"subagent\" cannot be combined.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tsubagent = undefined;\n\t\t\t\t}\n\t\t\t\tif (chain && deterministic !== undefined) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-deterministic-chain\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring deterministic config in ${fullPath}: frontmatter field \"deterministic\" cannot be combined with \"chain\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tdeterministic = undefined;\n\t\t\t\t}\n\t\t\t\tif (chain && (safeWorkers !== undefined || safeReviewers !== undefined || safeFinalApplier !== undefined)) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-lineup-chain\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring compare lineup config in ${fullPath}: frontmatter fields \"workers\"/\"reviewers\"/\"finalApplier\" cannot be combined with \"chain\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tsafeWorkers = undefined;\n\t\t\t\t\tsafeReviewers = undefined;\n\t\t\t\t\tsafeFinalApplier = undefined;\n\t\t\t\t}\n\t\t\t\tif (subagent !== undefined && (safeWorkers !== undefined || safeReviewers !== undefined || safeFinalApplier !== undefined)) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-lineup-subagent\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring compare lineup config in ${fullPath}: frontmatter fields \"workers\"/\"reviewers\"/\"finalApplier\" cannot be combined with \"subagent\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tsafeWorkers = undefined;\n\t\t\t\t\tsafeReviewers = undefined;\n\t\t\t\t\tsafeFinalApplier = undefined;\n\t\t\t\t}\n\t\t\t\tif (subagent !== undefined && deterministic !== undefined) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-deterministic-subagent\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring deterministic config in ${fullPath}: frontmatter field \"deterministic\" cannot be combined with \"subagent\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tdeterministic = undefined;\n\t\t\t\t}\n\t\t\t\tif (subagent === undefined && inheritContext) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-inherit-context\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring inheritContext in ${fullPath}: frontmatter field \"inheritContext\" requires \"subagent\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tlet safeParallel = parallel;\n\t\t\t\tif (safeParallel !== undefined && chain) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-parallel\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring parallel in ${fullPath}: frontmatter field \"parallel\" cannot be combined with \"chain\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tsafeParallel = undefined;\n\t\t\t\t}\n\t\t\t\tif (safeParallel !== undefined && subagent === undefined) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-parallel\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring parallel in ${fullPath}: frontmatter field \"parallel\" requires \"subagent\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tsafeParallel = undefined;\n\t\t\t\t}\n\t\t\t\tif (safeParallel !== undefined && (safeWorkers !== undefined || safeReviewers !== undefined || safeFinalApplier !== undefined)) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-lineup-parallel\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring compare lineup config in ${fullPath}: frontmatter fields \"workers\"/\"reviewers\"/\"finalApplier\" cannot be combined with \"parallel\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tsafeWorkers = undefined;\n\t\t\t\t\tsafeReviewers = undefined;\n\t\t\t\t\tsafeFinalApplier = undefined;\n\t\t\t\t}\n\t\t\t\tif (safeParallel !== undefined && deterministic !== undefined) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-deterministic-parallel\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring deterministic config in ${fullPath}: frontmatter field \"deterministic\" cannot be combined with \"parallel\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tdeterministic = undefined;\n\t\t\t\t}\n\t\t\t\tconst hasLineup = safeWorkers !== undefined || safeReviewers !== undefined || safeFinalApplier !== undefined;\n\t\t\t\tif (!hasBestOfN && hasLegacyCompareFields) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-compare-frontmatter\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Skipping prompt template at ${fullPath}: compare template authoring moved under \"bestOfN:\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (hasBestOfN && !hasLineup) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-best-of-n\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Skipping prompt template at ${fullPath}: \"bestOfN\" did not produce a valid compare configuration.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (!chain && subagent === undefined && !hasLineup && cwd) {\n\t\t\t\t\tif (deterministic) {\n\t\t\t\t\t\tdeterministic = { ...deterministic, ...(deterministic.cwd ? {} : { cwd }) };\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\t\"invalid-cwd\",\n\t\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t\t`Ignoring cwd in ${fullPath}: frontmatter field \"cwd\" requires \"subagent\", \"chain\", or compare lineups (\"workers\"/\"reviewers\"/\"finalApplier\").`,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst hasModelField = Object.hasOwn(frontmatter, \"model\");\n\t\t\t\tconst parsedModels = chain ? [] : normalizeModelSpecs(frontmatter.model, fullPath, source, diagnostics);\n\t\t\t\tif (!chain && hasModelField && !parsedModels) continue;\n\t\t\t\tconst models = chain ? [] : (parsedModels ?? []);\n\t\t\t\tconst rotate = chain ? false : normalizeRotate(frontmatter.rotate, fullPath, source, diagnostics);\n\n\t\t\t\tconst name = entry.name.slice(0, -3);\n\t\t\t\tif (RESERVED_COMMAND_NAMES.has(name)) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"reserved-command-name\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Skipping prompt template at ${fullPath}: command name \"${name}\" is reserved.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst safeInheritContext = subagent !== undefined && inheritContext;\n\t\t\t\tconst safeCwd = (chain || subagent !== undefined || hasLineup) ? cwd : undefined;\n\t\t\t\tconst description = normalizeStringField(\"description\", frontmatter.description, fullPath, source, diagnostics) ?? \"\";\n\t\t\t\tconst skill = chain ? undefined : normalizeStringField(\"skill\", frontmatter.skill, fullPath, source, diagnostics);\n\t\t\t\tlet thinking: ThinkingLevel | undefined;\n\t\t\t\tlet thinkingLevels: ThinkingLevel[] | undefined;\n\t\t\t\tif (!chain) {\n\t\t\t\t\tif (rotate && typeof frontmatter.thinking === \"string\" && frontmatter.thinking.includes(\",\")) {\n\t\t\t\t\t\tthinkingLevels = normalizeThinkingLevels(frontmatter.thinking, models.length, fullPath, source, diagnostics);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthinking = normalizeThinking(frontmatter.thinking, fullPath, source, diagnostics);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst restore = normalizeRestore(frontmatter.restore, fullPath, source, diagnostics);\n\t\t\t\tconst fresh = normalizeFresh(frontmatter.fresh, fullPath, source, diagnostics);\n\t\t\t\tconst loop = normalizeLoop(frontmatter.loop, fullPath, source, diagnostics);\n\t\t\t\tconst converge = normalizeConverge(frontmatter.converge, fullPath, source, diagnostics);\n\t\t\t\tlet boomerang = normalizeBoomerang(frontmatter.boomerang, fullPath, source, diagnostics);\n\t\t\t\tif (chain && boomerang) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-boomerang-chain\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring boomerang in ${fullPath}: frontmatter fields \"chain\" and \"boomerang\" cannot be combined.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tboomerang = false;\n\t\t\t\t}\n\t\t\t\tif (loop !== undefined && deterministic !== undefined) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-deterministic-loop\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring deterministic config in ${fullPath}: frontmatter field \"deterministic\" cannot be combined with \"loop\" in v1.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tdeterministic = undefined;\n\t\t\t\t}\n\t\t\t\tconst worktreeInput = hasBestOfN ? bestOfN?.worktree : frontmatter.worktree;\n\t\t\t\tconst worktree = normalizeWorktree(worktreeInput, fullPath, source, diagnostics);\n\t\t\t\tlet safeWorktree: boolean | undefined;\n\t\t\t\tif (worktree) {\n\t\t\t\t\tif (chain) {\n\t\t\t\t\t\tconst parsedChain = parsedChainDeclarationResult ?? parseChainDeclaration(chain);\n\t\t\t\t\t\tconst hasParallelStep = parsedChain.steps.some((step) => \"parallel\" in step);\n\t\t\t\t\t\tif (parsedChain.invalidSegments.length > 0 || parsedChain.steps.length === 0 || !hasParallelStep) {\n\t\t\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\t\t\"invalid-worktree\",\n\t\t\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t\t\t`Ignoring worktree in ${fullPath}: frontmatter field \"worktree\" requires either \"chain\" with at least one parallel() step, \"subagent\" with frontmatter field \"parallel\", or compare lineups (\"workers\"/\"reviewers\"/\"finalApplier\").`,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsafeWorktree = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (subagent !== undefined && safeParallel !== undefined) {\n\t\t\t\t\t\tsafeWorktree = true;\n\t\t\t\t\t} else if (hasLineup) {\n\t\t\t\t\t\tsafeWorktree = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\t\"invalid-worktree\",\n\t\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t\t`Ignoring worktree in ${fullPath}: frontmatter field \"worktree\" requires either \"chain\" with at least one parallel() step, \"subagent\" with frontmatter field \"parallel\", or compare lineups (\"workers\"/\"reviewers\"/\"finalApplier\").`,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst hasModelConditionalDirectives = /<if-model(?:\\s|>)|<else(?:\\s|>)|<\\/if-model\\s*>|<\\/else(?:\\s|>)/.test(body);\n\t\t\t\tconst hasExtensionSpecificConfig =\n\t\t\t\t\tskill !== undefined ||\n\t\t\t\t\tthinking !== undefined ||\n\t\t\t\t\tfresh === true ||\n\t\t\t\t\tloop !== undefined ||\n\t\t\t\t\tconverge === false ||\n\t\t\t\t\tboomerang === true ||\n\t\t\t\t\tsafeParallel !== undefined ||\n\t\t\t\t\tdeterministic !== undefined ||\n\t\t\t\t\thasLineup ||\n\t\t\t\t\tsafeWorktree === true ||\n\t\t\t\t\tsubagent !== undefined ||\n\t\t\t\t\tsafeInheritContext ||\n\t\t\t\t\thasModelConditionalDirectives;\n\t\t\t\tif (!chain && !hasModelField && !hasExtensionSpecificConfig && !includePlainPrompts) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tprompts.push({\n\t\t\t\t\tname,\n\t\t\t\t\tdescription,\n\t\t\t\t\tcontent: body,\n\t\t\t\t\tmodels,\n\t\t\t\t\tchain: chain || undefined,\n\t\t\t\t\tchainContext,\n\t\t\t\t\trestore,\n\t\t\t\t\tskill,\n\t\t\t\t\tthinking,\n\t\t\t\t\tthinkingLevels,\n\t\t\t\t\trotate: rotate || undefined,\n\t\t\t\t\tfresh: fresh || undefined,\n\t\t\t\t\tloop: loop !== undefined ? loop : undefined,\n\t\t\t\t\tconverge: converge === false ? false : undefined,\n\t\t\t\t\tboomerang: boomerang || undefined,\n\t\t\t\t\tparallel: safeParallel,\n\t\t\t\t\tworktree: safeWorktree,\n\t\t\t\t\tdeterministic,\n\t\t\t\t\tsubagent,\n\t\t\t\t\tinheritContext: safeInheritContext || undefined,\n\t\t\t\t\tcwd: safeCwd || undefined,\n\t\t\t\t\tworkers: safeWorkers,\n\t\t\t\t\treviewers: safeReviewers,\n\t\t\t\t\tfinalApplier: safeFinalApplier,\n\t\t\t\t\tsource,\n\t\t\t\t\tsubdir: subdir || undefined,\n\t\t\t\t\tfilePath: fullPath,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tdiagnostics.push(\n\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\"invalid-prompt-file\",\n\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\tsource,\n\t\t\t\t\t\t`Skipping prompt template at ${fullPath}: ${error instanceof Error ? error.message : String(error)}.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"unreadable-directory\",\n\t\t\t\tdir,\n\t\t\t\tsource,\n\t\t\t\t`Skipping prompt directory ${dir}: ${error instanceof Error ? error.message : String(error)}.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn { prompts, diagnostics };\n}\n\nfunction loadPromptsWithModelFromConfiguredPath(\n\tconfiguredPath: ConfiguredPromptPath,\n\tincludePlainPrompts: boolean,\n\tseenFiles: Set<string>,\n): { prompts: PromptWithModel[]; diagnostics: PromptLoaderDiagnostic[] } {\n\tconst diagnostics: PromptLoaderDiagnostic[] = [];\n\tconst { rawPath, resolvedPath, settingsPath, source, baseDir, patterns } = configuredPath;\n\tconst shouldLoadFile = createPromptFileFilter(patterns, baseDir);\n\n\tif (!existsSync(resolvedPath)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"missing-prompt-path\",\n\t\t\t\tresolvedPath,\n\t\t\t\tsource,\n\t\t\t\t`Skipping configured prompt path ${JSON.stringify(rawPath)} from ${settingsPath}: resolved path ${resolvedPath} does not exist.`,\n\t\t\t),\n\t\t);\n\t\treturn { prompts: [], diagnostics };\n\t}\n\n\tlet stats: ReturnType<typeof statSync>;\n\ttry {\n\t\tstats = statSync(resolvedPath);\n\t} catch (error) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"unreadable-prompt-path\",\n\t\t\t\tresolvedPath,\n\t\t\t\tsource,\n\t\t\t\t`Skipping configured prompt path ${JSON.stringify(rawPath)} from ${settingsPath}: ${error instanceof Error ? error.message : String(error)}.`,\n\t\t\t),\n\t\t);\n\t\treturn { prompts: [], diagnostics };\n\t}\n\n\tif (stats.isDirectory()) {\n\t\treturn loadPromptsWithModelFromDir(resolvedPath, source, includePlainPrompts, \"\", new Set<string>(), undefined, seenFiles, shouldLoadFile);\n\t}\n\n\tif (!stats.isFile() || !resolvedPath.endsWith(\".md\")) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-prompt-path\",\n\t\t\t\tresolvedPath,\n\t\t\t\tsource,\n\t\t\t\t`Skipping configured prompt path ${JSON.stringify(rawPath)} from ${settingsPath}: expected a directory or .md file.`,\n\t\t\t),\n\t\t);\n\t\treturn { prompts: [], diagnostics };\n\t}\n\n\treturn loadPromptsWithModelFromDir(dirname(resolvedPath), source, includePlainPrompts, \"\", new Set<string>(), basename(resolvedPath), seenFiles, shouldLoadFile);\n}\n\nexport function loadPromptsWithModel(cwd: string, includePlainPrompts = false): LoadPromptsWithModelResult {\n\tconst agentDir = getAgentDir();\n\tconst globalDir = join(agentDir, \"prompts\");\n\tconst projectBaseDir = resolve(cwd, CONFIG_DIR_NAME);\n\tconst projectDir = join(projectBaseDir, \"prompts\");\n\tconst promptMap = new Map<string, PromptWithModel>();\n\tconst diagnostics: PromptLoaderDiagnostic[] = [];\n\tconst seenPromptFiles = new Set<string>();\n\n\tfunction addPrompt(prompt: PromptWithModel) {\n\t\tconst existing = promptMap.get(prompt.name);\n\t\tif (!existing) {\n\t\t\tpromptMap.set(prompt.name, prompt);\n\t\t\treturn;\n\t\t}\n\n\t\tif (existing.source === prompt.source) {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\"duplicate-command-name\",\n\t\t\t\t\tprompt.filePath,\n\t\t\t\t\tprompt.source,\n\t\t\t\t\t`Skipping ${prompt.source} prompt template \"${prompt.name}\" at ${prompt.filePath} because it conflicts with ${existing.filePath}.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\tfunction addResult(result: { prompts: PromptWithModel[]; diagnostics: PromptLoaderDiagnostic[] }) {\n\t\tdiagnostics.push(...result.diagnostics);\n\t\tfor (const prompt of result.prompts) {\n\t\t\taddPrompt(prompt);\n\t\t}\n\t}\n\n\tconst projectSettingsPaths = loadConfiguredPromptPaths(join(projectBaseDir, \"settings.json\"), \"project\", projectBaseDir, diagnostics);\n\tconst globalSettingsPaths = loadConfiguredPromptPaths(join(agentDir, \"settings.json\"), \"user\", agentDir, diagnostics);\n\tconst projectDefaultFilter = createPromptFileFilter(projectSettingsPaths.patterns.filter(isSettingsPromptOverridePattern), projectBaseDir);\n\tconst globalDefaultFilter = createPromptFileFilter(globalSettingsPaths.patterns.filter(isSettingsPromptOverridePattern), agentDir);\n\n\tfor (const configuredPath of projectSettingsPaths.paths) {\n\t\taddResult(loadPromptsWithModelFromConfiguredPath(configuredPath, includePlainPrompts, seenPromptFiles));\n\t}\n\taddResult(loadPromptsWithModelFromDir(projectDir, \"project\", includePlainPrompts, \"\", new Set<string>(), undefined, seenPromptFiles, projectDefaultFilter));\n\tfor (const configuredPath of globalSettingsPaths.paths) {\n\t\taddResult(loadPromptsWithModelFromConfiguredPath(configuredPath, includePlainPrompts, seenPromptFiles));\n\t}\n\taddResult(loadPromptsWithModelFromDir(globalDir, \"user\", includePlainPrompts, \"\", new Set<string>(), undefined, seenPromptFiles, globalDefaultFilter));\n\n\treturn { prompts: promptMap, diagnostics };\n}\n\nfunction effectiveLineupCount(slots: DelegationLineupSlot[] | undefined): number {\n\treturn slots?.reduce((total, slot) => total + (slot.count ?? 1), 0) ?? 0;\n}\n\nexport function buildPromptCommandDescription(prompt: PromptWithModel): string {\n\tconst sourceLabel = prompt.subdir ? `(${prompt.source}:${prompt.subdir})` : `(${prompt.source})`;\n\tif (prompt.chain) {\n\t\tconst chainContextLabel = prompt.chainContext ? ` ${prompt.chainContext}` : \"\";\n\t\tconst cwdLabel = prompt.cwd ? ` cwd:${prompt.cwd}` : \"\";\n\t\tconst worktreeLabel = prompt.worktree ? \" worktree\" : \"\";\n\t\tconst details = `[chain: ${prompt.chain}${chainContextLabel}${cwdLabel}${worktreeLabel}] ${sourceLabel}`;\n\t\treturn prompt.description ? `${prompt.description} ${details}` : details;\n\t}\n\tconst modelLabel = prompt.models.length > 0 ? prompt.models.map((model) => model.split(\"/\").pop() || model).join(\"|\") : \"current\";\n\tconst rotateLabel = prompt.rotate ? \" rotate\" : \"\";\n\tconst skillLabel = prompt.skill ? ` +${prompt.skill}` : \"\";\n\tconst thinkingValue = prompt.thinkingLevels ? prompt.thinkingLevels.join(\",\") : prompt.thinking;\n\tconst thinkingLabel = thinkingValue ? ` ${thinkingValue}` : \"\";\n\tconst loopLabel = prompt.loop !== undefined ? ` loop:${prompt.loop === null ? \"unlimited\" : prompt.loop}` : \"\";\n\tconst boomerangLabel = prompt.boomerang ? \" boomerang\" : \"\";\n\tconst subagentLabel = prompt.subagent ? ` subagent:${prompt.subagent === true ? \"delegate\" : prompt.subagent}` : \"\";\n\tconst parallelLabel = prompt.parallel !== undefined ? ` parallel:${prompt.parallel}` : \"\";\n\tconst deterministicLabel = prompt.deterministic ? ` deterministic-step:${prompt.deterministic.handoff}` : \"\";\n\tconst workersLabel = prompt.workers ? ` workers:${effectiveLineupCount(prompt.workers)}` : \"\";\n\tconst reviewersLabel = prompt.reviewers ? ` reviewers:${effectiveLineupCount(prompt.reviewers)}` : \"\";\n\tconst finalApplierLabel = prompt.finalApplier ? \" final-applier\" : \"\";\n\tconst cwdLabel = prompt.cwd ? ` cwd:${prompt.cwd}` : \"\";\n\tconst inheritContextLabel = prompt.inheritContext ? \" fork\" : \"\";\n\tconst worktreeLabel = prompt.worktree ? \" worktree\" : \"\";\n\tconst details =\n\t\t`[${modelLabel}${rotateLabel}${thinkingLabel}${skillLabel}${loopLabel}${boomerangLabel}${subagentLabel}${parallelLabel}${deterministicLabel}${workersLabel}${reviewersLabel}${finalApplierLabel}${cwdLabel}${inheritContextLabel}${worktreeLabel}] ${sourceLabel}`;\n\treturn prompt.description ? `${prompt.description} ${details}` : details;\n}\n\nfunction getSkillCandidates(baseDir: string, skillName: string): string[] {\n\treturn [join(baseDir, skillName, \"SKILL.md\"), join(baseDir, `${skillName}.md`)];\n}\n\nfunction* walkAncestors(startDir: string, stopDir?: string): Generator<string> {\n\tlet current = startDir;\n\twhile (true) {\n\t\tyield current;\n\t\tif (stopDir && current === stopDir) return;\n\t\tconst parent = dirname(current);\n\t\tif (parent === current) return;\n\t\tcurrent = parent;\n\t}\n}\n\nfunction findRepoRoot(startDir: string): string | undefined {\n\tfor (const dir of walkAncestors(startDir)) {\n\t\tif (existsSync(join(dir, \".git\"))) return dir;\n\t}\n\treturn undefined;\n}\n\nfunction findFirstExisting(paths: string[]): string | undefined {\n\tfor (const path of paths) {\n\t\tif (existsSync(path)) return path;\n\t}\n\treturn undefined;\n}\n\nexport function resolveSkillPath(skillName: string, cwd: string): string | undefined {\n\tconst projectDir = resolve(cwd);\n\n\tconst projectPiSkill = findFirstExisting(getSkillCandidates(resolve(projectDir, CONFIG_DIR_NAME, \"skills\"), skillName));\n\tif (projectPiSkill) return projectPiSkill;\n\n\tconst repoRoot = findRepoRoot(projectDir);\n\tfor (const dir of walkAncestors(projectDir, repoRoot)) {\n\t\tconst projectAgentsSkill = findFirstExisting(getSkillCandidates(join(dir, \".agents\", \"skills\"), skillName));\n\t\tif (projectAgentsSkill) return projectAgentsSkill;\n\t}\n\n\tconst globalPiSkill = findFirstExisting(getSkillCandidates(join(getAgentDir(), \"skills\"), skillName));\n\tif (globalPiSkill) return globalPiSkill;\n\n\treturn findFirstExisting(getSkillCandidates(join(homedir(), \".agents\", \"skills\"), skillName));\n}\n\nexport function readSkillContent(skillPath: string): string {\n\tconst raw = readFileSync(skillPath, \"utf-8\");\n\treturn parseFrontmatter(raw).body;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"prompt-loader.d.ts","sourceRoot":"","sources":["../../../src/builtin-extensions/pi-prompt-template-model/prompt-loader.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAMnE,eAAO,MAAM,sBAAsB,aAgCjC,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,CAAC;AAE9C,MAAM,WAAW,oBAAoB;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,OAAO,GAAG,YAAY,GAAG,YAAY,CAAC;AAEpF,MAAM,MAAM,sBAAsB,GAC/B;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAChC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAEpD,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAEtD,MAAM,WAAW,iBAAiB;IACjC,SAAS,EAAE,sBAAsB,CAAC;IAClC,OAAO,EAAE,oBAAoB,CAAC;IAC9B,cAAc,EAAE,OAAO,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,gBAAgB,CAAC;CACvB;AAED,MAAM,WAAW,eAAe;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,cAAc,CAAC,EAAE,aAAa,EAAE,CAAC;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,QAAQ,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IACzB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACjC,SAAS,CAAC,EAAE,oBAAoB,EAAE,CAAC;IACnC,YAAY,CAAC,EAAE,oBAAoB,CAAC;IACpC,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,sBAAsB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,YAAY,CAAC;IACrB,GAAG,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,0BAA0B;IAC1C,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACtC,WAAW,EAAE,sBAAsB,EAAE,CAAC;CACtC;AA8hCD,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAG7D;AA+3BD,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,mBAAmB,UAAQ,GAAG,0BAA0B,CAkDzG;AAMD,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CA4B7E;AA+BD,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAgBnF;AAED,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAG1D","sourcesContent":["// @ts-nocheck\nimport { existsSync, readdirSync, readFileSync, realpathSync, statSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { basename, dirname, isAbsolute, join, relative, resolve } from \"node:path\";\nimport { minimatch } from \"minimatch\";\nimport type { ThinkingLevel } from \"@ashx-j/lunr-agent\";\nimport { CONFIG_DIR_NAME, getAgentDir } from \"../../config.ts\";\nimport { parseFrontmatter } from \"../../utils/frontmatter.ts\";\nimport { parseChainDeclaration } from \"./chain-parser.ts\";\n\nconst VALID_THINKING_LEVELS = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\"] as const;\nexport const RESERVED_COMMAND_NAMES = new Set([\n\t\"chain-prompts\",\n\t\"prompt-tool\",\n\t\"settings\",\n\t\"model\",\n\t\"scoped-models\",\n\t\"export\",\n\t\"share\",\n\t\"copy\",\n\t\"name\",\n\t\"session\",\n\t\"hotkeys\",\n\t\"fork\",\n\t\"tree\",\n\t\"login\",\n\t\"logout\",\n\t// lunr: /auth and /deauth aliases of /login and /logout\n\t\"auth\",\n\t\"deauth\",\n\t\"new\",\n\t\"compact\",\n\t\"resume\",\n\t\"reload\",\n\t\"quit\",\n\t// lunr: /exit alias of /quit\n\t\"exit\",\n\t\"mode\",\n\t\"manual\",\n\t\"yolo\",\n\t\"auto\",\n\t\"processes\",\n\t\"rollback\",\n]);\n\nexport type PromptSource = \"user\" | \"project\";\n\nexport interface DelegationLineupSlot {\n\tagent: string;\n\tmodel?: string;\n\ttask?: string;\n\ttaskSuffix?: string;\n\tcwd?: string;\n\tcount?: number;\n}\n\nexport type DeterministicHandoff = \"always\" | \"never\" | \"on-success\" | \"on-failure\";\n\nexport type DeterministicExecution =\n\t| { kind: \"run\"; command: string }\n\t| { kind: \"command\"; command: string; args: string[]; shell: boolean }\n\t| { kind: \"script\"; path: string; args: string[] };\n\nexport type DeterministicEnv = Record<string, string>;\n\nexport interface DeterministicStep {\n\texecution: DeterministicExecution;\n\thandoff: DeterministicHandoff;\n\tnonInteractive: boolean;\n\ttimeoutMs?: number;\n\tcwd?: string;\n\tenv?: DeterministicEnv;\n}\n\nexport interface PromptWithModel {\n\tname: string;\n\tdescription: string;\n\tcontent: string;\n\tmodels: string[];\n\tchain?: string;\n\tchainContext?: \"summary\";\n\trestore: boolean;\n\tskill?: string;\n\tthinking?: ThinkingLevel;\n\tthinkingLevels?: ThinkingLevel[];\n\trotate?: boolean;\n\tfresh?: boolean;\n\tloop?: number | null;\n\tconverge?: boolean;\n\tboomerang?: boolean;\n\tparallel?: number;\n\tworktree?: boolean;\n\tdeterministic?: DeterministicStep;\n\tsubagent?: true | string;\n\tinheritContext?: boolean;\n\tcwd?: string;\n\tworkers?: DelegationLineupSlot[];\n\treviewers?: DelegationLineupSlot[];\n\tfinalApplier?: DelegationLineupSlot;\n\tsource: PromptSource;\n\tsubdir?: string;\n\tfilePath: string;\n}\n\nexport interface PromptLoaderDiagnostic {\n\tcode: string;\n\tmessage: string;\n\tfilePath: string;\n\tsource: PromptSource;\n\tkey: string;\n}\n\nexport interface LoadPromptsWithModelResult {\n\tprompts: Map<string, PromptWithModel>;\n\tdiagnostics: PromptLoaderDiagnostic[];\n}\n\nfunction createDiagnostic(\n\tcode: string,\n\tfilePath: string,\n\tsource: PromptSource,\n\tmessage: string,\n): PromptLoaderDiagnostic {\n\treturn {\n\t\tcode,\n\t\tmessage,\n\t\tfilePath,\n\t\tsource,\n\t\tkey: `${code}:${filePath}:${message}`,\n\t};\n}\n\nfunction lexicalCompare(a: string, b: string): number {\n\tif (a < b) return -1;\n\tif (a > b) return 1;\n\treturn 0;\n}\n\nfunction normalizeStringField(\n\tfield: string,\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): string | undefined {\n\tif (value === undefined) return undefined;\n\tif (typeof value !== \"string\") {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t`invalid-${field}`,\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: expected a string.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst normalized = value.trim();\n\treturn normalized.length > 0 ? normalized : undefined;\n}\n\nfunction isValidModelSelectionSpec(spec: string): boolean {\n\tif (!spec || spec.includes(\"*\") || /\\s/.test(spec)) return false;\n\n\tconst slashIndex = spec.indexOf(\"/\");\n\tif (slashIndex === -1) return true;\n\tif (slashIndex === 0) return false;\n\tconst modelId = spec.slice(slashIndex + 1);\n\tif (modelId.length === 0) return false;\n\tif (modelId.split(\"/\").some((segment) => segment.length === 0)) return false;\n\treturn true;\n}\n\nfunction normalizeFrontmatterRecord(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): Record<string, unknown> | undefined {\n\tif (value && typeof value === \"object\" && !Array.isArray(value)) {\n\t\treturn value as Record<string, unknown>;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-frontmatter\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Skipping prompt template at ${filePath}: frontmatter must be a key-value object.`,\n\t\t),\n\t);\n\treturn undefined;\n}\n\nfunction normalizeModelSpecs(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): string[] | undefined {\n\tif (value === undefined) return undefined;\n\tif (typeof value !== \"string\") {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-model\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Skipping prompt template at ${filePath}: frontmatter field \"model\" must be a string.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst models = value\n\t\t.split(\",\")\n\t\t.map((item) => item.trim())\n\t\t.filter(Boolean);\n\n\tif (models.length === 0) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"empty-model\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Skipping prompt template at ${filePath}: frontmatter field \"model\" is empty.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst invalidSpec = models.find((model) => !isValidModelSelectionSpec(model));\n\tif (invalidSpec) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-model-spec\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Skipping prompt template at ${filePath}: invalid model spec ${JSON.stringify(invalidSpec)} in frontmatter field \"model\".`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\treturn models;\n}\n\nfunction normalizeRestore(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): boolean {\n\tif (value === undefined) return true;\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"true\") return true;\n\t\tif (normalized === \"false\") return false;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-restore\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Using default restore=true for ${filePath}: frontmatter field \"restore\" must be true or false.`,\n\t\t),\n\t);\n\treturn true;\n}\n\nfunction normalizeFresh(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): boolean {\n\tif (value === undefined) return false;\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"true\") return true;\n\t\tif (normalized === \"false\") return false;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-fresh\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Using default fresh=false for ${filePath}: frontmatter field \"fresh\" must be true or false.`,\n\t\t),\n\t);\n\treturn false;\n}\n\nfunction normalizeRotate(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): boolean {\n\tif (value === undefined) return false;\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"true\") return true;\n\t\tif (normalized === \"false\") return false;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-rotate\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Using default rotate=false for ${filePath}: frontmatter field \"rotate\" must be true or false.`,\n\t\t),\n\t);\n\treturn false;\n}\n\nfunction normalizeBoomerang(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): boolean {\n\tif (value === undefined) return false;\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"true\") return true;\n\t\tif (normalized === \"false\") return false;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-boomerang\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Using default boomerang=false for ${filePath}: frontmatter field \"boomerang\" must be true or false.`,\n\t\t),\n\t);\n\treturn false;\n}\n\nfunction normalizeLoop(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): number | null | undefined {\n\tif (value === undefined) return undefined;\n\n\tif (value === true || (typeof value === \"string\" && value.trim().toLowerCase() === \"unlimited\")) {\n\t\treturn null;\n\t}\n\n\tlet normalizedValue: number | undefined;\n\tif (typeof value === \"number\") {\n\t\tnormalizedValue = value;\n\t} else if (typeof value === \"string\" && /^\\d+$/.test(value.trim())) {\n\t\tnormalizedValue = parseInt(value.trim(), 10);\n\t}\n\n\tif (normalizedValue !== undefined && Number.isInteger(normalizedValue) && normalizedValue >= 1 && normalizedValue <= 999) {\n\t\treturn normalizedValue;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-loop\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Ignoring invalid loop value in ${filePath}: frontmatter field \"loop\" must be an integer between 1 and 999, true, or \"unlimited\".`,\n\t\t),\n\t);\n\treturn undefined;\n}\n\nfunction normalizeParallel(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): number | undefined {\n\tif (value === undefined) return undefined;\n\n\tlet normalizedValue: number | undefined;\n\tif (typeof value === \"number\") {\n\t\tnormalizedValue = value;\n\t} else if (typeof value === \"string\" && /^\\d+$/.test(value.trim())) {\n\t\tnormalizedValue = parseInt(value.trim(), 10);\n\t}\n\n\tif (normalizedValue !== undefined && Number.isInteger(normalizedValue) && normalizedValue >= 2) {\n\t\treturn normalizedValue;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-parallel\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Ignoring invalid parallel value in ${filePath}: frontmatter field \"parallel\" must be an integer greater than or equal to 2.`,\n\t\t),\n\t);\n\treturn undefined;\n}\n\nfunction normalizeStringArrayField(\n\tfield: string,\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): string[] | undefined {\n\tif (value === undefined) return [];\n\tif (!Array.isArray(value)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t`invalid-${field}`,\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: expected an array of strings.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst args: string[] = [];\n\tfor (const entry of value) {\n\t\tif (typeof entry !== \"string\") {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t`invalid-${field}`,\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: expected an array of strings.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\targs.push(entry);\n\t}\n\treturn args;\n}\n\nfunction normalizeDeterministicHandoff(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): DeterministicHandoff {\n\tif (value === undefined) return \"always\";\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"always\" || normalized === \"never\" || normalized === \"on-success\" || normalized === \"on-failure\") {\n\t\t\treturn normalized;\n\t\t}\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-deterministic-handoff\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Using default deterministic handoff=always for ${filePath}: expected \"always\", \"never\", \"on-success\", or \"on-failure\".`,\n\t\t),\n\t);\n\treturn \"always\";\n}\n\nfunction normalizeTimeoutMs(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): number | undefined {\n\tif (value === undefined) return undefined;\n\tlet timeoutMs: number | undefined;\n\tif (typeof value === \"number\") timeoutMs = value;\n\tif (typeof value === \"string\" && /^\\d+$/.test(value.trim())) timeoutMs = parseInt(value.trim(), 10);\n\tif (timeoutMs !== undefined && Number.isInteger(timeoutMs) && timeoutMs >= 1) return timeoutMs;\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-deterministic-timeout\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Ignoring invalid deterministic timeout in ${filePath}: expected an integer greater than or equal to 1 (milliseconds).`,\n\t\t),\n\t);\n\treturn undefined;\n}\n\nfunction normalizeDeterministicEnv(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): DeterministicEnv | undefined {\n\tif (value === undefined) return undefined;\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic-env\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid deterministic env in ${filePath}: expected an object with string/number/boolean values.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst env: DeterministicEnv = {};\n\tfor (const [key, raw] of Object.entries(value as Record<string, unknown>)) {\n\t\tif (!key.trim()) {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\"invalid-deterministic-env\",\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid deterministic env in ${filePath}: env keys must be non-empty strings.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\tif (typeof raw !== \"string\" && typeof raw !== \"number\" && typeof raw !== \"boolean\") {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\"invalid-deterministic-env\",\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid deterministic env in ${filePath}: env value for ${JSON.stringify(key)} must be a string, number, or boolean.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\tenv[key] = String(raw);\n\t}\n\n\treturn Object.keys(env).length > 0 ? env : undefined;\n}\n\nfunction normalizeDeterministicNonInteractive(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): boolean {\n\tif (value === undefined) return true;\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"true\") return true;\n\t\tif (normalized === \"false\") return false;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-deterministic-non-interactive\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Using default deterministic nonInteractive=true for ${filePath}: expected true or false.`,\n\t\t),\n\t);\n\treturn true;\n}\n\nfunction normalizeDeterministicRunValue(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): DeterministicExecution | undefined {\n\tif (typeof value === \"string\") {\n\t\tconst command = value.trim();\n\t\tif (command) return { kind: \"run\", command };\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic-run\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid deterministic run value in ${filePath}: expected a non-empty string or an object with command/args.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic-run\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid deterministic run value in ${filePath}: expected a non-empty string or an object with command/args.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst record = value as Record<string, unknown>;\n\tconst command = normalizeStringField(\"deterministic.run.command\", record.command, filePath, source, diagnostics);\n\tif (!command) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic-run\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid deterministic run value in ${filePath}: expected object field \"command\" to be a non-empty string.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\tconst args = normalizeStringArrayField(\"deterministic.run.args\", record.args, filePath, source, diagnostics);\n\tif (!args) return undefined;\n\tlet shell = false;\n\tif (record.shell !== undefined) {\n\t\tif (typeof record.shell === \"boolean\") {\n\t\t\tshell = record.shell;\n\t\t} else {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\"invalid-deterministic-run\",\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid deterministic run value in ${filePath}: object field \"shell\" must be true or false.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t}\n\treturn { kind: \"command\", command, args, shell };\n}\n\nfunction normalizeDeterministicScriptValue(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): DeterministicExecution | undefined {\n\tif (typeof value === \"string\") {\n\t\tconst path = value.trim();\n\t\tif (path) return { kind: \"script\", path, args: [] };\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic-script\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid deterministic script value in ${filePath}: expected a non-empty string or an object with path/args.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic-script\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid deterministic script value in ${filePath}: expected a non-empty string or an object with path/args.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst record = value as Record<string, unknown>;\n\tconst path = normalizeStringField(\"deterministic.script.path\", record.path, filePath, source, diagnostics);\n\tif (!path) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic-script\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid deterministic script value in ${filePath}: expected object field \"path\" to be a non-empty string.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\tconst args = normalizeStringArrayField(\"deterministic.script.args\", record.args, filePath, source, diagnostics);\n\tif (!args) return undefined;\n\treturn { kind: \"script\", path, args };\n}\n\nfunction normalizeDeterministic(\n\tfrontmatter: Record<string, unknown>,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): DeterministicStep | undefined {\n\tconst hasNested = Object.hasOwn(frontmatter, \"deterministic\");\n\tconst hasRun = Object.hasOwn(frontmatter, \"run\");\n\tconst hasScript = Object.hasOwn(frontmatter, \"script\");\n\tconst hasHandoff = Object.hasOwn(frontmatter, \"handoff\");\n\tconst hasTimeout = Object.hasOwn(frontmatter, \"timeout\");\n\tconst hasEnv = Object.hasOwn(frontmatter, \"env\");\n\tconst hasNonInteractive = Object.hasOwn(frontmatter, \"nonInteractive\");\n\tif (!hasNested && !hasRun && !hasScript && !hasHandoff && !hasTimeout && !hasEnv && !hasNonInteractive) return undefined;\n\n\tif (hasNested && (hasRun || hasScript || hasHandoff || hasTimeout || hasEnv || hasNonInteractive)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic-mixed-shorthand\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring top-level deterministic shorthand in ${filePath}: use either \"deterministic\" or top-level run/script/handoff/timeout/env/nonInteractive, not both.`,\n\t\t\t),\n\t\t);\n\t}\n\n\tlet record: Record<string, unknown>;\n\tif (hasNested) {\n\t\tconst raw = frontmatter.deterministic;\n\t\tif (!raw || typeof raw !== \"object\" || Array.isArray(raw)) {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\"invalid-deterministic\",\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid deterministic config in ${filePath}: frontmatter field \"deterministic\" must be an object.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\trecord = raw as Record<string, unknown>;\n\t} else {\n\t\trecord = {\n\t\t\trun: frontmatter.run,\n\t\t\tscript: frontmatter.script,\n\t\t\thandoff: frontmatter.handoff,\n\t\t\ttimeout: frontmatter.timeout,\n\t\t\tenv: frontmatter.env,\n\t\t\tnonInteractive: frontmatter.nonInteractive,\n\t\t};\n\t}\n\n\tconst runValue = Object.hasOwn(record, \"run\") ? record.run : undefined;\n\tconst scriptValue = Object.hasOwn(record, \"script\") ? record.script : undefined;\n\tif (runValue !== undefined && scriptValue !== undefined) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring deterministic config in ${filePath}: \"run\" and \"script\" cannot be declared together.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst execution = runValue !== undefined\n\t\t? normalizeDeterministicRunValue(runValue, filePath, source, diagnostics)\n\t\t: scriptValue !== undefined\n\t\t\t? normalizeDeterministicScriptValue(scriptValue, filePath, source, diagnostics)\n\t\t\t: undefined;\n\tif (!execution) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-deterministic\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring deterministic config in ${filePath}: expected either \"run\" or \"script\".`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst handoff = normalizeDeterministicHandoff(record.handoff, filePath, source, diagnostics);\n\tconst timeoutMs = normalizeTimeoutMs(record.timeout, filePath, source, diagnostics);\n\tconst cwd = normalizeCwd(record.cwd, filePath, source, diagnostics);\n\tconst env = normalizeDeterministicEnv(record.env, filePath, source, diagnostics);\n\tconst nonInteractive = normalizeDeterministicNonInteractive(record.nonInteractive, filePath, source, diagnostics);\n\treturn {\n\t\texecution,\n\t\thandoff,\n\t\tnonInteractive,\n\t\t...(timeoutMs !== undefined ? { timeoutMs } : {}),\n\t\t...(cwd ? { cwd } : {}),\n\t\t...(env ? { env } : {}),\n\t};\n}\n\nfunction normalizeLineupSlot(\n\tvalue: unknown,\n\tfield: \"workers\" | \"reviewers\" | \"finalApplier\",\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n\tindex: number,\n): DelegationLineupSlot | undefined {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t`invalid-${field}`,\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} must be an object.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst slot = value as Record<string, unknown>;\n\tif (slot.agent !== undefined && slot.subagent !== undefined) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t`invalid-${field}`,\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} cannot combine \"agent\" and \"subagent\".`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tlet agent: string | undefined;\n\tif (typeof slot.agent === \"string\" && slot.agent.trim()) {\n\t\tagent = slot.agent.trim();\n\t} else if (slot.agent !== undefined) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t`invalid-${field}`,\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} requires a non-empty string \"agent\".`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tif (!agent && slot.subagent !== undefined) {\n\t\tif (slot.subagent === true) {\n\t\t\tagent = field === \"reviewers\" ? \"reviewer\" : \"delegate\";\n\t\t} else if (typeof slot.subagent === \"string\" && slot.subagent.trim()) {\n\t\t\tagent = slot.subagent.trim();\n\t\t} else {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t`invalid-${field}`,\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} requires \"subagent\" to be true or a non-empty string.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tif (!agent) {\n\t\tagent = field === \"reviewers\" ? \"reviewer\" : \"delegate\";\n\t}\n\n\tconst normalized: DelegationLineupSlot = {\n\t\tagent,\n\t};\n\n\tif (slot.model !== undefined) {\n\t\tif (typeof slot.model !== \"string\" || !slot.model.trim()) {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t`invalid-${field}`,\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} has an invalid \"model\".`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\tconst modelSpec = slot.model.trim();\n\t\tif (!isValidModelSelectionSpec(modelSpec)) {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t`invalid-${field}`,\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} has invalid model spec ${JSON.stringify(modelSpec)}.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\tnormalized.model = modelSpec;\n\t}\n\n\tif (slot.task !== undefined) {\n\t\tif (typeof slot.task !== \"string\") {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t`invalid-${field}`,\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} has a non-string \"task\".`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\tconst task = slot.task.trim();\n\t\tif (task) normalized.task = task;\n\t}\n\n\tif (slot.taskSuffix !== undefined) {\n\t\tif (typeof slot.taskSuffix !== \"string\") {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t`invalid-${field}`,\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} has a non-string \"taskSuffix\".`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\tconst taskSuffix = slot.taskSuffix.trim();\n\t\tif (taskSuffix) normalized.taskSuffix = taskSuffix;\n\t}\n\n\tif (slot.cwd !== undefined) {\n\t\tif (typeof slot.cwd !== \"string\") {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t`invalid-${field}`,\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} has a non-string \"cwd\".`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\tconst cwdRaw = slot.cwd.trim();\n\t\tif (cwdRaw) {\n\t\t\tconst expanded = expandCwdPath(cwdRaw);\n\t\t\tif (!expanded) {\n\t\t\t\tdiagnostics.push(\n\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t`invalid-${field}`,\n\t\t\t\t\t\tfilePath,\n\t\t\t\t\t\tsource,\n\t\t\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} \"cwd\" must be an absolute path.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\tnormalized.cwd = expanded;\n\t\t}\n\t}\n\n\tif (slot.count !== undefined) {\n\t\tlet count: number | undefined;\n\t\tif (typeof slot.count === \"number\") {\n\t\t\tcount = slot.count;\n\t\t} else if (typeof slot.count === \"string\" && /^\\d+$/.test(slot.count.trim())) {\n\t\t\tcount = parseInt(slot.count.trim(), 10);\n\t\t}\n\t\tif (count === undefined || !Number.isInteger(count) || count < 1) {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t`invalid-${field}`,\n\t\t\t\t\tfilePath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: slot ${index + 1} \"count\" must be an integer greater than or equal to 1.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn undefined;\n\t\t}\n\t\tnormalized.count = count;\n\t}\n\n\treturn normalized;\n}\n\nfunction normalizeLineup(\n\tvalue: unknown,\n\tfield: \"workers\" | \"reviewers\",\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): DelegationLineupSlot[] | undefined {\n\tif (value === undefined) return undefined;\n\tif (!Array.isArray(value)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t`invalid-${field}`,\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: expected an array of slot objects.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\tif (value.length === 0) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t`invalid-${field}`,\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid ${field} value in ${filePath}: expected at least one slot.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst slots: DelegationLineupSlot[] = [];\n\tfor (let i = 0; i < value.length; i++) {\n\t\tconst normalized = normalizeLineupSlot(value[i], field, filePath, source, diagnostics, i);\n\t\tif (!normalized) return undefined;\n\t\tslots.push(normalized);\n\t}\n\treturn slots;\n}\n\nfunction normalizeFinalApplier(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): DelegationLineupSlot | undefined {\n\tif (value === undefined) return undefined;\n\tconst normalized = normalizeLineupSlot(value, \"finalApplier\", filePath, source, diagnostics, 0);\n\tif (!normalized) return undefined;\n\tconst slot = value as Record<string, unknown>;\n\tif (Object.hasOwn(slot, \"count\")) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-final-applier\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid finalApplier value in ${filePath}: slot 1 \"count\" is not supported.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\tif (Object.hasOwn(slot, \"cwd\")) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-final-applier\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid finalApplier value in ${filePath}: slot 1 \"cwd\" is not supported.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\treturn normalized;\n}\n\nfunction normalizeBestOfN(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): Record<string, unknown> | undefined {\n\tif (value === undefined) return undefined;\n\tif (value && typeof value === \"object\" && !Array.isArray(value)) {\n\t\treturn value as Record<string, unknown>;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-best-of-n\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Ignoring invalid bestOfN value in ${filePath}: frontmatter field \"bestOfN\" must be an object.`,\n\t\t),\n\t);\n\treturn undefined;\n}\n\nfunction pushLegacyCompareFieldDiagnostic(\n\tfield: \"workers\" | \"reviewers\" | \"finalApplier\",\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n) {\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t`invalid-${field}`,\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Ignoring top-level ${field} in ${filePath}: compare template authoring moved to \"bestOfN.${field}\".`,\n\t\t),\n\t);\n}\n\nfunction normalizeConverge(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): boolean {\n\tif (value === undefined) return true;\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"true\") return true;\n\t\tif (normalized === \"false\") return false;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-converge\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Using default converge=true for ${filePath}: frontmatter field \"converge\" must be true or false.`,\n\t\t),\n\t);\n\treturn true;\n}\n\nfunction normalizeWorktree(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): boolean {\n\tif (value === undefined) return false;\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"true\") return true;\n\t\tif (normalized === \"false\") return false;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-worktree\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Using default worktree=false for ${filePath}: frontmatter field \"worktree\" must be true or false.`,\n\t\t),\n\t);\n\treturn false;\n}\n\nfunction normalizeSubagent(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): true | string | undefined {\n\tif (value === undefined) return undefined;\n\tif (value === true) return true;\n\tif (value === false) return undefined;\n\tif (typeof value !== \"string\") {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-subagent\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid subagent value in ${filePath}: frontmatter field \"subagent\" must be true or a non-empty string.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst normalized = value.trim();\n\tif (!normalized) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-subagent\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid subagent value in ${filePath}: frontmatter field \"subagent\" must be true or a non-empty string.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\treturn normalized;\n}\n\nexport function expandCwdPath(raw: string): string | undefined {\n\tconst expanded = raw.startsWith(\"~/\") ? join(homedir(), raw.slice(2)) : raw;\n\treturn isAbsolute(expanded) ? expanded : undefined;\n}\n\nfunction normalizeCwd(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): string | undefined {\n\tif (value === undefined) return undefined;\n\tif (typeof value !== \"string\") {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-cwd\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid cwd in ${filePath}: expected a string.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst trimmed = value.trim();\n\tif (!trimmed) return undefined;\n\tconst expanded = expandCwdPath(trimmed);\n\tif (!expanded) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-cwd\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring cwd in ${filePath}: must be an absolute path.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\treturn expanded;\n}\n\nfunction normalizeInheritContext(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): boolean {\n\tif (value === undefined) return false;\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"true\") return true;\n\t\tif (normalized === \"false\") return false;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-inherit-context\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Using default inheritContext=false for ${filePath}: frontmatter field \"inheritContext\" must be true or false.`,\n\t\t),\n\t);\n\treturn false;\n}\n\nfunction normalizeChain(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): string | undefined {\n\tif (value === undefined) return undefined;\n\tif (typeof value !== \"string\") {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-chain\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid chain value in ${filePath}: frontmatter field \"chain\" must be a string.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tconst normalized = value.trim();\n\tif (normalized.length > 0) return normalized;\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"empty-chain\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Ignoring invalid chain value in ${filePath}: frontmatter field \"chain\" must be a non-empty string.`,\n\t\t),\n\t);\n\treturn undefined;\n}\n\nfunction normalizeChainContext(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): \"summary\" | undefined {\n\tif (value === undefined) return undefined;\n\tif (typeof value === \"string\") {\n\t\tconst normalized = value.trim().toLowerCase();\n\t\tif (normalized === \"summary\") return \"summary\";\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-chain-context\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Ignoring invalid chainContext value in ${filePath}: frontmatter field \"chainContext\" must be \"summary\".`,\n\t\t),\n\t);\n\treturn undefined;\n}\n\nfunction normalizeThinking(\n\tvalue: unknown,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): ThinkingLevel | undefined {\n\tconst thinking = normalizeStringField(\"thinking\", value, filePath, source, diagnostics);\n\tif (thinking === undefined) return undefined;\n\n\tconst normalized = thinking.toLowerCase();\n\tif ((VALID_THINKING_LEVELS as readonly string[]).includes(normalized)) {\n\t\treturn normalized as ThinkingLevel;\n\t}\n\n\tdiagnostics.push(\n\t\tcreateDiagnostic(\n\t\t\t\"invalid-thinking\",\n\t\t\tfilePath,\n\t\t\tsource,\n\t\t\t`Ignoring invalid thinking level in ${filePath}: ${JSON.stringify(thinking)}.`,\n\t\t),\n\t);\n\treturn undefined;\n}\n\nfunction normalizeThinkingLevels(\n\tvalue: unknown,\n\tmodelCount: number,\n\tfilePath: string,\n\tsource: PromptSource,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): ThinkingLevel[] | undefined {\n\tif (typeof value !== \"string\") return undefined;\n\n\tconst levels = value\n\t\t.split(\",\")\n\t\t.map((item) => item.trim())\n\t\t.filter(Boolean);\n\n\tconst invalidLevel = levels.find((level) => !(VALID_THINKING_LEVELS as readonly string[]).includes(level.toLowerCase()));\n\tif (invalidLevel) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-thinking-levels\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring invalid thinking level in ${filePath}: ${JSON.stringify(invalidLevel)}.`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\tif (levels.length !== modelCount) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-thinking-level-count\",\n\t\t\t\tfilePath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring comma-separated thinking levels in ${filePath}: expected ${modelCount} entries to match frontmatter field \"model\".`,\n\t\t\t),\n\t\t);\n\t\treturn undefined;\n\t}\n\n\treturn levels.map((level) => level.toLowerCase() as ThinkingLevel);\n}\n\ninterface ConfiguredPromptPath {\n\trawPath: string;\n\tresolvedPath: string;\n\tsettingsPath: string;\n\tsource: PromptSource;\n\tbaseDir: string;\n\tpatterns: string[];\n}\n\ninterface ConfiguredPromptPaths {\n\tpaths: ConfiguredPromptPath[];\n\tpatterns: string[];\n}\n\nfunction expandConfiguredPromptPath(rawPath: string, baseDir: string): string {\n\tconst trimmed = rawPath.trim();\n\tconst expanded = trimmed === \"~\" ? homedir() : trimmed.startsWith(\"~/\") ? join(homedir(), trimmed.slice(2)) : trimmed;\n\treturn isAbsolute(expanded) ? resolve(expanded) : resolve(baseDir, expanded);\n}\n\nfunction isSettingsPromptPattern(value: string): boolean {\n\treturn value.startsWith(\"!\") || value.startsWith(\"+\") || value.startsWith(\"-\") || value.includes(\"*\") || value.includes(\"?\");\n}\n\nfunction isSettingsPromptOverridePattern(value: string): boolean {\n\treturn value.startsWith(\"!\") || value.startsWith(\"+\") || value.startsWith(\"-\");\n}\n\nfunction toPosixPath(path: string): string {\n\treturn path.replace(/\\\\/g, \"/\");\n}\n\nfunction normalizeExactPromptPattern(pattern: string): string {\n\tconst normalized = pattern.startsWith(\"./\") || pattern.startsWith(\".\\\\\") ? pattern.slice(2) : pattern;\n\treturn toPosixPath(normalized);\n}\n\nfunction matchesPromptPattern(filePath: string, pattern: string, baseDir: string): boolean {\n\tconst normalizedPattern = toPosixPath(pattern);\n\tconst rel = toPosixPath(relative(baseDir, filePath));\n\tconst name = basename(filePath);\n\tconst filePathPosix = toPosixPath(filePath);\n\treturn [rel, name, filePathPosix].some((candidate) => minimatch(candidate, normalizedPattern));\n}\n\nfunction matchesExactPromptPattern(filePath: string, pattern: string, baseDir: string): boolean {\n\tconst normalizedPattern = normalizeExactPromptPattern(pattern);\n\tconst rel = toPosixPath(relative(baseDir, filePath));\n\tconst filePathPosix = toPosixPath(filePath);\n\treturn normalizedPattern === rel || normalizedPattern === filePathPosix;\n}\n\nfunction shouldLoadPromptFile(filePath: string, patterns: string[], baseDir: string): boolean {\n\tconst includes: string[] = [];\n\tconst excludes: string[] = [];\n\tconst forceIncludes: string[] = [];\n\tconst forceExcludes: string[] = [];\n\n\tfor (const pattern of patterns) {\n\t\tif (pattern.startsWith(\"+\")) {\n\t\t\tforceIncludes.push(pattern.slice(1));\n\t\t} else if (pattern.startsWith(\"-\")) {\n\t\t\tforceExcludes.push(pattern.slice(1));\n\t\t} else if (pattern.startsWith(\"!\")) {\n\t\t\texcludes.push(pattern.slice(1));\n\t\t} else {\n\t\t\tincludes.push(pattern);\n\t\t}\n\t}\n\n\tlet enabled = includes.length === 0 || includes.some((pattern) => matchesPromptPattern(filePath, pattern, baseDir));\n\tif (excludes.some((pattern) => matchesPromptPattern(filePath, pattern, baseDir))) enabled = false;\n\tif (forceIncludes.some((pattern) => matchesExactPromptPattern(filePath, pattern, baseDir))) enabled = true;\n\tif (forceExcludes.some((pattern) => matchesExactPromptPattern(filePath, pattern, baseDir))) enabled = false;\n\treturn enabled;\n}\n\nfunction createPromptFileFilter(patterns: string[], baseDir: string): ((filePath: string) => boolean) | undefined {\n\treturn patterns.length === 0 ? undefined : (filePath) => shouldLoadPromptFile(filePath, patterns, baseDir);\n}\n\nfunction loadConfiguredPromptPaths(\n\tsettingsPath: string,\n\tsource: PromptSource,\n\tbaseDir: string,\n\tdiagnostics: PromptLoaderDiagnostic[],\n): ConfiguredPromptPaths {\n\tif (!existsSync(settingsPath)) return { paths: [], patterns: [] };\n\n\tlet rawSettings: string;\n\ttry {\n\t\trawSettings = readFileSync(settingsPath, \"utf-8\");\n\t} catch (error) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"unreadable-settings\",\n\t\t\t\tsettingsPath,\n\t\t\t\tsource,\n\t\t\t\t`Skipping prompt settings at ${settingsPath}: ${error instanceof Error ? error.message : String(error)}.`,\n\t\t\t),\n\t\t);\n\t\treturn { paths: [], patterns: [] };\n\t}\n\n\tlet parsed: unknown;\n\ttry {\n\t\tparsed = JSON.parse(rawSettings);\n\t} catch (error) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-settings-json\",\n\t\t\t\tsettingsPath,\n\t\t\t\tsource,\n\t\t\t\t`Skipping prompt settings at ${settingsPath}: ${error instanceof Error ? error.message : String(error)}.`,\n\t\t\t),\n\t\t);\n\t\treturn { paths: [], patterns: [] };\n\t}\n\n\tif (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-settings\",\n\t\t\t\tsettingsPath,\n\t\t\t\tsource,\n\t\t\t\t`Skipping prompt settings at ${settingsPath}: settings must be a JSON object.`,\n\t\t\t),\n\t\t);\n\t\treturn { paths: [], patterns: [] };\n\t}\n\n\tconst prompts = (parsed as Record<string, unknown>).prompts;\n\tif (prompts === undefined) return { paths: [], patterns: [] };\n\tif (!Array.isArray(prompts)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-settings-prompts\",\n\t\t\t\tsettingsPath,\n\t\t\t\tsource,\n\t\t\t\t`Ignoring prompts in ${settingsPath}: expected \"prompts\" to be an array of strings.`,\n\t\t\t),\n\t\t);\n\t\treturn { paths: [], patterns: [] };\n\t}\n\n\tconst configuredPaths: Omit<ConfiguredPromptPath, \"patterns\">[] = [];\n\tconst patterns: string[] = [];\n\tfor (let index = 0; index < prompts.length; index++) {\n\t\tconst rawPath = prompts[index];\n\t\tif (typeof rawPath !== \"string\" || rawPath.trim().length === 0) {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\"invalid-settings-prompt-entry\",\n\t\t\t\t\tsettingsPath,\n\t\t\t\t\tsource,\n\t\t\t\t\t`Ignoring prompts[${index}] in ${settingsPath}: expected a non-empty string.`,\n\t\t\t\t),\n\t\t\t);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst trimmed = rawPath.trim();\n\t\tif (isSettingsPromptPattern(trimmed)) {\n\t\t\tpatterns.push(trimmed);\n\t\t\tcontinue;\n\t\t}\n\t\tconfiguredPaths.push({\n\t\t\trawPath: trimmed,\n\t\t\tresolvedPath: expandConfiguredPromptPath(trimmed, baseDir),\n\t\t\tsettingsPath,\n\t\t\tsource,\n\t\t\tbaseDir,\n\t\t});\n\t}\n\n\treturn { paths: configuredPaths.map((path) => ({ ...path, patterns })), patterns };\n}\n\nfunction canonicalizePromptFile(filePath: string): string {\n\ttry {\n\t\treturn realpathSync(filePath);\n\t} catch {\n\t\treturn resolve(filePath);\n\t}\n}\n\nfunction loadPromptsWithModelFromDir(\n\tdir: string,\n\tsource: PromptSource,\n\tincludePlainPrompts: boolean,\n\tsubdir = \"\",\n\tvisitedDirectories = new Set<string>(),\n\tonlyFileName?: string,\n\tseenFiles?: Set<string>,\n\tshouldLoadFile?: (filePath: string) => boolean,\n): { prompts: PromptWithModel[]; diagnostics: PromptLoaderDiagnostic[] } {\n\tconst prompts: PromptWithModel[] = [];\n\tconst diagnostics: PromptLoaderDiagnostic[] = [];\n\n\tif (!existsSync(dir)) {\n\t\treturn { prompts, diagnostics };\n\t}\n\n\tlet canonicalDir: string;\n\ttry {\n\t\tcanonicalDir = realpathSync(dir);\n\t} catch (error) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"unreadable-directory\",\n\t\t\t\tdir,\n\t\t\t\tsource,\n\t\t\t\t`Skipping prompt directory ${dir}: ${error instanceof Error ? error.message : String(error)}.`,\n\t\t\t),\n\t\t);\n\t\treturn { prompts, diagnostics };\n\t}\n\n\tif (visitedDirectories.has(canonicalDir)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"directory-cycle\",\n\t\t\t\tdir,\n\t\t\t\tsource,\n\t\t\t\t`Skipping already visited prompt directory at ${dir}.`,\n\t\t\t),\n\t\t);\n\t\treturn { prompts, diagnostics };\n\t}\n\n\tvisitedDirectories.add(canonicalDir);\n\n\ttry {\n\t\tconst entries = readdirSync(dir, { withFileTypes: true }).sort((a, b) => lexicalCompare(a.name, b.name));\n\n\t\tfor (const entry of entries) {\n\t\t\tif (onlyFileName && entry.name !== onlyFileName) continue;\n\t\t\tconst fullPath = join(dir, entry.name);\n\n\t\t\tlet isFile = entry.isFile();\n\t\t\tlet isDirectory = entry.isDirectory();\n\t\t\tif (entry.isSymbolicLink()) {\n\t\t\t\ttry {\n\t\t\t\t\tconst stats = statSync(fullPath);\n\t\t\t\t\tisFile = stats.isFile();\n\t\t\t\t\tisDirectory = stats.isDirectory();\n\t\t\t\t} catch (error) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"unreadable-symlink\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Skipping unreadable symlink at ${fullPath}: ${error instanceof Error ? error.message : String(error)}.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (isDirectory) {\n\t\t\t\tif (onlyFileName) continue;\n\t\t\t\tconst nextSubdir = subdir ? `${subdir}:${entry.name}` : entry.name;\n\t\t\t\tconst nested = loadPromptsWithModelFromDir(fullPath, source, includePlainPrompts, nextSubdir, visitedDirectories, undefined, seenFiles, shouldLoadFile);\n\t\t\t\tprompts.push(...nested.prompts);\n\t\t\t\tdiagnostics.push(...nested.diagnostics);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (!isFile || !entry.name.endsWith(\".md\")) continue;\n\t\t\tif (shouldLoadFile && !shouldLoadFile(fullPath)) continue;\n\t\t\tconst canonicalFile = canonicalizePromptFile(fullPath);\n\t\t\tif (seenFiles?.has(canonicalFile)) continue;\n\t\t\tseenFiles?.add(canonicalFile);\n\n\t\t\ttry {\n\t\t\t\tconst rawContent = readFileSync(fullPath, \"utf-8\");\n\t\t\t\tconst parsed = parseFrontmatter<Record<string, unknown>>(rawContent);\n\t\t\t\tconst frontmatter = normalizeFrontmatterRecord(parsed.frontmatter, fullPath, source, diagnostics);\n\t\t\t\tif (!frontmatter) continue;\n\t\t\t\tconst { body } = parsed;\n\t\t\t\tconst chain = normalizeChain(frontmatter.chain, fullPath, source, diagnostics);\n\t\t\t\tlet parsedChainDeclarationResult:\n\t\t\t\t\t| ReturnType<typeof parseChainDeclaration>\n\t\t\t\t\t| undefined;\n\t\t\t\tconst chainContext = chain ? normalizeChainContext(frontmatter.chainContext, fullPath, source, diagnostics) : undefined;\n\t\t\t\tif (chain && /\\bparallel\\s*\\(/.test(chain)) {\n\t\t\t\t\tparsedChainDeclarationResult = parseChainDeclaration(chain);\n\t\t\t\t\tif (parsedChainDeclarationResult.invalidSegments.length > 0 || parsedChainDeclarationResult.steps.length === 0) {\n\t\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\t\"invalid-chain-declaration\",\n\t\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t\t`Skipping prompt template at ${fullPath}: invalid chain declaration segment ${JSON.stringify(parsedChainDeclarationResult.invalidSegments[0] ?? chain)}.`,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tlet subagent = normalizeSubagent(frontmatter.subagent, fullPath, source, diagnostics);\n\t\t\t\tconst cwd = normalizeCwd(frontmatter.cwd, fullPath, source, diagnostics);\n\t\t\t\tconst inheritContext = normalizeInheritContext(frontmatter.inheritContext, fullPath, source, diagnostics);\n\t\t\t\tconst parallel = normalizeParallel(frontmatter.parallel, fullPath, source, diagnostics);\n\t\t\t\tconst hasBestOfN = Object.hasOwn(frontmatter, \"bestOfN\");\n\t\t\t\tconst bestOfN = normalizeBestOfN(frontmatter.bestOfN, fullPath, source, diagnostics);\n\t\t\t\tlet deterministic = normalizeDeterministic(frontmatter, fullPath, source, diagnostics);\n\t\t\t\tconst hasLegacyWorkers = Object.hasOwn(frontmatter, \"workers\");\n\t\t\t\tconst hasLegacyReviewers = Object.hasOwn(frontmatter, \"reviewers\");\n\t\t\t\tconst hasLegacyFinalApplier = Object.hasOwn(frontmatter, \"finalApplier\");\n\t\t\t\tconst hasLegacyCompareFields = hasLegacyWorkers || hasLegacyReviewers || hasLegacyFinalApplier;\n\t\t\t\tif (hasLegacyWorkers) {\n\t\t\t\t\tpushLegacyCompareFieldDiagnostic(\"workers\", fullPath, source, diagnostics);\n\t\t\t\t}\n\t\t\t\tif (hasLegacyReviewers) {\n\t\t\t\t\tpushLegacyCompareFieldDiagnostic(\"reviewers\", fullPath, source, diagnostics);\n\t\t\t\t}\n\t\t\t\tif (hasLegacyFinalApplier) {\n\t\t\t\t\tpushLegacyCompareFieldDiagnostic(\"finalApplier\", fullPath, source, diagnostics);\n\t\t\t\t}\n\t\t\t\tif (hasBestOfN && Object.hasOwn(frontmatter, \"worktree\")) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-worktree\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring top-level worktree in ${fullPath}: use \"bestOfN.worktree\" for compare template authoring.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tconst workers = normalizeLineup(hasBestOfN ? bestOfN?.workers : undefined, \"workers\", fullPath, source, diagnostics);\n\t\t\t\tconst reviewers = normalizeLineup(hasBestOfN ? bestOfN?.reviewers : undefined, \"reviewers\", fullPath, source, diagnostics);\n\t\t\t\tconst finalApplier = normalizeFinalApplier(hasBestOfN ? bestOfN?.finalApplier : undefined, fullPath, source, diagnostics);\n\t\t\t\tlet safeWorkers = workers;\n\t\t\t\tlet safeReviewers = reviewers;\n\t\t\t\tlet safeFinalApplier = finalApplier;\n\t\t\t\tif (chain && subagent !== undefined) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-subagent-chain\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring subagent in ${fullPath}: frontmatter fields \"chain\" and \"subagent\" cannot be combined.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tsubagent = undefined;\n\t\t\t\t}\n\t\t\t\tif (chain && deterministic !== undefined) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-deterministic-chain\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring deterministic config in ${fullPath}: frontmatter field \"deterministic\" cannot be combined with \"chain\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tdeterministic = undefined;\n\t\t\t\t}\n\t\t\t\tif (chain && (safeWorkers !== undefined || safeReviewers !== undefined || safeFinalApplier !== undefined)) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-lineup-chain\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring compare lineup config in ${fullPath}: frontmatter fields \"workers\"/\"reviewers\"/\"finalApplier\" cannot be combined with \"chain\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tsafeWorkers = undefined;\n\t\t\t\t\tsafeReviewers = undefined;\n\t\t\t\t\tsafeFinalApplier = undefined;\n\t\t\t\t}\n\t\t\t\tif (subagent !== undefined && (safeWorkers !== undefined || safeReviewers !== undefined || safeFinalApplier !== undefined)) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-lineup-subagent\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring compare lineup config in ${fullPath}: frontmatter fields \"workers\"/\"reviewers\"/\"finalApplier\" cannot be combined with \"subagent\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tsafeWorkers = undefined;\n\t\t\t\t\tsafeReviewers = undefined;\n\t\t\t\t\tsafeFinalApplier = undefined;\n\t\t\t\t}\n\t\t\t\tif (subagent !== undefined && deterministic !== undefined) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-deterministic-subagent\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring deterministic config in ${fullPath}: frontmatter field \"deterministic\" cannot be combined with \"subagent\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tdeterministic = undefined;\n\t\t\t\t}\n\t\t\t\tif (subagent === undefined && inheritContext) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-inherit-context\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring inheritContext in ${fullPath}: frontmatter field \"inheritContext\" requires \"subagent\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tlet safeParallel = parallel;\n\t\t\t\tif (safeParallel !== undefined && chain) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-parallel\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring parallel in ${fullPath}: frontmatter field \"parallel\" cannot be combined with \"chain\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tsafeParallel = undefined;\n\t\t\t\t}\n\t\t\t\tif (safeParallel !== undefined && subagent === undefined) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-parallel\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring parallel in ${fullPath}: frontmatter field \"parallel\" requires \"subagent\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tsafeParallel = undefined;\n\t\t\t\t}\n\t\t\t\tif (safeParallel !== undefined && (safeWorkers !== undefined || safeReviewers !== undefined || safeFinalApplier !== undefined)) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-lineup-parallel\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring compare lineup config in ${fullPath}: frontmatter fields \"workers\"/\"reviewers\"/\"finalApplier\" cannot be combined with \"parallel\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tsafeWorkers = undefined;\n\t\t\t\t\tsafeReviewers = undefined;\n\t\t\t\t\tsafeFinalApplier = undefined;\n\t\t\t\t}\n\t\t\t\tif (safeParallel !== undefined && deterministic !== undefined) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-deterministic-parallel\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring deterministic config in ${fullPath}: frontmatter field \"deterministic\" cannot be combined with \"parallel\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tdeterministic = undefined;\n\t\t\t\t}\n\t\t\t\tconst hasLineup = safeWorkers !== undefined || safeReviewers !== undefined || safeFinalApplier !== undefined;\n\t\t\t\tif (!hasBestOfN && hasLegacyCompareFields) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-compare-frontmatter\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Skipping prompt template at ${fullPath}: compare template authoring moved under \"bestOfN:\".`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (hasBestOfN && !hasLineup) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-best-of-n\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Skipping prompt template at ${fullPath}: \"bestOfN\" did not produce a valid compare configuration.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (!chain && subagent === undefined && !hasLineup && cwd) {\n\t\t\t\t\tif (deterministic) {\n\t\t\t\t\t\tdeterministic = { ...deterministic, ...(deterministic.cwd ? {} : { cwd }) };\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\t\"invalid-cwd\",\n\t\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t\t`Ignoring cwd in ${fullPath}: frontmatter field \"cwd\" requires \"subagent\", \"chain\", or compare lineups (\"workers\"/\"reviewers\"/\"finalApplier\").`,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst hasModelField = Object.hasOwn(frontmatter, \"model\");\n\t\t\t\tconst parsedModels = chain ? [] : normalizeModelSpecs(frontmatter.model, fullPath, source, diagnostics);\n\t\t\t\tif (!chain && hasModelField && !parsedModels) continue;\n\t\t\t\tconst models = chain ? [] : (parsedModels ?? []);\n\t\t\t\tconst rotate = chain ? false : normalizeRotate(frontmatter.rotate, fullPath, source, diagnostics);\n\n\t\t\t\tconst name = entry.name.slice(0, -3);\n\t\t\t\tif (RESERVED_COMMAND_NAMES.has(name)) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"reserved-command-name\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Skipping prompt template at ${fullPath}: command name \"${name}\" is reserved.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tconst safeInheritContext = subagent !== undefined && inheritContext;\n\t\t\t\tconst safeCwd = (chain || subagent !== undefined || hasLineup) ? cwd : undefined;\n\t\t\t\tconst description = normalizeStringField(\"description\", frontmatter.description, fullPath, source, diagnostics) ?? \"\";\n\t\t\t\tconst skill = chain ? undefined : normalizeStringField(\"skill\", frontmatter.skill, fullPath, source, diagnostics);\n\t\t\t\tlet thinking: ThinkingLevel | undefined;\n\t\t\t\tlet thinkingLevels: ThinkingLevel[] | undefined;\n\t\t\t\tif (!chain) {\n\t\t\t\t\tif (rotate && typeof frontmatter.thinking === \"string\" && frontmatter.thinking.includes(\",\")) {\n\t\t\t\t\t\tthinkingLevels = normalizeThinkingLevels(frontmatter.thinking, models.length, fullPath, source, diagnostics);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthinking = normalizeThinking(frontmatter.thinking, fullPath, source, diagnostics);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst restore = normalizeRestore(frontmatter.restore, fullPath, source, diagnostics);\n\t\t\t\tconst fresh = normalizeFresh(frontmatter.fresh, fullPath, source, diagnostics);\n\t\t\t\tconst loop = normalizeLoop(frontmatter.loop, fullPath, source, diagnostics);\n\t\t\t\tconst converge = normalizeConverge(frontmatter.converge, fullPath, source, diagnostics);\n\t\t\t\tlet boomerang = normalizeBoomerang(frontmatter.boomerang, fullPath, source, diagnostics);\n\t\t\t\tif (chain && boomerang) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-boomerang-chain\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring boomerang in ${fullPath}: frontmatter fields \"chain\" and \"boomerang\" cannot be combined.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tboomerang = false;\n\t\t\t\t}\n\t\t\t\tif (loop !== undefined && deterministic !== undefined) {\n\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\"invalid-deterministic-loop\",\n\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t`Ignoring deterministic config in ${fullPath}: frontmatter field \"deterministic\" cannot be combined with \"loop\" in v1.`,\n\t\t\t\t\t\t),\n\t\t\t\t\t);\n\t\t\t\t\tdeterministic = undefined;\n\t\t\t\t}\n\t\t\t\tconst worktreeInput = hasBestOfN ? bestOfN?.worktree : frontmatter.worktree;\n\t\t\t\tconst worktree = normalizeWorktree(worktreeInput, fullPath, source, diagnostics);\n\t\t\t\tlet safeWorktree: boolean | undefined;\n\t\t\t\tif (worktree) {\n\t\t\t\t\tif (chain) {\n\t\t\t\t\t\tconst parsedChain = parsedChainDeclarationResult ?? parseChainDeclaration(chain);\n\t\t\t\t\t\tconst hasParallelStep = parsedChain.steps.some((step) => \"parallel\" in step);\n\t\t\t\t\t\tif (parsedChain.invalidSegments.length > 0 || parsedChain.steps.length === 0 || !hasParallelStep) {\n\t\t\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\t\t\"invalid-worktree\",\n\t\t\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t\t\t`Ignoring worktree in ${fullPath}: frontmatter field \"worktree\" requires either \"chain\" with at least one parallel() step, \"subagent\" with frontmatter field \"parallel\", or compare lineups (\"workers\"/\"reviewers\"/\"finalApplier\").`,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tsafeWorktree = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (subagent !== undefined && safeParallel !== undefined) {\n\t\t\t\t\t\tsafeWorktree = true;\n\t\t\t\t\t} else if (hasLineup) {\n\t\t\t\t\t\tsafeWorktree = true;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdiagnostics.push(\n\t\t\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\t\t\"invalid-worktree\",\n\t\t\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\t\t\tsource,\n\t\t\t\t\t\t\t\t`Ignoring worktree in ${fullPath}: frontmatter field \"worktree\" requires either \"chain\" with at least one parallel() step, \"subagent\" with frontmatter field \"parallel\", or compare lineups (\"workers\"/\"reviewers\"/\"finalApplier\").`,\n\t\t\t\t\t\t\t),\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tconst hasModelConditionalDirectives = /<if-model(?:\\s|>)|<else(?:\\s|>)|<\\/if-model\\s*>|<\\/else(?:\\s|>)/.test(body);\n\t\t\t\tconst hasExtensionSpecificConfig =\n\t\t\t\t\tskill !== undefined ||\n\t\t\t\t\tthinking !== undefined ||\n\t\t\t\t\tfresh === true ||\n\t\t\t\t\tloop !== undefined ||\n\t\t\t\t\tconverge === false ||\n\t\t\t\t\tboomerang === true ||\n\t\t\t\t\tsafeParallel !== undefined ||\n\t\t\t\t\tdeterministic !== undefined ||\n\t\t\t\t\thasLineup ||\n\t\t\t\t\tsafeWorktree === true ||\n\t\t\t\t\tsubagent !== undefined ||\n\t\t\t\t\tsafeInheritContext ||\n\t\t\t\t\thasModelConditionalDirectives;\n\t\t\t\tif (!chain && !hasModelField && !hasExtensionSpecificConfig && !includePlainPrompts) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tprompts.push({\n\t\t\t\t\tname,\n\t\t\t\t\tdescription,\n\t\t\t\t\tcontent: body,\n\t\t\t\t\tmodels,\n\t\t\t\t\tchain: chain || undefined,\n\t\t\t\t\tchainContext,\n\t\t\t\t\trestore,\n\t\t\t\t\tskill,\n\t\t\t\t\tthinking,\n\t\t\t\t\tthinkingLevels,\n\t\t\t\t\trotate: rotate || undefined,\n\t\t\t\t\tfresh: fresh || undefined,\n\t\t\t\t\tloop: loop !== undefined ? loop : undefined,\n\t\t\t\t\tconverge: converge === false ? false : undefined,\n\t\t\t\t\tboomerang: boomerang || undefined,\n\t\t\t\t\tparallel: safeParallel,\n\t\t\t\t\tworktree: safeWorktree,\n\t\t\t\t\tdeterministic,\n\t\t\t\t\tsubagent,\n\t\t\t\t\tinheritContext: safeInheritContext || undefined,\n\t\t\t\t\tcwd: safeCwd || undefined,\n\t\t\t\t\tworkers: safeWorkers,\n\t\t\t\t\treviewers: safeReviewers,\n\t\t\t\t\tfinalApplier: safeFinalApplier,\n\t\t\t\t\tsource,\n\t\t\t\t\tsubdir: subdir || undefined,\n\t\t\t\t\tfilePath: fullPath,\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tdiagnostics.push(\n\t\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\t\"invalid-prompt-file\",\n\t\t\t\t\t\tfullPath,\n\t\t\t\t\t\tsource,\n\t\t\t\t\t\t`Skipping prompt template at ${fullPath}: ${error instanceof Error ? error.message : String(error)}.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t} catch (error) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"unreadable-directory\",\n\t\t\t\tdir,\n\t\t\t\tsource,\n\t\t\t\t`Skipping prompt directory ${dir}: ${error instanceof Error ? error.message : String(error)}.`,\n\t\t\t),\n\t\t);\n\t}\n\n\treturn { prompts, diagnostics };\n}\n\nfunction loadPromptsWithModelFromConfiguredPath(\n\tconfiguredPath: ConfiguredPromptPath,\n\tincludePlainPrompts: boolean,\n\tseenFiles: Set<string>,\n): { prompts: PromptWithModel[]; diagnostics: PromptLoaderDiagnostic[] } {\n\tconst diagnostics: PromptLoaderDiagnostic[] = [];\n\tconst { rawPath, resolvedPath, settingsPath, source, baseDir, patterns } = configuredPath;\n\tconst shouldLoadFile = createPromptFileFilter(patterns, baseDir);\n\n\tif (!existsSync(resolvedPath)) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"missing-prompt-path\",\n\t\t\t\tresolvedPath,\n\t\t\t\tsource,\n\t\t\t\t`Skipping configured prompt path ${JSON.stringify(rawPath)} from ${settingsPath}: resolved path ${resolvedPath} does not exist.`,\n\t\t\t),\n\t\t);\n\t\treturn { prompts: [], diagnostics };\n\t}\n\n\tlet stats: ReturnType<typeof statSync>;\n\ttry {\n\t\tstats = statSync(resolvedPath);\n\t} catch (error) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"unreadable-prompt-path\",\n\t\t\t\tresolvedPath,\n\t\t\t\tsource,\n\t\t\t\t`Skipping configured prompt path ${JSON.stringify(rawPath)} from ${settingsPath}: ${error instanceof Error ? error.message : String(error)}.`,\n\t\t\t),\n\t\t);\n\t\treturn { prompts: [], diagnostics };\n\t}\n\n\tif (stats.isDirectory()) {\n\t\treturn loadPromptsWithModelFromDir(resolvedPath, source, includePlainPrompts, \"\", new Set<string>(), undefined, seenFiles, shouldLoadFile);\n\t}\n\n\tif (!stats.isFile() || !resolvedPath.endsWith(\".md\")) {\n\t\tdiagnostics.push(\n\t\t\tcreateDiagnostic(\n\t\t\t\t\"invalid-prompt-path\",\n\t\t\t\tresolvedPath,\n\t\t\t\tsource,\n\t\t\t\t`Skipping configured prompt path ${JSON.stringify(rawPath)} from ${settingsPath}: expected a directory or .md file.`,\n\t\t\t),\n\t\t);\n\t\treturn { prompts: [], diagnostics };\n\t}\n\n\treturn loadPromptsWithModelFromDir(dirname(resolvedPath), source, includePlainPrompts, \"\", new Set<string>(), basename(resolvedPath), seenFiles, shouldLoadFile);\n}\n\nexport function loadPromptsWithModel(cwd: string, includePlainPrompts = false): LoadPromptsWithModelResult {\n\tconst agentDir = getAgentDir();\n\tconst globalDir = join(agentDir, \"prompts\");\n\tconst projectBaseDir = resolve(cwd, CONFIG_DIR_NAME);\n\tconst projectDir = join(projectBaseDir, \"prompts\");\n\tconst promptMap = new Map<string, PromptWithModel>();\n\tconst diagnostics: PromptLoaderDiagnostic[] = [];\n\tconst seenPromptFiles = new Set<string>();\n\n\tfunction addPrompt(prompt: PromptWithModel) {\n\t\tconst existing = promptMap.get(prompt.name);\n\t\tif (!existing) {\n\t\t\tpromptMap.set(prompt.name, prompt);\n\t\t\treturn;\n\t\t}\n\n\t\tif (existing.source === prompt.source) {\n\t\t\tdiagnostics.push(\n\t\t\t\tcreateDiagnostic(\n\t\t\t\t\t\"duplicate-command-name\",\n\t\t\t\t\tprompt.filePath,\n\t\t\t\t\tprompt.source,\n\t\t\t\t\t`Skipping ${prompt.source} prompt template \"${prompt.name}\" at ${prompt.filePath} because it conflicts with ${existing.filePath}.`,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\t}\n\n\tfunction addResult(result: { prompts: PromptWithModel[]; diagnostics: PromptLoaderDiagnostic[] }) {\n\t\tdiagnostics.push(...result.diagnostics);\n\t\tfor (const prompt of result.prompts) {\n\t\t\taddPrompt(prompt);\n\t\t}\n\t}\n\n\tconst projectSettingsPaths = loadConfiguredPromptPaths(join(projectBaseDir, \"settings.json\"), \"project\", projectBaseDir, diagnostics);\n\tconst globalSettingsPaths = loadConfiguredPromptPaths(join(agentDir, \"settings.json\"), \"user\", agentDir, diagnostics);\n\tconst projectDefaultFilter = createPromptFileFilter(projectSettingsPaths.patterns.filter(isSettingsPromptOverridePattern), projectBaseDir);\n\tconst globalDefaultFilter = createPromptFileFilter(globalSettingsPaths.patterns.filter(isSettingsPromptOverridePattern), agentDir);\n\n\tfor (const configuredPath of projectSettingsPaths.paths) {\n\t\taddResult(loadPromptsWithModelFromConfiguredPath(configuredPath, includePlainPrompts, seenPromptFiles));\n\t}\n\taddResult(loadPromptsWithModelFromDir(projectDir, \"project\", includePlainPrompts, \"\", new Set<string>(), undefined, seenPromptFiles, projectDefaultFilter));\n\tfor (const configuredPath of globalSettingsPaths.paths) {\n\t\taddResult(loadPromptsWithModelFromConfiguredPath(configuredPath, includePlainPrompts, seenPromptFiles));\n\t}\n\taddResult(loadPromptsWithModelFromDir(globalDir, \"user\", includePlainPrompts, \"\", new Set<string>(), undefined, seenPromptFiles, globalDefaultFilter));\n\n\treturn { prompts: promptMap, diagnostics };\n}\n\nfunction effectiveLineupCount(slots: DelegationLineupSlot[] | undefined): number {\n\treturn slots?.reduce((total, slot) => total + (slot.count ?? 1), 0) ?? 0;\n}\n\nexport function buildPromptCommandDescription(prompt: PromptWithModel): string {\n\tconst sourceLabel = prompt.subdir ? `(${prompt.source}:${prompt.subdir})` : `(${prompt.source})`;\n\tif (prompt.chain) {\n\t\tconst chainContextLabel = prompt.chainContext ? ` ${prompt.chainContext}` : \"\";\n\t\tconst cwdLabel = prompt.cwd ? ` cwd:${prompt.cwd}` : \"\";\n\t\tconst worktreeLabel = prompt.worktree ? \" worktree\" : \"\";\n\t\tconst details = `[chain: ${prompt.chain}${chainContextLabel}${cwdLabel}${worktreeLabel}] ${sourceLabel}`;\n\t\treturn prompt.description ? `${prompt.description} ${details}` : details;\n\t}\n\tconst modelLabel = prompt.models.length > 0 ? prompt.models.map((model) => model.split(\"/\").pop() || model).join(\"|\") : \"current\";\n\tconst rotateLabel = prompt.rotate ? \" rotate\" : \"\";\n\tconst skillLabel = prompt.skill ? ` +${prompt.skill}` : \"\";\n\tconst thinkingValue = prompt.thinkingLevels ? prompt.thinkingLevels.join(\",\") : prompt.thinking;\n\tconst thinkingLabel = thinkingValue ? ` ${thinkingValue}` : \"\";\n\tconst loopLabel = prompt.loop !== undefined ? ` loop:${prompt.loop === null ? \"unlimited\" : prompt.loop}` : \"\";\n\tconst boomerangLabel = prompt.boomerang ? \" boomerang\" : \"\";\n\tconst subagentLabel = prompt.subagent ? ` subagent:${prompt.subagent === true ? \"delegate\" : prompt.subagent}` : \"\";\n\tconst parallelLabel = prompt.parallel !== undefined ? ` parallel:${prompt.parallel}` : \"\";\n\tconst deterministicLabel = prompt.deterministic ? ` deterministic-step:${prompt.deterministic.handoff}` : \"\";\n\tconst workersLabel = prompt.workers ? ` workers:${effectiveLineupCount(prompt.workers)}` : \"\";\n\tconst reviewersLabel = prompt.reviewers ? ` reviewers:${effectiveLineupCount(prompt.reviewers)}` : \"\";\n\tconst finalApplierLabel = prompt.finalApplier ? \" final-applier\" : \"\";\n\tconst cwdLabel = prompt.cwd ? ` cwd:${prompt.cwd}` : \"\";\n\tconst inheritContextLabel = prompt.inheritContext ? \" fork\" : \"\";\n\tconst worktreeLabel = prompt.worktree ? \" worktree\" : \"\";\n\tconst details =\n\t\t`[${modelLabel}${rotateLabel}${thinkingLabel}${skillLabel}${loopLabel}${boomerangLabel}${subagentLabel}${parallelLabel}${deterministicLabel}${workersLabel}${reviewersLabel}${finalApplierLabel}${cwdLabel}${inheritContextLabel}${worktreeLabel}] ${sourceLabel}`;\n\treturn prompt.description ? `${prompt.description} ${details}` : details;\n}\n\nfunction getSkillCandidates(baseDir: string, skillName: string): string[] {\n\treturn [join(baseDir, skillName, \"SKILL.md\"), join(baseDir, `${skillName}.md`)];\n}\n\nfunction* walkAncestors(startDir: string, stopDir?: string): Generator<string> {\n\tlet current = startDir;\n\twhile (true) {\n\t\tyield current;\n\t\tif (stopDir && current === stopDir) return;\n\t\tconst parent = dirname(current);\n\t\tif (parent === current) return;\n\t\tcurrent = parent;\n\t}\n}\n\nfunction findRepoRoot(startDir: string): string | undefined {\n\tfor (const dir of walkAncestors(startDir)) {\n\t\tif (existsSync(join(dir, \".git\"))) return dir;\n\t}\n\treturn undefined;\n}\n\nfunction findFirstExisting(paths: string[]): string | undefined {\n\tfor (const path of paths) {\n\t\tif (existsSync(path)) return path;\n\t}\n\treturn undefined;\n}\n\nexport function resolveSkillPath(skillName: string, cwd: string): string | undefined {\n\tconst projectDir = resolve(cwd);\n\n\tconst projectPiSkill = findFirstExisting(getSkillCandidates(resolve(projectDir, CONFIG_DIR_NAME, \"skills\"), skillName));\n\tif (projectPiSkill) return projectPiSkill;\n\n\tconst repoRoot = findRepoRoot(projectDir);\n\tfor (const dir of walkAncestors(projectDir, repoRoot)) {\n\t\tconst projectAgentsSkill = findFirstExisting(getSkillCandidates(join(dir, \".agents\", \"skills\"), skillName));\n\t\tif (projectAgentsSkill) return projectAgentsSkill;\n\t}\n\n\tconst globalPiSkill = findFirstExisting(getSkillCandidates(join(getAgentDir(), \"skills\"), skillName));\n\tif (globalPiSkill) return globalPiSkill;\n\n\treturn findFirstExisting(getSkillCandidates(join(homedir(), \".agents\", \"skills\"), skillName));\n}\n\nexport function readSkillContent(skillPath: string): string {\n\tconst raw = readFileSync(skillPath, \"utf-8\");\n\treturn parseFrontmatter(raw).body;\n}\n"]}
|
|
@@ -3,7 +3,8 @@ import { existsSync, readdirSync, readFileSync, realpathSync, statSync } from "n
|
|
|
3
3
|
import { homedir } from "node:os";
|
|
4
4
|
import { basename, dirname, isAbsolute, join, relative, resolve } from "node:path";
|
|
5
5
|
import { minimatch } from "minimatch";
|
|
6
|
-
import { CONFIG_DIR_NAME, getAgentDir
|
|
6
|
+
import { CONFIG_DIR_NAME, getAgentDir } from "../../config.js";
|
|
7
|
+
import { parseFrontmatter } from "../../utils/frontmatter.js";
|
|
7
8
|
import { parseChainDeclaration } from "./chain-parser.js";
|
|
8
9
|
const VALID_THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh"];
|
|
9
10
|
export const RESERVED_COMMAND_NAMES = new Set([
|