@agent-profile/web 0.1.5 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/client/_app/immutable/assets/9.BDcQmxob.css +1 -0
- package/build/client/_app/immutable/assets/9.BDcQmxob.css.br +0 -0
- package/build/client/_app/immutable/assets/9.BDcQmxob.css.gz +0 -0
- package/build/client/_app/immutable/chunks/BcMnim1Z.js +2 -0
- package/build/client/_app/immutable/chunks/BcMnim1Z.js.br +0 -0
- package/build/client/_app/immutable/chunks/BcMnim1Z.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D5fBh0I2.js +1 -0
- package/build/client/_app/immutable/chunks/D5fBh0I2.js.br +2 -0
- package/build/client/_app/immutable/chunks/D5fBh0I2.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DJ5W1vn7.js +3 -0
- package/build/client/_app/immutable/chunks/DJ5W1vn7.js.br +0 -0
- package/build/client/_app/immutable/chunks/DJ5W1vn7.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DTBN031P.js +1 -0
- package/build/client/_app/immutable/chunks/DTBN031P.js.br +2 -0
- package/build/client/_app/immutable/chunks/DTBN031P.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D_wMLkFK.js +1 -0
- package/build/client/_app/immutable/chunks/D_wMLkFK.js.br +2 -0
- package/build/client/_app/immutable/chunks/D_wMLkFK.js.gz +0 -0
- package/build/client/_app/immutable/chunks/m4VeB-e-.js +3 -0
- package/build/client/_app/immutable/chunks/m4VeB-e-.js.br +0 -0
- package/build/client/_app/immutable/chunks/m4VeB-e-.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.DMWpO7sJ.js +2 -0
- package/build/client/_app/immutable/entry/app.DMWpO7sJ.js.br +0 -0
- package/build/client/_app/immutable/entry/app.DMWpO7sJ.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.BBaMgJ1R.js +1 -0
- package/build/client/_app/immutable/entry/start.BBaMgJ1R.js.br +0 -0
- package/build/client/_app/immutable/entry/start.BBaMgJ1R.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.Dv0k2Jqi.js +1 -0
- package/build/client/_app/immutable/nodes/0.Dv0k2Jqi.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.Dv0k2Jqi.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.E6HqFVj7.js +1 -0
- package/build/client/_app/immutable/nodes/1.E6HqFVj7.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.E6HqFVj7.js.gz +0 -0
- package/build/client/_app/immutable/nodes/10.DorD5wKe.js +3 -0
- package/build/client/_app/immutable/nodes/10.DorD5wKe.js.br +0 -0
- package/build/client/_app/immutable/nodes/10.DorD5wKe.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{10.Bhdlxk-S.js → 11.3lkgWYOd.js} +2 -2
- package/build/client/_app/immutable/nodes/11.3lkgWYOd.js.br +0 -0
- package/build/client/_app/immutable/nodes/11.3lkgWYOd.js.gz +0 -0
- package/build/client/_app/immutable/nodes/12.p6ol8gkx.js +1 -0
- package/build/client/_app/immutable/nodes/12.p6ol8gkx.js.br +0 -0
- package/build/client/_app/immutable/nodes/12.p6ol8gkx.js.gz +0 -0
- package/build/client/_app/immutable/nodes/{2.CI-wpOC8.js → 2.DMK5rlQk.js} +2 -2
- package/build/client/_app/immutable/nodes/2.DMK5rlQk.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.DMK5rlQk.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.BBvN4Erf.js +2 -0
- package/build/client/_app/immutable/nodes/3.BBvN4Erf.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.BBvN4Erf.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.3VL8fZOS.js +4 -0
- package/build/client/_app/immutable/nodes/4.3VL8fZOS.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.3VL8fZOS.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.CiNtblYV.js +2 -0
- package/build/client/_app/immutable/nodes/5.CiNtblYV.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.CiNtblYV.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.BRCCYakl.js +5 -0
- package/build/client/_app/immutable/nodes/6.BRCCYakl.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.BRCCYakl.js.gz +0 -0
- package/build/client/_app/immutable/nodes/7.Bn-YL1OM.js +4 -0
- package/build/client/_app/immutable/nodes/7.Bn-YL1OM.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.Bn-YL1OM.js.gz +0 -0
- package/build/client/_app/immutable/nodes/8.CkQQuOBs.js +1 -0
- package/build/client/_app/immutable/nodes/8.CkQQuOBs.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.CkQQuOBs.js.gz +0 -0
- package/build/client/_app/immutable/nodes/9.6KxRZbKJ.js +9 -0
- package/build/client/_app/immutable/nodes/9.6KxRZbKJ.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.6KxRZbKJ.js.gz +0 -0
- package/build/client/_app/version.json +1 -1
- package/build/client/_app/version.json.br +0 -0
- package/build/client/_app/version.json.gz +0 -0
- package/build/server/chunks/{0-DWEpTDaF.js → 0-D1xG012U.js} +8 -8
- package/build/server/chunks/{0-DWEpTDaF.js.map → 0-D1xG012U.js.map} +1 -1
- package/build/server/chunks/1-B1kTzRNn.js +9 -0
- package/build/server/chunks/{1-B68UkVTE.js.map → 1-B1kTzRNn.js.map} +1 -1
- package/build/server/chunks/{9-tHCipeiW.js → 10-DahfOzGu.js} +7 -7
- package/build/server/chunks/10-DahfOzGu.js.map +1 -0
- package/build/server/chunks/11-mzYblRmm.js +9 -0
- package/build/server/chunks/11-mzYblRmm.js.map +1 -0
- package/build/server/chunks/{11-Ms74wtl9.js → 12-Dw1Y6Xen.js} +5 -5
- package/build/server/chunks/{11-Ms74wtl9.js.map → 12-Dw1Y6Xen.js.map} +1 -1
- package/build/server/chunks/{2-bmpngDVe.js → 2-Cbd6Pglj.js} +3 -3
- package/build/server/chunks/{2-bmpngDVe.js.map → 2-Cbd6Pglj.js.map} +1 -1
- package/build/server/chunks/3-DjAsck26.js +9 -0
- package/build/server/chunks/{3-BkezOAX7.js.map → 3-DjAsck26.js.map} +1 -1
- package/build/server/chunks/{4-CSfQwQwV.js → 4-CKQYCTZo.js} +5 -5
- package/build/server/chunks/{4-CSfQwQwV.js.map → 4-CKQYCTZo.js.map} +1 -1
- package/build/server/chunks/5-BDp1sX0Q.js +9 -0
- package/build/server/chunks/{5-D_pZV4fS.js.map → 5-BDp1sX0Q.js.map} +1 -1
- package/build/server/chunks/6-CUIuzy6O.js +9 -0
- package/build/server/chunks/{6-DcbRMrH1.js.map → 6-CUIuzy6O.js.map} +1 -1
- package/build/server/chunks/{7-BsMFIBGU.js → 7-BDv5_nF1.js} +6 -6
- package/build/server/chunks/{7-BsMFIBGU.js.map → 7-BDv5_nF1.js.map} +1 -1
- package/build/server/chunks/8-CspJz0xl.js +9 -0
- package/build/server/chunks/{8-DWleYW_e.js.map → 8-CspJz0xl.js.map} +1 -1
- package/build/server/chunks/9-BpgaO-rd.js +33 -0
- package/build/server/chunks/9-BpgaO-rd.js.map +1 -0
- package/build/server/chunks/{Badge-BYK3z3lr.js → Badge-DCQxSQCS.js} +2 -2
- package/build/server/chunks/{Badge-BYK3z3lr.js.map → Badge-DCQxSQCS.js.map} +1 -1
- package/build/server/chunks/{SafetyBadge-BXNCgLE-.js → SafetyBadge-BxEGojgX.js} +2 -2
- package/build/server/chunks/{SafetyBadge-BXNCgLE-.js.map → SafetyBadge-BxEGojgX.js.map} +1 -1
- package/build/server/chunks/{_layout.svelte-Cv35k3JT.js → _layout.svelte-6X0-Uv9x.js} +15 -5
- package/build/server/chunks/_layout.svelte-6X0-Uv9x.js.map +1 -0
- package/build/server/chunks/{_page.svelte-BftcSD3f.js → _page.svelte-1wUrXGW-.js} +3 -3
- package/build/server/chunks/{_page.svelte-BftcSD3f.js.map → _page.svelte-1wUrXGW-.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-B-Kaw1RF.js → _page.svelte-B3CasgD8.js} +2 -2
- package/build/server/chunks/{_page.svelte-B-Kaw1RF.js.map → _page.svelte-B3CasgD8.js.map} +1 -1
- package/build/server/chunks/_page.svelte-BEU4JrAd.js +433 -0
- package/build/server/chunks/_page.svelte-BEU4JrAd.js.map +1 -0
- package/build/server/chunks/{_page.svelte-Cat8tEeF.js → _page.svelte-Bi4xsxv7.js} +4 -4
- package/build/server/chunks/{_page.svelte-Cat8tEeF.js.map → _page.svelte-Bi4xsxv7.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-CIEY8g8A.js → _page.svelte-BikYFdJv.js} +4 -4
- package/build/server/chunks/{_page.svelte-CIEY8g8A.js.map → _page.svelte-BikYFdJv.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-CmuUQI4Y.js → _page.svelte-Bx-fv-rO.js} +43 -20
- package/build/server/chunks/_page.svelte-Bx-fv-rO.js.map +1 -0
- package/build/server/chunks/{_page.svelte-DZX4Bixr.js → _page.svelte-CveCaqpY.js} +5 -5
- package/build/server/chunks/{_page.svelte-DZX4Bixr.js.map → _page.svelte-CveCaqpY.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-DyI46sDh.js → _page.svelte-D8ffqrO3.js} +3 -3
- package/build/server/chunks/{_page.svelte-DyI46sDh.js.map → _page.svelte-D8ffqrO3.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-DLQqGym0.js → _page.svelte-DNmC-yjw.js} +4 -4
- package/build/server/chunks/{_page.svelte-DLQqGym0.js.map → _page.svelte-DNmC-yjw.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-DHNevyzi.js → _page.svelte-wL3fdD1l.js} +4 -4
- package/build/server/chunks/{_page.svelte-DHNevyzi.js.map → _page.svelte-wL3fdD1l.js.map} +1 -1
- package/build/server/chunks/{_page.svelte-CUnw0pLx.js → _page.svelte-xTZOj1o8.js} +3 -3
- package/build/server/chunks/{_page.svelte-CUnw0pLx.js.map → _page.svelte-xTZOj1o8.js.map} +1 -1
- package/build/server/chunks/_server.ts-BBDD0W6t.js +167 -0
- package/build/server/chunks/_server.ts-BBDD0W6t.js.map +1 -0
- package/build/server/chunks/_server.ts-BkOJmVFg.js +101 -0
- package/build/server/chunks/_server.ts-BkOJmVFg.js.map +1 -0
- package/build/server/chunks/{_server.ts-BUQYdxPs.js → _server.ts-BkcLO56D.js} +2 -2
- package/build/server/chunks/{_server.ts-BUQYdxPs.js.map → _server.ts-BkcLO56D.js.map} +1 -1
- package/build/server/chunks/{_server.ts-Dq1jAomo.js → _server.ts-C2WpZqPW.js} +4 -4
- package/build/server/chunks/{_server.ts-Dq1jAomo.js.map → _server.ts-C2WpZqPW.js.map} +1 -1
- package/build/server/chunks/{_server.ts-5396UuLQ.js → _server.ts-CKn8ym8s.js} +2 -2
- package/build/server/chunks/{_server.ts-5396UuLQ.js.map → _server.ts-CKn8ym8s.js.map} +1 -1
- package/build/server/chunks/{_server.ts-DHt1bGpF.js → _server.ts-CaVH9FSD.js} +4 -4
- package/build/server/chunks/{_server.ts-DHt1bGpF.js.map → _server.ts-CaVH9FSD.js.map} +1 -1
- package/build/server/chunks/_server.ts-D7iLlRbM.js +337 -0
- package/build/server/chunks/_server.ts-D7iLlRbM.js.map +1 -0
- package/build/server/chunks/_server.ts-DPqZOGG_.js +18 -0
- package/build/server/chunks/_server.ts-DPqZOGG_.js.map +1 -0
- package/build/server/chunks/{_server.ts-sMKRiXFg.js → _server.ts-Dz9oKgWc.js} +5 -5
- package/build/server/chunks/{_server.ts-sMKRiXFg.js.map → _server.ts-Dz9oKgWc.js.map} +1 -1
- package/build/server/chunks/{_server.ts-CvdpZfED.js → _server.ts-fVP0SuTW.js} +2 -2
- package/build/server/chunks/{_server.ts-CvdpZfED.js.map → _server.ts-fVP0SuTW.js.map} +1 -1
- package/build/server/chunks/{client-92HF3fc9.js → client-CydontyB.js} +3 -3
- package/build/server/chunks/{client-92HF3fc9.js.map → client-CydontyB.js.map} +1 -1
- package/build/server/chunks/{dev-Duv_-rxF.js → dev-BdIdjvaY.js} +216 -82
- package/build/server/chunks/dev-BdIdjvaY.js.map +1 -0
- package/build/server/chunks/{doctorSummary-Bm0dY6PW.js → doctorSummary-BOtGdd9z.js} +3 -3
- package/build/server/chunks/{doctorSummary-Bm0dY6PW.js.map → doctorSummary-BOtGdd9z.js.map} +1 -1
- package/build/server/chunks/{error.svelte-BEI8QxGW.js → error.svelte-_CDx8UPv.js} +4 -4
- package/build/server/chunks/{error.svelte-BEI8QxGW.js.map → error.svelte-_CDx8UPv.js.map} +1 -1
- package/build/server/chunks/{hooks.server-BKavEpqC.js → hooks.server-Dva4z7fv.js} +35 -1
- package/build/server/chunks/hooks.server-Dva4z7fv.js.map +1 -0
- package/build/server/chunks/{internal-DBeni9My.js → internal-DyPeC3rk.js} +21 -16
- package/build/server/chunks/internal-DyPeC3rk.js.map +1 -0
- package/build/server/chunks/{marketingSeo-Do5o0grg.js → marketingSeo-CugwK52J.js} +2 -2
- package/build/server/chunks/{marketingSeo-Do5o0grg.js.map → marketingSeo-CugwK52J.js.map} +1 -1
- package/build/server/chunks/migrationReport-f6NoxAVZ.js +40 -0
- package/build/server/chunks/migrationReport-f6NoxAVZ.js.map +1 -0
- package/build/server/chunks/{profileApiHelpers-BFzohffv.js → profileApiHelpers-DCoI7zMU.js} +3 -3
- package/build/server/chunks/{profileApiHelpers-BFzohffv.js.map → profileApiHelpers-DCoI7zMU.js.map} +1 -1
- package/build/server/chunks/{projectContext-Cxsfz84C.js → projectContext-B1D-bieW.js} +2439 -127
- package/build/server/chunks/projectContext-B1D-bieW.js.map +1 -0
- package/build/server/chunks/{src2-DNqJAXv6.js → src2-BtraGDB1.js} +2 -2
- package/build/server/chunks/src2-BtraGDB1.js.map +1 -0
- package/build/server/chunks/{src3-jm480tTA.js → src3-BXch_OaJ.js} +347 -10
- package/build/server/chunks/src3-BXch_OaJ.js.map +1 -0
- package/build/server/chunks/{tokenStore-DQfTa-N3.js → tokenStore-CTHhmHsk.js} +30 -2
- package/build/server/chunks/tokenStore-CTHhmHsk.js.map +1 -0
- package/build/server/index.js +4 -5
- package/build/server/index.js.map +1 -1
- package/build/server/manifest.js +58 -22
- package/build/server/manifest.js.map +1 -1
- package/package.json +7 -7
- package/build/client/_app/immutable/chunks/6SrQtk22.js +0 -3
- package/build/client/_app/immutable/chunks/6SrQtk22.js.br +0 -0
- package/build/client/_app/immutable/chunks/6SrQtk22.js.gz +0 -0
- package/build/client/_app/immutable/chunks/B1X0Iqjr.js +0 -3
- package/build/client/_app/immutable/chunks/B1X0Iqjr.js.br +0 -0
- package/build/client/_app/immutable/chunks/B1X0Iqjr.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BN4Ca4cJ.js +0 -1
- package/build/client/_app/immutable/chunks/BN4Ca4cJ.js.br +0 -0
- package/build/client/_app/immutable/chunks/BN4Ca4cJ.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BYeYmN2n.js +0 -1
- package/build/client/_app/immutable/chunks/BYeYmN2n.js.br +0 -2
- package/build/client/_app/immutable/chunks/BYeYmN2n.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D0_SwbnT.js +0 -2
- package/build/client/_app/immutable/chunks/D0_SwbnT.js.br +0 -0
- package/build/client/_app/immutable/chunks/D0_SwbnT.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DRoN73NW.js +0 -1
- package/build/client/_app/immutable/chunks/DRoN73NW.js.br +0 -2
- package/build/client/_app/immutable/chunks/DRoN73NW.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.B45QQayJ.js +0 -2
- package/build/client/_app/immutable/entry/app.B45QQayJ.js.br +0 -0
- package/build/client/_app/immutable/entry/app.B45QQayJ.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.BIlQ_snM.js +0 -1
- package/build/client/_app/immutable/entry/start.BIlQ_snM.js.br +0 -0
- package/build/client/_app/immutable/entry/start.BIlQ_snM.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.JRffyfUR.js +0 -1
- package/build/client/_app/immutable/nodes/0.JRffyfUR.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.JRffyfUR.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.56EgwKsF.js +0 -1
- package/build/client/_app/immutable/nodes/1.56EgwKsF.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.56EgwKsF.js.gz +0 -0
- package/build/client/_app/immutable/nodes/10.Bhdlxk-S.js.br +0 -0
- package/build/client/_app/immutable/nodes/10.Bhdlxk-S.js.gz +0 -0
- package/build/client/_app/immutable/nodes/11.DAqRx2TI.js +0 -1
- package/build/client/_app/immutable/nodes/11.DAqRx2TI.js.br +0 -0
- package/build/client/_app/immutable/nodes/11.DAqRx2TI.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.CI-wpOC8.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.CI-wpOC8.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.Bphawycs.js +0 -2
- package/build/client/_app/immutable/nodes/3.Bphawycs.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.Bphawycs.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.BGFkNM65.js +0 -4
- package/build/client/_app/immutable/nodes/4.BGFkNM65.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.BGFkNM65.js.gz +0 -0
- package/build/client/_app/immutable/nodes/5.VTs5grF0.js +0 -2
- package/build/client/_app/immutable/nodes/5.VTs5grF0.js.br +0 -0
- package/build/client/_app/immutable/nodes/5.VTs5grF0.js.gz +0 -0
- package/build/client/_app/immutable/nodes/6.CndSdLIk.js +0 -5
- package/build/client/_app/immutable/nodes/6.CndSdLIk.js.br +0 -0
- package/build/client/_app/immutable/nodes/6.CndSdLIk.js.gz +0 -0
- package/build/client/_app/immutable/nodes/7.DpFk4StA.js +0 -4
- package/build/client/_app/immutable/nodes/7.DpFk4StA.js.br +0 -0
- package/build/client/_app/immutable/nodes/7.DpFk4StA.js.gz +0 -0
- package/build/client/_app/immutable/nodes/8.Y7A99ODL.js +0 -1
- package/build/client/_app/immutable/nodes/8.Y7A99ODL.js.br +0 -0
- package/build/client/_app/immutable/nodes/8.Y7A99ODL.js.gz +0 -0
- package/build/client/_app/immutable/nodes/9.DF3LeTGi.js +0 -3
- package/build/client/_app/immutable/nodes/9.DF3LeTGi.js.br +0 -0
- package/build/client/_app/immutable/nodes/9.DF3LeTGi.js.gz +0 -0
- package/build/server/chunks/1-B68UkVTE.js +0 -9
- package/build/server/chunks/10-D7op0myD.js +0 -9
- package/build/server/chunks/10-D7op0myD.js.map +0 -1
- package/build/server/chunks/3-BkezOAX7.js +0 -9
- package/build/server/chunks/5-D_pZV4fS.js +0 -9
- package/build/server/chunks/6-DcbRMrH1.js +0 -9
- package/build/server/chunks/8-DWleYW_e.js +0 -9
- package/build/server/chunks/9-tHCipeiW.js.map +0 -1
- package/build/server/chunks/_layout.svelte-Cv35k3JT.js.map +0 -1
- package/build/server/chunks/_page.svelte-CmuUQI4Y.js.map +0 -1
- package/build/server/chunks/dev-Duv_-rxF.js.map +0 -1
- package/build/server/chunks/hooks.server-BKavEpqC.js.map +0 -1
- package/build/server/chunks/internal-DBeni9My.js.map +0 -1
- package/build/server/chunks/projectContext-Cxsfz84C.js.map +0 -1
- package/build/server/chunks/src2-DNqJAXv6.js.map +0 -1
- package/build/server/chunks/src3-jm480tTA.js.map +0 -1
- package/build/server/chunks/tokenStore-DQfTa-N3.js.map +0 -1
- /package/build/client/_app/immutable/assets/{9.BsbC-D7w.css → 10.BsbC-D7w.css} +0 -0
- /package/build/client/_app/immutable/assets/{9.BsbC-D7w.css.br → 10.BsbC-D7w.css.br} +0 -0
- /package/build/client/_app/immutable/assets/{9.BsbC-D7w.css.gz → 10.BsbC-D7w.css.gz} +0 -0
- /package/build/client/_app/immutable/chunks/{I8rQr1kY.js → CP97kCR3.js} +0 -0
- /package/build/client/_app/immutable/chunks/{I8rQr1kY.js.br → CP97kCR3.js.br} +0 -0
- /package/build/client/_app/immutable/chunks/{I8rQr1kY.js.gz → CP97kCR3.js.gz} +0 -0
- /package/build/client/_app/immutable/chunks/{BFYQcBYR.js → O6-aNYLC.js} +0 -0
- /package/build/client/_app/immutable/chunks/{BFYQcBYR.js.br → O6-aNYLC.js.br} +0 -0
- /package/build/client/_app/immutable/chunks/{BFYQcBYR.js.gz → O6-aNYLC.js.gz} +0 -0
|
@@ -16222,9 +16222,22 @@ var ai_profile_schema_default = {
|
|
|
16222
16222
|
"properties": {
|
|
16223
16223
|
"sdd": { "type": "boolean" },
|
|
16224
16224
|
"tdd": { "type": "boolean" },
|
|
16225
|
-
"finalReview": { "type": "boolean" }
|
|
16225
|
+
"finalReview": { "type": "boolean" },
|
|
16226
|
+
"codeReview": { "type": "boolean" },
|
|
16227
|
+
"refactoring": { "type": "boolean" },
|
|
16228
|
+
"documentation": { "type": "boolean" },
|
|
16229
|
+
"subagentDrivenDevelopment": { "type": "boolean" }
|
|
16226
16230
|
}
|
|
16227
16231
|
},
|
|
16232
|
+
"capabilities": {
|
|
16233
|
+
"type": "object",
|
|
16234
|
+
"additionalProperties": false,
|
|
16235
|
+
"properties": { "delegation": {
|
|
16236
|
+
"type": "object",
|
|
16237
|
+
"additionalProperties": false,
|
|
16238
|
+
"properties": { "subagents": { "$ref": "#/definitions/subagents" } }
|
|
16239
|
+
} }
|
|
16240
|
+
},
|
|
16228
16241
|
"permissions": {
|
|
16229
16242
|
"type": "object",
|
|
16230
16243
|
"additionalProperties": false,
|
|
@@ -16310,11 +16323,315 @@ var ai_profile_schema_default = {
|
|
|
16310
16323
|
"minItems": 1,
|
|
16311
16324
|
"uniqueItems": true,
|
|
16312
16325
|
"items": { "$ref": "#/definitions/slug" }
|
|
16326
|
+
},
|
|
16327
|
+
"subagents": {
|
|
16328
|
+
"type": "object",
|
|
16329
|
+
"additionalProperties": false,
|
|
16330
|
+
"required": ["enabled"],
|
|
16331
|
+
"properties": {
|
|
16332
|
+
"enabled": { "type": "boolean" },
|
|
16333
|
+
"defaults": {
|
|
16334
|
+
"type": "object",
|
|
16335
|
+
"additionalProperties": false,
|
|
16336
|
+
"properties": {
|
|
16337
|
+
"maxConcurrent": {
|
|
16338
|
+
"type": "integer",
|
|
16339
|
+
"minimum": 1
|
|
16340
|
+
},
|
|
16341
|
+
"maxDepth": {
|
|
16342
|
+
"type": "integer",
|
|
16343
|
+
"minimum": 1
|
|
16344
|
+
}
|
|
16345
|
+
}
|
|
16346
|
+
},
|
|
16347
|
+
"agents": {
|
|
16348
|
+
"type": "array",
|
|
16349
|
+
"items": { "$ref": "#/definitions/subagent" }
|
|
16350
|
+
}
|
|
16351
|
+
},
|
|
16352
|
+
"if": {
|
|
16353
|
+
"properties": { "enabled": { "const": true } },
|
|
16354
|
+
"required": ["enabled"]
|
|
16355
|
+
},
|
|
16356
|
+
"then": {
|
|
16357
|
+
"required": ["agents"],
|
|
16358
|
+
"properties": { "agents": {
|
|
16359
|
+
"type": "array",
|
|
16360
|
+
"minItems": 1,
|
|
16361
|
+
"items": { "$ref": "#/definitions/subagent" }
|
|
16362
|
+
} }
|
|
16363
|
+
}
|
|
16364
|
+
},
|
|
16365
|
+
"subagent": { "oneOf": [{ "$ref": "#/definitions/subagentTemplateRef" }, { "$ref": "#/definitions/subagentInline" }] },
|
|
16366
|
+
"subagentTemplateRef": {
|
|
16367
|
+
"type": "object",
|
|
16368
|
+
"additionalProperties": false,
|
|
16369
|
+
"required": ["useTemplate"],
|
|
16370
|
+
"properties": { "useTemplate": {
|
|
16371
|
+
"type": "string",
|
|
16372
|
+
"enum": [
|
|
16373
|
+
"implementer",
|
|
16374
|
+
"spec-reviewer",
|
|
16375
|
+
"code-quality-reviewer"
|
|
16376
|
+
]
|
|
16377
|
+
} }
|
|
16378
|
+
},
|
|
16379
|
+
"subagentInline": {
|
|
16380
|
+
"type": "object",
|
|
16381
|
+
"additionalProperties": false,
|
|
16382
|
+
"required": [
|
|
16383
|
+
"name",
|
|
16384
|
+
"description",
|
|
16385
|
+
"purpose",
|
|
16386
|
+
"prompt",
|
|
16387
|
+
"toolScope"
|
|
16388
|
+
],
|
|
16389
|
+
"properties": {
|
|
16390
|
+
"name": {
|
|
16391
|
+
"type": "string",
|
|
16392
|
+
"minLength": 1,
|
|
16393
|
+
"pattern": "^[a-z0-9][a-z0-9-]*$",
|
|
16394
|
+
"not": { "enum": [
|
|
16395
|
+
"default",
|
|
16396
|
+
"worker",
|
|
16397
|
+
"explorer",
|
|
16398
|
+
"explore",
|
|
16399
|
+
"plan",
|
|
16400
|
+
"general-purpose",
|
|
16401
|
+
"codebase_investigator",
|
|
16402
|
+
"remote-codebase-investigator",
|
|
16403
|
+
"generalist",
|
|
16404
|
+
"browser_agent"
|
|
16405
|
+
] }
|
|
16406
|
+
},
|
|
16407
|
+
"description": {
|
|
16408
|
+
"type": "string",
|
|
16409
|
+
"minLength": 1,
|
|
16410
|
+
"pattern": "^[^\\r\\n]+$"
|
|
16411
|
+
},
|
|
16412
|
+
"purpose": {
|
|
16413
|
+
"type": "string",
|
|
16414
|
+
"minLength": 1,
|
|
16415
|
+
"pattern": "^[^\\r\\n]+$"
|
|
16416
|
+
},
|
|
16417
|
+
"prompt": {
|
|
16418
|
+
"type": "string",
|
|
16419
|
+
"minLength": 1
|
|
16420
|
+
},
|
|
16421
|
+
"toolScope": {
|
|
16422
|
+
"type": "string",
|
|
16423
|
+
"enum": ["read-only", "workspace-write"]
|
|
16424
|
+
},
|
|
16425
|
+
"modelPreference": {
|
|
16426
|
+
"type": "string",
|
|
16427
|
+
"enum": [
|
|
16428
|
+
"inherit",
|
|
16429
|
+
"fast",
|
|
16430
|
+
"balanced",
|
|
16431
|
+
"capable"
|
|
16432
|
+
]
|
|
16433
|
+
},
|
|
16434
|
+
"maxTurns": {
|
|
16435
|
+
"type": "integer",
|
|
16436
|
+
"minimum": 1
|
|
16437
|
+
},
|
|
16438
|
+
"timeoutMinutes": {
|
|
16439
|
+
"type": "integer",
|
|
16440
|
+
"minimum": 1
|
|
16441
|
+
},
|
|
16442
|
+
"mcpServers": {
|
|
16443
|
+
"type": "array",
|
|
16444
|
+
"items": { "type": "string" },
|
|
16445
|
+
"maxItems": 0
|
|
16446
|
+
}
|
|
16447
|
+
}
|
|
16313
16448
|
}
|
|
16314
16449
|
}
|
|
16315
16450
|
};
|
|
16316
16451
|
//#endregion
|
|
16317
16452
|
//#region ../../packages/core/src/profile.ts
|
|
16453
|
+
var SUBAGENT_TEMPLATE_NAMES = [
|
|
16454
|
+
"implementer",
|
|
16455
|
+
"spec-reviewer",
|
|
16456
|
+
"code-quality-reviewer"
|
|
16457
|
+
];
|
|
16458
|
+
function isSubagentTemplateRef(entry) {
|
|
16459
|
+
return typeof entry.useTemplate === "string";
|
|
16460
|
+
}
|
|
16461
|
+
function freezeTemplate(template) {
|
|
16462
|
+
if (template.mcpServers !== void 0) Object.freeze(template.mcpServers);
|
|
16463
|
+
return Object.freeze(template);
|
|
16464
|
+
}
|
|
16465
|
+
function cloneTemplate(template) {
|
|
16466
|
+
const clone = {
|
|
16467
|
+
name: template.name,
|
|
16468
|
+
description: template.description,
|
|
16469
|
+
purpose: template.purpose,
|
|
16470
|
+
prompt: template.prompt,
|
|
16471
|
+
toolScope: template.toolScope
|
|
16472
|
+
};
|
|
16473
|
+
if (template.modelPreference !== void 0) clone.modelPreference = template.modelPreference;
|
|
16474
|
+
if (template.maxTurns !== void 0) clone.maxTurns = template.maxTurns;
|
|
16475
|
+
if (template.timeoutMinutes !== void 0) clone.timeoutMinutes = template.timeoutMinutes;
|
|
16476
|
+
if (template.mcpServers !== void 0) clone.mcpServers = [...template.mcpServers];
|
|
16477
|
+
return clone;
|
|
16478
|
+
}
|
|
16479
|
+
var SUBAGENT_TEMPLATES_RAW = {
|
|
16480
|
+
implementer: {
|
|
16481
|
+
name: "implementer",
|
|
16482
|
+
description: "Use for a bounded implementation task after the parent agent has provided the full task text, relevant spec excerpts, file ownership, constraints, and expected tests. Returns an explicit status and does not commit or push unless the parent request includes that requirement.",
|
|
16483
|
+
purpose: "Implement one scoped task with tests, self-review, and honest escalation when requirements or architecture are unclear.",
|
|
16484
|
+
prompt: `You are implementing one bounded task.
|
|
16485
|
+
|
|
16486
|
+
Work only from the task text, spec excerpts, file ownership, constraints,
|
|
16487
|
+
and allowed commands provided in the prompt. Do not assume hidden chat
|
|
16488
|
+
history. If essential context is missing, report NEEDS_CONTEXT instead of
|
|
16489
|
+
guessing.
|
|
16490
|
+
|
|
16491
|
+
Before editing, restate the goal, non-goals, acceptance criteria, and files
|
|
16492
|
+
you expect to touch. If the task is ambiguous, architectural, or broader than
|
|
16493
|
+
the prompt says, stop and report BLOCKED or NEEDS_CONTEXT.
|
|
16494
|
+
|
|
16495
|
+
Implement exactly what the task specifies. Follow the repository's SDD/TDD
|
|
16496
|
+
workflow. Add or update focused tests where practical, verify RED before
|
|
16497
|
+
behavior changes when the task changes behavior, implement the smallest
|
|
16498
|
+
passing change, then verify GREEN. Preserve existing patterns and avoid
|
|
16499
|
+
unrelated refactors.
|
|
16500
|
+
|
|
16501
|
+
Do not commit, push, create branches, install dependencies, access secrets,
|
|
16502
|
+
contact production systems, or upload source unless the parent prompt
|
|
16503
|
+
explicitly authorizes that action.
|
|
16504
|
+
|
|
16505
|
+
Before reporting back, self-review for completeness, quality, scope control,
|
|
16506
|
+
and test validity. Fix issues you find if they are inside the assigned scope.
|
|
16507
|
+
|
|
16508
|
+
Report exactly:
|
|
16509
|
+
- Status: DONE | DONE_WITH_CONCERNS | BLOCKED | NEEDS_CONTEXT
|
|
16510
|
+
- What changed
|
|
16511
|
+
- Tests run and results
|
|
16512
|
+
- Files changed
|
|
16513
|
+
- Self-review findings
|
|
16514
|
+
- Concerns, missing context, or follow-up work`,
|
|
16515
|
+
toolScope: "workspace-write",
|
|
16516
|
+
modelPreference: "balanced",
|
|
16517
|
+
maxTurns: 18,
|
|
16518
|
+
timeoutMinutes: 20,
|
|
16519
|
+
mcpServers: []
|
|
16520
|
+
},
|
|
16521
|
+
"spec-reviewer": {
|
|
16522
|
+
name: "spec-reviewer",
|
|
16523
|
+
description: "Use after an implementation worker reports DONE or DONE_WITH_CONCERNS to verify the actual changed files against the task text, approved spec, acceptance criteria, and claimed result. Reads code and docs only; does not edit.",
|
|
16524
|
+
purpose: "Catch missing requirements, extra scope, and misunderstandings before code-quality review.",
|
|
16525
|
+
prompt: `You are reviewing whether an implementation matches its specification.
|
|
16526
|
+
|
|
16527
|
+
Work only from the full task text, approved spec excerpts, acceptance
|
|
16528
|
+
criteria, changed-file list, and implementer report provided in the prompt.
|
|
16529
|
+
Do not assume hidden chat history and do not trust the implementer report
|
|
16530
|
+
without checking the actual files.
|
|
16531
|
+
|
|
16532
|
+
Read the changed code and documentation. Compare actual behavior against the
|
|
16533
|
+
requested behavior line by line. Look for missing requirements, extra
|
|
16534
|
+
unrequested work, changed contracts, wrong interpretation, and fixture or
|
|
16535
|
+
documentation drift.
|
|
16536
|
+
|
|
16537
|
+
Do not edit files, run broad commands, install dependencies, read secrets,
|
|
16538
|
+
contact production systems, or upload source. If the prompt lacks enough
|
|
16539
|
+
context to review, report NEEDS_CONTEXT.
|
|
16540
|
+
|
|
16541
|
+
Report exactly:
|
|
16542
|
+
- Status: COMPLIANT | ISSUES_FOUND | NEEDS_CONTEXT
|
|
16543
|
+
- Requirements checked
|
|
16544
|
+
- Findings with severity, path, and line or symbol when available
|
|
16545
|
+
- Extra or out-of-scope work, if any
|
|
16546
|
+
- Missing tests or docs tied to acceptance criteria
|
|
16547
|
+
- Recommendation: proceed to code-quality review, fix first, or request context`,
|
|
16548
|
+
toolScope: "read-only",
|
|
16549
|
+
modelPreference: "capable",
|
|
16550
|
+
maxTurns: 10,
|
|
16551
|
+
timeoutMinutes: 8,
|
|
16552
|
+
mcpServers: []
|
|
16553
|
+
},
|
|
16554
|
+
"code-quality-reviewer": {
|
|
16555
|
+
name: "code-quality-reviewer",
|
|
16556
|
+
description: "Use only after spec review passes to assess maintainability, decomposition, tests, naming, risky mocks, and local code quality in the changed files. Reads code and docs only; does not edit.",
|
|
16557
|
+
purpose: "Catch maintainability and test-quality risks after the implementation is known to match the spec.",
|
|
16558
|
+
prompt: `You are reviewing code quality after spec compliance has passed.
|
|
16559
|
+
|
|
16560
|
+
Work only from the full task text, approved spec excerpts, changed-file list,
|
|
16561
|
+
spec-review result, test results, and implementer report provided in the
|
|
16562
|
+
prompt. Do not assume hidden chat history.
|
|
16563
|
+
|
|
16564
|
+
Review only the change's contribution. Do not flag pre-existing file size or
|
|
16565
|
+
architecture unless the change makes it materially worse. Check whether each
|
|
16566
|
+
touched file has a clear responsibility, whether names describe intent,
|
|
16567
|
+
whether complex predicates should be named, whether tests verify behavior
|
|
16568
|
+
rather than mocks, whether mocks preserve required real side effects, and
|
|
16569
|
+
whether new APIs exist only for tests.
|
|
16570
|
+
|
|
16571
|
+
Do not edit files, run broad commands, install dependencies, read secrets,
|
|
16572
|
+
contact production systems, or upload source. If the prompt lacks enough
|
|
16573
|
+
context to review, report NEEDS_CONTEXT.
|
|
16574
|
+
|
|
16575
|
+
Report exactly:
|
|
16576
|
+
- Status: ACCEPTABLE | ISSUES_FOUND | NEEDS_CONTEXT
|
|
16577
|
+
- Strengths
|
|
16578
|
+
- Issues grouped as Critical, Important, or Minor
|
|
16579
|
+
- Test-quality concerns
|
|
16580
|
+
- Maintainability concerns
|
|
16581
|
+
- Assessment: ready, fix first, or request context`,
|
|
16582
|
+
toolScope: "read-only",
|
|
16583
|
+
modelPreference: "capable",
|
|
16584
|
+
maxTurns: 10,
|
|
16585
|
+
timeoutMinutes: 8,
|
|
16586
|
+
mcpServers: []
|
|
16587
|
+
}
|
|
16588
|
+
};
|
|
16589
|
+
var SUBAGENT_TEMPLATES = {
|
|
16590
|
+
implementer: freezeTemplate(SUBAGENT_TEMPLATES_RAW.implementer),
|
|
16591
|
+
"spec-reviewer": freezeTemplate(SUBAGENT_TEMPLATES_RAW["spec-reviewer"]),
|
|
16592
|
+
"code-quality-reviewer": freezeTemplate(SUBAGENT_TEMPLATES_RAW["code-quality-reviewer"])
|
|
16593
|
+
};
|
|
16594
|
+
function expandSubagentEntry(entry) {
|
|
16595
|
+
if (isSubagentTemplateRef(entry)) return cloneTemplate(SUBAGENT_TEMPLATES[entry.useTemplate]);
|
|
16596
|
+
return entry;
|
|
16597
|
+
}
|
|
16598
|
+
function getSubagentTemplateRefs(profile) {
|
|
16599
|
+
const block = profile.capabilities?.delegation?.subagents;
|
|
16600
|
+
if (!block || block.enabled !== true) return [];
|
|
16601
|
+
const refs = [];
|
|
16602
|
+
for (const entry of block.agents ?? []) if (isSubagentTemplateRef(entry)) refs.push(entry.useTemplate);
|
|
16603
|
+
return refs;
|
|
16604
|
+
}
|
|
16605
|
+
function normalizeSubagentName(name) {
|
|
16606
|
+
return name.toLowerCase().replace(/_/gu, "-");
|
|
16607
|
+
}
|
|
16608
|
+
function getSubagentDefaults(profile) {
|
|
16609
|
+
const defaults = profile.capabilities?.delegation?.subagents?.defaults;
|
|
16610
|
+
return {
|
|
16611
|
+
maxConcurrent: defaults?.maxConcurrent ?? 3,
|
|
16612
|
+
maxDepth: defaults?.maxDepth ?? 1
|
|
16613
|
+
};
|
|
16614
|
+
}
|
|
16615
|
+
function getEnabledSubagents(profile) {
|
|
16616
|
+
const block = profile.capabilities?.delegation?.subagents;
|
|
16617
|
+
if (!block || block.enabled !== true) return [];
|
|
16618
|
+
return (block.agents ?? []).map((entry) => expandSubagentEntry(entry));
|
|
16619
|
+
}
|
|
16620
|
+
var SUBAGENT_BUILTIN_NAMES_NORMALIZED = new Set([
|
|
16621
|
+
"default",
|
|
16622
|
+
"worker",
|
|
16623
|
+
"explorer",
|
|
16624
|
+
"explore",
|
|
16625
|
+
"plan",
|
|
16626
|
+
"general-purpose",
|
|
16627
|
+
"codebase-investigator",
|
|
16628
|
+
"remote-codebase-investigator",
|
|
16629
|
+
"generalist",
|
|
16630
|
+
"browser-agent"
|
|
16631
|
+
]);
|
|
16632
|
+
function isSubagentBuiltinNameCollision(name) {
|
|
16633
|
+
return SUBAGENT_BUILTIN_NAMES_NORMALIZED.has(normalizeSubagentName(name));
|
|
16634
|
+
}
|
|
16318
16635
|
var compiledValidator;
|
|
16319
16636
|
var DEFAULT_SAFETY = {
|
|
16320
16637
|
mode: "guarded",
|
|
@@ -16398,6 +16715,11 @@ function validateProfileValue(value) {
|
|
|
16398
16715
|
const validate = getValidator();
|
|
16399
16716
|
if (validate(value)) {
|
|
16400
16717
|
const profile = value;
|
|
16718
|
+
const subagentIssues = validateSubagentSemantics(profile);
|
|
16719
|
+
if (subagentIssues.length > 0) return {
|
|
16720
|
+
ok: false,
|
|
16721
|
+
issues: subagentIssues.sort((left, right) => compareIssues$1(left, right))
|
|
16722
|
+
};
|
|
16401
16723
|
return {
|
|
16402
16724
|
ok: true,
|
|
16403
16725
|
profile,
|
|
@@ -16410,6 +16732,38 @@ function validateProfileValue(value) {
|
|
|
16410
16732
|
issues: toValidationIssues(validate.errors ?? [], value)
|
|
16411
16733
|
};
|
|
16412
16734
|
}
|
|
16735
|
+
function validateSubagentSemantics(profile) {
|
|
16736
|
+
const subagents = profile.capabilities?.delegation?.subagents;
|
|
16737
|
+
if (!subagents || subagents.enabled !== true) return [];
|
|
16738
|
+
const entries = subagents.agents ?? [];
|
|
16739
|
+
const issues = [];
|
|
16740
|
+
const seenRaw = /* @__PURE__ */ new Map();
|
|
16741
|
+
const seenNormalized = /* @__PURE__ */ new Map();
|
|
16742
|
+
entries.forEach((entry, index) => {
|
|
16743
|
+
const name = expandSubagentEntry(entry).name;
|
|
16744
|
+
const rawIndex = seenRaw.get(name);
|
|
16745
|
+
if (rawIndex !== void 0) issues.push({
|
|
16746
|
+
code: "schema_validation_error",
|
|
16747
|
+
path: `/capabilities/delegation/subagents/agents/${index}/name`,
|
|
16748
|
+
expected: "unique subagent name",
|
|
16749
|
+
actual: "duplicate",
|
|
16750
|
+
message: `/capabilities/delegation/subagents/agents/${index}/name duplicates the name used at index ${rawIndex}.`
|
|
16751
|
+
});
|
|
16752
|
+
else seenRaw.set(name, index);
|
|
16753
|
+
const normalized = normalizeSubagentName(name);
|
|
16754
|
+
const normalizedIndex = seenNormalized.get(normalized);
|
|
16755
|
+
if (normalizedIndex !== void 0 && normalizedIndex !== index) {
|
|
16756
|
+
if (!(rawIndex !== void 0)) issues.push({
|
|
16757
|
+
code: "schema_validation_error",
|
|
16758
|
+
path: `/capabilities/delegation/subagents/agents/${index}/name`,
|
|
16759
|
+
expected: "unique normalized subagent id",
|
|
16760
|
+
actual: "duplicate after hyphen/underscore folding",
|
|
16761
|
+
message: `/capabilities/delegation/subagents/agents/${index}/name collides with the name used at index ${normalizedIndex} after normalization.`
|
|
16762
|
+
});
|
|
16763
|
+
} else if (normalizedIndex === void 0) seenNormalized.set(normalized, index);
|
|
16764
|
+
});
|
|
16765
|
+
return issues;
|
|
16766
|
+
}
|
|
16413
16767
|
function normalizeSafety(profile) {
|
|
16414
16768
|
return {
|
|
16415
16769
|
mode: profile.safety?.mode ?? DEFAULT_SAFETY.mode,
|
|
@@ -16449,11 +16803,17 @@ function renderProfileYaml(profile) {
|
|
|
16449
16803
|
if (profile.safety.requiresSandbox !== void 0) safety["requiresSandbox"] = profile.safety.requiresSandbox;
|
|
16450
16804
|
doc["safety"] = safety;
|
|
16451
16805
|
}
|
|
16452
|
-
|
|
16806
|
+
const workflow = {
|
|
16453
16807
|
sdd: profile.workflow.sdd,
|
|
16454
16808
|
tdd: profile.workflow.tdd,
|
|
16455
16809
|
finalReview: profile.workflow.finalReview
|
|
16456
16810
|
};
|
|
16811
|
+
if (profile.workflow.codeReview !== void 0) workflow["codeReview"] = profile.workflow.codeReview;
|
|
16812
|
+
if (profile.workflow.refactoring !== void 0) workflow["refactoring"] = profile.workflow.refactoring;
|
|
16813
|
+
if (profile.workflow.documentation !== void 0) workflow["documentation"] = profile.workflow.documentation;
|
|
16814
|
+
if (profile.workflow.subagentDrivenDevelopment !== void 0) workflow["subagentDrivenDevelopment"] = profile.workflow.subagentDrivenDevelopment;
|
|
16815
|
+
doc["workflow"] = workflow;
|
|
16816
|
+
if (profile.capabilities !== void 0) doc["capabilities"] = buildCapabilitiesDoc(profile.capabilities);
|
|
16457
16817
|
if (profile.permissions !== void 0) doc["permissions"] = buildPermissionsDoc(profile.permissions);
|
|
16458
16818
|
return distExports.stringify(doc, {
|
|
16459
16819
|
lineWidth: 0,
|
|
@@ -16461,6 +16821,40 @@ function renderProfileYaml(profile) {
|
|
|
16461
16821
|
sortMapEntries: false
|
|
16462
16822
|
}).replace(/\n+$/, "") + "\n";
|
|
16463
16823
|
}
|
|
16824
|
+
function buildCapabilitiesDoc(capabilities) {
|
|
16825
|
+
const doc = {};
|
|
16826
|
+
if (capabilities.delegation !== void 0) {
|
|
16827
|
+
const delegation = {};
|
|
16828
|
+
const subagents = capabilities.delegation.subagents;
|
|
16829
|
+
if (subagents !== void 0) {
|
|
16830
|
+
const block = { enabled: subagents.enabled };
|
|
16831
|
+
if (subagents.defaults !== void 0) {
|
|
16832
|
+
const defaults = {};
|
|
16833
|
+
if (subagents.defaults.maxConcurrent !== void 0) defaults["maxConcurrent"] = subagents.defaults.maxConcurrent;
|
|
16834
|
+
if (subagents.defaults.maxDepth !== void 0) defaults["maxDepth"] = subagents.defaults.maxDepth;
|
|
16835
|
+
if (Object.keys(defaults).length > 0) block["defaults"] = defaults;
|
|
16836
|
+
}
|
|
16837
|
+
if (subagents.agents !== void 0) block["agents"] = subagents.agents.map((entry) => isSubagentTemplateRef(entry) ? { useTemplate: entry.useTemplate } : buildSubagentDoc(entry));
|
|
16838
|
+
delegation["subagents"] = block;
|
|
16839
|
+
}
|
|
16840
|
+
if (Object.keys(delegation).length > 0) doc["delegation"] = delegation;
|
|
16841
|
+
}
|
|
16842
|
+
return doc;
|
|
16843
|
+
}
|
|
16844
|
+
function buildSubagentDoc(agent) {
|
|
16845
|
+
const out = {
|
|
16846
|
+
name: agent.name,
|
|
16847
|
+
description: agent.description,
|
|
16848
|
+
purpose: agent.purpose,
|
|
16849
|
+
prompt: agent.prompt,
|
|
16850
|
+
toolScope: agent.toolScope
|
|
16851
|
+
};
|
|
16852
|
+
if (agent.modelPreference !== void 0) out["modelPreference"] = agent.modelPreference;
|
|
16853
|
+
if (agent.maxTurns !== void 0) out["maxTurns"] = agent.maxTurns;
|
|
16854
|
+
if (agent.timeoutMinutes !== void 0) out["timeoutMinutes"] = agent.timeoutMinutes;
|
|
16855
|
+
if (agent.mcpServers !== void 0) out["mcpServers"] = agent.mcpServers;
|
|
16856
|
+
return out;
|
|
16857
|
+
}
|
|
16464
16858
|
function buildPermissionsDoc(p) {
|
|
16465
16859
|
const doc = {};
|
|
16466
16860
|
if (p.filesystem !== void 0) {
|
|
@@ -16654,12 +17048,15 @@ function getDefaultTargetIds() {
|
|
|
16654
17048
|
"lockfile",
|
|
16655
17049
|
"tabnine-guidelines",
|
|
16656
17050
|
"tabnine-mcp-config",
|
|
17051
|
+
"tabnine-subagents",
|
|
16657
17052
|
"codex-config",
|
|
16658
17053
|
"codex-workflow-skills",
|
|
17054
|
+
"codex-subagents",
|
|
16659
17055
|
"claude-settings",
|
|
16660
17056
|
"claude-mcp",
|
|
16661
17057
|
"claude-md",
|
|
16662
|
-
"claude-workflow-skills"
|
|
17058
|
+
"claude-workflow-skills",
|
|
17059
|
+
"claude-subagents"
|
|
16663
17060
|
];
|
|
16664
17061
|
}
|
|
16665
17062
|
function createGeneratedTextFile(path, target, templateId, text) {
|
|
@@ -16694,17 +17091,20 @@ function compareText(left, right) {
|
|
|
16694
17091
|
}
|
|
16695
17092
|
//#endregion
|
|
16696
17093
|
//#region ../../packages/compiler/src/lockfile.ts
|
|
17094
|
+
var SUPPORTED_VERSIONS = new Set([1, 2]);
|
|
16697
17095
|
function buildLockfile(input) {
|
|
17096
|
+
const profilePath = safeOutputPath(input.profilePath ?? "ai-profile.yaml");
|
|
17097
|
+
const mixedByPath = new Map((input.mixedOutputs ?? []).map((entry) => [safeOutputPath(entry.path), entry]));
|
|
16698
17098
|
return {
|
|
16699
|
-
version:
|
|
17099
|
+
version: 2,
|
|
16700
17100
|
profile: {
|
|
16701
|
-
path:
|
|
17101
|
+
path: profilePath,
|
|
16702
17102
|
schemaVersion: 1,
|
|
16703
17103
|
sha256: sha256Hex(input.profileBytes)
|
|
16704
17104
|
},
|
|
16705
17105
|
compiler: input.compiler ?? AGENT_PROFILE_COMPILER,
|
|
16706
17106
|
templates: input.templates.map(toLockTemplate).sort(compareLockTemplates),
|
|
16707
|
-
outputs: input.files.map(
|
|
17107
|
+
outputs: input.files.map((file) => toLockOutputV2(file, mixedByPath)).sort(compareLockOutputsV2)
|
|
16708
17108
|
};
|
|
16709
17109
|
}
|
|
16710
17110
|
function serializeLockfile(lockfile) {
|
|
@@ -16713,6 +17113,28 @@ function serializeLockfile(lockfile) {
|
|
|
16713
17113
|
function createLockfileFile(input) {
|
|
16714
17114
|
return createGeneratedTextFile("ai-profile.lock", "lockfile", "targets/lockfile@1", serializeLockfile(buildLockfile(input)));
|
|
16715
17115
|
}
|
|
17116
|
+
/**
|
|
17117
|
+
* Migrate a parsed v1 lockfile to v2 by promoting every v1 output to
|
|
17118
|
+
* `generated-owned`. Order, hashes, target, and template ids are copied
|
|
17119
|
+
* unchanged. The migration is deterministic and idempotent: calling it on the
|
|
17120
|
+
* result of `buildLockfile(input)` for the same inputs produces byte-identical
|
|
17121
|
+
* v2 bytes.
|
|
17122
|
+
*/
|
|
17123
|
+
function migrateLockfileV1ToV2(lockfile) {
|
|
17124
|
+
return {
|
|
17125
|
+
version: 2,
|
|
17126
|
+
profile: lockfile.profile,
|
|
17127
|
+
compiler: lockfile.compiler,
|
|
17128
|
+
templates: [...lockfile.templates].sort(compareLockTemplates),
|
|
17129
|
+
outputs: lockfile.outputs.map((output) => ({
|
|
17130
|
+
path: output.path,
|
|
17131
|
+
target: output.target,
|
|
17132
|
+
templateId: output.templateId,
|
|
17133
|
+
ownership: "generated-owned",
|
|
17134
|
+
sha256: output.sha256
|
|
17135
|
+
})).sort(compareLockOutputsV2)
|
|
17136
|
+
};
|
|
17137
|
+
}
|
|
16716
17138
|
function validateLockfileText(source) {
|
|
16717
17139
|
try {
|
|
16718
17140
|
return validateLockfileValue(JSON.parse(source));
|
|
@@ -16731,14 +17153,48 @@ function validateLockfileText(source) {
|
|
|
16731
17153
|
}
|
|
16732
17154
|
function validateLockfileValue(value) {
|
|
16733
17155
|
const issues = [];
|
|
16734
|
-
|
|
17156
|
+
if (!isRecord(value)) {
|
|
17157
|
+
issues.push(schemaIssue("/", "object", describeValue(value)));
|
|
17158
|
+
return {
|
|
17159
|
+
ok: false,
|
|
17160
|
+
issues
|
|
17161
|
+
};
|
|
17162
|
+
}
|
|
17163
|
+
const version = value.version;
|
|
17164
|
+
if (typeof version !== "number" || !SUPPORTED_VERSIONS.has(version)) {
|
|
17165
|
+
issues.push({
|
|
17166
|
+
code: "lockfile_unsupported_version",
|
|
17167
|
+
path: "/version",
|
|
17168
|
+
expected: "supported lockfile version (1 or 2)",
|
|
17169
|
+
actual: describeValue(version),
|
|
17170
|
+
message: `/version is not a supported lockfile version.`
|
|
17171
|
+
});
|
|
17172
|
+
return {
|
|
17173
|
+
ok: false,
|
|
17174
|
+
issues
|
|
17175
|
+
};
|
|
17176
|
+
}
|
|
17177
|
+
if (version === 1) {
|
|
17178
|
+
validateLockfileV1Object(value, issues);
|
|
17179
|
+
if (issues.length > 0) return {
|
|
17180
|
+
ok: false,
|
|
17181
|
+
issues: issues.sort(compareLockfileIssues)
|
|
17182
|
+
};
|
|
17183
|
+
return {
|
|
17184
|
+
ok: true,
|
|
17185
|
+
lockfile: value,
|
|
17186
|
+
version: 1
|
|
17187
|
+
};
|
|
17188
|
+
}
|
|
17189
|
+
validateLockfileV2Object(value, issues);
|
|
16735
17190
|
if (issues.length > 0) return {
|
|
16736
17191
|
ok: false,
|
|
16737
17192
|
issues: issues.sort(compareLockfileIssues)
|
|
16738
17193
|
};
|
|
16739
17194
|
return {
|
|
16740
17195
|
ok: true,
|
|
16741
|
-
lockfile: value
|
|
17196
|
+
lockfile: value,
|
|
17197
|
+
version: 2
|
|
16742
17198
|
};
|
|
16743
17199
|
}
|
|
16744
17200
|
function toLockTemplate(template) {
|
|
@@ -16749,7 +17205,7 @@ function toLockTemplate(template) {
|
|
|
16749
17205
|
sha256: template.sha256
|
|
16750
17206
|
};
|
|
16751
17207
|
}
|
|
16752
|
-
function
|
|
17208
|
+
function validateLockfileV1Object(value, issues) {
|
|
16753
17209
|
if (!isRecord(value)) {
|
|
16754
17210
|
issues.push(schemaIssue("/", "object", describeValue(value)));
|
|
16755
17211
|
return;
|
|
@@ -16765,7 +17221,25 @@ function validateLockfileObject(value, issues) {
|
|
|
16765
17221
|
validateProfile(value.profile, issues);
|
|
16766
17222
|
validateCompiler(value.compiler, issues);
|
|
16767
17223
|
validateTemplates(value.templates, issues);
|
|
16768
|
-
|
|
17224
|
+
validateOutputsV1(value.outputs, issues);
|
|
17225
|
+
}
|
|
17226
|
+
function validateLockfileV2Object(value, issues) {
|
|
17227
|
+
if (!isRecord(value)) {
|
|
17228
|
+
issues.push(schemaIssue("/", "object", describeValue(value)));
|
|
17229
|
+
return;
|
|
17230
|
+
}
|
|
17231
|
+
requireExactKeys(value, "/", [
|
|
17232
|
+
"version",
|
|
17233
|
+
"profile",
|
|
17234
|
+
"compiler",
|
|
17235
|
+
"templates",
|
|
17236
|
+
"outputs"
|
|
17237
|
+
], issues);
|
|
17238
|
+
if (value.version !== 2) issues.push(schemaIssue("/version", "constant 2", describeValue(value.version)));
|
|
17239
|
+
validateProfile(value.profile, issues);
|
|
17240
|
+
validateCompiler(value.compiler, issues);
|
|
17241
|
+
validateTemplates(value.templates, issues);
|
|
17242
|
+
validateOutputsV2(value.outputs, issues);
|
|
16769
17243
|
}
|
|
16770
17244
|
function validateProfile(value, issues) {
|
|
16771
17245
|
if (!isRecord(value)) {
|
|
@@ -16823,7 +17297,7 @@ function validateTemplates(value, issues) {
|
|
|
16823
17297
|
previous = current;
|
|
16824
17298
|
});
|
|
16825
17299
|
}
|
|
16826
|
-
function
|
|
17300
|
+
function validateOutputsV1(value, issues) {
|
|
16827
17301
|
if (!Array.isArray(value)) {
|
|
16828
17302
|
issues.push(schemaIssue("/outputs", "array", describeValue(value)));
|
|
16829
17303
|
return;
|
|
@@ -16856,6 +17330,89 @@ function validateOutputs(value, issues) {
|
|
|
16856
17330
|
previous = current;
|
|
16857
17331
|
});
|
|
16858
17332
|
}
|
|
17333
|
+
function validateOutputsV2(value, issues) {
|
|
17334
|
+
if (!Array.isArray(value)) {
|
|
17335
|
+
issues.push(schemaIssue("/outputs", "array", describeValue(value)));
|
|
17336
|
+
return;
|
|
17337
|
+
}
|
|
17338
|
+
let previous;
|
|
17339
|
+
value.forEach((item, index) => {
|
|
17340
|
+
const path = `/outputs/${index}`;
|
|
17341
|
+
if (!isRecord(item)) {
|
|
17342
|
+
issues.push(schemaIssue(path, "object", describeValue(item)));
|
|
17343
|
+
return;
|
|
17344
|
+
}
|
|
17345
|
+
const ownership = item.ownership;
|
|
17346
|
+
if (ownership === "generated-owned") {
|
|
17347
|
+
requireExactKeys(item, path, [
|
|
17348
|
+
"path",
|
|
17349
|
+
"target",
|
|
17350
|
+
"templateId",
|
|
17351
|
+
"ownership",
|
|
17352
|
+
"sha256"
|
|
17353
|
+
], issues);
|
|
17354
|
+
validatePath(item.path, `${path}/path`, issues);
|
|
17355
|
+
validateString(item.target, `${path}/target`, issues);
|
|
17356
|
+
validateString(item.templateId, `${path}/templateId`, issues);
|
|
17357
|
+
validateHash(item.sha256, `${path}/sha256`, issues);
|
|
17358
|
+
} else if (ownership === "mixed") {
|
|
17359
|
+
requireExactKeys(item, path, [
|
|
17360
|
+
"path",
|
|
17361
|
+
"target",
|
|
17362
|
+
"templateId",
|
|
17363
|
+
"ownership",
|
|
17364
|
+
"regions"
|
|
17365
|
+
], issues);
|
|
17366
|
+
validatePath(item.path, `${path}/path`, issues);
|
|
17367
|
+
validateString(item.target, `${path}/target`, issues);
|
|
17368
|
+
validateString(item.templateId, `${path}/templateId`, issues);
|
|
17369
|
+
validateRegions(item.regions, `${path}/regions`, issues);
|
|
17370
|
+
} else if (ownership === "manual-owned") {
|
|
17371
|
+
requireExactKeys(item, path, [
|
|
17372
|
+
"path",
|
|
17373
|
+
"target",
|
|
17374
|
+
"templateId",
|
|
17375
|
+
"ownership"
|
|
17376
|
+
], issues);
|
|
17377
|
+
validatePath(item.path, `${path}/path`, issues);
|
|
17378
|
+
if (item.target !== "manual") issues.push(schemaIssue(`${path}/target`, "\"manual\"", describeValue(item.target)));
|
|
17379
|
+
if (item.templateId !== "manual") issues.push(schemaIssue(`${path}/templateId`, "\"manual\"", describeValue(item.templateId)));
|
|
17380
|
+
} else issues.push(schemaIssue(`${path}/ownership`, "\"generated-owned\" | \"mixed\" | \"manual-owned\"", describeValue(ownership)));
|
|
17381
|
+
const current = item;
|
|
17382
|
+
if (previous && compareLockOutputsV2(previous, current) > 0) issues.push({
|
|
17383
|
+
code: "lockfile_order_error",
|
|
17384
|
+
path,
|
|
17385
|
+
expected: "outputs sorted by path then target",
|
|
17386
|
+
actual: "out of order",
|
|
17387
|
+
message: `${path} is not in deterministic order.`
|
|
17388
|
+
});
|
|
17389
|
+
previous = current;
|
|
17390
|
+
});
|
|
17391
|
+
}
|
|
17392
|
+
function validateRegions(value, pathPrefix, issues) {
|
|
17393
|
+
if (!Array.isArray(value)) {
|
|
17394
|
+
issues.push(schemaIssue(pathPrefix, "array", describeValue(value)));
|
|
17395
|
+
return;
|
|
17396
|
+
}
|
|
17397
|
+
if (value.length !== 1) issues.push(schemaIssue(pathPrefix, "exactly one generated region", `${value.length} regions`));
|
|
17398
|
+
value.forEach((item, index) => {
|
|
17399
|
+
const path = `${pathPrefix}/${index}`;
|
|
17400
|
+
if (!isRecord(item)) {
|
|
17401
|
+
issues.push(schemaIssue(path, "object", describeValue(item)));
|
|
17402
|
+
return;
|
|
17403
|
+
}
|
|
17404
|
+
requireExactKeys(item, path, [
|
|
17405
|
+
"id",
|
|
17406
|
+
"target",
|
|
17407
|
+
"templateId",
|
|
17408
|
+
"sha256"
|
|
17409
|
+
], issues);
|
|
17410
|
+
if (item.id !== "agent-profile:generated") issues.push(schemaIssue(`${path}/id`, "\"agent-profile:generated\"", describeValue(item.id)));
|
|
17411
|
+
validateString(item.target, `${path}/target`, issues);
|
|
17412
|
+
validateString(item.templateId, `${path}/templateId`, issues);
|
|
17413
|
+
validateHash(item.sha256, `${path}/sha256`, issues);
|
|
17414
|
+
});
|
|
17415
|
+
}
|
|
16859
17416
|
function requireExactKeys(value, path, keys, issues) {
|
|
16860
17417
|
const allowed = new Set(keys);
|
|
16861
17418
|
for (const key of keys) if (!Object.prototype.hasOwnProperty.call(value, key)) issues.push(schemaIssue(`${path}/${escapeJsonPointerSegment(key)}`, "required property", "missing"));
|
|
@@ -16913,11 +17470,26 @@ function escapeJsonPointerSegment(segment) {
|
|
|
16913
17470
|
function isRecord(value) {
|
|
16914
17471
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
16915
17472
|
}
|
|
16916
|
-
function
|
|
17473
|
+
function toLockOutputV2(file, mixedByPath) {
|
|
17474
|
+
const safePath = safeOutputPath(file.path);
|
|
17475
|
+
const mixed = mixedByPath.get(safePath);
|
|
17476
|
+
if (mixed) return {
|
|
17477
|
+
path: safePath,
|
|
17478
|
+
target: file.target,
|
|
17479
|
+
templateId: file.templateId,
|
|
17480
|
+
ownership: "mixed",
|
|
17481
|
+
regions: [{
|
|
17482
|
+
id: "agent-profile:generated",
|
|
17483
|
+
target: mixed.target,
|
|
17484
|
+
templateId: mixed.templateId,
|
|
17485
|
+
sha256: mixed.regionHash
|
|
17486
|
+
}]
|
|
17487
|
+
};
|
|
16917
17488
|
return {
|
|
16918
|
-
path:
|
|
17489
|
+
path: safePath,
|
|
16919
17490
|
target: file.target,
|
|
16920
17491
|
templateId: file.templateId,
|
|
17492
|
+
ownership: "generated-owned",
|
|
16921
17493
|
sha256: file.sha256
|
|
16922
17494
|
};
|
|
16923
17495
|
}
|
|
@@ -16927,106 +17499,663 @@ function compareLockTemplates(left, right) {
|
|
|
16927
17499
|
function compareLockOutputs(left, right) {
|
|
16928
17500
|
return compareText(left.path, right.path) || compareText(left.target, right.target);
|
|
16929
17501
|
}
|
|
16930
|
-
|
|
16931
|
-
|
|
16932
|
-
var WORKFLOW_SKILLS = [
|
|
16933
|
-
{
|
|
16934
|
-
id: "sdd-change",
|
|
16935
|
-
workflowFlag: "sdd"
|
|
16936
|
-
},
|
|
16937
|
-
{
|
|
16938
|
-
id: "tdd-change",
|
|
16939
|
-
workflowFlag: "tdd"
|
|
16940
|
-
},
|
|
16941
|
-
{
|
|
16942
|
-
id: "final-review",
|
|
16943
|
-
workflowFlag: "finalReview"
|
|
16944
|
-
}
|
|
16945
|
-
];
|
|
16946
|
-
var TEMPLATE_SOURCES = [
|
|
16947
|
-
{
|
|
16948
|
-
id: "targets/agents-md@1",
|
|
16949
|
-
target: "agents-md",
|
|
16950
|
-
version: "1",
|
|
16951
|
-
source: renderAgentsMdTemplateSource()
|
|
16952
|
-
},
|
|
16953
|
-
{
|
|
16954
|
-
id: "targets/lockfile@1",
|
|
16955
|
-
target: "lockfile",
|
|
16956
|
-
version: "1",
|
|
16957
|
-
source: renderLockfileTemplateSource()
|
|
16958
|
-
},
|
|
16959
|
-
guidelineTemplateSource("targets/tabnine-guidelines/00-general-agent-behavior@1", renderGeneralAgentBehaviorTemplateSource),
|
|
16960
|
-
guidelineTemplateSource("targets/tabnine-guidelines/10-sdd-workflow@1", renderSddWorkflowGuideline),
|
|
16961
|
-
guidelineTemplateSource("targets/tabnine-guidelines/20-tdd-workflow@1", renderTddWorkflowGuideline),
|
|
16962
|
-
guidelineTemplateSource("targets/tabnine-guidelines/30-stack-typescript-svelte@1", renderTypeScriptSvelteGuideline),
|
|
16963
|
-
guidelineTemplateSource("targets/tabnine-guidelines/40-stack-java-spring@1", renderJavaSpringGuideline),
|
|
16964
|
-
guidelineTemplateSource("targets/tabnine-guidelines/50-testing-playwright-junit@1", renderPlaywrightJunitGuideline),
|
|
16965
|
-
guidelineTemplateSource("targets/tabnine-guidelines/90-final-review@1", renderFinalReviewGuideline),
|
|
16966
|
-
{
|
|
16967
|
-
id: "targets/tabnine-mcp-config@1",
|
|
16968
|
-
target: "tabnine-mcp-config",
|
|
16969
|
-
version: "1",
|
|
16970
|
-
source: JSON.stringify({ mcpServers: {} }, null, 2)
|
|
16971
|
-
},
|
|
16972
|
-
{
|
|
16973
|
-
id: "targets/codex-config@1",
|
|
16974
|
-
target: "codex-config",
|
|
16975
|
-
version: "1",
|
|
16976
|
-
source: renderCodexConfigToml()
|
|
16977
|
-
},
|
|
16978
|
-
workflowSkillTemplateSource("targets/codex-workflow-skills/sdd-change@1", "codex-workflow-skills", "sdd-change"),
|
|
16979
|
-
workflowSkillTemplateSource("targets/codex-workflow-skills/tdd-change@1", "codex-workflow-skills", "tdd-change"),
|
|
16980
|
-
workflowSkillTemplateSource("targets/codex-workflow-skills/final-review@1", "codex-workflow-skills", "final-review"),
|
|
16981
|
-
{
|
|
16982
|
-
id: "targets/claude-settings@1",
|
|
16983
|
-
target: "claude-settings",
|
|
16984
|
-
version: "1",
|
|
16985
|
-
source: renderClaudeSettingsJson()
|
|
16986
|
-
},
|
|
16987
|
-
{
|
|
16988
|
-
id: "targets/claude-mcp@1",
|
|
16989
|
-
target: "claude-mcp",
|
|
16990
|
-
version: "1",
|
|
16991
|
-
source: JSON.stringify({ mcpServers: {} }, null, 2)
|
|
16992
|
-
},
|
|
16993
|
-
{
|
|
16994
|
-
id: "targets/claude-md@1",
|
|
16995
|
-
target: "claude-md",
|
|
16996
|
-
version: "1",
|
|
16997
|
-
source: renderClaudeMd()
|
|
16998
|
-
},
|
|
16999
|
-
workflowSkillTemplateSource("targets/claude-workflow-skills/sdd-change@1", "claude-workflow-skills", "sdd-change"),
|
|
17000
|
-
workflowSkillTemplateSource("targets/claude-workflow-skills/tdd-change@1", "claude-workflow-skills", "tdd-change"),
|
|
17001
|
-
workflowSkillTemplateSource("targets/claude-workflow-skills/final-review@1", "claude-workflow-skills", "final-review")
|
|
17002
|
-
];
|
|
17003
|
-
function getDefaultTemplates() {
|
|
17004
|
-
return TEMPLATE_SOURCES.map(({ id, target, version, source }) => ({
|
|
17005
|
-
id,
|
|
17006
|
-
target,
|
|
17007
|
-
version,
|
|
17008
|
-
sha256: sha256Hex(normalizeGeneratedText(source))
|
|
17009
|
-
})).sort(compareTemplates);
|
|
17502
|
+
function compareLockOutputsV2(left, right) {
|
|
17503
|
+
return compareText(left.path, right.path) || compareText(left.target, right.target);
|
|
17010
17504
|
}
|
|
17011
|
-
|
|
17012
|
-
|
|
17013
|
-
|
|
17014
|
-
|
|
17015
|
-
|
|
17016
|
-
|
|
17017
|
-
|
|
17018
|
-
|
|
17019
|
-
|
|
17020
|
-
|
|
17021
|
-
|
|
17022
|
-
|
|
17023
|
-
|
|
17505
|
+
/**
|
|
17506
|
+
* Normalize a v1 or v2 lockfile to a uniform v2 view for consumers. v1
|
|
17507
|
+
* outputs are promoted to `generated-owned` outputs.
|
|
17508
|
+
*/
|
|
17509
|
+
function toLockfileV2View(lockfile) {
|
|
17510
|
+
if (lockfile.version === 2) return lockfile;
|
|
17511
|
+
return migrateLockfileV1ToV2(lockfile);
|
|
17512
|
+
}
|
|
17513
|
+
//#endregion
|
|
17514
|
+
//#region ../../packages/compiler/src/regions.ts
|
|
17515
|
+
var GENERATED_START_MARKER = "<!-- agent-profile:generated:start -->";
|
|
17516
|
+
var GENERATED_END_MARKER = "<!-- agent-profile:generated:end -->";
|
|
17517
|
+
var MANUAL_START_MARKER = "<!-- agent-profile:manual:start -->";
|
|
17518
|
+
var MANUAL_END_MARKER = "<!-- agent-profile:manual:end -->";
|
|
17519
|
+
var LEGACY_GENERATED_MARKER = "<!-- Generated by Agent Profile Compiler. Do not edit by hand. -->";
|
|
17520
|
+
var GENERATED_START_RE = /^<!-- agent-profile:generated:start -->$/u;
|
|
17521
|
+
var GENERATED_END_RE = /^<!-- agent-profile:generated:end -->$/u;
|
|
17522
|
+
var MANUAL_START_RE = /^<!-- agent-profile:manual:start -->$/u;
|
|
17523
|
+
var MANUAL_END_RE = /^<!-- agent-profile:manual:end -->$/u;
|
|
17524
|
+
/**
|
|
17525
|
+
* Parse a mixed-ownership instruction file (AGENTS.md or CLAUDE.md) into its
|
|
17526
|
+
* generated and manual regions. Raw bytes are preserved; no normalization is
|
|
17527
|
+
* applied so that hashes match the on-disk content exactly.
|
|
17528
|
+
*
|
|
17529
|
+
* The Phase 14 spec defines a strict file shape: the file begins with the
|
|
17530
|
+
* generated start marker, the two regions are separated by exactly one blank
|
|
17531
|
+
* line, and the file ends with the manual end marker plus a single trailing
|
|
17532
|
+
* newline. Markers that appear inside fenced code blocks (``` ... ```) are
|
|
17533
|
+
* not counted as region markers.
|
|
17534
|
+
*/
|
|
17535
|
+
function parseMixedFile(bytes) {
|
|
17536
|
+
const text = bytes.toString("utf8");
|
|
17537
|
+
const lineEndings = [];
|
|
17538
|
+
const lines = [];
|
|
17539
|
+
let position = 0;
|
|
17540
|
+
while (position < text.length) {
|
|
17541
|
+
const newlineIndex = text.indexOf("\n", position);
|
|
17542
|
+
if (newlineIndex === -1) {
|
|
17543
|
+
lines.push(text.slice(position));
|
|
17544
|
+
lineEndings.push("");
|
|
17545
|
+
break;
|
|
17546
|
+
}
|
|
17547
|
+
let lineEnd = newlineIndex;
|
|
17548
|
+
let ending = "\n";
|
|
17549
|
+
if (lineEnd > position && text[lineEnd - 1] === "\r") {
|
|
17550
|
+
lineEnd = newlineIndex - 1;
|
|
17551
|
+
ending = "\r\n";
|
|
17552
|
+
}
|
|
17553
|
+
lines.push(text.slice(position, lineEnd));
|
|
17554
|
+
lineEndings.push(ending);
|
|
17555
|
+
position = newlineIndex + 1;
|
|
17556
|
+
}
|
|
17557
|
+
const inFence = computeCodeFenceMask(lines);
|
|
17558
|
+
const matches = {
|
|
17559
|
+
generatedStart: [],
|
|
17560
|
+
generatedEnd: [],
|
|
17561
|
+
manualStart: [],
|
|
17562
|
+
manualEnd: []
|
|
17563
|
+
};
|
|
17564
|
+
lines.forEach((line, index) => {
|
|
17565
|
+
if (inFence[index]) return;
|
|
17566
|
+
if (GENERATED_START_RE.test(line)) matches.generatedStart.push(index);
|
|
17567
|
+
if (GENERATED_END_RE.test(line)) matches.generatedEnd.push(index);
|
|
17568
|
+
if (MANUAL_START_RE.test(line)) matches.manualStart.push(index);
|
|
17569
|
+
if (MANUAL_END_RE.test(line)) matches.manualEnd.push(index);
|
|
17570
|
+
});
|
|
17571
|
+
const issues = [];
|
|
17572
|
+
if (matches.generatedStart.length > 1 || matches.generatedEnd.length > 1 || matches.manualStart.length > 1 || matches.manualEnd.length > 1) {
|
|
17573
|
+
issues.push({
|
|
17574
|
+
code: "duplicate-markers",
|
|
17575
|
+
message: "Mixed instruction file contains duplicate generated/manual region markers."
|
|
17576
|
+
});
|
|
17577
|
+
return {
|
|
17578
|
+
ok: false,
|
|
17579
|
+
issues
|
|
17580
|
+
};
|
|
17581
|
+
}
|
|
17582
|
+
if (matches.generatedStart.length !== 1 || matches.generatedEnd.length !== 1 || matches.manualStart.length !== 1 || matches.manualEnd.length !== 1) {
|
|
17583
|
+
issues.push({
|
|
17584
|
+
code: "missing-markers",
|
|
17585
|
+
message: "Mixed instruction file is missing one or more required region markers."
|
|
17586
|
+
});
|
|
17587
|
+
return {
|
|
17588
|
+
ok: false,
|
|
17589
|
+
issues
|
|
17590
|
+
};
|
|
17591
|
+
}
|
|
17592
|
+
const gs = matches.generatedStart[0];
|
|
17593
|
+
const ge = matches.generatedEnd[0];
|
|
17594
|
+
const ms = matches.manualStart[0];
|
|
17595
|
+
const me = matches.manualEnd[0];
|
|
17596
|
+
if (!(gs < ge && ge < ms && ms < me)) {
|
|
17597
|
+
issues.push({
|
|
17598
|
+
code: "out-of-order",
|
|
17599
|
+
message: "Mixed instruction file region markers must appear in generated-start, generated-end, manual-start, manual-end order."
|
|
17600
|
+
});
|
|
17601
|
+
return {
|
|
17602
|
+
ok: false,
|
|
17603
|
+
issues
|
|
17604
|
+
};
|
|
17605
|
+
}
|
|
17606
|
+
if (gs !== 0) {
|
|
17607
|
+
issues.push({
|
|
17608
|
+
code: "preamble",
|
|
17609
|
+
message: "Mixed instruction file must begin with the generated start marker; no preamble bytes are allowed."
|
|
17610
|
+
});
|
|
17611
|
+
return {
|
|
17612
|
+
ok: false,
|
|
17613
|
+
issues
|
|
17614
|
+
};
|
|
17615
|
+
}
|
|
17616
|
+
if (ms !== ge + 2 || (lines[ge + 1] ?? "") !== "") {
|
|
17617
|
+
issues.push({
|
|
17618
|
+
code: "missing-blank-line",
|
|
17619
|
+
message: "Mixed instruction file must have exactly one blank line between the generated and manual regions."
|
|
17620
|
+
});
|
|
17621
|
+
return {
|
|
17622
|
+
ok: false,
|
|
17623
|
+
issues
|
|
17624
|
+
};
|
|
17625
|
+
}
|
|
17626
|
+
if (!(lines.length === me + 1 && (lineEndings[me] ?? "").length > 0)) {
|
|
17627
|
+
issues.push({
|
|
17628
|
+
code: "missing-trailing-newline",
|
|
17629
|
+
message: "Mixed instruction file must end with the manual end marker followed by exactly one trailing newline."
|
|
17630
|
+
});
|
|
17631
|
+
return {
|
|
17632
|
+
ok: false,
|
|
17633
|
+
issues
|
|
17634
|
+
};
|
|
17635
|
+
}
|
|
17636
|
+
const generatedInnerBytes = computeRangeBytes(bytes, lines, lineEndings, gs, ge);
|
|
17637
|
+
return {
|
|
17638
|
+
ok: true,
|
|
17639
|
+
generatedInner: generatedInnerBytes,
|
|
17640
|
+
manualInner: computeRangeBytes(bytes, lines, lineEndings, ms, me),
|
|
17641
|
+
generatedInnerHash: sha256Hex(generatedInnerBytes)
|
|
17642
|
+
};
|
|
17643
|
+
}
|
|
17644
|
+
function computeCodeFenceMask(lines) {
|
|
17645
|
+
const mask = new Array(lines.length).fill(false);
|
|
17646
|
+
let open = false;
|
|
17647
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
17648
|
+
const line = lines[index] ?? "";
|
|
17649
|
+
if (/^\s{0,3}(?:```|~~~)/u.test(line)) {
|
|
17650
|
+
mask[index] = open || true;
|
|
17651
|
+
open = !open;
|
|
17652
|
+
continue;
|
|
17653
|
+
}
|
|
17654
|
+
mask[index] = open;
|
|
17655
|
+
}
|
|
17656
|
+
return mask;
|
|
17657
|
+
}
|
|
17658
|
+
function computeRangeBytes(bytes, lines, lineEndings, startMarkerIndex, endMarkerIndex) {
|
|
17659
|
+
const startByte = computeByteOffsetAfterLine(lines, lineEndings, startMarkerIndex);
|
|
17660
|
+
const endByte = computeByteOffsetAtLineStart(lines, lineEndings, endMarkerIndex);
|
|
17661
|
+
return bytes.subarray(startByte, endByte);
|
|
17662
|
+
}
|
|
17663
|
+
function computeByteOffsetAfterLine(lines, lineEndings, lineIndex) {
|
|
17664
|
+
let offset = 0;
|
|
17665
|
+
for (let index = 0; index <= lineIndex; index += 1) {
|
|
17666
|
+
offset += Buffer.byteLength(lines[index] ?? "", "utf8");
|
|
17667
|
+
offset += Buffer.byteLength(lineEndings[index] ?? "", "utf8");
|
|
17668
|
+
}
|
|
17669
|
+
return offset;
|
|
17670
|
+
}
|
|
17671
|
+
function computeByteOffsetAtLineStart(lines, lineEndings, lineIndex) {
|
|
17672
|
+
let offset = 0;
|
|
17673
|
+
for (let index = 0; index < lineIndex; index += 1) {
|
|
17674
|
+
offset += Buffer.byteLength(lines[index] ?? "", "utf8");
|
|
17675
|
+
offset += Buffer.byteLength(lineEndings[index] ?? "", "utf8");
|
|
17676
|
+
}
|
|
17677
|
+
return offset;
|
|
17678
|
+
}
|
|
17679
|
+
/**
|
|
17680
|
+
* Quick predicate: do any of the four region markers appear in the file?
|
|
17681
|
+
* Used to detect partial markers and choose ownership. Marker lines inside
|
|
17682
|
+
* fenced code blocks (``` ... ``` / ~~~ ... ~~~) are not counted.
|
|
17683
|
+
*/
|
|
17684
|
+
function hasAnyRegionMarker(bytes) {
|
|
17685
|
+
const lines = bytes.toString("utf8").split(/\r?\n/u);
|
|
17686
|
+
const fence = computeCodeFenceMask(lines);
|
|
17687
|
+
return lines.some((line, index) => !fence[index] && (GENERATED_START_RE.test(line) || GENERATED_END_RE.test(line) || MANUAL_START_RE.test(line) || MANUAL_END_RE.test(line)));
|
|
17688
|
+
}
|
|
17689
|
+
function hasAllRegionMarkers(bytes) {
|
|
17690
|
+
const lines = bytes.toString("utf8").split(/\r?\n/u);
|
|
17691
|
+
const fence = computeCodeFenceMask(lines);
|
|
17692
|
+
const present = (re) => lines.some((line, index) => !fence[index] && re.test(line));
|
|
17693
|
+
return present(GENERATED_START_RE) && present(GENERATED_END_RE) && present(MANUAL_START_RE) && present(MANUAL_END_RE);
|
|
17694
|
+
}
|
|
17695
|
+
function hasLegacyGeneratedMarker(bytes) {
|
|
17696
|
+
return bytes.toString("utf8").split(/\r?\n/u).some((line) => line === LEGACY_GENERATED_MARKER);
|
|
17697
|
+
}
|
|
17698
|
+
/**
|
|
17699
|
+
* Build a mixed-ownership file from a generated inner body and a manual inner
|
|
17700
|
+
* body. The output uses LF line endings between markers and ends with a single
|
|
17701
|
+
* trailing newline.
|
|
17702
|
+
*
|
|
17703
|
+
* `generatedInner` is treated as the bytes strictly between the generated
|
|
17704
|
+
* markers (excluding marker lines). It is emitted verbatim; callers are
|
|
17705
|
+
* responsible for ensuring it is LF-normalized.
|
|
17706
|
+
*
|
|
17707
|
+
* `manualInner` is the bytes strictly between the manual markers and is
|
|
17708
|
+
* emitted verbatim with no normalization.
|
|
17709
|
+
*/
|
|
17710
|
+
function serializeMixedFile(input) {
|
|
17711
|
+
const manualInner = endsWithNewline(input.manualInner) ? input.manualInner : Buffer.concat([input.manualInner, Buffer.from("\n", "utf8")]);
|
|
17712
|
+
const parts = [
|
|
17713
|
+
Buffer.from(`${GENERATED_START_MARKER}\n`, "utf8"),
|
|
17714
|
+
input.generatedInner,
|
|
17715
|
+
Buffer.from(`${GENERATED_END_MARKER}\n`, "utf8"),
|
|
17716
|
+
Buffer.from("\n", "utf8"),
|
|
17717
|
+
Buffer.from(`${MANUAL_START_MARKER}\n`, "utf8"),
|
|
17718
|
+
manualInner,
|
|
17719
|
+
Buffer.from(`${MANUAL_END_MARKER}\n`, "utf8")
|
|
17720
|
+
];
|
|
17721
|
+
return Buffer.concat(parts);
|
|
17722
|
+
}
|
|
17723
|
+
function endsWithNewline(bytes) {
|
|
17724
|
+
if (bytes.length === 0) return false;
|
|
17725
|
+
return bytes[bytes.length - 1] === 10;
|
|
17726
|
+
}
|
|
17727
|
+
/**
|
|
17728
|
+
* Replace only the generated region of an existing mixed file with a new
|
|
17729
|
+
* generated inner body. The manual region bytes and surrounding shape are
|
|
17730
|
+
* preserved byte-for-byte.
|
|
17731
|
+
*
|
|
17732
|
+
* Returns `undefined` if the existing bytes are not a valid mixed file; the
|
|
17733
|
+
* caller must refuse to write in that case.
|
|
17734
|
+
*/
|
|
17735
|
+
function replaceGeneratedRegion(existing, newGeneratedInner) {
|
|
17736
|
+
if (!parseMixedFile(existing).ok) return void 0;
|
|
17737
|
+
const text = existing.toString("utf8");
|
|
17738
|
+
let cursor = 0;
|
|
17739
|
+
let position = 0;
|
|
17740
|
+
let generatedStartInnerByte = -1;
|
|
17741
|
+
let generatedEndLineStartByte = -1;
|
|
17742
|
+
while (position < text.length) {
|
|
17743
|
+
const newlineIndex = text.indexOf("\n", position);
|
|
17744
|
+
const hasNewline = newlineIndex !== -1;
|
|
17745
|
+
let lineEnd = hasNewline ? newlineIndex : text.length;
|
|
17746
|
+
let endingLength = 0;
|
|
17747
|
+
if (hasNewline) {
|
|
17748
|
+
endingLength = 1;
|
|
17749
|
+
if (lineEnd > position && text[lineEnd - 1] === "\r") {
|
|
17750
|
+
lineEnd -= 1;
|
|
17751
|
+
endingLength = 2;
|
|
17752
|
+
}
|
|
17753
|
+
}
|
|
17754
|
+
const line = text.slice(position, lineEnd);
|
|
17755
|
+
const lineBytes = Buffer.byteLength(line, "utf8");
|
|
17756
|
+
if (line === "<!-- agent-profile:generated:start -->" && generatedStartInnerByte === -1) generatedStartInnerByte = cursor + lineBytes + endingLength;
|
|
17757
|
+
if (line === "<!-- agent-profile:generated:end -->" && generatedEndLineStartByte === -1) generatedEndLineStartByte = cursor;
|
|
17758
|
+
cursor += lineBytes + endingLength;
|
|
17759
|
+
position = hasNewline ? newlineIndex + 1 : text.length;
|
|
17760
|
+
}
|
|
17761
|
+
if (generatedStartInnerByte === -1 || generatedEndLineStartByte === -1) return;
|
|
17762
|
+
const before = existing.subarray(0, generatedStartInnerByte);
|
|
17763
|
+
const after = existing.subarray(generatedEndLineStartByte);
|
|
17764
|
+
return Buffer.concat([
|
|
17765
|
+
before,
|
|
17766
|
+
newGeneratedInner,
|
|
17767
|
+
after
|
|
17768
|
+
]);
|
|
17769
|
+
}
|
|
17770
|
+
//#endregion
|
|
17771
|
+
//#region ../../packages/compiler/src/guidance-content.ts
|
|
17772
|
+
var REACT_STACK_TOPIC = {
|
|
17773
|
+
tabnineTitle: "TypeScript and React Stack",
|
|
17774
|
+
agentsMdTitle: "Stack Guidance — React",
|
|
17775
|
+
intro: "Use the existing TypeScript and React conventions in the repository.",
|
|
17776
|
+
subsections: [
|
|
17777
|
+
{
|
|
17778
|
+
heading: "TypeScript Discipline",
|
|
17779
|
+
bullets: [
|
|
17780
|
+
"Do not use `any` without a documented reason.",
|
|
17781
|
+
"Declare explicit types for exported functions, props, and return values.",
|
|
17782
|
+
"Reuse existing types and utilities before adding new ones."
|
|
17783
|
+
]
|
|
17784
|
+
},
|
|
17785
|
+
{
|
|
17786
|
+
heading: "Component Conventions",
|
|
17787
|
+
bullets: [
|
|
17788
|
+
"Use function components with typed props.",
|
|
17789
|
+
"Co-locate components with the modules that own them.",
|
|
17790
|
+
"Keep render-only components free of side effects."
|
|
17791
|
+
]
|
|
17792
|
+
},
|
|
17793
|
+
{
|
|
17794
|
+
heading: "Hook Discipline",
|
|
17795
|
+
bullets: [
|
|
17796
|
+
"Add memoization (`useMemo`, `useCallback`) only when a measured re-render or referential-identity problem exists.",
|
|
17797
|
+
"Keep state local; do not introduce a global store by default.",
|
|
17798
|
+
"Honor the rules of hooks; never call hooks conditionally."
|
|
17799
|
+
]
|
|
17800
|
+
},
|
|
17801
|
+
{
|
|
17802
|
+
heading: "Styling",
|
|
17803
|
+
bullets: ["Follow the existing styling approach in the repository.", "Do not introduce a new CSS framework or component library."]
|
|
17804
|
+
},
|
|
17805
|
+
{
|
|
17806
|
+
heading: "API Calls",
|
|
17807
|
+
bullets: [
|
|
17808
|
+
"Reuse existing client utilities for HTTP and data access.",
|
|
17809
|
+
"Type both request payloads and response bodies.",
|
|
17810
|
+
"Handle error and loading states explicitly."
|
|
17811
|
+
]
|
|
17812
|
+
},
|
|
17813
|
+
{
|
|
17814
|
+
heading: "SDD and TDD Focus",
|
|
17815
|
+
bullets: [
|
|
17816
|
+
"Cover state transitions, API success, error, and loading paths.",
|
|
17817
|
+
"Cover accessibility-affecting behavior (focus, keyboard, ARIA).",
|
|
17818
|
+
"Add or update focused tests before changing observable behavior."
|
|
17819
|
+
]
|
|
17820
|
+
}
|
|
17821
|
+
],
|
|
17822
|
+
tabnineChecklistReference: "See `90-final-review.md` for the shared final-review checklist.",
|
|
17823
|
+
agentsMdChecklistReference: "See the `## Completion Checklist` section for shared review steps."
|
|
17824
|
+
};
|
|
17825
|
+
var CODE_REVIEW_TOPIC = {
|
|
17826
|
+
tabnineTitle: "Code Review",
|
|
17827
|
+
agentsMdTitle: "Code Review",
|
|
17828
|
+
intro: "Use these rules when reviewing a pull request or proposed change.",
|
|
17829
|
+
subsections: [
|
|
17830
|
+
{
|
|
17831
|
+
heading: "Review Focus",
|
|
17832
|
+
bullets: [
|
|
17833
|
+
"Correctness and edge cases.",
|
|
17834
|
+
"Security, including input validation and secret handling.",
|
|
17835
|
+
"Performance hotspots and obvious complexity regressions.",
|
|
17836
|
+
"Unnecessary complexity or premature abstraction.",
|
|
17837
|
+
"Consistency with existing project style.",
|
|
17838
|
+
"Missing or weakened tests.",
|
|
17839
|
+
"Weak typing or unjustified `any`.",
|
|
17840
|
+
"Accessibility-affecting behavior in user-facing changes.",
|
|
17841
|
+
"Error handling and observability gaps.",
|
|
17842
|
+
"Dependency risk and license concerns.",
|
|
17843
|
+
"Spec compliance."
|
|
17844
|
+
]
|
|
17845
|
+
},
|
|
17846
|
+
{
|
|
17847
|
+
heading: "Severity Labels",
|
|
17848
|
+
bullets: [
|
|
17849
|
+
"Blocker: must fix before merge (correctness, security, contract break).",
|
|
17850
|
+
"High: must fix before merge unless explicitly deferred.",
|
|
17851
|
+
"Medium: should fix before merge or open a tracked follow-up.",
|
|
17852
|
+
"Low: nit or polish; safe to defer."
|
|
17853
|
+
]
|
|
17854
|
+
},
|
|
17855
|
+
{
|
|
17856
|
+
heading: "Output Format",
|
|
17857
|
+
bullets: [
|
|
17858
|
+
"Summary: one paragraph of intent and overall verdict.",
|
|
17859
|
+
"Spec Compliance: cite the spec and any deviation.",
|
|
17860
|
+
"Findings: grouped by severity, each with file, function, and concrete suggestion.",
|
|
17861
|
+
"Tests: list coverage gaps and whether tests were run.",
|
|
17862
|
+
"Safety Review: secrets, production access, dependency installs, network access.",
|
|
17863
|
+
"Final recommendation: approve, request changes, or block with reason."
|
|
17864
|
+
]
|
|
17865
|
+
},
|
|
17866
|
+
{
|
|
17867
|
+
heading: "Review Discipline",
|
|
17868
|
+
bullets: [
|
|
17869
|
+
"Skip nitpicks the autoformatter or linter already handles.",
|
|
17870
|
+
"Do not propose broad rewrites; keep suggestions actionable.",
|
|
17871
|
+
"Reference the specific file, function, or component in every finding."
|
|
17872
|
+
]
|
|
17873
|
+
}
|
|
17874
|
+
],
|
|
17875
|
+
tabnineChecklistReference: "See `90-final-review.md` for the shared final-review checklist.",
|
|
17876
|
+
agentsMdChecklistReference: "See the `## Completion Checklist` section for shared review steps."
|
|
17877
|
+
};
|
|
17878
|
+
var REFACTORING_TOPIC = {
|
|
17879
|
+
tabnineTitle: "Refactoring",
|
|
17880
|
+
agentsMdTitle: "Refactoring",
|
|
17881
|
+
intro: "Use these rules when restructuring code without changing observable behavior.",
|
|
17882
|
+
subsections: [
|
|
17883
|
+
{
|
|
17884
|
+
heading: "Principles",
|
|
17885
|
+
bullets: [
|
|
17886
|
+
"Refactor to remove duplication, clarify intent, or unlock a planned change.",
|
|
17887
|
+
"Do not refactor for style preference alone or to chase a new pattern.",
|
|
17888
|
+
"Keep refactoring commits separate from behavior changes."
|
|
17889
|
+
]
|
|
17890
|
+
},
|
|
17891
|
+
{
|
|
17892
|
+
heading: "Safe Refactoring Workflow",
|
|
17893
|
+
bullets: [
|
|
17894
|
+
"Identify the code smell or constraint that motivates the change.",
|
|
17895
|
+
"Check existing abstractions before introducing a new one.",
|
|
17896
|
+
"Define expected behavior in tests before restructuring.",
|
|
17897
|
+
"Make the smallest extraction that solves the problem.",
|
|
17898
|
+
"Preserve public behavior; run tests and golden fixtures after each step.",
|
|
17899
|
+
"Summarize what was intentionally not changed in the review notes."
|
|
17900
|
+
]
|
|
17901
|
+
},
|
|
17902
|
+
{
|
|
17903
|
+
heading: "Restrictions",
|
|
17904
|
+
bullets: [
|
|
17905
|
+
"Do not rename public APIs without explicit approval.",
|
|
17906
|
+
"Do not move files across modules without explicit approval.",
|
|
17907
|
+
"Do not change schemas, endpoint contracts, or build tooling without explicit approval.",
|
|
17908
|
+
"Do not refactor and add features in the same change."
|
|
17909
|
+
]
|
|
17910
|
+
}
|
|
17911
|
+
],
|
|
17912
|
+
tabnineChecklistReference: "See `90-final-review.md` for the shared final-review checklist.",
|
|
17913
|
+
agentsMdChecklistReference: "See the `## Completion Checklist` section for shared review steps."
|
|
17914
|
+
};
|
|
17915
|
+
var DOCUMENTATION_TOPIC = {
|
|
17916
|
+
tabnineTitle: "Documentation",
|
|
17917
|
+
agentsMdTitle: "Documentation",
|
|
17918
|
+
intro: "Use these rules when adding or updating project documentation.",
|
|
17919
|
+
subsections: [
|
|
17920
|
+
{
|
|
17921
|
+
heading: "When to Update Documentation",
|
|
17922
|
+
bullets: [
|
|
17923
|
+
"Setup or onboarding steps changed.",
|
|
17924
|
+
"Workflow, command, or build step changed.",
|
|
17925
|
+
"Public API surface changed.",
|
|
17926
|
+
"Configuration or environment variables changed.",
|
|
17927
|
+
"Testing command changed.",
|
|
17928
|
+
"Deployment or release procedure changed.",
|
|
17929
|
+
"Troubleshooting guidance is newly known."
|
|
17930
|
+
]
|
|
17931
|
+
},
|
|
17932
|
+
{
|
|
17933
|
+
heading: "Style",
|
|
17934
|
+
bullets: [
|
|
17935
|
+
"Write for maintainers, not marketing.",
|
|
17936
|
+
"Provide copy-pasteable commands where applicable.",
|
|
17937
|
+
"Keep examples current; remove examples that no longer run.",
|
|
17938
|
+
"Reference file paths when they help a reader navigate."
|
|
17939
|
+
]
|
|
17940
|
+
},
|
|
17941
|
+
{
|
|
17942
|
+
heading: "README Rules",
|
|
17943
|
+
bullets: [
|
|
17944
|
+
"Keep the existing structure intact.",
|
|
17945
|
+
"Add only relevant new sections.",
|
|
17946
|
+
"Do not rewrite the README without an explicit request."
|
|
17947
|
+
]
|
|
17948
|
+
},
|
|
17949
|
+
{
|
|
17950
|
+
heading: "Code Comment Policy",
|
|
17951
|
+
bullets: [
|
|
17952
|
+
"Comment non-obvious business rules and invariants.",
|
|
17953
|
+
"Comment tricky edge cases the code alone does not reveal.",
|
|
17954
|
+
"Comment surprising technical constraints and security-sensitive behavior.",
|
|
17955
|
+
"Do not write comments that restate the code."
|
|
17956
|
+
]
|
|
17957
|
+
}
|
|
17958
|
+
],
|
|
17959
|
+
tabnineChecklistReference: "See `90-final-review.md` for the shared final-review checklist.",
|
|
17960
|
+
agentsMdChecklistReference: "See the `## Completion Checklist` section for shared review steps."
|
|
17961
|
+
};
|
|
17962
|
+
function renderTopicAsTabnineGuideline(topic) {
|
|
17963
|
+
const sections = topic.subsections.map((subsection) => `## ${subsection.heading}\n\n${subsection.bullets.map((bullet) => `- ${bullet}`).join("\n")}\n`).join("\n");
|
|
17964
|
+
return `<!-- Generated by Agent Profile Compiler. Do not edit by hand. -->
|
|
17965
|
+
|
|
17966
|
+
# ${topic.tabnineTitle}
|
|
17967
|
+
|
|
17968
|
+
${topic.intro}
|
|
17969
|
+
|
|
17970
|
+
${sections}
|
|
17971
|
+
${topic.tabnineChecklistReference}
|
|
17972
|
+
`;
|
|
17973
|
+
}
|
|
17974
|
+
function renderTopicAsAgentsMdSection(topic) {
|
|
17975
|
+
const subsections = topic.subsections.map((subsection) => `**${subsection.heading}**\n\n${subsection.bullets.map((bullet) => `- ${bullet}`).join("\n")}`).join("\n\n");
|
|
17976
|
+
return `## ${topic.agentsMdTitle}
|
|
17977
|
+
|
|
17978
|
+
${topic.intro}
|
|
17979
|
+
|
|
17980
|
+
${subsections}
|
|
17981
|
+
|
|
17982
|
+
${topic.agentsMdChecklistReference}
|
|
17983
|
+
`;
|
|
17984
|
+
}
|
|
17985
|
+
//#endregion
|
|
17986
|
+
//#region ../../packages/compiler/src/compiler.ts
|
|
17987
|
+
var WORKFLOW_SKILLS = [
|
|
17988
|
+
{
|
|
17989
|
+
id: "grill-change",
|
|
17990
|
+
workflowFlag: "sdd"
|
|
17991
|
+
},
|
|
17992
|
+
{
|
|
17993
|
+
id: "request-to-spec-issues",
|
|
17994
|
+
workflowFlag: "sdd"
|
|
17995
|
+
},
|
|
17996
|
+
{
|
|
17997
|
+
id: "sdd-change",
|
|
17998
|
+
workflowFlag: "sdd"
|
|
17999
|
+
},
|
|
18000
|
+
{
|
|
18001
|
+
id: "tdd-change",
|
|
18002
|
+
workflowFlag: "tdd"
|
|
18003
|
+
},
|
|
18004
|
+
{
|
|
18005
|
+
id: "final-review",
|
|
18006
|
+
workflowFlag: "finalReview"
|
|
18007
|
+
},
|
|
18008
|
+
{
|
|
18009
|
+
id: "subagent-driven-change",
|
|
18010
|
+
workflowFlag: "subagentDrivenDevelopment"
|
|
18011
|
+
}
|
|
18012
|
+
];
|
|
18013
|
+
var TEMPLATE_SOURCES = [
|
|
18014
|
+
{
|
|
18015
|
+
id: "targets/agents-md@1",
|
|
18016
|
+
target: "agents-md",
|
|
18017
|
+
version: "1",
|
|
18018
|
+
source: renderAgentsMdTemplateSource()
|
|
18019
|
+
},
|
|
18020
|
+
agentsMdTopicTemplateSource("targets/agents-md/30-stack-typescript-react@1", REACT_STACK_TOPIC),
|
|
18021
|
+
agentsMdTopicTemplateSource("targets/agents-md/60-code-review@1", CODE_REVIEW_TOPIC),
|
|
18022
|
+
agentsMdTopicTemplateSource("targets/agents-md/70-refactoring@1", REFACTORING_TOPIC),
|
|
18023
|
+
agentsMdTopicTemplateSource("targets/agents-md/80-documentation@1", DOCUMENTATION_TOPIC),
|
|
18024
|
+
{
|
|
18025
|
+
id: "targets/lockfile@1",
|
|
18026
|
+
target: "lockfile",
|
|
18027
|
+
version: "1",
|
|
18028
|
+
source: renderLockfileTemplateSource()
|
|
18029
|
+
},
|
|
18030
|
+
guidelineTemplateSource("targets/tabnine-guidelines/00-general-agent-behavior@1", renderGeneralAgentBehaviorTemplateSource),
|
|
18031
|
+
guidelineTemplateSource("targets/tabnine-guidelines/05-planning-workflow@1", renderPlanningWorkflowGuideline),
|
|
18032
|
+
guidelineTemplateSource("targets/tabnine-guidelines/10-sdd-workflow@1", renderSddWorkflowGuideline),
|
|
18033
|
+
guidelineTemplateSource("targets/tabnine-guidelines/20-tdd-workflow@1", renderTddWorkflowGuideline),
|
|
18034
|
+
guidelineTemplateSource("targets/tabnine-guidelines/30-stack-typescript-svelte@1", renderTypeScriptSvelteGuideline),
|
|
18035
|
+
guidelineTemplateSource("targets/tabnine-guidelines/30-stack-typescript-react@1", renderTypeScriptReactGuideline),
|
|
18036
|
+
guidelineTemplateSource("targets/tabnine-guidelines/40-stack-java-spring@1", renderJavaSpringGuideline),
|
|
18037
|
+
guidelineTemplateSource("targets/tabnine-guidelines/50-testing-playwright-junit@1", renderPlaywrightJunitGuideline),
|
|
18038
|
+
guidelineTemplateSource("targets/tabnine-guidelines/60-code-review@1", renderCodeReviewGuideline),
|
|
18039
|
+
guidelineTemplateSource("targets/tabnine-guidelines/70-refactoring@1", renderRefactoringGuideline),
|
|
18040
|
+
guidelineTemplateSource("targets/tabnine-guidelines/80-documentation@1", renderDocumentationGuideline),
|
|
18041
|
+
guidelineTemplateSource("targets/tabnine-guidelines/90-final-review@1", renderFinalReviewGuideline),
|
|
18042
|
+
{
|
|
18043
|
+
id: "targets/tabnine-mcp-config@1",
|
|
18044
|
+
target: "tabnine-mcp-config",
|
|
18045
|
+
version: "1",
|
|
18046
|
+
source: JSON.stringify({ mcpServers: {} }, null, 2)
|
|
18047
|
+
},
|
|
18048
|
+
{
|
|
18049
|
+
id: "targets/codex-config@1",
|
|
18050
|
+
target: "codex-config",
|
|
18051
|
+
version: "1",
|
|
18052
|
+
source: renderCodexConfigToml()
|
|
18053
|
+
},
|
|
18054
|
+
workflowSkillTemplateSource("targets/codex-workflow-skills/grill-change@1", "codex-workflow-skills", "grill-change"),
|
|
18055
|
+
workflowSkillTemplateSource("targets/codex-workflow-skills/request-to-spec-issues@1", "codex-workflow-skills", "request-to-spec-issues"),
|
|
18056
|
+
workflowSkillTemplateSource("targets/codex-workflow-skills/sdd-change@1", "codex-workflow-skills", "sdd-change"),
|
|
18057
|
+
workflowSkillTemplateSource("targets/codex-workflow-skills/tdd-change@2", "codex-workflow-skills", "tdd-change"),
|
|
18058
|
+
workflowSkillTemplateSource("targets/codex-workflow-skills/final-review@1", "codex-workflow-skills", "final-review"),
|
|
18059
|
+
workflowSkillTemplateSource("targets/codex-workflow-skills/subagent-driven-change@1", "codex-workflow-skills", "subagent-driven-change"),
|
|
18060
|
+
{
|
|
18061
|
+
id: "targets/claude-settings@1",
|
|
18062
|
+
target: "claude-settings",
|
|
18063
|
+
version: "1",
|
|
18064
|
+
source: renderClaudeSettingsJson()
|
|
18065
|
+
},
|
|
18066
|
+
{
|
|
18067
|
+
id: "targets/claude-mcp@1",
|
|
18068
|
+
target: "claude-mcp",
|
|
18069
|
+
version: "1",
|
|
18070
|
+
source: JSON.stringify({ mcpServers: {} }, null, 2)
|
|
18071
|
+
},
|
|
18072
|
+
{
|
|
18073
|
+
id: "targets/claude-md@1",
|
|
18074
|
+
target: "claude-md",
|
|
18075
|
+
version: "1",
|
|
18076
|
+
source: renderClaudeMd()
|
|
18077
|
+
},
|
|
18078
|
+
workflowSkillTemplateSource("targets/claude-workflow-skills/grill-change@1", "claude-workflow-skills", "grill-change"),
|
|
18079
|
+
workflowSkillTemplateSource("targets/claude-workflow-skills/request-to-spec-issues@1", "claude-workflow-skills", "request-to-spec-issues"),
|
|
18080
|
+
workflowSkillTemplateSource("targets/claude-workflow-skills/sdd-change@1", "claude-workflow-skills", "sdd-change"),
|
|
18081
|
+
workflowSkillTemplateSource("targets/claude-workflow-skills/tdd-change@2", "claude-workflow-skills", "tdd-change"),
|
|
18082
|
+
workflowSkillTemplateSource("targets/claude-workflow-skills/final-review@1", "claude-workflow-skills", "final-review"),
|
|
18083
|
+
workflowSkillTemplateSource("targets/claude-workflow-skills/subagent-driven-change@1", "claude-workflow-skills", "subagent-driven-change")
|
|
18084
|
+
];
|
|
18085
|
+
function getDefaultTemplates() {
|
|
18086
|
+
return TEMPLATE_SOURCES.map(({ id, target, version, source }) => ({
|
|
18087
|
+
id,
|
|
18088
|
+
target,
|
|
18089
|
+
version,
|
|
18090
|
+
sha256: sha256Hex(normalizeGeneratedText(source))
|
|
18091
|
+
})).sort(compareTemplates);
|
|
18092
|
+
}
|
|
18093
|
+
function compileProfile(request) {
|
|
18094
|
+
const targets = uniqueTargets(request.targets ?? getEnabledTargetIds(request.profile));
|
|
18095
|
+
const templates = request.templates ?? mergeTemplates(getDefaultTemplates(), getSubagentTemplates(request.profile));
|
|
18096
|
+
const issues = validateTargets(request.profile, targets, templates);
|
|
18097
|
+
if (issues.length > 0) return {
|
|
18098
|
+
ok: false,
|
|
18099
|
+
issues: issues.sort(compareIssues)
|
|
18100
|
+
};
|
|
18101
|
+
const files = targets.flatMap((target) => renderTarget(target, request.profile));
|
|
18102
|
+
const requiredTemplateIds = getRequiredTemplateIdSet(targets, request.profile);
|
|
18103
|
+
return {
|
|
18104
|
+
ok: true,
|
|
18105
|
+
files: files.sort(compareGeneratedFiles),
|
|
18106
|
+
templates: templates.filter((template) => requiredTemplateIds.has(template.id)).sort(compareTemplates)
|
|
18107
|
+
};
|
|
18108
|
+
}
|
|
18109
|
+
function mergeTemplates(base, extra) {
|
|
18110
|
+
const seen = new Set(base.map((template) => template.id));
|
|
18111
|
+
const result = [...base];
|
|
18112
|
+
for (const template of extra) if (!seen.has(template.id)) {
|
|
18113
|
+
seen.add(template.id);
|
|
18114
|
+
result.push(template);
|
|
18115
|
+
}
|
|
18116
|
+
return result.sort(compareTemplates);
|
|
18117
|
+
}
|
|
18118
|
+
function getSubagentTemplates(profile) {
|
|
18119
|
+
const agents = getEnabledSubagents(profile);
|
|
18120
|
+
if (agents.length === 0) return [];
|
|
18121
|
+
const effective = deriveEffectivePermissions(profile);
|
|
18122
|
+
const templates = [];
|
|
18123
|
+
if (profile.clients.claude.enabled) for (const agent of agents) templates.push({
|
|
18124
|
+
id: `targets/claude-subagents/${agent.name}@1`,
|
|
18125
|
+
target: "claude-subagents",
|
|
18126
|
+
version: "1",
|
|
18127
|
+
sha256: sha256Hex(normalizeGeneratedText(renderClaudeSubagent(agent, effective)))
|
|
18128
|
+
});
|
|
18129
|
+
if (profile.clients.codex.enabled) for (const agent of agents) templates.push({
|
|
18130
|
+
id: `targets/codex-subagents/${agent.name}@1`,
|
|
18131
|
+
target: "codex-subagents",
|
|
18132
|
+
version: "1",
|
|
18133
|
+
sha256: sha256Hex(normalizeGeneratedText(renderCodexSubagent(agent, effective)))
|
|
18134
|
+
});
|
|
18135
|
+
if (profile.clients.tabnine.enabled) for (const agent of agents) {
|
|
18136
|
+
if (agent.toolScope !== "read-only") continue;
|
|
18137
|
+
templates.push({
|
|
18138
|
+
id: `targets/tabnine-subagents/${agent.name}@1`,
|
|
18139
|
+
target: "tabnine-subagents",
|
|
18140
|
+
version: "1",
|
|
18141
|
+
sha256: sha256Hex(normalizeGeneratedText(renderTabnineSubagent(agent)))
|
|
18142
|
+
});
|
|
18143
|
+
}
|
|
18144
|
+
return templates;
|
|
17024
18145
|
}
|
|
17025
18146
|
function renderAgentsMd(profile) {
|
|
17026
18147
|
const effectivePermissions = deriveEffectivePermissions(profile);
|
|
17027
18148
|
const enabledClients = renderEnabledClients(profile);
|
|
18149
|
+
const reactSection = profile.stack.frameworks.includes("react") ? `\n${renderTopicAsAgentsMdSection(REACT_STACK_TOPIC)}` : "";
|
|
18150
|
+
const codeReviewSection = profile.workflow.codeReview === true ? `\n${renderTopicAsAgentsMdSection(CODE_REVIEW_TOPIC)}` : "";
|
|
18151
|
+
const refactoringSection = profile.workflow.refactoring === true ? `\n${renderTopicAsAgentsMdSection(REFACTORING_TOPIC)}` : "";
|
|
18152
|
+
const documentationSection = profile.workflow.documentation === true ? `\n${renderTopicAsAgentsMdSection(DOCUMENTATION_TOPIC)}` : "";
|
|
17028
18153
|
return normalizeGeneratedText(`# AGENTS.md
|
|
17029
18154
|
|
|
18155
|
+
## Instruction Precedence
|
|
18156
|
+
|
|
18157
|
+
If generated and manual instructions conflict, follow the manual project instructions unless they would weaken safety, privacy, or permission limits. Safety, privacy, and explicit deny rules always win.
|
|
18158
|
+
|
|
17030
18159
|
## Project
|
|
17031
18160
|
|
|
17032
18161
|
Name: ${escapeMarkdownText(profile.profile.name)}
|
|
@@ -17039,7 +18168,7 @@ Description: ${escapeMarkdownText(profile.profile.description)}
|
|
|
17039
18168
|
- Frameworks: ${renderList(profile.stack.frameworks)}
|
|
17040
18169
|
- Package managers: ${renderList(profile.stack.packageManagers)}
|
|
17041
18170
|
- Testing: ${renderList(profile.stack.testing)}
|
|
17042
|
-
|
|
18171
|
+
${reactSection}
|
|
17043
18172
|
## Enabled AI Clients
|
|
17044
18173
|
|
|
17045
18174
|
${enabledClients}
|
|
@@ -17049,7 +18178,7 @@ ${enabledClients}
|
|
|
17049
18178
|
- SDD: ${renderRequired(profile.workflow.sdd)}
|
|
17050
18179
|
- TDD: ${renderRequired(profile.workflow.tdd)}
|
|
17051
18180
|
- Final implementation review: ${renderRequired(profile.workflow.finalReview)}
|
|
17052
|
-
|
|
18181
|
+
${codeReviewSection}${refactoringSection}${documentationSection}
|
|
17053
18182
|
## Permissions
|
|
17054
18183
|
|
|
17055
18184
|
| Permission | Mode |
|
|
@@ -17086,6 +18215,10 @@ Cursor, Aider, Copilot, hosted gateways, enterprise RBAC, SIEM integrations, and
|
|
|
17086
18215
|
function renderClaudeMd() {
|
|
17087
18216
|
return `<!-- Generated by Agent Profile Compiler. Do not edit by hand. -->
|
|
17088
18217
|
|
|
18218
|
+
## Instruction Precedence
|
|
18219
|
+
|
|
18220
|
+
If generated and manual instructions conflict, follow the manual project instructions unless they would weaken safety, privacy, or permission limits. Safety, privacy, and explicit deny rules always win.
|
|
18221
|
+
|
|
17089
18222
|
@AGENTS.md
|
|
17090
18223
|
|
|
17091
18224
|
# Claude Code
|
|
@@ -17117,7 +18250,10 @@ function renderTarget(target, profile) {
|
|
|
17117
18250
|
case "tabnine-guidelines": return renderTabnineGuidelines(profile);
|
|
17118
18251
|
case "lockfile": return [];
|
|
17119
18252
|
case "tabnine-mcp-config": return [createGeneratedTextFile(".tabnine/mcp_servers.json", "tabnine-mcp-config", "targets/tabnine-mcp-config@1", JSON.stringify({ mcpServers: {} }, null, 2))];
|
|
17120
|
-
case "codex-config": return [createGeneratedTextFile(".codex/config.toml", "codex-config", "targets/codex-config@1", renderCodexConfigToml())];
|
|
18253
|
+
case "codex-config": return [createGeneratedTextFile(".codex/config.toml", "codex-config", "targets/codex-config@1", renderCodexConfigToml(profile))];
|
|
18254
|
+
case "codex-subagents": return renderCodexSubagentFiles(profile);
|
|
18255
|
+
case "claude-subagents": return renderClaudeSubagentFiles(profile);
|
|
18256
|
+
case "tabnine-subagents": return renderTabnineSubagentFiles(profile);
|
|
17121
18257
|
case "codex-workflow-skills": return renderWorkflowSkillFiles(profile, "codex-workflow-skills", ".agents/skills");
|
|
17122
18258
|
case "claude-settings": return [createGeneratedTextFile(".claude/settings.json", "claude-settings", "targets/claude-settings@1", renderClaudeSettingsJson())];
|
|
17123
18259
|
case "claude-mcp": return [createGeneratedTextFile(".mcp.json", "claude-mcp", "targets/claude-mcp@1", JSON.stringify({ mcpServers: {} }, null, 2))];
|
|
@@ -17128,19 +18264,216 @@ function renderTarget(target, profile) {
|
|
|
17128
18264
|
function renderTabnineGuidelines(profile) {
|
|
17129
18265
|
const common = { target: "tabnine-guidelines" };
|
|
17130
18266
|
const files = [createGeneratedTextFile(".tabnine/guidelines/00-general-agent-behavior.md", common.target, "targets/tabnine-guidelines/00-general-agent-behavior@1", renderGeneralAgentBehaviorGuideline(profile))];
|
|
17131
|
-
if (profile.workflow.sdd)
|
|
18267
|
+
if (profile.workflow.sdd) {
|
|
18268
|
+
files.push(createGeneratedTextFile(".tabnine/guidelines/05-planning-workflow.md", common.target, "targets/tabnine-guidelines/05-planning-workflow@1", renderPlanningWorkflowGuideline()));
|
|
18269
|
+
files.push(createGeneratedTextFile(".tabnine/guidelines/10-sdd-workflow.md", common.target, "targets/tabnine-guidelines/10-sdd-workflow@1", renderSddWorkflowGuideline()));
|
|
18270
|
+
}
|
|
17132
18271
|
if (profile.workflow.tdd) files.push(createGeneratedTextFile(".tabnine/guidelines/20-tdd-workflow.md", common.target, "targets/tabnine-guidelines/20-tdd-workflow@1", renderTddWorkflowGuideline()));
|
|
17133
18272
|
if (hasStack(profile, "languages", "typescript") && hasStack(profile, "frameworks", "sveltekit")) files.push(createGeneratedTextFile(".tabnine/guidelines/30-stack-typescript-svelte.md", common.target, "targets/tabnine-guidelines/30-stack-typescript-svelte@1", renderTypeScriptSvelteGuideline()));
|
|
18273
|
+
if (hasStack(profile, "frameworks", "react")) files.push(createGeneratedTextFile(".tabnine/guidelines/30-stack-typescript-react.md", common.target, "targets/tabnine-guidelines/30-stack-typescript-react@1", renderTypeScriptReactGuideline()));
|
|
17134
18274
|
if (hasStack(profile, "languages", "java") && hasStack(profile, "frameworks", "spring-boot")) files.push(createGeneratedTextFile(".tabnine/guidelines/40-stack-java-spring.md", common.target, "targets/tabnine-guidelines/40-stack-java-spring@1", renderJavaSpringGuideline()));
|
|
17135
18275
|
if (hasAnyStack(profile, "testing", ["playwright", "junit"])) files.push(createGeneratedTextFile(".tabnine/guidelines/50-testing-playwright-junit.md", common.target, "targets/tabnine-guidelines/50-testing-playwright-junit@1", renderPlaywrightJunitGuideline()));
|
|
18276
|
+
if (profile.workflow.codeReview === true) files.push(createGeneratedTextFile(".tabnine/guidelines/60-code-review.md", common.target, "targets/tabnine-guidelines/60-code-review@1", renderCodeReviewGuideline()));
|
|
18277
|
+
if (profile.workflow.refactoring === true) files.push(createGeneratedTextFile(".tabnine/guidelines/70-refactoring.md", common.target, "targets/tabnine-guidelines/70-refactoring@1", renderRefactoringGuideline()));
|
|
18278
|
+
if (profile.workflow.documentation === true) files.push(createGeneratedTextFile(".tabnine/guidelines/80-documentation.md", common.target, "targets/tabnine-guidelines/80-documentation@1", renderDocumentationGuideline()));
|
|
17136
18279
|
if (profile.workflow.finalReview) files.push(createGeneratedTextFile(".tabnine/guidelines/90-final-review.md", common.target, "targets/tabnine-guidelines/90-final-review@1", renderFinalReviewGuideline()));
|
|
17137
18280
|
return files;
|
|
17138
18281
|
}
|
|
17139
18282
|
function renderWorkflowSkillFiles(profile, target, rootPath) {
|
|
17140
|
-
return WORKFLOW_SKILLS.filter((skill) => profile.workflow[skill.workflowFlag]).map((skill) => createGeneratedTextFile(`${rootPath}/${skill.id}/SKILL.md`, target,
|
|
18283
|
+
return WORKFLOW_SKILLS.filter((skill) => profile.workflow[skill.workflowFlag]).map((skill) => createGeneratedTextFile(`${rootPath}/${skill.id}/SKILL.md`, target, getWorkflowSkillTemplateId(target, skill.id), renderWorkflowSkill(skill.id)));
|
|
18284
|
+
}
|
|
18285
|
+
function getWorkflowSkillTemplateId(target, skill) {
|
|
18286
|
+
return `targets/${target}/${skill}@${skill === "tdd-change" ? "2" : "1"}`;
|
|
17141
18287
|
}
|
|
17142
18288
|
function renderWorkflowSkill(skill) {
|
|
17143
18289
|
switch (skill) {
|
|
18290
|
+
case "grill-change": return `---
|
|
18291
|
+
name: grill-change
|
|
18292
|
+
description: Use when a stakeholder request is rough, ambiguous, or underspecified and needs clarification before planning, writing a spec, or creating issues.
|
|
18293
|
+
---
|
|
18294
|
+
|
|
18295
|
+
<!-- Generated by Agent Profile Compiler. Do not edit by hand. -->
|
|
18296
|
+
|
|
18297
|
+
# Grill Change
|
|
18298
|
+
|
|
18299
|
+
## Purpose
|
|
18300
|
+
|
|
18301
|
+
Clarify a stakeholder request before any spec, issue plan, or implementation work starts. The output is an agreement record for a follow-up synthesis workflow; it is not an implementation plan.
|
|
18302
|
+
|
|
18303
|
+
## Operating Rules
|
|
18304
|
+
|
|
18305
|
+
1. Ask one focused question, then wait for the user's answer.
|
|
18306
|
+
2. Include a recommended answer with the question and explain why that answer is safest for the project.
|
|
18307
|
+
3. Inspect relevant local specs, ADRs, docs, fixtures, and code before asking questions that local context can answer.
|
|
18308
|
+
4. Challenge vague terms, overloaded words, and claims that conflict with repository evidence.
|
|
18309
|
+
5. Prefer concrete examples, edge cases, and tradeoff choices over broad brainstorming.
|
|
18310
|
+
6. Keep implementation details provisional until the product intent and non-goals are settled.
|
|
18311
|
+
7. Capture durable terms and hard-to-reverse decisions in the agreement record when they crystallize.
|
|
18312
|
+
8. Do not create issue lists, edit files, or start implementation during the grill.
|
|
18313
|
+
|
|
18314
|
+
## Question Format
|
|
18315
|
+
|
|
18316
|
+
Use this shape for each question:
|
|
18317
|
+
|
|
18318
|
+
Question: \`<one decision or missing fact>\`
|
|
18319
|
+
Recommended answer: \`<the default direction you would choose>\`
|
|
18320
|
+
Why: \`<short reason based on product intent, safety, contracts, or repo evidence>\`
|
|
18321
|
+
|
|
18322
|
+
## Decision Checks
|
|
18323
|
+
|
|
18324
|
+
Before ending the grill, confirm:
|
|
18325
|
+
|
|
18326
|
+
- the problem in the stakeholder's terms
|
|
18327
|
+
- the desired outcome
|
|
18328
|
+
- explicit non-goals
|
|
18329
|
+
- product intent and why the change matters
|
|
18330
|
+
- tradeoff direction for ambiguous implementation choices
|
|
18331
|
+
- user-visible behavior changes
|
|
18332
|
+
- compatibility and migration expectations
|
|
18333
|
+
- durable terminology and hard-to-reverse decisions
|
|
18334
|
+
- safety and privacy constraints
|
|
18335
|
+
- unresolved unknowns, if any
|
|
18336
|
+
|
|
18337
|
+
## Output
|
|
18338
|
+
|
|
18339
|
+
When the user agrees the grill is complete, return:
|
|
18340
|
+
|
|
18341
|
+
- Problem
|
|
18342
|
+
- Intent
|
|
18343
|
+
- Non-goals
|
|
18344
|
+
- Decisions made
|
|
18345
|
+
- Durable terms and hard-to-reverse decisions
|
|
18346
|
+
- Decision rules for implementation tradeoffs
|
|
18347
|
+
- Open questions or risks
|
|
18348
|
+
- Confirmation that post-grill synthesis can run next
|
|
18349
|
+
|
|
18350
|
+
## Safety
|
|
18351
|
+
|
|
18352
|
+
- Do not upload source code.
|
|
18353
|
+
- Do not read or print secrets.
|
|
18354
|
+
- Do not ask for credentials, environment values, production data, or private endpoints.
|
|
18355
|
+
- Do not propose \`bypassPermissions\`, tool pre-approval, dependency auto-installation, hosted execution, or remote MCP behavior.
|
|
18356
|
+
- Do not write files, create issues, commit changes, or run implementation commands during the grill.
|
|
18357
|
+
`;
|
|
18358
|
+
case "request-to-spec-issues": return `---
|
|
18359
|
+
name: request-to-spec-issues
|
|
18360
|
+
description: Use after a grill-change session is complete to turn the agreement record into an intent-first spec candidate and vertical TDD-ready issue briefs.
|
|
18361
|
+
---
|
|
18362
|
+
|
|
18363
|
+
<!-- Generated by Agent Profile Compiler. Do not edit by hand. -->
|
|
18364
|
+
|
|
18365
|
+
# Request To Spec Issues
|
|
18366
|
+
|
|
18367
|
+
## Purpose
|
|
18368
|
+
|
|
18369
|
+
Convert a completed \`grill-change\` agreement record into an intent-first spec candidate and vertical TDD-ready issue briefs. Preserve product intent and decision rules so implementation choices follow the agreed direction.
|
|
18370
|
+
|
|
18371
|
+
## Preconditions
|
|
18372
|
+
|
|
18373
|
+
- The grill is complete.
|
|
18374
|
+
- The user has confirmed the direction is ready for synthesis.
|
|
18375
|
+
- Relevant local specs, ADRs, docs, fixtures, and code context have been checked.
|
|
18376
|
+
- If there is no completed grill agreement, stop and run \`grill-change\` first.
|
|
18377
|
+
|
|
18378
|
+
## Synthesis Rules
|
|
18379
|
+
|
|
18380
|
+
1. Do not re-interview the user unless the grill record contains a contradiction or a genuinely missing decision.
|
|
18381
|
+
2. Keep product intent, non-goals, durable terms, and hard-to-reverse decisions above implementation mechanics.
|
|
18382
|
+
3. Preserve existing spec contracts and safety rules unless the user explicitly approved changing them.
|
|
18383
|
+
4. Split work into vertical behavior slices, not file layers.
|
|
18384
|
+
5. Make every issue small enough for a focused RED, GREEN, refactor loop.
|
|
18385
|
+
6. Mark dependencies and parallel-safe work explicitly.
|
|
18386
|
+
7. Propose architecture rescue candidates before feature slices when a change would deepen an already fragmented codebase.
|
|
18387
|
+
|
|
18388
|
+
## Architecture Rescue Candidates
|
|
18389
|
+
|
|
18390
|
+
When architecture rescue is needed, propose candidates before feature issues. Each candidate must include:
|
|
18391
|
+
|
|
18392
|
+
- Files or modules involved
|
|
18393
|
+
- Current friction
|
|
18394
|
+
- Proposed deeper module or clearer interface
|
|
18395
|
+
- Expected locality and leverage improvement
|
|
18396
|
+
- Expected test improvement
|
|
18397
|
+
- ADR or spec conflicts
|
|
18398
|
+
- Recommended dependency state: prerequisite, parallel, or later cleanup
|
|
18399
|
+
|
|
18400
|
+
## Spec Candidate
|
|
18401
|
+
|
|
18402
|
+
Include these sections:
|
|
18403
|
+
|
|
18404
|
+
- Status
|
|
18405
|
+
- Problem
|
|
18406
|
+
- Goal
|
|
18407
|
+
- Intent
|
|
18408
|
+
- Decision Rules
|
|
18409
|
+
- Non-Goals
|
|
18410
|
+
- User Flow
|
|
18411
|
+
- Inputs
|
|
18412
|
+
- Outputs
|
|
18413
|
+
- Contracts
|
|
18414
|
+
- Security Rules
|
|
18415
|
+
- Acceptance Criteria
|
|
18416
|
+
- Tests
|
|
18417
|
+
- TDD Strategy
|
|
18418
|
+
- Issue Plan
|
|
18419
|
+
- Documentation Updates
|
|
18420
|
+
- Final Review Checklist
|
|
18421
|
+
|
|
18422
|
+
\`TDD Strategy\` complements \`Tests\`; it must not replace the required \`Tests\`
|
|
18423
|
+
section from \`docs/specs/SPEC_TEMPLATE.md\`.
|
|
18424
|
+
|
|
18425
|
+
## Issue Brief Format
|
|
18426
|
+
|
|
18427
|
+
Each issue brief must include:
|
|
18428
|
+
|
|
18429
|
+
- Title
|
|
18430
|
+
- Parent spec or request
|
|
18431
|
+
- Intent summary
|
|
18432
|
+
- Behavior slice
|
|
18433
|
+
- Non-goals
|
|
18434
|
+
- Acceptance criteria
|
|
18435
|
+
- Expected RED proof
|
|
18436
|
+
- Expected GREEN proof
|
|
18437
|
+
- Test command guidance
|
|
18438
|
+
- Likely file ownership
|
|
18439
|
+
- Dependencies
|
|
18440
|
+
- Parallelism notes
|
|
18441
|
+
- Contract impact
|
|
18442
|
+
- Security impact
|
|
18443
|
+
- Documentation impact
|
|
18444
|
+
- Implementation context
|
|
18445
|
+
- Review expectations
|
|
18446
|
+
|
|
18447
|
+
## Dependency States
|
|
18448
|
+
|
|
18449
|
+
Use these states:
|
|
18450
|
+
|
|
18451
|
+
- \`ready\`
|
|
18452
|
+
- \`blocked\`
|
|
18453
|
+
- \`parallel-safe\`
|
|
18454
|
+
- \`sequenced\`
|
|
18455
|
+
- \`human-gate\`
|
|
18456
|
+
|
|
18457
|
+
## Output
|
|
18458
|
+
|
|
18459
|
+
Return:
|
|
18460
|
+
|
|
18461
|
+
- Spec candidate or spec patch
|
|
18462
|
+
- Vertical issue briefs
|
|
18463
|
+
- Dependency map
|
|
18464
|
+
- Parallelism map
|
|
18465
|
+
- Human gates
|
|
18466
|
+
- Recommended next step
|
|
18467
|
+
|
|
18468
|
+
## Safety
|
|
18469
|
+
|
|
18470
|
+
- Do not upload source code.
|
|
18471
|
+
- Do not read or print secrets.
|
|
18472
|
+
- Do not include credentials, environment values, production data, or private endpoints.
|
|
18473
|
+
- Do not create GitHub issues, labels, projects, or milestones.
|
|
18474
|
+
- Do not write files unless the user explicitly asks for local file writes after reviewing the synthesis.
|
|
18475
|
+
- Do not propose \`bypassPermissions\`, tool pre-approval, dependency auto-installation, hosted execution, or remote MCP behavior.
|
|
18476
|
+
`;
|
|
17144
18477
|
case "sdd-change": return `---
|
|
17145
18478
|
name: sdd-change
|
|
17146
18479
|
description: Use when implementing a meaningful repository change that requires an approved spec before code edits.
|
|
@@ -17168,7 +18501,7 @@ description: Use when implementing a meaningful repository change that requires
|
|
|
17168
18501
|
`;
|
|
17169
18502
|
case "tdd-change": return `---
|
|
17170
18503
|
name: tdd-change
|
|
17171
|
-
description: Use when changing behavior where a focused failing test or golden fixture
|
|
18504
|
+
description: Use when changing behavior where a focused failing test or golden fixture must prove RED before implementation and GREEN after the minimal fix.
|
|
17172
18505
|
---
|
|
17173
18506
|
|
|
17174
18507
|
<!-- Generated by Agent Profile Compiler. Do not edit by hand. -->
|
|
@@ -17178,11 +18511,24 @@ description: Use when changing behavior where a focused failing test or golden f
|
|
|
17178
18511
|
## Instructions
|
|
17179
18512
|
|
|
17180
18513
|
1. Identify the smallest observable behavior covered by the approved spec.
|
|
17181
|
-
2. Add or update
|
|
17182
|
-
3.
|
|
17183
|
-
4. Implement the smallest change that satisfies the test and spec.
|
|
17184
|
-
5. Run the
|
|
17185
|
-
6.
|
|
18514
|
+
2. Add or update one focused failing test or golden fixture before changing behavior code.
|
|
18515
|
+
3. Run the narrowest relevant test command and confirm RED: the test fails for the expected reason, not because of a typo, setup error, or unrelated failure.
|
|
18516
|
+
4. Implement the smallest change that satisfies the failing test and the spec.
|
|
18517
|
+
5. Run the same focused test command and confirm GREEN: the test passes without new warnings or unrelated failures.
|
|
18518
|
+
6. Refactor only after GREEN, then rerun the focused test command.
|
|
18519
|
+
7. Do not update golden files only to hide an unexplained behavior change.
|
|
18520
|
+
|
|
18521
|
+
## Testing Anti-Patterns
|
|
18522
|
+
|
|
18523
|
+
- Do not assert on mock elements or mock call counts when a real behavior assertion is possible.
|
|
18524
|
+
- Do not add production methods, flags, or exports that exist only for tests.
|
|
18525
|
+
- Do not mock a dependency until you understand the side effects the test needs.
|
|
18526
|
+
- Keep test doubles structurally complete enough to match the real data shape consumed by the code.
|
|
18527
|
+
- If mock setup is larger than the behavior under test, consider a narrower integration test or a simpler production boundary.
|
|
18528
|
+
|
|
18529
|
+
## Output
|
|
18530
|
+
|
|
18531
|
+
Report the RED command and expected failure, the GREEN command and passing result, any refactor rerun, and any TDD exception that required human approval.
|
|
17186
18532
|
|
|
17187
18533
|
## Safety
|
|
17188
18534
|
|
|
@@ -17211,6 +18557,55 @@ description: Use before handing off an implementation to compare the diff agains
|
|
|
17211
18557
|
## Output
|
|
17212
18558
|
|
|
17213
18559
|
Return a concise final review with spec compliance, tests run, contract impact, security impact, and remaining risks.
|
|
18560
|
+
`;
|
|
18561
|
+
case "subagent-driven-change": return `---
|
|
18562
|
+
name: subagent-driven-change
|
|
18563
|
+
description: Use when a scoped implementation can be delegated to an implementation subagent and then independently reviewed for spec compliance before code quality.
|
|
18564
|
+
---
|
|
18565
|
+
|
|
18566
|
+
<!-- Generated by Agent Profile Compiler. Do not edit by hand. -->
|
|
18567
|
+
|
|
18568
|
+
# Subagent-Driven Change
|
|
18569
|
+
|
|
18570
|
+
## Preconditions
|
|
18571
|
+
|
|
18572
|
+
Use this workflow only when the task has a clear spec, acceptance criteria, and file ownership. Keep tightly coupled or architectural decisions in the parent session unless the user explicitly asks for delegation.
|
|
18573
|
+
|
|
18574
|
+
Required subagents: \`implementer\`, \`spec-reviewer\`, and \`code-quality-reviewer\`.
|
|
18575
|
+
|
|
18576
|
+
## Fresh Context
|
|
18577
|
+
|
|
18578
|
+
Each subagent prompt must include the full task text, relevant spec excerpts, non-goals, acceptance criteria, file ownership, constraints, expected tests, and any command limits. Do not rely on hidden chat history or a previous subagent's memory.
|
|
18579
|
+
|
|
18580
|
+
## Flow
|
|
18581
|
+
|
|
18582
|
+
1. Dispatch \`implementer\` with one bounded task and the complete context it needs.
|
|
18583
|
+
2. If \`implementer\` returns \`BLOCKED\` or \`NEEDS_CONTEXT\`, resolve that before continuing.
|
|
18584
|
+
3. If \`implementer\` returns \`DONE_WITH_CONCERNS\`, read the concerns before review and decide whether to fix, narrow scope, or continue.
|
|
18585
|
+
4. Dispatch \`spec-reviewer\` with the original task, relevant spec excerpts, changed files, and implementer report.
|
|
18586
|
+
5. Fix or escalate every spec-review issue before requesting code-quality review.
|
|
18587
|
+
6. Dispatch \`code-quality-reviewer\` only after spec review reports compliance.
|
|
18588
|
+
7. Fix Critical and Important code-quality issues before handoff, or document why a finding is intentionally deferred.
|
|
18589
|
+
8. Run the relevant tests, golden tests, and doctor/check commands required by the spec before final response.
|
|
18590
|
+
|
|
18591
|
+
## Status Values
|
|
18592
|
+
|
|
18593
|
+
Implementation worker status values: \`DONE\`, \`DONE_WITH_CONCERNS\`, \`BLOCKED\`, \`NEEDS_CONTEXT\`.
|
|
18594
|
+
|
|
18595
|
+
Spec reviewer status values: \`COMPLIANT\`, \`ISSUES_FOUND\`, \`NEEDS_CONTEXT\`.
|
|
18596
|
+
|
|
18597
|
+
Code-quality reviewer status values: \`ACCEPTABLE\`, \`ISSUES_FOUND\`, \`NEEDS_CONTEXT\`.
|
|
18598
|
+
|
|
18599
|
+
## Safety
|
|
18600
|
+
|
|
18601
|
+
- Do not ask subagents to commit, push, create branches, install dependencies, read secrets, contact production systems, or upload source unless the user explicitly requested that action.
|
|
18602
|
+
- Do not accept an implementation report without reading reviewer findings.
|
|
18603
|
+
- Do not run code-quality review before spec-compliance review passes.
|
|
18604
|
+
- Keep generated files deterministic and lockfile-tracked.
|
|
18605
|
+
|
|
18606
|
+
## Output
|
|
18607
|
+
|
|
18608
|
+
Final handoff must list what changed, tests run, contract impact, security impact, remaining risks or TODOs, and whether the spec acceptance criteria are fully met.
|
|
17214
18609
|
`;
|
|
17215
18610
|
}
|
|
17216
18611
|
}
|
|
@@ -17248,6 +18643,23 @@ Use the repository-local profile as the source of truth for agent behavior.
|
|
|
17248
18643
|
- Ask before mutating files, running shell commands, installing dependencies, or using external network access.
|
|
17249
18644
|
`;
|
|
17250
18645
|
}
|
|
18646
|
+
function renderPlanningWorkflowGuideline() {
|
|
18647
|
+
return `<!-- Generated by Agent Profile Compiler. Do not edit by hand. -->
|
|
18648
|
+
|
|
18649
|
+
# Planning Workflow
|
|
18650
|
+
|
|
18651
|
+
Use this before implementation when a stakeholder request is rough, ambiguous, or not yet tied to an approved spec.
|
|
18652
|
+
|
|
18653
|
+
- Clarify the request one decision at a time before writing or changing specs.
|
|
18654
|
+
- Provide a recommended answer and short rationale for each open decision.
|
|
18655
|
+
- Check local specs, ADRs, docs, fixtures, and generated artifacts before asking questions.
|
|
18656
|
+
- Preserve product intent, non-goals, tradeoffs, durable terms, and hard-to-reverse decisions.
|
|
18657
|
+
- If no completed clarification exists, complete the grill-style clarification first.
|
|
18658
|
+
- After clarification, prepare an intent-first spec candidate and vertical TDD-ready issue briefs.
|
|
18659
|
+
- Include dependencies, expected RED proof, expected GREEN proof, file ownership, contract impact, security impact, and review expectations in each issue brief.
|
|
18660
|
+
- Do not create GitHub issues, write files, upload source, read secrets, install dependencies, or change runtime permissions unless explicitly requested and allowed.
|
|
18661
|
+
`;
|
|
18662
|
+
}
|
|
17251
18663
|
function renderSddWorkflowGuideline() {
|
|
17252
18664
|
return `<!-- Generated by Agent Profile Compiler. Do not edit by hand. -->
|
|
17253
18665
|
|
|
@@ -17276,6 +18688,18 @@ Test-driven development is required for this project.
|
|
|
17276
18688
|
- Do not update golden fixtures to hide an unexplained behavior change.
|
|
17277
18689
|
`;
|
|
17278
18690
|
}
|
|
18691
|
+
function renderTypeScriptReactGuideline() {
|
|
18692
|
+
return renderTopicAsTabnineGuideline(REACT_STACK_TOPIC);
|
|
18693
|
+
}
|
|
18694
|
+
function renderCodeReviewGuideline() {
|
|
18695
|
+
return renderTopicAsTabnineGuideline(CODE_REVIEW_TOPIC);
|
|
18696
|
+
}
|
|
18697
|
+
function renderRefactoringGuideline() {
|
|
18698
|
+
return renderTopicAsTabnineGuideline(REFACTORING_TOPIC);
|
|
18699
|
+
}
|
|
18700
|
+
function renderDocumentationGuideline() {
|
|
18701
|
+
return renderTopicAsTabnineGuideline(DOCUMENTATION_TOPIC);
|
|
18702
|
+
}
|
|
17279
18703
|
function renderTypeScriptSvelteGuideline() {
|
|
17280
18704
|
return `<!-- Generated by Agent Profile Compiler. Do not edit by hand. -->
|
|
17281
18705
|
|
|
@@ -17334,14 +18758,115 @@ Final implementation review is required for this project.
|
|
|
17334
18758
|
- List remaining risks or TODOs before considering the task complete.
|
|
17335
18759
|
`;
|
|
17336
18760
|
}
|
|
17337
|
-
function renderCodexConfigToml() {
|
|
17338
|
-
|
|
18761
|
+
function renderCodexConfigToml(profile) {
|
|
18762
|
+
const base = `approval_policy = "on-request"
|
|
17339
18763
|
sandbox_mode = "workspace-write"
|
|
17340
18764
|
allow_login_shell = false
|
|
17341
18765
|
|
|
17342
18766
|
[sandbox_workspace_write]
|
|
17343
18767
|
network_access = false
|
|
17344
18768
|
`;
|
|
18769
|
+
if (!profile || getEnabledSubagents(profile).length === 0) return base;
|
|
18770
|
+
const defaults = getSubagentDefaults(profile);
|
|
18771
|
+
return `${base}
|
|
18772
|
+
[agents]
|
|
18773
|
+
max_threads = ${defaults.maxConcurrent}
|
|
18774
|
+
max_depth = ${defaults.maxDepth}
|
|
18775
|
+
`;
|
|
18776
|
+
}
|
|
18777
|
+
function renderClaudeSubagentFiles(profile) {
|
|
18778
|
+
const agents = getEnabledSubagents(profile);
|
|
18779
|
+
const effective = deriveEffectivePermissions(profile);
|
|
18780
|
+
return agents.map((agent) => createGeneratedTextFile(`.claude/agents/${agent.name}.md`, "claude-subagents", `targets/claude-subagents/${agent.name}@1`, renderClaudeSubagent(agent, effective)));
|
|
18781
|
+
}
|
|
18782
|
+
function renderCodexSubagentFiles(profile) {
|
|
18783
|
+
const agents = getEnabledSubagents(profile);
|
|
18784
|
+
const effective = deriveEffectivePermissions(profile);
|
|
18785
|
+
return agents.map((agent) => createGeneratedTextFile(`.codex/agents/${agent.name}.toml`, "codex-subagents", `targets/codex-subagents/${agent.name}@1`, renderCodexSubagent(agent, effective)));
|
|
18786
|
+
}
|
|
18787
|
+
function renderTabnineSubagentFiles(profile) {
|
|
18788
|
+
return getEnabledSubagents(profile).filter((agent) => agent.toolScope === "read-only").map((agent) => createGeneratedTextFile(`.tabnine/agent/agents/${agent.name}.md`, "tabnine-subagents", `targets/tabnine-subagents/${agent.name}@1`, renderTabnineSubagent(agent)));
|
|
18789
|
+
}
|
|
18790
|
+
function titleCaseFromKebab(name) {
|
|
18791
|
+
return name.split("-").filter((part) => part.length > 0).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
18792
|
+
}
|
|
18793
|
+
function renderClaudeSubagent(agent, effective) {
|
|
18794
|
+
const lines = ["---", `name: ${yamlScalarSafe(agent.name)}`];
|
|
18795
|
+
lines.push(`description: ${yamlScalarSafe(agent.description)}`);
|
|
18796
|
+
if (agent.toolScope === "read-only") lines.push("tools: Read, Glob, Grep");
|
|
18797
|
+
else {
|
|
18798
|
+
const tools = [
|
|
18799
|
+
"Read",
|
|
18800
|
+
"Glob",
|
|
18801
|
+
"Grep"
|
|
18802
|
+
];
|
|
18803
|
+
if (effective.filesystem.write !== "deny") tools.push("Edit", "Write");
|
|
18804
|
+
if (effective.shell.run !== "deny") tools.push("Bash");
|
|
18805
|
+
if (effective.network.external !== "deny") tools.push("WebFetch");
|
|
18806
|
+
lines.push(`tools: ${tools.join(", ")}`);
|
|
18807
|
+
}
|
|
18808
|
+
const model = agent.modelPreference ?? "inherit";
|
|
18809
|
+
lines.push(`model: ${model === "inherit" ? "inherit" : "inherit"}`);
|
|
18810
|
+
if (agent.toolScope === "read-only") lines.push("permissionMode: plan");
|
|
18811
|
+
if (agent.maxTurns !== void 0) lines.push(`maxTurns: ${agent.maxTurns}`);
|
|
18812
|
+
lines.push("---", "");
|
|
18813
|
+
lines.push("<!-- Generated by Agent Profile Compiler. Do not edit by hand. -->");
|
|
18814
|
+
lines.push("");
|
|
18815
|
+
lines.push(`# ${titleCaseFromKebab(agent.name)}`);
|
|
18816
|
+
lines.push("");
|
|
18817
|
+
lines.push(agent.prompt.trim());
|
|
18818
|
+
lines.push("");
|
|
18819
|
+
return lines.join("\n");
|
|
18820
|
+
}
|
|
18821
|
+
function renderCodexSubagent(agent, effective) {
|
|
18822
|
+
const lines = [
|
|
18823
|
+
"# Generated by Agent Profile Compiler. Do not edit by hand.",
|
|
18824
|
+
"",
|
|
18825
|
+
`name = "${escapeTomlString(agent.name)}"`,
|
|
18826
|
+
`description = "${escapeTomlString(agent.description)}"`
|
|
18827
|
+
];
|
|
18828
|
+
if (agent.toolScope === "workspace-write" && effective.filesystem.write !== "deny") lines.push(`sandbox_mode = "workspace-write"`);
|
|
18829
|
+
else lines.push(`sandbox_mode = "read-only"`);
|
|
18830
|
+
if (agent.prompt.includes(`"""`)) throw new Error(`Codex subagent ${agent.name} prompt contains a TOML triple-quote sequence; compile validation should have rejected this.`);
|
|
18831
|
+
lines.push("developer_instructions = \"\"\"");
|
|
18832
|
+
for (const promptLine of agent.prompt.trim().split(/\r?\n/u)) lines.push(promptLine);
|
|
18833
|
+
lines.push("\"\"\"");
|
|
18834
|
+
lines.push("");
|
|
18835
|
+
return lines.join("\n");
|
|
18836
|
+
}
|
|
18837
|
+
function renderTabnineSubagent(agent) {
|
|
18838
|
+
const lines = ["---", `name: ${yamlScalarSafe(agent.name)}`];
|
|
18839
|
+
lines.push(`description: ${yamlScalarSafe(agent.description)}`);
|
|
18840
|
+
lines.push("kind: local");
|
|
18841
|
+
lines.push("tools:");
|
|
18842
|
+
for (const tool of ["grep_search", "read_file"].sort()) lines.push(` - ${tool}`);
|
|
18843
|
+
if (agent.maxTurns !== void 0) lines.push(`max_turns: ${agent.maxTurns}`);
|
|
18844
|
+
if (agent.timeoutMinutes !== void 0) lines.push(`timeout_mins: ${agent.timeoutMinutes}`);
|
|
18845
|
+
lines.push("---", "");
|
|
18846
|
+
lines.push("<!-- Generated by Agent Profile Compiler. Do not edit by hand. -->");
|
|
18847
|
+
lines.push("");
|
|
18848
|
+
lines.push(`# ${titleCaseFromKebab(agent.name)}`);
|
|
18849
|
+
lines.push("");
|
|
18850
|
+
lines.push(agent.prompt.trim());
|
|
18851
|
+
lines.push("");
|
|
18852
|
+
return lines.join("\n");
|
|
18853
|
+
}
|
|
18854
|
+
function escapeTomlString(value) {
|
|
18855
|
+
return value.replace(/\\/gu, "\\\\").replace(/"/gu, "\\\"");
|
|
18856
|
+
}
|
|
18857
|
+
function yamlScalarSafe(value) {
|
|
18858
|
+
if (yamlScalarNeedsQuoting(value)) return JSON.stringify(value);
|
|
18859
|
+
return value;
|
|
18860
|
+
}
|
|
18861
|
+
function yamlScalarNeedsQuoting(value) {
|
|
18862
|
+
if (value.length === 0) return true;
|
|
18863
|
+
if (/[\r\n\t]/u.test(value)) return true;
|
|
18864
|
+
if (/^\s|\s$/u.test(value)) return true;
|
|
18865
|
+
if (/^[\-?:,\[\]{}#&*!|>'"%@`]/u.test(value)) return true;
|
|
18866
|
+
if (value.includes(": ") || value.includes(" #")) return true;
|
|
18867
|
+
if (/^(?:true|false|null|yes|no|on|off|~)$/iu.test(value)) return true;
|
|
18868
|
+
if (/^[+\-]?\d+(?:\.\d+)?(?:[eE][+\-]?\d+)?$/u.test(value)) return true;
|
|
18869
|
+
return false;
|
|
17345
18870
|
}
|
|
17346
18871
|
function renderAgentsMdTemplateSource() {
|
|
17347
18872
|
return `# AGENTS.md
|
|
@@ -17380,6 +18905,14 @@ function guidelineTemplateSource(id, render) {
|
|
|
17380
18905
|
source: render()
|
|
17381
18906
|
};
|
|
17382
18907
|
}
|
|
18908
|
+
function agentsMdTopicTemplateSource(id, topic) {
|
|
18909
|
+
return {
|
|
18910
|
+
id,
|
|
18911
|
+
target: "agents-md",
|
|
18912
|
+
version: "1",
|
|
18913
|
+
source: renderTopicAsAgentsMdSection(topic)
|
|
18914
|
+
};
|
|
18915
|
+
}
|
|
17383
18916
|
function workflowSkillTemplateSource(id, target, skill) {
|
|
17384
18917
|
return {
|
|
17385
18918
|
id,
|
|
@@ -17418,9 +18951,19 @@ function renderClaudeSettingsJson() {
|
|
|
17418
18951
|
}
|
|
17419
18952
|
function getEnabledTargetIds(profile) {
|
|
17420
18953
|
const targets = ["agents-md"];
|
|
17421
|
-
|
|
17422
|
-
if (profile.clients.
|
|
17423
|
-
|
|
18954
|
+
const subagentsEnabled = getEnabledSubagents(profile).length > 0;
|
|
18955
|
+
if (profile.clients.tabnine.enabled) {
|
|
18956
|
+
targets.push("tabnine-guidelines", "tabnine-mcp-config");
|
|
18957
|
+
if (subagentsEnabled) targets.push("tabnine-subagents");
|
|
18958
|
+
}
|
|
18959
|
+
if (profile.clients.codex.enabled) {
|
|
18960
|
+
targets.push("codex-config", "codex-workflow-skills");
|
|
18961
|
+
if (subagentsEnabled) targets.push("codex-subagents");
|
|
18962
|
+
}
|
|
18963
|
+
if (profile.clients.claude.enabled) {
|
|
18964
|
+
targets.push("claude-settings", "claude-mcp", "claude-md", "claude-workflow-skills");
|
|
18965
|
+
if (subagentsEnabled) targets.push("claude-subagents");
|
|
18966
|
+
}
|
|
17424
18967
|
return targets;
|
|
17425
18968
|
}
|
|
17426
18969
|
function validateTargets(profile, targets, templates) {
|
|
@@ -17428,6 +18971,56 @@ function validateTargets(profile, targets, templates) {
|
|
|
17428
18971
|
const templateIds = new Set(templates.map((template) => template.id));
|
|
17429
18972
|
const enabledTargets = new Set(getEnabledTargetIds(profile));
|
|
17430
18973
|
const issues = [];
|
|
18974
|
+
if (profile.workflow.subagentDrivenDevelopment === true) {
|
|
18975
|
+
const refs = new Set(getSubagentTemplateRefs(profile));
|
|
18976
|
+
const missing = SUBAGENT_TEMPLATE_NAMES.filter((name) => !refs.has(name));
|
|
18977
|
+
if (missing.length > 0) issues.push({
|
|
18978
|
+
code: "missing_required_template_reference",
|
|
18979
|
+
path: "/workflow/subagentDrivenDevelopment",
|
|
18980
|
+
expected: `useTemplate references for ${SUBAGENT_TEMPLATE_NAMES.join(", ")}`,
|
|
18981
|
+
actual: `missing ${missing.join(", ")}`,
|
|
18982
|
+
message: `workflow.subagentDrivenDevelopment requires capabilities.delegation.subagents.agents[].useTemplate references for ${missing.join(", ")}.`
|
|
18983
|
+
});
|
|
18984
|
+
}
|
|
18985
|
+
if (targets.includes("tabnine-subagents")) {
|
|
18986
|
+
const writeAgents = getEnabledSubagents(profile).filter((agent) => agent.toolScope === "workspace-write");
|
|
18987
|
+
for (const agent of writeAgents) issues.push({
|
|
18988
|
+
code: "unsafe_generated_content",
|
|
18989
|
+
path: `.tabnine/agent/agents/${agent.name}.md`,
|
|
18990
|
+
expected: "read-only Tabnine subagent",
|
|
18991
|
+
actual: "workspace-write Tabnine subagent",
|
|
18992
|
+
message: `tabnine-subagents cannot emit workspace-write agent ${agent.name} while Tabnine subagents are experimental/no-confirmation.`
|
|
18993
|
+
});
|
|
18994
|
+
}
|
|
18995
|
+
if (targets.includes("codex-subagents")) {
|
|
18996
|
+
const effective = deriveEffectivePermissions(profile);
|
|
18997
|
+
for (const agent of getEnabledSubagents(profile)) {
|
|
18998
|
+
if (agent.toolScope === "workspace-write" && effective.filesystem.write === "deny") issues.push({
|
|
18999
|
+
code: "unsafe_generated_content",
|
|
19000
|
+
path: `.codex/agents/${agent.name}.toml`,
|
|
19001
|
+
expected: "narrower than effectivePermissions",
|
|
19002
|
+
actual: "workspace-write subagent under filesystem.write=deny",
|
|
19003
|
+
message: `codex-subagents cannot emit workspace-write agent ${agent.name} because effectivePermissions.filesystem.write is deny.`
|
|
19004
|
+
});
|
|
19005
|
+
if (agent.prompt.includes(`"""`)) issues.push({
|
|
19006
|
+
code: "unsafe_generated_content",
|
|
19007
|
+
path: `.codex/agents/${agent.name}.toml`,
|
|
19008
|
+
expected: "prompt without TOML triple-quote sequence",
|
|
19009
|
+
actual: "prompt contains \"\"\" delimiter",
|
|
19010
|
+
message: `codex-subagents prompt for ${agent.name} contains a TOML triple-quote sequence that would break developer_instructions.`
|
|
19011
|
+
});
|
|
19012
|
+
}
|
|
19013
|
+
}
|
|
19014
|
+
if (targets.includes("claude-subagents")) {
|
|
19015
|
+
const effective = deriveEffectivePermissions(profile);
|
|
19016
|
+
for (const agent of getEnabledSubagents(profile)) if (agent.toolScope === "workspace-write" && effective.filesystem.write === "deny") issues.push({
|
|
19017
|
+
code: "unsafe_generated_content",
|
|
19018
|
+
path: `.claude/agents/${agent.name}.md`,
|
|
19019
|
+
expected: "narrower than effectivePermissions",
|
|
19020
|
+
actual: "workspace-write subagent under filesystem.write=deny",
|
|
19021
|
+
message: `claude-subagents cannot emit workspace-write agent ${agent.name} because effectivePermissions.filesystem.write is deny.`
|
|
19022
|
+
});
|
|
19023
|
+
}
|
|
17431
19024
|
for (const target of targets) {
|
|
17432
19025
|
if (!supportedTargets.has(target)) {
|
|
17433
19026
|
issues.push({
|
|
@@ -17449,7 +19042,7 @@ function validateTargets(profile, targets, templates) {
|
|
|
17449
19042
|
});
|
|
17450
19043
|
continue;
|
|
17451
19044
|
}
|
|
17452
|
-
for (const templateId of getRequiredTemplateIds(target)) if (!templateIds.has(templateId)) issues.push({
|
|
19045
|
+
for (const templateId of getRequiredTemplateIds(target, profile)) if (!templateIds.has(templateId)) issues.push({
|
|
17453
19046
|
code: "missing_template",
|
|
17454
19047
|
path: target,
|
|
17455
19048
|
expected: templateId,
|
|
@@ -17459,8 +19052,48 @@ function validateTargets(profile, targets, templates) {
|
|
|
17459
19052
|
}
|
|
17460
19053
|
return issues;
|
|
17461
19054
|
}
|
|
17462
|
-
function
|
|
17463
|
-
return
|
|
19055
|
+
function getRequiredTemplateIdSet(targets, profile) {
|
|
19056
|
+
return new Set(targets.flatMap((target) => getRequiredTemplateIds(target, profile)));
|
|
19057
|
+
}
|
|
19058
|
+
function getRequiredTemplateIds(target, profile) {
|
|
19059
|
+
switch (target) {
|
|
19060
|
+
case "agents-md": return ["targets/agents-md@1", ...getRequiredAgentsMdTopicTemplateIds(profile)];
|
|
19061
|
+
case "tabnine-guidelines": return getRequiredTabnineGuidelineTemplateIds(profile);
|
|
19062
|
+
case "codex-workflow-skills": return getRequiredWorkflowSkillTemplateIds(profile, "codex-workflow-skills");
|
|
19063
|
+
case "claude-workflow-skills": return getRequiredWorkflowSkillTemplateIds(profile, "claude-workflow-skills");
|
|
19064
|
+
case "claude-subagents": return getEnabledSubagents(profile).map((agent) => `targets/claude-subagents/${agent.name}@1`);
|
|
19065
|
+
case "codex-subagents": return getEnabledSubagents(profile).map((agent) => `targets/codex-subagents/${agent.name}@1`);
|
|
19066
|
+
case "tabnine-subagents": return getEnabledSubagents(profile).filter((agent) => agent.toolScope === "read-only").map((agent) => `targets/tabnine-subagents/${agent.name}@1`);
|
|
19067
|
+
default: return TEMPLATE_SOURCES.filter((template) => template.target === target).map((template) => template.id);
|
|
19068
|
+
}
|
|
19069
|
+
}
|
|
19070
|
+
function getRequiredAgentsMdTopicTemplateIds(profile) {
|
|
19071
|
+
const ids = [];
|
|
19072
|
+
if (hasStack(profile, "frameworks", "react")) ids.push("targets/agents-md/30-stack-typescript-react@1");
|
|
19073
|
+
if (profile.workflow.codeReview === true) ids.push("targets/agents-md/60-code-review@1");
|
|
19074
|
+
if (profile.workflow.refactoring === true) ids.push("targets/agents-md/70-refactoring@1");
|
|
19075
|
+
if (profile.workflow.documentation === true) ids.push("targets/agents-md/80-documentation@1");
|
|
19076
|
+
return ids;
|
|
19077
|
+
}
|
|
19078
|
+
function getRequiredTabnineGuidelineTemplateIds(profile) {
|
|
19079
|
+
const ids = ["targets/tabnine-guidelines/00-general-agent-behavior@1"];
|
|
19080
|
+
if (profile.workflow.sdd) {
|
|
19081
|
+
ids.push("targets/tabnine-guidelines/05-planning-workflow@1");
|
|
19082
|
+
ids.push("targets/tabnine-guidelines/10-sdd-workflow@1");
|
|
19083
|
+
}
|
|
19084
|
+
if (profile.workflow.tdd) ids.push("targets/tabnine-guidelines/20-tdd-workflow@1");
|
|
19085
|
+
if (hasStack(profile, "languages", "typescript") && hasStack(profile, "frameworks", "sveltekit")) ids.push("targets/tabnine-guidelines/30-stack-typescript-svelte@1");
|
|
19086
|
+
if (hasStack(profile, "frameworks", "react")) ids.push("targets/tabnine-guidelines/30-stack-typescript-react@1");
|
|
19087
|
+
if (hasStack(profile, "languages", "java") && hasStack(profile, "frameworks", "spring-boot")) ids.push("targets/tabnine-guidelines/40-stack-java-spring@1");
|
|
19088
|
+
if (hasAnyStack(profile, "testing", ["playwright", "junit"])) ids.push("targets/tabnine-guidelines/50-testing-playwright-junit@1");
|
|
19089
|
+
if (profile.workflow.codeReview === true) ids.push("targets/tabnine-guidelines/60-code-review@1");
|
|
19090
|
+
if (profile.workflow.refactoring === true) ids.push("targets/tabnine-guidelines/70-refactoring@1");
|
|
19091
|
+
if (profile.workflow.documentation === true) ids.push("targets/tabnine-guidelines/80-documentation@1");
|
|
19092
|
+
if (profile.workflow.finalReview) ids.push("targets/tabnine-guidelines/90-final-review@1");
|
|
19093
|
+
return ids;
|
|
19094
|
+
}
|
|
19095
|
+
function getRequiredWorkflowSkillTemplateIds(profile, target) {
|
|
19096
|
+
return WORKFLOW_SKILLS.filter((skill) => profile.workflow[skill.workflowFlag]).map((skill) => getWorkflowSkillTemplateId(target, skill.id));
|
|
17464
19097
|
}
|
|
17465
19098
|
function uniqueTargets(targets) {
|
|
17466
19099
|
return Array.from(new Set(targets));
|
|
@@ -17498,6 +19131,92 @@ function compareIssues(left, right) {
|
|
|
17498
19131
|
}
|
|
17499
19132
|
//#endregion
|
|
17500
19133
|
//#region ../../packages/compiler/src/write-plan.ts
|
|
19134
|
+
async function planWrites(request) {
|
|
19135
|
+
return planWritesWithResolvedRoot(await fsPromises.realpath(path.resolve(request.rootDir)), request.writes);
|
|
19136
|
+
}
|
|
19137
|
+
async function planWritesWithResolvedRoot(rootRealPath, plannedWrites) {
|
|
19138
|
+
const writes = normalizeWrites(plannedWrites);
|
|
19139
|
+
const actions = [];
|
|
19140
|
+
for (const write of writes) {
|
|
19141
|
+
const current = await readOptionalFile(await assertWritePathContained(rootRealPath, write.path));
|
|
19142
|
+
const action = current ? Buffer.from(current).equals(Buffer.from(write.bytes)) ? "unchanged" : "change" : "create";
|
|
19143
|
+
actions.push({
|
|
19144
|
+
path: write.path,
|
|
19145
|
+
action,
|
|
19146
|
+
plannedBytes: write.bytes.byteLength
|
|
19147
|
+
});
|
|
19148
|
+
}
|
|
19149
|
+
return {
|
|
19150
|
+
actions,
|
|
19151
|
+
counts: countActions(actions)
|
|
19152
|
+
};
|
|
19153
|
+
}
|
|
19154
|
+
async function applyWritePlan(request) {
|
|
19155
|
+
const rootRealPath = await fsPromises.realpath(path.resolve(request.rootDir));
|
|
19156
|
+
const writes = normalizeWrites(request.writes);
|
|
19157
|
+
const plan = await planWritesWithResolvedRoot(rootRealPath, writes);
|
|
19158
|
+
const writesByPath = new Map(writes.map((write) => [write.path, write]));
|
|
19159
|
+
for (const action of plan.actions) {
|
|
19160
|
+
if (action.action === "unchanged") continue;
|
|
19161
|
+
const write = writesByPath.get(action.path);
|
|
19162
|
+
if (!write) continue;
|
|
19163
|
+
const absolutePath = await assertWritePathContained(rootRealPath, write.path);
|
|
19164
|
+
await fsPromises.mkdir(path.dirname(absolutePath), { recursive: true });
|
|
19165
|
+
await fsPromises.writeFile(absolutePath, write.bytes);
|
|
19166
|
+
}
|
|
19167
|
+
return plan;
|
|
19168
|
+
}
|
|
19169
|
+
function normalizeWrites(writes) {
|
|
19170
|
+
return writes.map((write) => ({
|
|
19171
|
+
path: safeOutputPath(write.path),
|
|
19172
|
+
bytes: typeof write.bytes === "string" ? Buffer.from(write.bytes, "utf8") : write.bytes
|
|
19173
|
+
})).sort((left, right) => compareText(left.path, right.path));
|
|
19174
|
+
}
|
|
19175
|
+
function countActions(actions) {
|
|
19176
|
+
return {
|
|
19177
|
+
create: actions.filter((action) => action.action === "create").length,
|
|
19178
|
+
change: actions.filter((action) => action.action === "change").length,
|
|
19179
|
+
unchanged: actions.filter((action) => action.action === "unchanged").length
|
|
19180
|
+
};
|
|
19181
|
+
}
|
|
19182
|
+
async function assertWritePathContained(rootRealPath, relativePath) {
|
|
19183
|
+
const safePath = safeOutputPath(relativePath);
|
|
19184
|
+
const absolutePath = path.resolve(rootRealPath, ...safePath.split("/").filter(Boolean));
|
|
19185
|
+
if (!isContainedBy(rootRealPath, absolutePath)) throw new Error(`Planned write escapes root: ${safePath}`);
|
|
19186
|
+
const existingTarget = await lstatOptional$1(absolutePath);
|
|
19187
|
+
if (existingTarget) {
|
|
19188
|
+
if (existingTarget.isSymbolicLink()) throw new Error(`Planned write target is a symlink (refusing to follow): ${safePath}`);
|
|
19189
|
+
if (!isContainedBy(rootRealPath, await fsPromises.realpath(absolutePath))) throw new Error(`Planned write target escapes root: ${safePath}`);
|
|
19190
|
+
}
|
|
19191
|
+
const existingParent = await findExistingAncestor(path.dirname(absolutePath));
|
|
19192
|
+
if (!isContainedBy(rootRealPath, await fsPromises.realpath(existingParent))) throw new Error(`Planned write parent escapes root: ${safePath}`);
|
|
19193
|
+
return absolutePath;
|
|
19194
|
+
}
|
|
19195
|
+
async function findExistingAncestor(startPath) {
|
|
19196
|
+
let current = startPath;
|
|
19197
|
+
while (true) {
|
|
19198
|
+
if (await lstatOptional$1(current)) return current;
|
|
19199
|
+
const parent = path.dirname(current);
|
|
19200
|
+
if (parent === current) throw new Error(`No existing parent directory for ${startPath}`);
|
|
19201
|
+
current = parent;
|
|
19202
|
+
}
|
|
19203
|
+
}
|
|
19204
|
+
async function readOptionalFile(absolutePath) {
|
|
19205
|
+
try {
|
|
19206
|
+
return await fsPromises.readFile(absolutePath);
|
|
19207
|
+
} catch (error) {
|
|
19208
|
+
if (isNodeError(error) && error.code === "ENOENT") return;
|
|
19209
|
+
throw error;
|
|
19210
|
+
}
|
|
19211
|
+
}
|
|
19212
|
+
async function lstatOptional$1(absolutePath) {
|
|
19213
|
+
try {
|
|
19214
|
+
return await fsPromises.lstat(absolutePath);
|
|
19215
|
+
} catch (error) {
|
|
19216
|
+
if (isNodeError(error) && error.code === "ENOENT") return;
|
|
19217
|
+
throw error;
|
|
19218
|
+
}
|
|
19219
|
+
}
|
|
17501
19220
|
function isContainedBy(rootPath, candidatePath) {
|
|
17502
19221
|
const relative = path.relative(rootPath, candidatePath);
|
|
17503
19222
|
return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
@@ -17592,6 +19311,599 @@ function computeFileEtag(bytes) {
|
|
|
17592
19311
|
return "sha256:" + createHash("sha256").update(bytes).digest("hex");
|
|
17593
19312
|
}
|
|
17594
19313
|
//#endregion
|
|
19314
|
+
//#region ../../packages/compiler/src/import-report.ts
|
|
19315
|
+
var PHASE_14_SUPPORTED_PATHS = [
|
|
19316
|
+
{
|
|
19317
|
+
path: "AGENTS.md",
|
|
19318
|
+
kind: "root-instructions",
|
|
19319
|
+
isLocalRuntime: false
|
|
19320
|
+
},
|
|
19321
|
+
{
|
|
19322
|
+
path: "CLAUDE.md",
|
|
19323
|
+
kind: "root-instructions",
|
|
19324
|
+
isLocalRuntime: false
|
|
19325
|
+
},
|
|
19326
|
+
{
|
|
19327
|
+
path: ".claude/settings.json",
|
|
19328
|
+
kind: "client-config",
|
|
19329
|
+
isLocalRuntime: false
|
|
19330
|
+
},
|
|
19331
|
+
{
|
|
19332
|
+
path: ".claude/settings.local.json",
|
|
19333
|
+
kind: "client-config",
|
|
19334
|
+
isLocalRuntime: true
|
|
19335
|
+
},
|
|
19336
|
+
{
|
|
19337
|
+
path: ".codex/config.toml",
|
|
19338
|
+
kind: "client-config",
|
|
19339
|
+
isLocalRuntime: true
|
|
19340
|
+
},
|
|
19341
|
+
{
|
|
19342
|
+
path: ".codex/hooks.json",
|
|
19343
|
+
kind: "client-config",
|
|
19344
|
+
isLocalRuntime: true
|
|
19345
|
+
},
|
|
19346
|
+
{
|
|
19347
|
+
path: ".mcp.json",
|
|
19348
|
+
kind: "mcp-config",
|
|
19349
|
+
isLocalRuntime: true
|
|
19350
|
+
}
|
|
19351
|
+
];
|
|
19352
|
+
var PHASE_14_SCAN_DIRS = [
|
|
19353
|
+
{
|
|
19354
|
+
root: ".agents/skills",
|
|
19355
|
+
kind: "workflow-skill",
|
|
19356
|
+
fileFilter: (rel) => rel.endsWith("/SKILL.md"),
|
|
19357
|
+
recursive: true
|
|
19358
|
+
},
|
|
19359
|
+
{
|
|
19360
|
+
root: ".claude/skills",
|
|
19361
|
+
kind: "workflow-skill",
|
|
19362
|
+
fileFilter: (rel) => rel.endsWith("/SKILL.md"),
|
|
19363
|
+
recursive: true
|
|
19364
|
+
},
|
|
19365
|
+
{
|
|
19366
|
+
root: ".claude/agents",
|
|
19367
|
+
kind: "subagent",
|
|
19368
|
+
fileFilter: (rel) => rel.endsWith(".md"),
|
|
19369
|
+
recursive: false
|
|
19370
|
+
},
|
|
19371
|
+
{
|
|
19372
|
+
root: ".codex/agents",
|
|
19373
|
+
kind: "subagent",
|
|
19374
|
+
fileFilter: (rel) => rel.endsWith(".toml"),
|
|
19375
|
+
recursive: false
|
|
19376
|
+
},
|
|
19377
|
+
{
|
|
19378
|
+
root: ".tabnine/agent/agents",
|
|
19379
|
+
kind: "subagent",
|
|
19380
|
+
fileFilter: (rel) => rel.endsWith(".md"),
|
|
19381
|
+
recursive: false
|
|
19382
|
+
}
|
|
19383
|
+
];
|
|
19384
|
+
var RECOMMENDED_IGNORE_LINES = [
|
|
19385
|
+
".cce/",
|
|
19386
|
+
".mcp.json",
|
|
19387
|
+
".claude/settings.local.json",
|
|
19388
|
+
".claude/worktrees/",
|
|
19389
|
+
".codex/config.toml",
|
|
19390
|
+
".codex/hooks.json"
|
|
19391
|
+
];
|
|
19392
|
+
async function buildPhase14ImportReport(input) {
|
|
19393
|
+
const files = [];
|
|
19394
|
+
let wouldUpdateRegions = 0;
|
|
19395
|
+
let preservedManualFiles = 0;
|
|
19396
|
+
let conflicts = 0;
|
|
19397
|
+
const collisionsByKey = /* @__PURE__ */ new Map();
|
|
19398
|
+
const lockfile = await readLockfileForRegions(input.rootDir);
|
|
19399
|
+
const ownershipByPath = /* @__PURE__ */ new Map();
|
|
19400
|
+
if (lockfile) for (const output of lockfile.outputs) ownershipByPath.set(output.path, output.ownership);
|
|
19401
|
+
for (const entry of PHASE_14_SUPPORTED_PATHS) {
|
|
19402
|
+
const read = await readRegionAwareFile(input.rootDir, entry.path);
|
|
19403
|
+
if (read.refused) {
|
|
19404
|
+
files.push({
|
|
19405
|
+
path: entry.path,
|
|
19406
|
+
exists: true,
|
|
19407
|
+
kind: entry.kind,
|
|
19408
|
+
ownership: "unknown",
|
|
19409
|
+
tags: [],
|
|
19410
|
+
action: "refuse-conflict",
|
|
19411
|
+
notes: ["symlinked; Phase 14 refuses to follow file symlinks"]
|
|
19412
|
+
});
|
|
19413
|
+
conflicts += 1;
|
|
19414
|
+
continue;
|
|
19415
|
+
}
|
|
19416
|
+
const existing = read.bytes;
|
|
19417
|
+
if (!existing) {
|
|
19418
|
+
if (entry.kind === "root-instructions") files.push({
|
|
19419
|
+
path: entry.path,
|
|
19420
|
+
exists: false,
|
|
19421
|
+
kind: entry.kind,
|
|
19422
|
+
ownership: "unknown",
|
|
19423
|
+
tags: [],
|
|
19424
|
+
action: "create",
|
|
19425
|
+
notes: []
|
|
19426
|
+
});
|
|
19427
|
+
continue;
|
|
19428
|
+
}
|
|
19429
|
+
const bytes = Buffer.from(existing);
|
|
19430
|
+
const tags = [];
|
|
19431
|
+
if (entry.isLocalRuntime) tags.push("local-runtime");
|
|
19432
|
+
if (containsAbsolutePathLiteral(bytes)) tags.push("contains-absolute-path");
|
|
19433
|
+
if (entry.kind === "client-config" && !entry.isLocalRuntime) {
|
|
19434
|
+
const ownership = ownershipByPath.get(entry.path) ?? "generated-owned";
|
|
19435
|
+
files.push({
|
|
19436
|
+
path: entry.path,
|
|
19437
|
+
exists: true,
|
|
19438
|
+
kind: entry.kind,
|
|
19439
|
+
ownership,
|
|
19440
|
+
tags,
|
|
19441
|
+
action: "preserve",
|
|
19442
|
+
notes: ["generated client config; refresh via `agent-profile compile --write`"]
|
|
19443
|
+
});
|
|
19444
|
+
preservedManualFiles += 1;
|
|
19445
|
+
continue;
|
|
19446
|
+
}
|
|
19447
|
+
if (entry.kind !== "root-instructions") {
|
|
19448
|
+
files.push({
|
|
19449
|
+
path: entry.path,
|
|
19450
|
+
exists: true,
|
|
19451
|
+
kind: entry.kind,
|
|
19452
|
+
ownership: "manual-owned",
|
|
19453
|
+
tags,
|
|
19454
|
+
action: "ignore-local-runtime",
|
|
19455
|
+
notes: entry.kind === "mcp-config" ? ["contains MCP entries; not imported into ai-profile.yaml in Phase 14"] : ["local runtime config; not adopted by Phase 14"]
|
|
19456
|
+
});
|
|
19457
|
+
preservedManualFiles += 1;
|
|
19458
|
+
continue;
|
|
19459
|
+
}
|
|
19460
|
+
if (hasAllRegionMarkers(bytes)) {
|
|
19461
|
+
const parsed = parseMixedFile(bytes);
|
|
19462
|
+
if (!parsed.ok) {
|
|
19463
|
+
files.push({
|
|
19464
|
+
path: entry.path,
|
|
19465
|
+
exists: true,
|
|
19466
|
+
kind: entry.kind,
|
|
19467
|
+
ownership: "unknown",
|
|
19468
|
+
tags,
|
|
19469
|
+
action: "refuse-conflict",
|
|
19470
|
+
notes: parsed.issues.map((item) => item.message)
|
|
19471
|
+
});
|
|
19472
|
+
conflicts += 1;
|
|
19473
|
+
continue;
|
|
19474
|
+
}
|
|
19475
|
+
files.push({
|
|
19476
|
+
path: entry.path,
|
|
19477
|
+
exists: true,
|
|
19478
|
+
kind: entry.kind,
|
|
19479
|
+
ownership: "mixed",
|
|
19480
|
+
tags,
|
|
19481
|
+
action: "update-generated-region",
|
|
19482
|
+
notes: []
|
|
19483
|
+
});
|
|
19484
|
+
if (input.strategy === "regions") wouldUpdateRegions += 1;
|
|
19485
|
+
continue;
|
|
19486
|
+
}
|
|
19487
|
+
if (hasAnyRegionMarker(bytes)) {
|
|
19488
|
+
files.push({
|
|
19489
|
+
path: entry.path,
|
|
19490
|
+
exists: true,
|
|
19491
|
+
kind: entry.kind,
|
|
19492
|
+
ownership: "unknown",
|
|
19493
|
+
tags,
|
|
19494
|
+
action: "refuse-conflict",
|
|
19495
|
+
notes: ["partial region markers; manual repair required"]
|
|
19496
|
+
});
|
|
19497
|
+
conflicts += 1;
|
|
19498
|
+
continue;
|
|
19499
|
+
}
|
|
19500
|
+
if (hasLegacyGeneratedMarker(bytes)) tags.push("generated-looking");
|
|
19501
|
+
if (input.strategy === "regions") {
|
|
19502
|
+
files.push({
|
|
19503
|
+
path: entry.path,
|
|
19504
|
+
exists: true,
|
|
19505
|
+
kind: entry.kind,
|
|
19506
|
+
ownership: "unknown",
|
|
19507
|
+
tags,
|
|
19508
|
+
action: "insert-regions",
|
|
19509
|
+
notes: ["existing content will be preserved in manual region"]
|
|
19510
|
+
});
|
|
19511
|
+
wouldUpdateRegions += 1;
|
|
19512
|
+
} else {
|
|
19513
|
+
files.push({
|
|
19514
|
+
path: entry.path,
|
|
19515
|
+
exists: true,
|
|
19516
|
+
kind: entry.kind,
|
|
19517
|
+
ownership: "unknown",
|
|
19518
|
+
tags,
|
|
19519
|
+
action: "preserve",
|
|
19520
|
+
notes: ["Run init --import --strategy regions --write to adopt into mixed ownership"]
|
|
19521
|
+
});
|
|
19522
|
+
preservedManualFiles += 1;
|
|
19523
|
+
}
|
|
19524
|
+
}
|
|
19525
|
+
for (const scan of PHASE_14_SCAN_DIRS) {
|
|
19526
|
+
const { files: discovered, refusals: scanRefusals } = await listFilesUnder(input.rootDir, scan.root, scan.recursive);
|
|
19527
|
+
for (const refusedPath of scanRefusals) {
|
|
19528
|
+
files.push({
|
|
19529
|
+
path: refusedPath,
|
|
19530
|
+
exists: true,
|
|
19531
|
+
kind: scan.kind,
|
|
19532
|
+
ownership: "unknown",
|
|
19533
|
+
tags: [],
|
|
19534
|
+
action: "refuse-conflict",
|
|
19535
|
+
notes: ["symlinked; Phase 14 refuses to follow file symlinks"]
|
|
19536
|
+
});
|
|
19537
|
+
conflicts += 1;
|
|
19538
|
+
}
|
|
19539
|
+
for (const relativePath of discovered) {
|
|
19540
|
+
if (!scan.fileFilter(relativePath)) continue;
|
|
19541
|
+
const read = await readRegionAwareFile(input.rootDir, relativePath);
|
|
19542
|
+
const tags = [];
|
|
19543
|
+
if (read.bytes) {
|
|
19544
|
+
const name = extractDeclaredName(Buffer.from(read.bytes), relativePath);
|
|
19545
|
+
if (name) recordName(scan.kind === "workflow-skill" ? "workflow-skill" : "subagent", name, relativePath, collisionsByKey);
|
|
19546
|
+
}
|
|
19547
|
+
if (read.refused) {
|
|
19548
|
+
files.push({
|
|
19549
|
+
path: relativePath,
|
|
19550
|
+
exists: true,
|
|
19551
|
+
kind: scan.kind,
|
|
19552
|
+
ownership: "unknown",
|
|
19553
|
+
tags,
|
|
19554
|
+
action: "refuse-conflict",
|
|
19555
|
+
notes: ["symlinked; Phase 14 refuses to follow file symlinks"]
|
|
19556
|
+
});
|
|
19557
|
+
conflicts += 1;
|
|
19558
|
+
continue;
|
|
19559
|
+
}
|
|
19560
|
+
if (!read.bytes) continue;
|
|
19561
|
+
const lockOwnership = ownershipByPath.get(relativePath);
|
|
19562
|
+
if (lockOwnership === "generated-owned") {
|
|
19563
|
+
files.push({
|
|
19564
|
+
path: relativePath,
|
|
19565
|
+
exists: true,
|
|
19566
|
+
kind: scan.kind,
|
|
19567
|
+
ownership: "generated-owned",
|
|
19568
|
+
tags,
|
|
19569
|
+
action: "preserve",
|
|
19570
|
+
notes: ["lockfile-owned generated output; refresh via `agent-profile compile --write`"]
|
|
19571
|
+
});
|
|
19572
|
+
preservedManualFiles += 1;
|
|
19573
|
+
continue;
|
|
19574
|
+
}
|
|
19575
|
+
if (lockOwnership === "mixed") {
|
|
19576
|
+
files.push({
|
|
19577
|
+
path: relativePath,
|
|
19578
|
+
exists: true,
|
|
19579
|
+
kind: scan.kind,
|
|
19580
|
+
ownership: "mixed",
|
|
19581
|
+
tags,
|
|
19582
|
+
action: "update-generated-region",
|
|
19583
|
+
notes: ["lockfile-owned mixed file; generated region is updated on compile --write"]
|
|
19584
|
+
});
|
|
19585
|
+
if (input.strategy === "regions") wouldUpdateRegions += 1;
|
|
19586
|
+
continue;
|
|
19587
|
+
}
|
|
19588
|
+
files.push({
|
|
19589
|
+
path: relativePath,
|
|
19590
|
+
exists: true,
|
|
19591
|
+
kind: scan.kind,
|
|
19592
|
+
ownership: "manual-owned",
|
|
19593
|
+
tags,
|
|
19594
|
+
action: "preserve",
|
|
19595
|
+
notes: [scan.kind === "workflow-skill" ? "existing workflow skill; not adopted as generated output" : "existing subagent file; not adopted as generated output"]
|
|
19596
|
+
});
|
|
19597
|
+
preservedManualFiles += 1;
|
|
19598
|
+
}
|
|
19599
|
+
}
|
|
19600
|
+
const gitignore = (await getLocalRuntimeGitignoreFindings(input.rootDir)).map((finding) => ({
|
|
19601
|
+
path: ".gitignore",
|
|
19602
|
+
line: finding.line,
|
|
19603
|
+
action: finding.action === "already-present" ? "already-present" : input.mode === "write" ? "would-add" : "suggest-add",
|
|
19604
|
+
reason: finding.reason
|
|
19605
|
+
}));
|
|
19606
|
+
const collisions = [];
|
|
19607
|
+
for (const [key, paths] of collisionsByKey) {
|
|
19608
|
+
if (paths.length < 2) continue;
|
|
19609
|
+
const [kindPart, name] = key.split("\0");
|
|
19610
|
+
collisions.push({
|
|
19611
|
+
name,
|
|
19612
|
+
kind: kindPart === "workflow-skill" ? "workflow-skill" : "subagent",
|
|
19613
|
+
paths: [...paths].sort()
|
|
19614
|
+
});
|
|
19615
|
+
for (const collidingPath of paths) {
|
|
19616
|
+
const row = files.find((f) => f.path === collidingPath);
|
|
19617
|
+
if (row && !row.notes.some((n) => n.startsWith("name collision"))) {
|
|
19618
|
+
const others = paths.filter((p) => p !== collidingPath).sort();
|
|
19619
|
+
row.notes.push(`name collision: \"${name}\" also declared by ${others.join(", ")}`);
|
|
19620
|
+
}
|
|
19621
|
+
}
|
|
19622
|
+
}
|
|
19623
|
+
collisions.sort((left, right) => {
|
|
19624
|
+
if (left.kind !== right.kind) return left.kind === "workflow-skill" ? -1 : 1;
|
|
19625
|
+
return left.name < right.name ? -1 : left.name > right.name ? 1 : 0;
|
|
19626
|
+
});
|
|
19627
|
+
return {
|
|
19628
|
+
command: "init",
|
|
19629
|
+
mode: input.mode,
|
|
19630
|
+
strategy: input.strategy,
|
|
19631
|
+
root: ".",
|
|
19632
|
+
profilePath: input.profilePath,
|
|
19633
|
+
stack: {
|
|
19634
|
+
languages: [...input.stack.languages].sort(),
|
|
19635
|
+
frameworks: [...input.stack.frameworks].sort(),
|
|
19636
|
+
packageManagers: [...input.stack.packageManagers].sort(),
|
|
19637
|
+
testing: [...input.stack.testing].sort()
|
|
19638
|
+
},
|
|
19639
|
+
files: files.sort((left, right) => left.path < right.path ? -1 : left.path > right.path ? 1 : 0),
|
|
19640
|
+
gitignore,
|
|
19641
|
+
collisions,
|
|
19642
|
+
summary: {
|
|
19643
|
+
wouldCreateProfile: input.wouldCreateProfile,
|
|
19644
|
+
wouldUpdateRegions,
|
|
19645
|
+
preservedManualFiles,
|
|
19646
|
+
conflicts,
|
|
19647
|
+
nameCollisions: collisions.length
|
|
19648
|
+
}
|
|
19649
|
+
};
|
|
19650
|
+
}
|
|
19651
|
+
function recordName(kind, name, path, map) {
|
|
19652
|
+
const key = `${kind}\0${name}`;
|
|
19653
|
+
const existing = map.get(key);
|
|
19654
|
+
if (existing) existing.push(path);
|
|
19655
|
+
else map.set(key, [path]);
|
|
19656
|
+
}
|
|
19657
|
+
/**
|
|
19658
|
+
* Extract the declared `name:` value from a SKILL.md / claude-style
|
|
19659
|
+
* subagent (.md with YAML frontmatter) or codex-style subagent (.toml).
|
|
19660
|
+
*
|
|
19661
|
+
* This deliberately avoids pulling in a YAML or TOML parser — the
|
|
19662
|
+
* relevant section is small, the line shape is fixed, and we want the
|
|
19663
|
+
* shared report module to stay dependency-light. Returns undefined when
|
|
19664
|
+
* no name is found; callers treat that as "this file does not
|
|
19665
|
+
* participate in collision detection."
|
|
19666
|
+
*/
|
|
19667
|
+
function extractDeclaredName(bytes, relativePath) {
|
|
19668
|
+
const text = bytes.toString("utf8");
|
|
19669
|
+
if (relativePath.endsWith(".toml")) return findTomlTopLevelName(text);
|
|
19670
|
+
if (relativePath.endsWith(".md")) return findYamlFrontmatterName(text);
|
|
19671
|
+
}
|
|
19672
|
+
function findYamlFrontmatterName(text) {
|
|
19673
|
+
const lines = text.split(/\r?\n/u);
|
|
19674
|
+
if (lines.length === 0 || lines[0].trim() !== "---") return void 0;
|
|
19675
|
+
for (let index = 1; index < lines.length; index += 1) {
|
|
19676
|
+
const line = lines[index];
|
|
19677
|
+
if (line.trim() === "---") return void 0;
|
|
19678
|
+
if (!line.startsWith("name")) continue;
|
|
19679
|
+
const match = line.match(/^name\s*:\s*(.+?)\s*$/u);
|
|
19680
|
+
if (!match) continue;
|
|
19681
|
+
return stripYamlQuotes(match[1]);
|
|
19682
|
+
}
|
|
19683
|
+
}
|
|
19684
|
+
function findTomlTopLevelName(text) {
|
|
19685
|
+
const lines = text.split(/\r?\n/u);
|
|
19686
|
+
for (const line of lines) {
|
|
19687
|
+
const trimmed = line.trim();
|
|
19688
|
+
if (trimmed.startsWith("#") || trimmed === "") continue;
|
|
19689
|
+
if (trimmed.startsWith("[")) break;
|
|
19690
|
+
const match = trimmed.match(/^name\s*=\s*(.+?)\s*$/u);
|
|
19691
|
+
if (!match) continue;
|
|
19692
|
+
return stripTomlQuotes(stripInlineTomlComment(match[1]));
|
|
19693
|
+
}
|
|
19694
|
+
}
|
|
19695
|
+
function stripInlineTomlComment(value) {
|
|
19696
|
+
let inDoubleQuote = false;
|
|
19697
|
+
let inSingleQuote = false;
|
|
19698
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
19699
|
+
const char = value[index];
|
|
19700
|
+
if (char === "\"" && !inSingleQuote) {
|
|
19701
|
+
if (inDoubleQuote && value[index - 1] === "\\") continue;
|
|
19702
|
+
inDoubleQuote = !inDoubleQuote;
|
|
19703
|
+
continue;
|
|
19704
|
+
}
|
|
19705
|
+
if (char === "'" && !inDoubleQuote) {
|
|
19706
|
+
inSingleQuote = !inSingleQuote;
|
|
19707
|
+
continue;
|
|
19708
|
+
}
|
|
19709
|
+
if (char === "#" && !inDoubleQuote && !inSingleQuote) return value.slice(0, index).replace(/\s+$/u, "");
|
|
19710
|
+
}
|
|
19711
|
+
return value.replace(/\s+$/u, "");
|
|
19712
|
+
}
|
|
19713
|
+
function stripYamlQuotes(value) {
|
|
19714
|
+
if (value.length >= 2) {
|
|
19715
|
+
const first = value[0];
|
|
19716
|
+
const last = value[value.length - 1];
|
|
19717
|
+
if (first === "\"" && last === "\"" || first === "'" && last === "'") return value.slice(1, -1);
|
|
19718
|
+
}
|
|
19719
|
+
return value;
|
|
19720
|
+
}
|
|
19721
|
+
function stripTomlQuotes(value) {
|
|
19722
|
+
if (value.startsWith("\"") && value.endsWith("\"") && value.length >= 2) return value.slice(1, -1);
|
|
19723
|
+
if (value.startsWith("'") && value.endsWith("'") && value.length >= 2) return value.slice(1, -1);
|
|
19724
|
+
return value;
|
|
19725
|
+
}
|
|
19726
|
+
async function readRegionAwareFile(rootDir, relativePath) {
|
|
19727
|
+
const safePath = safeOutputPath(relativePath);
|
|
19728
|
+
const absolutePath = path.resolve(rootDir, ...safePath.split("/"));
|
|
19729
|
+
let stat;
|
|
19730
|
+
try {
|
|
19731
|
+
stat = await fsPromises.lstat(absolutePath);
|
|
19732
|
+
} catch (error) {
|
|
19733
|
+
if (isNodeNotFound(error)) return {
|
|
19734
|
+
refused: false,
|
|
19735
|
+
bytes: void 0
|
|
19736
|
+
};
|
|
19737
|
+
throw error;
|
|
19738
|
+
}
|
|
19739
|
+
if (stat.isSymbolicLink()) return { refused: true };
|
|
19740
|
+
if (!stat.isFile()) return {
|
|
19741
|
+
refused: false,
|
|
19742
|
+
bytes: void 0
|
|
19743
|
+
};
|
|
19744
|
+
return {
|
|
19745
|
+
refused: false,
|
|
19746
|
+
bytes: await fsPromises.readFile(absolutePath)
|
|
19747
|
+
};
|
|
19748
|
+
}
|
|
19749
|
+
async function listFilesUnder(rootDir, relativeRoot, recursive) {
|
|
19750
|
+
const files = [];
|
|
19751
|
+
const refusals = [];
|
|
19752
|
+
const rootStat = await lstatOptional(path.join(rootDir, relativeRoot));
|
|
19753
|
+
if (!rootStat) return {
|
|
19754
|
+
files: [],
|
|
19755
|
+
refusals: []
|
|
19756
|
+
};
|
|
19757
|
+
if (rootStat.isSymbolicLink()) return {
|
|
19758
|
+
files: [],
|
|
19759
|
+
refusals: [relativeRoot]
|
|
19760
|
+
};
|
|
19761
|
+
if (!rootStat.isDirectory()) return {
|
|
19762
|
+
files: [],
|
|
19763
|
+
refusals: []
|
|
19764
|
+
};
|
|
19765
|
+
await walk(rootDir, relativeRoot, recursive, files, refusals);
|
|
19766
|
+
return {
|
|
19767
|
+
files: files.sort(),
|
|
19768
|
+
refusals: refusals.sort()
|
|
19769
|
+
};
|
|
19770
|
+
}
|
|
19771
|
+
async function walk(rootDir, relativeRoot, recursive, out, refusals) {
|
|
19772
|
+
let entries;
|
|
19773
|
+
try {
|
|
19774
|
+
entries = await fsPromises.readdir(path.join(rootDir, relativeRoot), { withFileTypes: true });
|
|
19775
|
+
} catch (error) {
|
|
19776
|
+
if (isNodeNotFound(error)) return;
|
|
19777
|
+
throw error;
|
|
19778
|
+
}
|
|
19779
|
+
for (const entry of entries) {
|
|
19780
|
+
const child = `${relativeRoot}/${entry.name}`;
|
|
19781
|
+
if (entry.isSymbolicLink()) {
|
|
19782
|
+
refusals.push(child);
|
|
19783
|
+
continue;
|
|
19784
|
+
}
|
|
19785
|
+
if (entry.isDirectory() && recursive) {
|
|
19786
|
+
await walk(rootDir, child, recursive, out, refusals);
|
|
19787
|
+
continue;
|
|
19788
|
+
}
|
|
19789
|
+
if (entry.isFile()) out.push(child);
|
|
19790
|
+
}
|
|
19791
|
+
}
|
|
19792
|
+
async function lstatOptional(absolutePath) {
|
|
19793
|
+
try {
|
|
19794
|
+
return await fsPromises.lstat(absolutePath);
|
|
19795
|
+
} catch (error) {
|
|
19796
|
+
if (isNodeNotFound(error)) return void 0;
|
|
19797
|
+
throw error;
|
|
19798
|
+
}
|
|
19799
|
+
}
|
|
19800
|
+
async function readOptionalBytes(rootDir, relativePath) {
|
|
19801
|
+
const result = await readRegionAwareFile(rootDir, relativePath);
|
|
19802
|
+
if (result.refused) return void 0;
|
|
19803
|
+
return result.bytes;
|
|
19804
|
+
}
|
|
19805
|
+
async function readOptionalText(rootDir, relativePath) {
|
|
19806
|
+
const bytes = await readOptionalBytes(rootDir, relativePath);
|
|
19807
|
+
if (!bytes) return void 0;
|
|
19808
|
+
return Buffer.from(bytes).toString("utf8");
|
|
19809
|
+
}
|
|
19810
|
+
async function readLockfileForRegions(rootDir) {
|
|
19811
|
+
const bytes = await readOptionalBytes(rootDir, "ai-profile.lock");
|
|
19812
|
+
if (!bytes) return void 0;
|
|
19813
|
+
const result = validateLockfileText(Buffer.from(bytes).toString("utf8"));
|
|
19814
|
+
if (!result.ok) return void 0;
|
|
19815
|
+
return toLockfileV2View(result.lockfile);
|
|
19816
|
+
}
|
|
19817
|
+
async function getLocalRuntimeGitignoreFindings(rootDir) {
|
|
19818
|
+
const lines = (await readOptionalText(rootDir, ".gitignore").catch(() => void 0) ?? "").split(/\r?\n/u).map((line) => line.trim()).filter((line) => line !== "" && !line.startsWith("#"));
|
|
19819
|
+
const findings = [];
|
|
19820
|
+
for (const recommended of RECOMMENDED_IGNORE_LINES) {
|
|
19821
|
+
const present = lines.some((line) => {
|
|
19822
|
+
return line.replace(/^\//u, "").replace(/\/$/u, "") === recommended.replace(/\/$/u, "");
|
|
19823
|
+
});
|
|
19824
|
+
findings.push({
|
|
19825
|
+
line: recommended,
|
|
19826
|
+
action: present ? "already-present" : "would-add",
|
|
19827
|
+
reason: "local runtime or machine-specific path"
|
|
19828
|
+
});
|
|
19829
|
+
}
|
|
19830
|
+
return findings;
|
|
19831
|
+
}
|
|
19832
|
+
function containsAbsolutePathLiteral(bytes) {
|
|
19833
|
+
const text = bytes.toString("utf8");
|
|
19834
|
+
return /[A-Z]:\\\\|"\/[A-Za-z]/u.test(text);
|
|
19835
|
+
}
|
|
19836
|
+
function isNodeNotFound(error) {
|
|
19837
|
+
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
19838
|
+
}
|
|
19839
|
+
var REGION_AWARE_ROOT_PATHS = ["AGENTS.md", "CLAUDE.md"];
|
|
19840
|
+
async function planRootInstructionsAdoption(rootDir, generatedBytesByPath = /* @__PURE__ */ new Map()) {
|
|
19841
|
+
const results = [];
|
|
19842
|
+
for (const relativePath of REGION_AWARE_ROOT_PATHS) {
|
|
19843
|
+
const read = await readRegionAwareFile(rootDir, relativePath);
|
|
19844
|
+
if (read.refused) {
|
|
19845
|
+
results.push({
|
|
19846
|
+
ok: false,
|
|
19847
|
+
path: relativePath,
|
|
19848
|
+
reason: "symlink"
|
|
19849
|
+
});
|
|
19850
|
+
continue;
|
|
19851
|
+
}
|
|
19852
|
+
const existing = read.bytes;
|
|
19853
|
+
if (!existing) {
|
|
19854
|
+
results.push({
|
|
19855
|
+
ok: false,
|
|
19856
|
+
path: relativePath,
|
|
19857
|
+
reason: "missing-file"
|
|
19858
|
+
});
|
|
19859
|
+
continue;
|
|
19860
|
+
}
|
|
19861
|
+
const compiled = generatedBytesByPath.get(relativePath);
|
|
19862
|
+
if (!compiled) {
|
|
19863
|
+
results.push({
|
|
19864
|
+
ok: false,
|
|
19865
|
+
path: relativePath,
|
|
19866
|
+
reason: "missing-generated-bytes"
|
|
19867
|
+
});
|
|
19868
|
+
continue;
|
|
19869
|
+
}
|
|
19870
|
+
const generatedInner = Buffer.from(compiled);
|
|
19871
|
+
const existingBuffer = Buffer.from(existing);
|
|
19872
|
+
if (hasAllRegionMarkers(existingBuffer)) {
|
|
19873
|
+
const updated = replaceGeneratedRegion(existingBuffer, generatedInner);
|
|
19874
|
+
if (updated) results.push({
|
|
19875
|
+
ok: true,
|
|
19876
|
+
path: relativePath,
|
|
19877
|
+
bytes: updated
|
|
19878
|
+
});
|
|
19879
|
+
else results.push({
|
|
19880
|
+
ok: false,
|
|
19881
|
+
path: relativePath,
|
|
19882
|
+
reason: "duplicate-markers"
|
|
19883
|
+
});
|
|
19884
|
+
continue;
|
|
19885
|
+
}
|
|
19886
|
+
if (hasAnyRegionMarker(existingBuffer)) {
|
|
19887
|
+
results.push({
|
|
19888
|
+
ok: false,
|
|
19889
|
+
path: relativePath,
|
|
19890
|
+
reason: "partial-markers"
|
|
19891
|
+
});
|
|
19892
|
+
continue;
|
|
19893
|
+
}
|
|
19894
|
+
const mixed = serializeMixedFile({
|
|
19895
|
+
generatedInner,
|
|
19896
|
+
manualInner: existingBuffer
|
|
19897
|
+
});
|
|
19898
|
+
results.push({
|
|
19899
|
+
ok: true,
|
|
19900
|
+
path: relativePath,
|
|
19901
|
+
bytes: mixed
|
|
19902
|
+
});
|
|
19903
|
+
}
|
|
19904
|
+
return results;
|
|
19905
|
+
}
|
|
19906
|
+
//#endregion
|
|
17595
19907
|
//#region src/lib/server/projectContext.ts
|
|
17596
19908
|
var PROFILE_FILENAME = "ai-profile.yaml";
|
|
17597
19909
|
/**
|
|
@@ -17672,5 +19984,5 @@ function truncatePreview(text, capBytes = 256 * 1024) {
|
|
|
17672
19984
|
};
|
|
17673
19985
|
}
|
|
17674
19986
|
|
|
17675
|
-
export { ProfileWriteError as P,
|
|
17676
|
-
//# sourceMappingURL=projectContext-
|
|
19987
|
+
export { writeProfileAtomic as A, ProfileWriteError as B, computeFileEtag as C, validateProfileValue as D, renderProfileYaml as E, truncatePreview as F, PHASE_14_SUPPORTED_PATHS as P, REGION_AWARE_ROOT_PATHS as R, applyWritePlan as a, buildPhase14ImportReport as b, compileProfile as c, deriveEffectivePermissions as d, containsSecretLikeLiteral as e, hasAnyRegionMarker as f, parseMixedFile as g, hasAllRegionMarkers as h, hasLegacyGeneratedMarker as i, createLockfileFile as j, sha256Hex as k, getEnabledSubagents as l, isSubagentBuiltinNameCollision as m, normalizeSafety as n, readLockfileForRegions as o, parseProfileYaml as p, planRootInstructionsAdoption as q, resolveProjectRoot as r, safeOutputPath as s, toLockfileV2View as t, planWrites as u, validateLockfileText as v, readRegionAwareFile as w, redactIfSecretLike as x, PHASE_14_SCAN_DIRS as y, loadProjectContext as z };
|
|
19988
|
+
//# sourceMappingURL=projectContext-B1D-bieW.js.map
|