@ebrindley/build 0.0.0-stage → 1.42.1-rc28
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-project/providers/catalog.json +13951 -0
- package/.build-project/providers/pricing.json +1978 -0
- package/.build-project/providers/registry.json +4103 -0
- package/.github/SECURITY.md +75 -0
- package/.nvmrc +1 -0
- package/CHANGELOG.md +661 -0
- package/CODE_OF_CONDUCT.md +44 -0
- package/CONTRIBUTING.md +24 -0
- package/INSTALL.md +623 -0
- package/LICENSE +21 -0
- package/README.md +118 -2
- package/THIRD_PARTY_NOTICES.txt +26 -0
- package/dist/ai-judge-UE5UOYOO.js +191 -0
- package/dist/allowlist-grounding-KPLN6NC5.js +16 -0
- package/dist/allowlist-utils-MZZKKXRD.js +31 -0
- package/dist/apply-completion-mode-EM37UZHB.js +110 -0
- package/dist/artifact-migrator-WPACNSEP.js +276 -0
- package/dist/ask-2OZ4JFQR.js +176 -0
- package/dist/auth-6UKBTJUQ.js +185 -0
- package/dist/auth-H5KJL6HL.js +165 -0
- package/dist/auth-LVJRJDMU.js +12 -0
- package/dist/auth-NHZOCNRR.js +94 -0
- package/dist/auth-PBXHWXGW.js +95 -0
- package/dist/auth-T7Y5DCAH.js +91 -0
- package/dist/auth-TVVKCHQW.js +13 -0
- package/dist/auth-UHB2UCSS.js +97 -0
- package/dist/auth-VACA3VUL.js +98 -0
- package/dist/auth-VVLC77S3.js +44 -0
- package/dist/auth-liveness-XO4AGDDD.js +53 -0
- package/dist/autoloop-cleanup-SI3VGAAR.js +106 -0
- package/dist/autoloop-evidence-gates-J5GG5YQB.js +39 -0
- package/dist/autoloop-gate-policy-SUNAEP6Q.js +169 -0
- package/dist/autoloop-helpers-VQGQNTT6.js +52 -0
- package/dist/autoloop-ledger-P6TIDP7C.js +96 -0
- package/dist/autoloop-ledger-subscriber-HFAGOZXH.js +161 -0
- package/dist/autoloop-run-defaults-GWGZBNT7.js +27 -0
- package/dist/autoloop-run-lock-GBWRM5A2.js +197 -0
- package/dist/autoloop-success-C32QVWOP.js +93 -0
- package/dist/autoloop-termination-summary-GI6IBQWD.js +58 -0
- package/dist/autoloop-trajectory-AMKSQISD.js +70 -0
- package/dist/autoloop-wall-clock-T7ZVIQOC.js +12 -0
- package/dist/automatic-branch-cleanup-R62X2C5O.js +49 -0
- package/dist/autonomous-loop-controller-2WL363LW.js +4386 -0
- package/dist/backend-YUTFDZXZ.js +30 -0
- package/dist/background-executor-Z3ODTMD7.js +260 -0
- package/dist/backlog-75QPEAMW.js +403 -0
- package/dist/backlog-execution-intent-GWUV5TUK.js +19 -0
- package/dist/backup-active-store-XHWLN34M.js +16 -0
- package/dist/backup-machine-stores-UI4LTJOY.js +251 -0
- package/dist/backup-telemetry-db-Z4ICYCNW.js +26 -0
- package/dist/branch-archive-manager-FMSQ7YJF.js +18 -0
- package/dist/branch-cleanup-manager-ST6FJGND.js +35 -0
- package/dist/build-gate-7NKWPY62.js +68 -0
- package/dist/build-root-S7DINODY.js +18 -0
- package/dist/change-summary-R6CB6VXJ.js +50 -0
- package/dist/chunk-24MNKKOM.js +173 -0
- package/dist/chunk-2H6VZFIO.js +235 -0
- package/dist/chunk-2JIX3EKV.js +39 -0
- package/dist/chunk-2KO7HVZM.js +106 -0
- package/dist/chunk-2L36U25O.js +100 -0
- package/dist/chunk-2NMNFUQA.js +475 -0
- package/dist/chunk-2OUAEH67.js +83 -0
- package/dist/chunk-2VLJUXJU.js +115 -0
- package/dist/chunk-2VUEDIUM.js +77 -0
- package/dist/chunk-2Y2IIHPI.js +430 -0
- package/dist/chunk-2YRG3LHZ.js +220 -0
- package/dist/chunk-2Z5Q3SUY.js +65 -0
- package/dist/chunk-32IYXIE5.js +873 -0
- package/dist/chunk-33IGPPUI.js +292 -0
- package/dist/chunk-352PCJLK.js +283 -0
- package/dist/chunk-35J4NE6S.js +226 -0
- package/dist/chunk-3C7WBIVK.js +1016 -0
- package/dist/chunk-3H3EY6U7.js +1225 -0
- package/dist/chunk-3H4MWYIC.js +198 -0
- package/dist/chunk-3HHWQR3N.js +2479 -0
- package/dist/chunk-3JKNRYEE.js +14 -0
- package/dist/chunk-3LECCYZY.js +128 -0
- package/dist/chunk-3LOY6YZI.js +852 -0
- package/dist/chunk-3M57DADF.js +44 -0
- package/dist/chunk-3NOTLVLG.js +3803 -0
- package/dist/chunk-3OPP2OZB.js +1480 -0
- package/dist/chunk-3P5IN5E7.js +9 -0
- package/dist/chunk-3PL22IYZ.js +20 -0
- package/dist/chunk-3REDAJUJ.js +14 -0
- package/dist/chunk-3S2R4XJI.js +203 -0
- package/dist/chunk-3UBZI5DW.js +61 -0
- package/dist/chunk-3VV5OBGG.js +308 -0
- package/dist/chunk-3WY5TU2O.js +823 -0
- package/dist/chunk-43OKHTW4.js +82 -0
- package/dist/chunk-45KUJBDI.js +112 -0
- package/dist/chunk-47X5LM7B.js +224 -0
- package/dist/chunk-4B6FQJ77.js +268 -0
- package/dist/chunk-4BTDUT2S.js +42 -0
- package/dist/chunk-4DJL2VXA.js +24 -0
- package/dist/chunk-4EBSXZ73.js +48 -0
- package/dist/chunk-4QKP6I4C.js +294 -0
- package/dist/chunk-4U6XK2DG.js +300 -0
- package/dist/chunk-4UMRUFBD.js +132 -0
- package/dist/chunk-4US4SYJ4.js +569 -0
- package/dist/chunk-4ZPLWEZO.js +154 -0
- package/dist/chunk-56WPYDJH.js +624 -0
- package/dist/chunk-57WRCJJW.js +50 -0
- package/dist/chunk-5AW4RMNG.js +24 -0
- package/dist/chunk-5EQN56OZ.js +155 -0
- package/dist/chunk-5F43TUIN.js +38 -0
- package/dist/chunk-5FKHIKTS.js +115 -0
- package/dist/chunk-5HDP7XZG.js +91 -0
- package/dist/chunk-5KQETTNS.js +152 -0
- package/dist/chunk-5PDVN2KO.js +498 -0
- package/dist/chunk-5UBIFVRD.js +509 -0
- package/dist/chunk-5YDE3Q62.js +46 -0
- package/dist/chunk-626AJVMU.js +302 -0
- package/dist/chunk-633XZ7UF.js +3583 -0
- package/dist/chunk-63DHNHGA.js +236 -0
- package/dist/chunk-666656AR.js +568 -0
- package/dist/chunk-67YRJPJO.js +19 -0
- package/dist/chunk-6CAU7VBA.js +20 -0
- package/dist/chunk-6CB3KJRY.js +21 -0
- package/dist/chunk-6DBMALXL.js +29 -0
- package/dist/chunk-6E25C4IA.js +269 -0
- package/dist/chunk-6FIBNIQU.js +73 -0
- package/dist/chunk-6G57FYBV.js +189 -0
- package/dist/chunk-6KZKRTG3.js +4885 -0
- package/dist/chunk-6LAH2UV2.js +525 -0
- package/dist/chunk-6PZY2TTU.js +921 -0
- package/dist/chunk-6T6NHXK4.js +230 -0
- package/dist/chunk-6TBEX4R4.js +432 -0
- package/dist/chunk-6TRD7TEE.js +911 -0
- package/dist/chunk-6XCP2RAI.js +47 -0
- package/dist/chunk-726G6WDL.js +351 -0
- package/dist/chunk-75EMT7BF.js +616 -0
- package/dist/chunk-762ACDZJ.js +4696 -0
- package/dist/chunk-77I6G4CO.js +1 -0
- package/dist/chunk-7DJ6SQH3.js +510 -0
- package/dist/chunk-7HPCIOMA.js +1383 -0
- package/dist/chunk-7HYBSRPZ.js +17503 -0
- package/dist/chunk-7KBEOPVB.js +73 -0
- package/dist/chunk-7LHJDJB3.js +2222 -0
- package/dist/chunk-7NVJMH52.js +306 -0
- package/dist/chunk-7RMARDVH.js +33 -0
- package/dist/chunk-7SEWU4QG.js +36 -0
- package/dist/chunk-7TUTZTI2.js +911 -0
- package/dist/chunk-7VBDFPUM.js +340 -0
- package/dist/chunk-7VRJHTGZ.js +6406 -0
- package/dist/chunk-7YAOUUKK.js +493 -0
- package/dist/chunk-AAAODV76.js +860 -0
- package/dist/chunk-AB4HUJVQ.js +339 -0
- package/dist/chunk-AEQWV746.js +611 -0
- package/dist/chunk-AHU3FKPA.js +11639 -0
- package/dist/chunk-AISTV5XU.js +226 -0
- package/dist/chunk-AJBTKGJZ.js +48 -0
- package/dist/chunk-AJJNW7XT.js +248 -0
- package/dist/chunk-AJN5Y5YZ.js +160 -0
- package/dist/chunk-ALDTFNZ3.js +150 -0
- package/dist/chunk-ARARVIZK.js +281 -0
- package/dist/chunk-ATBM6AW5.js +53 -0
- package/dist/chunk-ATKEKM3E.js +206 -0
- package/dist/chunk-AUJLW6JZ.js +92 -0
- package/dist/chunk-AY3MHEFM.js +24 -0
- package/dist/chunk-B7PYTV72.js +236 -0
- package/dist/chunk-B7YRSULE.js +1423 -0
- package/dist/chunk-BAWJNMWF.js +339 -0
- package/dist/chunk-BBPIILO2.js +88 -0
- package/dist/chunk-BD3PGW6A.js +957 -0
- package/dist/chunk-BDPYFAB4.js +44 -0
- package/dist/chunk-BIUV23HH.js +729 -0
- package/dist/chunk-BQ3VAGXH.js +243 -0
- package/dist/chunk-BQJOGAWT.js +31 -0
- package/dist/chunk-BT7EG7CO.js +68 -0
- package/dist/chunk-BV3XQQLU.js +27 -0
- package/dist/chunk-BY6ODHNZ.js +78 -0
- package/dist/chunk-BZRLSZNV.js +79 -0
- package/dist/chunk-C3DH3NCY.js +2773 -0
- package/dist/chunk-C3KCMAJP.js +756 -0
- package/dist/chunk-C7AGUJ5K.js +267 -0
- package/dist/chunk-CBSWKQCX.js +342 -0
- package/dist/chunk-CE5OZBYY.js +21 -0
- package/dist/chunk-CFCVYHSW.js +373 -0
- package/dist/chunk-CHA2HDE5.js +126 -0
- package/dist/chunk-CIHWPGS5.js +146 -0
- package/dist/chunk-CJBSZX3F.js +127 -0
- package/dist/chunk-CLA6QIJM.js +43 -0
- package/dist/chunk-CPSVQR2I.js +365 -0
- package/dist/chunk-CRPRVNQ4.js +254 -0
- package/dist/chunk-CSIE4Y7C.js +1093 -0
- package/dist/chunk-CSOPSYDY.js +142 -0
- package/dist/chunk-CSXLLEGB.js +205 -0
- package/dist/chunk-CTDLERWU.js +293 -0
- package/dist/chunk-CULBXMSK.js +110 -0
- package/dist/chunk-D2M2Y5ID.js +21 -0
- package/dist/chunk-D37WY7SH.js +1060 -0
- package/dist/chunk-D4VJFCGZ.js +89 -0
- package/dist/chunk-D6WTZMZB.js +48 -0
- package/dist/chunk-DBHOWDUH.js +976 -0
- package/dist/chunk-DCACX7BV.js +19364 -0
- package/dist/chunk-DFHX4XYA.js +128 -0
- package/dist/chunk-DIKBRRKE.js +176 -0
- package/dist/chunk-DJG5RIOR.js +9 -0
- package/dist/chunk-DNIOIISW.js +616 -0
- package/dist/chunk-DOA5G7IA.js +315 -0
- package/dist/chunk-DP7FKP6W.js +855 -0
- package/dist/chunk-DS2JZ677.js +79 -0
- package/dist/chunk-DSRLVYBS.js +82 -0
- package/dist/chunk-EAEVKNJA.js +209 -0
- package/dist/chunk-EEUESN3T.js +575 -0
- package/dist/chunk-EJ4LUU5Y.js +73 -0
- package/dist/chunk-EJIWTPSZ.js +1063 -0
- package/dist/chunk-EJVCDTAN.js +116 -0
- package/dist/chunk-EKLUBDBQ.js +627 -0
- package/dist/chunk-EN62WLFD.js +849 -0
- package/dist/chunk-ENYRCL43.js +26 -0
- package/dist/chunk-EP22ZMFO.js +273 -0
- package/dist/chunk-EP4SVAVI.js +87 -0
- package/dist/chunk-EPAMVGI3.js +1562 -0
- package/dist/chunk-EPRMH6HO.js +24 -0
- package/dist/chunk-ES6NWJ36.js +4057 -0
- package/dist/chunk-ETA2K4KI.js +30 -0
- package/dist/chunk-ETAD4NKD.js +31 -0
- package/dist/chunk-EUWIIDQ7.js +93 -0
- package/dist/chunk-EVE3OD2W.js +141 -0
- package/dist/chunk-EXA26FFC.js +459 -0
- package/dist/chunk-EXSPAA35.js +244 -0
- package/dist/chunk-F55YABKV.js +258 -0
- package/dist/chunk-F5DNGU5W.js +27 -0
- package/dist/chunk-F622MJYV.js +103 -0
- package/dist/chunk-F6NIQD74.js +5111 -0
- package/dist/chunk-FAWJTC34.js +43 -0
- package/dist/chunk-FAZBRHGG.js +47 -0
- package/dist/chunk-FIEUSGNJ.js +39 -0
- package/dist/chunk-FKCG7K6H.js +1146 -0
- package/dist/chunk-FOVVXV45.js +229 -0
- package/dist/chunk-FRBPKBFE.js +30 -0
- package/dist/chunk-FSA5BPFI.js +268 -0
- package/dist/chunk-FSJ5TTZ3.js +29 -0
- package/dist/chunk-FT7SGLXT.js +193 -0
- package/dist/chunk-FUUVZZUB.js +62 -0
- package/dist/chunk-FYMRVUNZ.js +1697 -0
- package/dist/chunk-FYTAA5FG.js +162 -0
- package/dist/chunk-G3VB2UCZ.js +3892 -0
- package/dist/chunk-G6OIMVXH.js +405 -0
- package/dist/chunk-G7PQCXVH.js +228 -0
- package/dist/chunk-GAB6UW52.js +1087 -0
- package/dist/chunk-GAFJEYLK.js +29 -0
- package/dist/chunk-GC4CRMTS.js +642 -0
- package/dist/chunk-GFHSIWHL.js +5297 -0
- package/dist/chunk-GI5M67YA.js +735 -0
- package/dist/chunk-GIJWHUWF.js +191 -0
- package/dist/chunk-GO6DRECI.js +1 -0
- package/dist/chunk-GOFVBTMN.js +314 -0
- package/dist/chunk-GQIP72ZJ.js +13 -0
- package/dist/chunk-GQXLXRFA.js +28 -0
- package/dist/chunk-GT6HFKJB.js +48 -0
- package/dist/chunk-GVJGSSKM.js +174 -0
- package/dist/chunk-GWHGTG37.js +36 -0
- package/dist/chunk-GZAJHLKO.js +18 -0
- package/dist/chunk-GZK62I3N.js +314 -0
- package/dist/chunk-H3HGMISG.js +483 -0
- package/dist/chunk-H3ISZJMJ.js +403 -0
- package/dist/chunk-H4HXVWEC.js +9 -0
- package/dist/chunk-H6MJGKAW.js +120 -0
- package/dist/chunk-HBTTGVR5.js +353 -0
- package/dist/chunk-HBZ322WZ.js +35 -0
- package/dist/chunk-HEP3ILP4.js +34 -0
- package/dist/chunk-HGFXODKO.js +106 -0
- package/dist/chunk-HHWDTB6S.js +59 -0
- package/dist/chunk-HKO45NLZ.js +286 -0
- package/dist/chunk-HLVTEA6A.js +89 -0
- package/dist/chunk-HS3SY6HN.js +160 -0
- package/dist/chunk-HT5OCGKN.js +899 -0
- package/dist/chunk-HXIIEMGF.js +78 -0
- package/dist/chunk-I56TH7VM.js +46 -0
- package/dist/chunk-I6FN3R5D.js +352 -0
- package/dist/chunk-I7SCBHJN.js +655 -0
- package/dist/chunk-IJM4GKAT.js +529 -0
- package/dist/chunk-IMEYU36R.js +344 -0
- package/dist/chunk-INJ3SS6A.js +936 -0
- package/dist/chunk-IUKOPCCE.js +441 -0
- package/dist/chunk-IVEPZQJO.js +33 -0
- package/dist/chunk-IVZEONFC.js +43 -0
- package/dist/chunk-IWBHRSG7.js +936 -0
- package/dist/chunk-IYY3HQAD.js +484 -0
- package/dist/chunk-J2ICMYDA.js +48 -0
- package/dist/chunk-J2QCFLUN.js +505 -0
- package/dist/chunk-J5HM6V5P.js +1039 -0
- package/dist/chunk-J6NZX6QH.js +398 -0
- package/dist/chunk-JBBB2Y47.js +432 -0
- package/dist/chunk-JDCZQZU7.js +42 -0
- package/dist/chunk-JEDNXGSS.js +169 -0
- package/dist/chunk-JHP7OT6K.js +89 -0
- package/dist/chunk-JLS65NUQ.js +14 -0
- package/dist/chunk-JNMWYMC6.js +38 -0
- package/dist/chunk-JNSTWNNW.js +25 -0
- package/dist/chunk-JOSK6GEU.js +9564 -0
- package/dist/chunk-JQUMSIGC.js +100 -0
- package/dist/chunk-JVHGMURQ.js +1106 -0
- package/dist/chunk-JYXS47FQ.js +951 -0
- package/dist/chunk-K2ZMW2Z5.js +2147 -0
- package/dist/chunk-K7FAFORM.js +14 -0
- package/dist/chunk-KBJXX3ON.js +333 -0
- package/dist/chunk-KHFKVQWY.js +486 -0
- package/dist/chunk-KHMEI3DQ.js +173 -0
- package/dist/chunk-KHW3UD7B.js +69 -0
- package/dist/chunk-KKQKWAMF.js +365 -0
- package/dist/chunk-KOKXJV2U.js +455 -0
- package/dist/chunk-KQ4NGOJI.js +14 -0
- package/dist/chunk-KQYQOXMS.js +342 -0
- package/dist/chunk-KTMW65UX.js +14 -0
- package/dist/chunk-KUEWV2JH.js +593 -0
- package/dist/chunk-KXYDV3HP.js +1523 -0
- package/dist/chunk-KZ4JMGZ5.js +96 -0
- package/dist/chunk-KZWGBUIO.js +2659 -0
- package/dist/chunk-L2CBG5IX.js +1892 -0
- package/dist/chunk-L2S235CU.js +314 -0
- package/dist/chunk-L32WD57F.js +98 -0
- package/dist/chunk-LDJCKAJP.js +123 -0
- package/dist/chunk-LDWNBEN7.js +541 -0
- package/dist/chunk-LJVH57G2.js +241 -0
- package/dist/chunk-LPQ7NZEN.js +209 -0
- package/dist/chunk-LRGH3CCV.js +148 -0
- package/dist/chunk-LULOGMMM.js +1133 -0
- package/dist/chunk-LWGKN2GY.js +8284 -0
- package/dist/chunk-LX4F24ZH.js +157 -0
- package/dist/chunk-M4BUEXXF.js +839 -0
- package/dist/chunk-M6UHOC4I.js +553 -0
- package/dist/chunk-MCBNWZNO.js +657 -0
- package/dist/chunk-MEMSY6VY.js +223 -0
- package/dist/chunk-MHLEZQQI.js +145 -0
- package/dist/chunk-MJ6WNSIX.js +192 -0
- package/dist/chunk-MKASIKWZ.js +442 -0
- package/dist/chunk-MNOVBYFU.js +60 -0
- package/dist/chunk-MO2BYAAF.js +2896 -0
- package/dist/chunk-MP6P7Y2A.js +180 -0
- package/dist/chunk-MQ4TFJAG.js +3365 -0
- package/dist/chunk-MT2WAIR3.js +131 -0
- package/dist/chunk-MTU7VTNN.js +1122 -0
- package/dist/chunk-MULMXX4V.js +150 -0
- package/dist/chunk-MW2DWWVA.js +147 -0
- package/dist/chunk-MY3ZPUN4.js +151 -0
- package/dist/chunk-MYLH2S4G.js +64 -0
- package/dist/chunk-MZ5WYKNA.js +28 -0
- package/dist/chunk-N3Q2JNPV.js +249 -0
- package/dist/chunk-N5DX4JAK.js +12 -0
- package/dist/chunk-NAINGKHF.js +35 -0
- package/dist/chunk-NEQUQHOX.js +223 -0
- package/dist/chunk-NHNPEZS4.js +1408 -0
- package/dist/chunk-NHTIXJCR.js +17 -0
- package/dist/chunk-NKLPMBNV.js +1154 -0
- package/dist/chunk-NMVZ5YES.js +199 -0
- package/dist/chunk-NRFRY3GE.js +256 -0
- package/dist/chunk-NTD6CSI6.js +1266 -0
- package/dist/chunk-NUO7B3SH.js +318 -0
- package/dist/chunk-NVOHIJKG.js +1319 -0
- package/dist/chunk-NXH3RX7O.js +523 -0
- package/dist/chunk-NXZ3DURF.js +257 -0
- package/dist/chunk-O26L6F7F.js +209 -0
- package/dist/chunk-O5RRIUEP.js +124 -0
- package/dist/chunk-O5X6BKAO.js +10 -0
- package/dist/chunk-O6ZQUVTR.js +31 -0
- package/dist/chunk-O7FE75QZ.js +306 -0
- package/dist/chunk-OC7Z6AJQ.js +81 -0
- package/dist/chunk-OH7IEZ63.js +307 -0
- package/dist/chunk-OI734GRS.js +115 -0
- package/dist/chunk-OJBH62DK.js +684 -0
- package/dist/chunk-OKJLVSTJ.js +247 -0
- package/dist/chunk-OMX5VL43.js +79 -0
- package/dist/chunk-ONHAMBN6.js +12 -0
- package/dist/chunk-ONYPLIVE.js +753 -0
- package/dist/chunk-OSK7QWPD.js +637 -0
- package/dist/chunk-OTXLMJKP.js +438 -0
- package/dist/chunk-OV5PKQMA.js +213 -0
- package/dist/chunk-OXK5HA4B.js +31 -0
- package/dist/chunk-OYDWFQA4.js +272 -0
- package/dist/chunk-OZAUKWHB.js +22 -0
- package/dist/chunk-P5P2EKGH.js +94 -0
- package/dist/chunk-P6SSWAKY.js +29 -0
- package/dist/chunk-P7CQGPLS.js +30 -0
- package/dist/chunk-P7RVCHQV.js +197 -0
- package/dist/chunk-PEBWDYIW.js +726 -0
- package/dist/chunk-PFCXFO7A.js +9193 -0
- package/dist/chunk-PFLDWMX6.js +168 -0
- package/dist/chunk-PHZGLQSK.js +15883 -0
- package/dist/chunk-PNFTPNSR.js +20 -0
- package/dist/chunk-PPHXX4W7.js +175 -0
- package/dist/chunk-PPZESPJT.js +262 -0
- package/dist/chunk-PRDHI2L5.js +296 -0
- package/dist/chunk-PSTKWHHN.js +32 -0
- package/dist/chunk-PV53ODOT.js +555 -0
- package/dist/chunk-PVJBTI7P.js +24 -0
- package/dist/chunk-PXKERBKX.js +100 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-Q3DHEZA5.js +85 -0
- package/dist/chunk-Q5RZDVQK.js +204 -0
- package/dist/chunk-Q64IR2Z2.js +4933 -0
- package/dist/chunk-Q6Z5UGPL.js +398 -0
- package/dist/chunk-QAMAV4DT.js +627 -0
- package/dist/chunk-QBWF4444.js +112 -0
- package/dist/chunk-QDKYT4CI.js +22805 -0
- package/dist/chunk-QFLBRWCJ.js +126 -0
- package/dist/chunk-QILAQACE.js +107 -0
- package/dist/chunk-QJ6OEH4K.js +3683 -0
- package/dist/chunk-QK3NLYTV.js +320 -0
- package/dist/chunk-QOFLUS24.js +535 -0
- package/dist/chunk-QOIASNEJ.js +98 -0
- package/dist/chunk-QP4UTSOV.js +3587 -0
- package/dist/chunk-QP5ST7RI.js +904 -0
- package/dist/chunk-QS5AGRZN.js +167 -0
- package/dist/chunk-QTAOU53N.js +107 -0
- package/dist/chunk-QTCLJHLZ.js +351 -0
- package/dist/chunk-QTOLTG4L.js +119 -0
- package/dist/chunk-QWDV4OSL.js +142 -0
- package/dist/chunk-QWMQ74KD.js +508 -0
- package/dist/chunk-QX6LOMMH.js +158 -0
- package/dist/chunk-QXBKIHY7.js +238 -0
- package/dist/chunk-QXBKTJT6.js +270 -0
- package/dist/chunk-QYQOVOLR.js +196 -0
- package/dist/chunk-R2CKS6WT.js +73 -0
- package/dist/chunk-R2TIYG7U.js +68 -0
- package/dist/chunk-R2W3LESH.js +465 -0
- package/dist/chunk-R5EXHMUN.js +100 -0
- package/dist/chunk-RBBTBCHX.js +289 -0
- package/dist/chunk-RBKLOUXA.js +121 -0
- package/dist/chunk-RCP2Y6DQ.js +86 -0
- package/dist/chunk-RCYEJSD5.js +260 -0
- package/dist/chunk-RFDVSI4N.js +134 -0
- package/dist/chunk-RGJU63FV.js +1717 -0
- package/dist/chunk-RI4EX2QE.js +18 -0
- package/dist/chunk-RIMARPCF.js +152 -0
- package/dist/chunk-RJ6RSNT6.js +42 -0
- package/dist/chunk-RNI2GUIF.js +131 -0
- package/dist/chunk-RPHUWJ3K.js +264 -0
- package/dist/chunk-RPIMAMV7.js +361 -0
- package/dist/chunk-RQFX6YRN.js +49 -0
- package/dist/chunk-RRC5BL7B.js +285 -0
- package/dist/chunk-RSYTSBOO.js +79 -0
- package/dist/chunk-RWQQIKIC.js +35 -0
- package/dist/chunk-RZUBOZH2.js +373 -0
- package/dist/chunk-S2E632FQ.js +380 -0
- package/dist/chunk-S2VQCZO4.js +22 -0
- package/dist/chunk-S2XIMQJQ.js +681 -0
- package/dist/chunk-S47ISY27.js +183 -0
- package/dist/chunk-S6I4KISU.js +142 -0
- package/dist/chunk-S6TAFQI5.js +2403 -0
- package/dist/chunk-SBBNT5ZJ.js +27 -0
- package/dist/chunk-SDJV2DTQ.js +491 -0
- package/dist/chunk-SDPIFNLD.js +33 -0
- package/dist/chunk-SF6YK3JI.js +835 -0
- package/dist/chunk-SK3ZFONO.js +976 -0
- package/dist/chunk-SKTFRFQ7.js +1775 -0
- package/dist/chunk-SNGM452K.js +2002 -0
- package/dist/chunk-STW7OFOA.js +581 -0
- package/dist/chunk-SU6UFUQY.js +1351 -0
- package/dist/chunk-SVJM3LJA.js +27 -0
- package/dist/chunk-SVUNZOPG.js +129 -0
- package/dist/chunk-T5XLUYV3.js +34 -0
- package/dist/chunk-T7E5JS6N.js +57 -0
- package/dist/chunk-TA3N5MMO.js +450 -0
- package/dist/chunk-TAJPCXSB.js +13 -0
- package/dist/chunk-TDEMDRN2.js +1639 -0
- package/dist/chunk-TDSEX5CF.js +24 -0
- package/dist/chunk-TGCVL74Y.js +28 -0
- package/dist/chunk-TGXXYDL4.js +1012 -0
- package/dist/chunk-TIKTYUJO.js +296 -0
- package/dist/chunk-TIZAJD4M.js +6029 -0
- package/dist/chunk-TLSEZZCG.js +5549 -0
- package/dist/chunk-TMBDRHAX.js +19 -0
- package/dist/chunk-TRURQUBP.js +1217 -0
- package/dist/chunk-TSQ256N5.js +152 -0
- package/dist/chunk-TUQMMFEQ.js +2244 -0
- package/dist/chunk-U424MJLC.js +81 -0
- package/dist/chunk-U4DRS6ZW.js +11 -0
- package/dist/chunk-U5KS22IN.js +204 -0
- package/dist/chunk-UAPHFJPN.js +673 -0
- package/dist/chunk-UB7LQITD.js +1040 -0
- package/dist/chunk-UBVRHGAZ.js +237 -0
- package/dist/chunk-UDNNAQN5.js +98 -0
- package/dist/chunk-UJP3XM54.js +342 -0
- package/dist/chunk-UJYDH2MW.js +305 -0
- package/dist/chunk-UKMPASIC.js +399 -0
- package/dist/chunk-UKUL3EHK.js +763 -0
- package/dist/chunk-UPHU64NB.js +1327 -0
- package/dist/chunk-URMSZXAD.js +43 -0
- package/dist/chunk-US3RT6CY.js +525 -0
- package/dist/chunk-UTDEOPKV.js +30 -0
- package/dist/chunk-UUUDKV7N.js +13 -0
- package/dist/chunk-UVKWU3SM.js +39 -0
- package/dist/chunk-V2TVPO3X.js +521 -0
- package/dist/chunk-V3KLVK7B.js +398 -0
- package/dist/chunk-V3YFFHDR.js +17 -0
- package/dist/chunk-VAG6GUBR.js +1162 -0
- package/dist/chunk-VBENAHDA.js +1814 -0
- package/dist/chunk-VBNCKCCI.js +16 -0
- package/dist/chunk-VCGSWN5M.js +1300 -0
- package/dist/chunk-VE2O2I7M.js +115 -0
- package/dist/chunk-VIFHYTI5.js +31 -0
- package/dist/chunk-VJER3FUS.js +5080 -0
- package/dist/chunk-VLMDM56Q.js +268 -0
- package/dist/chunk-VMFZEVVX.js +99 -0
- package/dist/chunk-VNDPQVUZ.js +1853 -0
- package/dist/chunk-VSPJRLGA.js +4783 -0
- package/dist/chunk-VSWC5ZXI.js +103 -0
- package/dist/chunk-VYI4DSZP.js +2017 -0
- package/dist/chunk-W4BAIQ6L.js +1212 -0
- package/dist/chunk-W7VQAL2K.js +2203 -0
- package/dist/chunk-WEI3ZDZH.js +33 -0
- package/dist/chunk-WEIUS5NT.js +26 -0
- package/dist/chunk-WEW7UFWE.js +546 -0
- package/dist/chunk-WGQAXLNA.js +384 -0
- package/dist/chunk-WJAL4JL3.js +206 -0
- package/dist/chunk-WKFOJ5ZG.js +141 -0
- package/dist/chunk-WMWQEFLN.js +2177 -0
- package/dist/chunk-WNECKKO2.js +154 -0
- package/dist/chunk-WPKLYOAM.js +195 -0
- package/dist/chunk-WSH37YQN.js +243 -0
- package/dist/chunk-WV3KQDPE.js +84 -0
- package/dist/chunk-WZFC4V4U.js +389 -0
- package/dist/chunk-XCOIBNET.js +13 -0
- package/dist/chunk-XDM65LBX.js +53 -0
- package/dist/chunk-XGU6PBO5.js +645 -0
- package/dist/chunk-XHOI4V62.js +43 -0
- package/dist/chunk-XIBVFMLQ.js +6858 -0
- package/dist/chunk-XJ2E7YEJ.js +117 -0
- package/dist/chunk-XON4ZCYX.js +69 -0
- package/dist/chunk-XQPEWJPI.js +127 -0
- package/dist/chunk-XSJTIFUY.js +31 -0
- package/dist/chunk-XT7OVWM3.js +64 -0
- package/dist/chunk-XTXYIISX.js +1104 -0
- package/dist/chunk-XV7NZL4B.js +57 -0
- package/dist/chunk-XWIZ6B5S.js +109 -0
- package/dist/chunk-XWLIKOBX.js +240 -0
- package/dist/chunk-XZOXEIN4.js +156 -0
- package/dist/chunk-XZRS7I7W.js +3673 -0
- package/dist/chunk-Y4ZDDHB6.js +44 -0
- package/dist/chunk-Y733RB7T.js +194 -0
- package/dist/chunk-YBHUB4XR.js +14931 -0
- package/dist/chunk-YKC75XK4.js +147 -0
- package/dist/chunk-YKMXFVK7.js +27 -0
- package/dist/chunk-YO5BAJ55.js +225 -0
- package/dist/chunk-YPDCLXNZ.js +568 -0
- package/dist/chunk-YSQPGVFK.js +116 -0
- package/dist/chunk-YTVVTIWJ.js +716 -0
- package/dist/chunk-YVCMDVBB.js +698 -0
- package/dist/chunk-YYTOA6DP.js +114 -0
- package/dist/chunk-Z5WGNULV.js +88 -0
- package/dist/chunk-Z6NGVVXG.js +66 -0
- package/dist/chunk-Z7CDQNH3.js +20 -0
- package/dist/chunk-ZH4G3FU5.js +187 -0
- package/dist/chunk-ZJB6SQPA.js +257 -0
- package/dist/chunk-ZL6E4HMY.js +42 -0
- package/dist/chunk-ZMLOC3DW.js +62 -0
- package/dist/chunk-ZORW64QH.js +101 -0
- package/dist/chunk-ZVVD2XGV.js +1369 -0
- package/dist/cli-utils-ER33ODC5.js +31 -0
- package/dist/cli-validation-6CHPTANV.js +146 -0
- package/dist/commit-utils-3STAY7C7.js +49 -0
- package/dist/compatibility-notice-IHNXR2JR.js +21 -0
- package/dist/compete-config-resolver-V3GDNJMM.js +125 -0
- package/dist/compete-results-XUM3PJHS.js +318 -0
- package/dist/competition-outcome-tracker-NWSMVUPG.js +62 -0
- package/dist/config-4HHE4OIK.js +238 -0
- package/dist/config-D6YAZASH.js +10 -0
- package/dist/config-MIPRDYYV.js +46 -0
- package/dist/config-audit-GA5DCUAI.js +371 -0
- package/dist/config-explain-4LMO556H.js +71 -0
- package/dist/config-loader-RGP634PC.js +51 -0
- package/dist/config-manager-J2UTO635.js +114 -0
- package/dist/config-merger-TVUJBZTS.js +14 -0
- package/dist/config-validator-H4ZVIE56.js +122 -0
- package/dist/cost-HSIV5U2Y.js +85 -0
- package/dist/data-migration-state-OAUL2WPQ.js +35 -0
- package/dist/db-migrator-NUOW5NKR.js +34 -0
- package/dist/default-paths-UILB62BN.js +49 -0
- package/dist/discovery-V6GYUJUC.js +53 -0
- package/dist/doctor-BBSMCDWE.js +271 -0
- package/dist/doctor-context-blocks-LPY75VZA.js +231 -0
- package/dist/doctor-instructions-import-JXHDDOE5.js +70 -0
- package/dist/doctor-purpose-6YJOXPBE.js +30 -0
- package/dist/domain-analyzer-S35ABUNA.js +48 -0
- package/dist/ensure-initialized-Q6PEU55O.js +78 -0
- package/dist/entry.js +922 -0
- package/dist/error-parser-core-MZFMFANN.js +70 -0
- package/dist/evaluation-context-GQBYDAEV.js +63 -0
- package/dist/evidence-plan-resolver-5FUAP3SA.js +111 -0
- package/dist/execution-data-writer-YCG5UH37.js +72 -0
- package/dist/execution-policy-applier-PWZM5LNA.js +63 -0
- package/dist/execution-preflight-DASJWWQF.js +223 -0
- package/dist/execution-roles-KNSNNB2D.js +112 -0
- package/dist/exit-code-error-QIY5DOKF.js +18 -0
- package/dist/external-temp-cleanup-CAW7LQ6R.js +360 -0
- package/dist/factory-YCYCB7AE.js +209 -0
- package/dist/file-utils-ZQYNBQBW.js +45 -0
- package/dist/flywheel-allowlist-revert-H22HA6JE.js +21 -0
- package/dist/flywheel-autoloop-executor-PDOASJEZ.js +316 -0
- package/dist/flywheel-autoloop-unverified-TOKYFCDC.js +36 -0
- package/dist/flywheel-competition-executor-YJUMMEJO.js +320 -0
- package/dist/flywheel-executor-JWU43KAY.js +437 -0
- package/dist/flywheel-git-isolation-FQ2TRWMB.js +56 -0
- package/dist/flywheel-manifest-HDPNMWWF.js +114 -0
- package/dist/flywheel-model-defaults-UHAKTZT3.js +110 -0
- package/dist/flywheel-preflight-III2C7TH.js +163 -0
- package/dist/flywheel-resume-2O45MS7Y.js +31 -0
- package/dist/flywheel-resume-execution-lease-P2BK257J.js +59 -0
- package/dist/flywheel-safety-AVAVFXIJ.js +19 -0
- package/dist/flywheel-scope-decision-ALJUUNGG.js +14 -0
- package/dist/get-telemetry-logger-MPDVO2JA.js +155 -0
- package/dist/git-message-style-KCXGMTDT.js +104 -0
- package/dist/guidance-profile-config-G3K5YQOO.js +113 -0
- package/dist/guidance-profile-renderer-TX4TNDFL.js +23 -0
- package/dist/identity-XLQJ4YJF.js +25 -0
- package/dist/index-query-6NUY4FKX.js +37 -0
- package/dist/index.js +85588 -0
- package/dist/indexer-DL54CM3K.js +44 -0
- package/dist/init-OUZ72344.js +245 -0
- package/dist/instructions-import-offer-NSYXSITC.js +363 -0
- package/dist/instructions-run-NBII7W36.js +114 -0
- package/dist/interrupted-work-E4TLKJLE.js +43 -0
- package/dist/invoke-provider-auth-NEWEIHCI.js +38 -0
- package/dist/judge-scoring.json +64 -0
- package/dist/lab-mode-YXQ2Y3NG.js +44 -0
- package/dist/lab-utils-5QAMDJR5.js +29 -0
- package/dist/linux-host-class-YDWQX65O.js +31 -0
- package/dist/llm-judge-executor-OJSNCTFJ.js +179 -0
- package/dist/local-ci-config-VZ4WWDT5.js +48 -0
- package/dist/local-executor-DCMDDRX2.js +280 -0
- package/dist/logger-5KNKS3O4.js +154 -0
- package/dist/matrix-prompt-builder-4ZBOGZSB.js +527 -0
- package/dist/matrix-result-parser-EZJM4YXP.js +14 -0
- package/dist/merge-batch-RTEEMVDB.js +313 -0
- package/dist/merge-batch-members-VIWGVRHP.js +24 -0
- package/dist/merge-queue-TIIUSOY6.js +126 -0
- package/dist/merge-queue-trust-DUNZ4J65.js +21 -0
- package/dist/metadata-UKSMWM6J.js +29 -0
- package/dist/model-catalog-readiness-R5KJBP5M.js +202 -0
- package/dist/model-invocations-db-XTUPPQ34.js +70 -0
- package/dist/model-resolver-JFZ2MHOJ.js +39 -0
- package/dist/model-resolver-SCQ57KAQ.js +217 -0
- package/dist/model-roles-D3OR4NAH.js +110 -0
- package/dist/monitor-F4SIU5G2.js +96 -0
- package/dist/nested-worktrees-2WUWQ75N.js +23 -0
- package/dist/next-S3IRLVER.js +96 -0
- package/dist/next-UKPFRXOO.js +148 -0
- package/dist/opportunistic-TL4S26VX.js +86 -0
- package/dist/optimization-config-resolver-NAEIYU6A.js +148 -0
- package/dist/package-HJR4QJT4.js +10 -0
- package/dist/parse-git-status-7PIYFPS2.js +21 -0
- package/dist/path-security-5WJSY56G.js +41 -0
- package/dist/paths-JUI7C4KU.js +45 -0
- package/dist/plan-backlog-list-fast-SSTQL5XP.js +89 -0
- package/dist/plan-backlog-show-fast-PFRAQ3JB.js +114 -0
- package/dist/plan-sprint-list-fast-HD2KBZSY.js +110 -0
- package/dist/plan-sprint-status-fast-YFYH7WQF.js +116 -0
- package/dist/plan-task-status-fast-JU5PNLUU.js +114 -0
- package/dist/plan-to-flywheel-PY5MSY2H.js +529 -0
- package/dist/preflight-PJHGTJNZ.js +12 -0
- package/dist/process-registry-B4ZUCN7T.js +28 -0
- package/dist/process-scanner-TU3QHWVB.js +23 -0
- package/dist/processes-6FHVGT72.js +28 -0
- package/dist/processes-json-fast-YWTMUWXB.js +72 -0
- package/dist/profile-HWTC56SG.js +209 -0
- package/dist/project-runtime-paths-2UQNG5Y4.js +41 -0
- package/dist/protected-branches-N36LDBFY.js +71 -0
- package/dist/provider-aware-resource-manager-YTFAHNGJ.js +40 -0
- package/dist/provider-matrix-2KO2V5OM.js +214 -0
- package/dist/provider-matrix-renderer-MEC3PER7.js +139 -0
- package/dist/provider-output-forwarding-2AHL7YMA.js +26 -0
- package/dist/provider-registry-WCZ65QHC.js +136 -0
- package/dist/provider-temp-cleanup-IUNPJCZF.js +14 -0
- package/dist/prune-engine-EOQVWEP6.js +448 -0
- package/dist/publication-turn-S42RZTQF.js +44 -0
- package/dist/quality-gate-JQMVCKOO.js +72 -0
- package/dist/quickstart-3O6FRCFB.js +105 -0
- package/dist/readiness-GW6ABRHB.js +139 -0
- package/dist/readiness-KFZCXDTT.js +215 -0
- package/dist/registry-7XG376SY.js +217 -0
- package/dist/repair-helpers-TTV5FEF4.js +117 -0
- package/dist/repo-root-YG6MQZDW.js +28 -0
- package/dist/resolution-engine-FFEK7HQ2.js +187 -0
- package/dist/resolve-provider-cli-ZEXVZKET.js +44 -0
- package/dist/restore-telemetry-db-E7BR5PO7.js +459 -0
- package/dist/routing-events-AW6SRZ6G.js +13 -0
- package/dist/routing-history-store-FMDDQL6W.js +39 -0
- package/dist/routing-planner-C6OHO3EY.js +221 -0
- package/dist/runner-KHDNQ5KU.js +1194 -0
- package/dist/runner-PIS2BW7Y.js +1801 -0
- package/dist/safety-E3JJVSFL.js +67 -0
- package/dist/safety-stanza-HE6GXP4G.js +49 -0
- package/dist/sandbox-7LBZC5PE.js +72 -0
- package/dist/sandbox-ASWCDYZL.js +80 -0
- package/dist/schema-extensions.sql +234 -0
- package/dist/security-JI22TBEB.js +17 -0
- package/dist/setup-bb-plugin-FQXLA76Y.js +531 -0
- package/dist/setup-claude-code-NF4ZSHVE.js +197 -0
- package/dist/setup-temp-cleanup-2APZ4HMA.js +29 -0
- package/dist/shared-utils-34HJZ6JX.js +40 -0
- package/dist/simple-artifact-goal-MQLDDMMX.js +29 -0
- package/dist/sprint-N7JFTEGL.js +403 -0
- package/dist/sprint-bridge-KJXIBNRJ.js +117 -0
- package/dist/sprint-completion-dependents-34SR7JVL.js +43 -0
- package/dist/sprint-execution-service-A6JPUBWY.js +376 -0
- package/dist/sprint-manager-MU2ZUWN2.js +140 -0
- package/dist/sqlite-timeout-config-U2CT4LKU.js +13 -0
- package/dist/sqlite-wrapper-FSGJ2QEW.js +19 -0
- package/dist/stale-cleanup-orchestrator-4X6324VF.js +71 -0
- package/dist/storage-access-I3V5LER7.js +31 -0
- package/dist/store-XVG64ZR2.js +25 -0
- package/dist/task-classifier-MN2DYE5R.js +558 -0
- package/dist/task-list-fast-7AT6LTTA.js +112 -0
- package/dist/task-manager-LHPBBRRE.js +136 -0
- package/dist/task-report-OLPAWBTK.js +64 -0
- package/dist/task-type-detector-6RG3YNZF.js +27 -0
- package/dist/task-type-resolver-EQHOUIHT.js +64 -0
- package/dist/telemetry-5VYSK772.js +212 -0
- package/dist/telemetry-health-tracker-4GFW2EMP.js +12 -0
- package/dist/telemetry-path-resolver-H3NFHHQY.js +34 -0
- package/dist/telemetry-reliability-URJDTNPZ.js +76 -0
- package/dist/transports-NREZQTJK.js +106 -0
- package/dist/unified-cost-tracker-5MTBJ2CL.js +59 -0
- package/dist/unified-state-cleanup-GGAXLHXF.js +292 -0
- package/dist/universal-cost-calculator-JTFEJVWK.js +70 -0
- package/dist/user-agents-QLIGPLP2.js +30 -0
- package/dist/variant-execution-I4ZZUAWY.js +319 -0
- package/dist/variant-opt-parser-JHCXKY2K.js +251 -0
- package/dist/variant-request-input-PL37N3AN.js +11 -0
- package/dist/variant-state-cleanup-KHMXRBZN.js +287 -0
- package/dist/variant-worker-COB5YTJX.js +4517 -0
- package/dist/variant-worker.js +26 -0
- package/dist/variants-XGDSXYG3.js +267 -0
- package/dist/verification-command-YSPU4VBH.js +66 -0
- package/dist/verify-command-timeout-DQUYH33Z.js +11 -0
- package/dist/verify-commands-LOHMOFKC.js +65 -0
- package/dist/warning-JSKSFKBT.js +13 -0
- package/dist/work-edge-K65NHVWY.js +50 -0
- package/dist/work-item-writer-KY5ZWZWW.js +30 -0
- package/dist/worker-JNXXEIT6.js +1504 -0
- package/dist/worker.js +21 -0
- package/dist/workspace-tree-identity-JO5PSKTW.js +52 -0
- package/dist/worktree-environment-WTVABAQW.js +64 -0
- package/dist/worktree-metrics-VZRQI26T.js +66 -0
- package/dist/writeback-TQFQBJNU.js +50 -0
- package/docs/CLI_REFERENCE.md +8287 -0
- package/docs/PROVIDER_SETUP.md +1737 -0
- package/docs/README.md +96 -0
- package/docs/TROUBLESHOOTING.md +2209 -0
- package/docs/getting-started/QUICK_START.md +260 -0
- package/docs/getting-started/README.md +198 -0
- package/docs/getting-started/SETUP.md +25 -0
- package/docs/reference/AGENT_CONTEXT.md +84 -0
- package/docs/reference/DELIVERY_ONBOARDING.md +198 -0
- package/docs/reference/PROVIDER_RELEASE_TIERS.md +34 -0
- package/docs/reference/SECURITY.md +291 -0
- package/docs/reference/TELEMETRY_PRIVACY.md +259 -0
- package/integrations/bb-plugin-build/README.md +391 -0
- package/integrations/bb-plugin-build/app.css +431 -0
- package/integrations/bb-plugin-build/app.tsx +6210 -0
- package/integrations/bb-plugin-build/package.json +45 -0
- package/integrations/bb-plugin-build/server.ts +488 -0
- package/integrations/bb-plugin-build/src/adapter.ts +3672 -0
- package/integrations/bb-plugin-build/src/backlog-authoring-model.ts +150 -0
- package/integrations/bb-plugin-build/src/backlog-authoring-schema.ts +458 -0
- package/integrations/bb-plugin-build/src/backlog-authoring-service.ts +467 -0
- package/integrations/bb-plugin-build/src/backlog-authoring-view.ts +1025 -0
- package/integrations/bb-plugin-build/src/command-evidence-schema.ts +13 -0
- package/integrations/bb-plugin-build/src/competition-defaults-schema.ts +122 -0
- package/integrations/bb-plugin-build/src/competition-defaults-service.ts +105 -0
- package/integrations/bb-plugin-build/src/competition-defaults-view.ts +138 -0
- package/integrations/bb-plugin-build/src/contract.ts +718 -0
- package/integrations/bb-plugin-build/src/execution-activity-view.ts +98 -0
- package/integrations/bb-plugin-build/src/finalize-model.ts +205 -0
- package/integrations/bb-plugin-build/src/finalize-schema.ts +150 -0
- package/integrations/bb-plugin-build/src/finalize-service.ts +330 -0
- package/integrations/bb-plugin-build/src/finalize-view.ts +159 -0
- package/integrations/bb-plugin-build/src/judge-operations-readback.ts +303 -0
- package/integrations/bb-plugin-build/src/judge-operations-schema.ts +33 -0
- package/integrations/bb-plugin-build/src/judge-operations-view.ts +459 -0
- package/integrations/bb-plugin-build/src/model.ts +1318 -0
- package/integrations/bb-plugin-build/src/monitor-service.ts +233 -0
- package/integrations/bb-plugin-build/src/panel-read-ux.ts +97 -0
- package/integrations/bb-plugin-build/src/patch-preview-schema.ts +166 -0
- package/integrations/bb-plugin-build/src/patch-preview-service.ts +480 -0
- package/integrations/bb-plugin-build/src/patch-preview-view.ts +109 -0
- package/integrations/bb-plugin-build/src/planning-readback.ts +228 -0
- package/integrations/bb-plugin-build/src/planning-service.ts +647 -0
- package/integrations/bb-plugin-build/src/planning-sync-evidence.ts +37 -0
- package/integrations/bb-plugin-build/src/planning-workspace-readback.ts +33 -0
- package/integrations/bb-plugin-build/src/planning-workspace-schema.ts +131 -0
- package/integrations/bb-plugin-build/src/planning-workspace.ts +333 -0
- package/integrations/bb-plugin-build/src/poll-handoff.ts +136 -0
- package/integrations/bb-plugin-build/src/project-target-server.ts +21 -0
- package/integrations/bb-plugin-build/src/project-target.ts +45 -0
- package/integrations/bb-plugin-build/src/reference-index.ts +218 -0
- package/integrations/bb-plugin-build/src/repository-identity.ts +17 -0
- package/integrations/bb-plugin-build/src/repository-schema.ts +30 -0
- package/integrations/bb-plugin-build/src/result-explorer-view.ts +597 -0
- package/integrations/bb-plugin-build/src/result-readback-model.ts +163 -0
- package/integrations/bb-plugin-build/src/result-readback-schema.ts +319 -0
- package/integrations/bb-plugin-build/src/result-readback-service.ts +333 -0
- package/integrations/bb-plugin-build/src/run-page-view.ts +332 -0
- package/integrations/bb-plugin-build/src/setup-config-schema.ts +293 -0
- package/integrations/bb-plugin-build/src/setup-config-service.ts +620 -0
- package/integrations/bb-plugin-build/src/setup-config-view.ts +388 -0
- package/integrations/bb-plugin-build/src/sprint-close-model.ts +150 -0
- package/integrations/bb-plugin-build/src/sprint-close-schema.ts +128 -0
- package/integrations/bb-plugin-build/src/sprint-close-service.ts +293 -0
- package/integrations/bb-plugin-build/src/sprint-close-view.ts +116 -0
- package/integrations/bb-plugin-build/src/sprint-composition-model.ts +709 -0
- package/integrations/bb-plugin-build/src/sprint-composition-readback.ts +231 -0
- package/integrations/bb-plugin-build/src/sprint-composition-schema.ts +597 -0
- package/integrations/bb-plugin-build/src/sprint-composition-service.ts +773 -0
- package/integrations/bb-plugin-build/src/sprint-composition-view.ts +1221 -0
- package/integrations/bb-plugin-build/src/sprint-execution-schema.ts +188 -0
- package/integrations/bb-plugin-build/src/sprint-execution-service.ts +289 -0
- package/integrations/bb-plugin-build/src/sprint-execution-view.ts +54 -0
- package/integrations/bb-plugin-build/src/task-authoring-model.ts +563 -0
- package/integrations/bb-plugin-build/src/task-authoring-schema.ts +629 -0
- package/integrations/bb-plugin-build/src/task-authoring-service.ts +842 -0
- package/integrations/bb-plugin-build/src/task-authoring-view.ts +1227 -0
- package/integrations/bb-plugin-build/src/task-catalog-schema.ts +46 -0
- package/integrations/bb-plugin-build/src/task-catalog-service.ts +44 -0
- package/integrations/bb-plugin-build/src/task-detail-readback.ts +56 -0
- package/integrations/bb-plugin-build/src/task-detail-schema.ts +171 -0
- package/integrations/bb-plugin-build/src/task-navigation.ts +446 -0
- package/integrations/bb-plugin-build/src/workbench-route.ts +74 -0
- package/package.json +306 -4
- package/schemas/README.md +80 -0
- package/schemas/build.config.schema.json +2110 -0
- package/schemas/config-v1.schema.json +136 -0
- package/schemas/execution-config.schema.json +47 -0
- package/schemas/judge-scoring.schema.json +257 -0
- package/schemas/provider-config.schema.json +179 -0
- package/schemas/telemetry-config.schema.json +79 -0
- package/schemas/user-preferences.schema.json +141 -0
- package/scripts/assert-node-runtime.mjs +146 -0
- package/scripts/preflight-native.mjs +49 -0
- package/scripts/setup-git-hooks.mjs +39 -0
- package/scripts/sync.sh +2871 -0
- package/scripts/write-node-launcher.sh +138 -0
- package/src/resources/gemini/slash-packs/default/plan.toml +15 -0
- package/src/resources/gemini/slash-packs/default/summary.toml +16 -0
- package/src/resources/gemini/slash-packs/default/tests.toml +16 -0
- package/templates/.build-project/README.md +41 -0
- package/templates/.build-project/agents/README.md +50 -0
- package/templates/.build-project/agents/architect.md +10 -0
- package/templates/.build-project/agents/code-reviewer.md +10 -0
- package/templates/.build-project/agents/debugger.md +10 -0
- package/templates/.build-project/agents/documenter.md +10 -0
- package/templates/.build-project/agents/test-automator.md +10 -0
- package/templates/.build-project/config/build.config.jsonc +64 -0
- package/templates/.build-project/config/project-context.template.json +6 -0
- package/templates/.build-project/config/task-type-aliases.presets/kanban.yaml +14 -0
- package/templates/.build-project/config/task-type-aliases.presets/scrum.yaml +17 -0
- package/templates/.build-project/config/task-type-aliases.presets/xp.yaml +12 -0
- package/templates/.build-project/config/task-type-aliases.yaml +29 -0
- package/templates/.build-project/gitignore.template +70 -0
- package/templates/.build-project/task-types/analysis.yaml +38 -0
- package/templates/.build-project/task-types/architecture.yaml +35 -0
- package/templates/.build-project/task-types/doc.yaml +34 -0
- package/templates/.build-project/task-types/feature.yaml +22 -0
- package/templates/.build-project/task-types/general.yaml +4 -0
- package/templates/.build-project/task-types/security.yaml +38 -0
- package/templates/AGENTS.template.md +85 -0
- package/templates/CLAUDE.template.md +1 -0
- package/templates/GEMINI.template.md +1 -0
- package/templates/builtin-workflows/code-review.yaml +73 -0
- package/templates/builtin-workflows/skills/code-review/SKILL.md +61 -0
- package/templates/builtin-workflows/skills/execution-contract-analysis/SKILL.md +24 -0
- package/templates/builtin-workflows/skills/execution-contract-code/SKILL.md +19 -0
- package/templates/builtin-workflows/skills/execution-contract-structured/SKILL.md +17 -0
- package/templates/ci/incident-intake.mjs +787 -0
- package/templates/ci/incidents.yml.template +103 -0
- package/templates/ci/node.yml.template +17 -0
- package/templates/ci/python.yml.template +17 -0
- package/templates/guard-kit/GUARD_SETUP.md.template +258 -0
- package/templates/guard-kit/build-guard.yml.template +189 -0
- package/templates/guard-kit/check.mjs.template +932 -0
- package/templates/guard-kit/config.json.template +7 -0
- package/templates/guard-kit/policy.json.template +1 -0
- package/templates/profiles/README.md +57 -0
- package/templates/profiles/frontier-claude.json +23 -0
- package/templates/profiles/frontier-codex.json +23 -0
|
@@ -0,0 +1,932 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Build guardrail kit gate (kit version {{KIT_VERSION}}).
|
|
4
|
+
*
|
|
5
|
+
* Self-contained, vendored gate script. Zero npm dependencies: only node:
|
|
6
|
+
* builtins are imported. Requires Node >= 24 (ESM, modern fs). Runs at gate
|
|
7
|
+
* time with no Build, no npm, and no network.
|
|
8
|
+
*
|
|
9
|
+
* Runs three check families over the diff between a base ref and HEAD. With
|
|
10
|
+
* --staged it runs only the built-in secret scan over the staged index. With
|
|
11
|
+
* --message <file> (`-` reads stdin) it runs only the attribution text rules
|
|
12
|
+
* over one commit message against this checkout's policy.json, the same rules
|
|
13
|
+
* the range scan applies to each commit message (for a commit-msg hook):
|
|
14
|
+
* 1. secret-scan: added diff lines matched against the built-in credential
|
|
15
|
+
* catalog (supported provider CLI keys plus the AWS, GCP, and GitHub paths
|
|
16
|
+
* they authenticate through) plus config.json extraSecretPatterns.
|
|
17
|
+
* 2. artifact-paths: changed paths matched against generated deny defaults
|
|
18
|
+
* plus config.json extraDenyPaths / extraArtifactPatterns. config.json
|
|
19
|
+
* allowPaths exempts matching paths from the DEFAULT denies only (a repo
|
|
20
|
+
* that commits dist/ on purpose), never from the extras it added itself.
|
|
21
|
+
* 3. guard-integrity: any changed path under this guard directory (check.mjs,
|
|
22
|
+
* config.json, policy.json, checks.lock) is a gate-critical finding.
|
|
23
|
+
* Matching is case-INSENSITIVE (a case-variant path like .build-project/Guard/x
|
|
24
|
+
* collides with the guard dir on case-insensitive filesystems).
|
|
25
|
+
* 4. attribution: when the BASE ref's committed policy.json says `human-only`
|
|
26
|
+
* (a PR cannot relax it by editing its own copy), every non-merge commit
|
|
27
|
+
* in the range (author, committer, message) and the pull-request body
|
|
28
|
+
* (BUILD_GUARD_PR_BODY_FILE, else GITHUB_EVENT_PATH) must carry no AI
|
|
29
|
+
* attribution. Structural rules: any Co-authored-by trailer and any
|
|
30
|
+
* `[bot]` author/committer outside policy.botAllow are findings.
|
|
31
|
+
* Catalog rules: the vendored provider identities, trailer keys, and
|
|
32
|
+
* bylines. Under `allow` the family is a no-op. policy.json is generated
|
|
33
|
+
* and hash-tracked (see build guard sync); missing or malformed fails
|
|
34
|
+
* closed.
|
|
35
|
+
*
|
|
36
|
+
* Exit codes:
|
|
37
|
+
* 0 clean.
|
|
38
|
+
* 1 hard failure (secret, artifact path, attribution). Blocks merge.
|
|
39
|
+
* 2 only guard-integrity findings (gate machinery changed) with no hard
|
|
40
|
+
* failure. Softer than 1: merge automation treats this as
|
|
41
|
+
* require-human-merge rather than block. A hard finding always dominates,
|
|
42
|
+
* so exit 1 wins when both are present.
|
|
43
|
+
*
|
|
44
|
+
* Config (this-dir config.json, all keys optional): baseRef, extraDenyPaths,
|
|
45
|
+
* allowPaths, extraSecretPatterns, extraArtifactPatterns. Config tunes policy VALUES only;
|
|
46
|
+
* it cannot enable or disable a check. Check on/off lives in the generated
|
|
47
|
+
* manifest below and is not consumer-editable.
|
|
48
|
+
*/
|
|
49
|
+
|
|
50
|
+
import { execFileSync } from 'node:child_process';
|
|
51
|
+
import { existsSync, readFileSync, realpathSync } from 'node:fs';
|
|
52
|
+
import { basename, dirname, join, relative } from 'node:path';
|
|
53
|
+
import { fileURLToPath } from 'node:url';
|
|
54
|
+
|
|
55
|
+
const MANIFEST = {{GENERATED_MANIFEST}};
|
|
56
|
+
|
|
57
|
+
// Fail CLOSED on a malformed manifest. Every check family gates on
|
|
58
|
+
// MANIFEST.checks.<key>; if the renderer and this template ever disagree on
|
|
59
|
+
// the manifest shape, a missing key must abort the run — never silently skip
|
|
60
|
+
// a check (a skipped check reads as a pass to merge automation).
|
|
61
|
+
const REQUIRED_CHECK_KEYS = [
|
|
62
|
+
'secretScan',
|
|
63
|
+
'artifactPaths',
|
|
64
|
+
'guardIntegrity',
|
|
65
|
+
'attribution',
|
|
66
|
+
];
|
|
67
|
+
for (const key of REQUIRED_CHECK_KEYS) {
|
|
68
|
+
if (typeof MANIFEST?.checks?.[key] !== 'boolean') {
|
|
69
|
+
process.stderr.write(
|
|
70
|
+
`Error: guard manifest is malformed (checks.${key} missing). ` +
|
|
71
|
+
'The generated gate is unusable; re-run: build init --guardrails --reinstall-guard\n'
|
|
72
|
+
);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (!Array.isArray(MANIFEST.defaultDenyPaths)) {
|
|
77
|
+
process.stderr.write(
|
|
78
|
+
'Error: guard manifest is malformed (defaultDenyPaths missing). ' +
|
|
79
|
+
'Re-run: build init --guardrails --reinstall-guard\n'
|
|
80
|
+
);
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// The guard directory is normally where this script lives. BUILD_GUARD_DIR
|
|
85
|
+
// overrides it for the trusted-base invocation pattern: CI extracts the BASE
|
|
86
|
+
// branch's copy of check.mjs to a temp path and runs that copy against the
|
|
87
|
+
// PR checkout (a PR-owned script could otherwise strip its own
|
|
88
|
+
// guard-integrity check before it runs). See the generated CI guidance.
|
|
89
|
+
/**
|
|
90
|
+
* Resolve symlinks so path comparisons against git output are stable (macOS:
|
|
91
|
+
* /var/... vs /private/var/...). Tolerates a missing path by realpathing the
|
|
92
|
+
* nearest existing ancestor and re-appending the missing tail — needed when a
|
|
93
|
+
* PR deletes the guard dir and BUILD_GUARD_DIR points at the gap.
|
|
94
|
+
*/
|
|
95
|
+
function realpathBestEffort(target) {
|
|
96
|
+
let head = target;
|
|
97
|
+
let tail = '';
|
|
98
|
+
for (;;) {
|
|
99
|
+
try {
|
|
100
|
+
const real = realpathSync(head);
|
|
101
|
+
return tail ? join(real, tail) : real;
|
|
102
|
+
} catch {
|
|
103
|
+
const parent = dirname(head);
|
|
104
|
+
if (parent === head) return target;
|
|
105
|
+
tail = tail ? join(basename(head), tail) : basename(head);
|
|
106
|
+
head = parent;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const SCRIPT_DIR = realpathBestEffort(
|
|
112
|
+
process.env.BUILD_GUARD_DIR
|
|
113
|
+
? process.env.BUILD_GUARD_DIR
|
|
114
|
+
: dirname(fileURLToPath(import.meta.url))
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
// Generated from src/core/guard-kit/secret-patterns.ts. Local staged checks
|
|
118
|
+
// and hosted commit-range checks execute this same vendored inventory.
|
|
119
|
+
const SECRET_PATTERNS = {{SECRET_PATTERNS}};
|
|
120
|
+
|
|
121
|
+
/** Normalize any git path to forward slashes before matching. */
|
|
122
|
+
function normalizePath(value) {
|
|
123
|
+
return value.replace(/\\/g, '/');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Case-insensitive prefix test for the guard NAMESPACE. Guard-integrity must
|
|
128
|
+
* catch case-variant paths (.build-project/Guard/x, .Build/guard/y): on a
|
|
129
|
+
* case-sensitive CI runner those are distinct paths, but when the merged
|
|
130
|
+
* branch is later checked out on a case-insensitive filesystem (macOS,
|
|
131
|
+
* Windows) they materialize INSIDE the real guard directory. Detection is
|
|
132
|
+
* deliberately broader than the exact tracked case.
|
|
133
|
+
*/
|
|
134
|
+
function isUnderGuardNamespace(filePath, guardDirPrefix) {
|
|
135
|
+
return filePath.toLowerCase().startsWith(guardDirPrefix.toLowerCase());
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Git cwd: prefer the guard dir when it exists (normal case), else fall back
|
|
139
|
+
// to the process cwd. The fallback matters for the trusted-base pattern when
|
|
140
|
+
// a PR DELETES the entire guard directory: BUILD_GUARD_DIR then points at a
|
|
141
|
+
// missing path, and spawning git from it would crash with a generic error
|
|
142
|
+
// instead of reaching the guard-integrity verdict (exit 2).
|
|
143
|
+
const GIT_CWD = existsSync(SCRIPT_DIR) ? SCRIPT_DIR : process.cwd();
|
|
144
|
+
|
|
145
|
+
function git(args, options = {}) {
|
|
146
|
+
try {
|
|
147
|
+
return execFileSync('git', args, {
|
|
148
|
+
cwd: GIT_CWD,
|
|
149
|
+
encoding: 'utf8',
|
|
150
|
+
maxBuffer: 64 * 1024 * 1024,
|
|
151
|
+
});
|
|
152
|
+
} catch (error) {
|
|
153
|
+
if (options.allowFailure) {
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function isCI() {
|
|
161
|
+
const value = process.env.CI;
|
|
162
|
+
return Boolean(value) && value !== '0' && value.toLowerCase() !== 'false';
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function loadConfig() {
|
|
166
|
+
const configPath = join(SCRIPT_DIR, 'config.json');
|
|
167
|
+
if (!existsSync(configPath)) {
|
|
168
|
+
return {};
|
|
169
|
+
}
|
|
170
|
+
let raw;
|
|
171
|
+
try {
|
|
172
|
+
raw = readFileSync(configPath, 'utf8');
|
|
173
|
+
} catch (error) {
|
|
174
|
+
throw new Error(`cannot read config.json at ${configPath}: ${error.message}`);
|
|
175
|
+
}
|
|
176
|
+
try {
|
|
177
|
+
return JSON.parse(raw);
|
|
178
|
+
} catch (error) {
|
|
179
|
+
throw new Error(`unparseable config.json at ${configPath}: ${error.message}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function parseArgs(argv) {
|
|
184
|
+
const parsed = {
|
|
185
|
+
formatJson: false,
|
|
186
|
+
listChecks: false,
|
|
187
|
+
staged: false,
|
|
188
|
+
message: null,
|
|
189
|
+
base: null,
|
|
190
|
+
};
|
|
191
|
+
for (let i = 0; i < argv.length; i++) {
|
|
192
|
+
const arg = argv[i];
|
|
193
|
+
if (arg === '--format') {
|
|
194
|
+
parsed.formatJson = argv[++i] === 'json';
|
|
195
|
+
} else if (arg === '--format=json') {
|
|
196
|
+
parsed.formatJson = true;
|
|
197
|
+
} else if (arg === '--list-checks') {
|
|
198
|
+
parsed.listChecks = true;
|
|
199
|
+
} else if (arg === '--staged') {
|
|
200
|
+
parsed.staged = true;
|
|
201
|
+
} else if (arg === '--message') {
|
|
202
|
+
parsed.message = argv[++i] ?? null;
|
|
203
|
+
} else if (arg === '--base') {
|
|
204
|
+
parsed.base = argv[++i] ?? null;
|
|
205
|
+
} else if (arg.startsWith('--base=')) {
|
|
206
|
+
parsed.base = arg.slice('--base='.length);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return parsed;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function resolveBaseRef(config, cliBase) {
|
|
213
|
+
if (cliBase) {
|
|
214
|
+
return cliBase;
|
|
215
|
+
}
|
|
216
|
+
if (process.env.BUILD_GUARD_BASE_REF) {
|
|
217
|
+
return process.env.BUILD_GUARD_BASE_REF;
|
|
218
|
+
}
|
|
219
|
+
const githubBase = (process.env.GITHUB_BASE_REF ?? '').trim();
|
|
220
|
+
if (githubBase) {
|
|
221
|
+
return `origin/${githubBase}`;
|
|
222
|
+
}
|
|
223
|
+
// config.json is BRANCH-OWNED, so it must never choose the base in CI: a
|
|
224
|
+
// PR could set baseRef to HEAD, empty the diff, and disable every check.
|
|
225
|
+
// Locally it is a convenience only (local runs are feedback, CI is the
|
|
226
|
+
// enforcement point). In CI the base comes from env/flags/origin/HEAD or
|
|
227
|
+
// the run fails closed.
|
|
228
|
+
if (config.baseRef && !isCI()) {
|
|
229
|
+
return config.baseRef;
|
|
230
|
+
}
|
|
231
|
+
const originHead = git(['symbolic-ref', '--quiet', 'refs/remotes/origin/HEAD'], {
|
|
232
|
+
allowFailure: true,
|
|
233
|
+
});
|
|
234
|
+
if (originHead) {
|
|
235
|
+
return originHead.trim().replace(/^refs\/remotes\//, '');
|
|
236
|
+
}
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** Parse `git diff --name-status -z` into a de-duplicated changed-path list. */
|
|
241
|
+
function parseNameStatusZ(raw) {
|
|
242
|
+
const tokens = raw.split('\0');
|
|
243
|
+
const entries = new Map();
|
|
244
|
+
const add = (path, status) => {
|
|
245
|
+
if (path && !entries.has(normalizePath(path))) {
|
|
246
|
+
entries.set(normalizePath(path), status);
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
let i = 0;
|
|
250
|
+
while (i < tokens.length) {
|
|
251
|
+
const status = tokens[i];
|
|
252
|
+
if (!status) {
|
|
253
|
+
i++;
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
if (/^[RC]\d*$/.test(status)) {
|
|
257
|
+
// Rename/copy: the source path effectively left (deleted) and the
|
|
258
|
+
// destination arrived.
|
|
259
|
+
add(tokens[i + 1], 'D');
|
|
260
|
+
add(tokens[i + 2], status[0]);
|
|
261
|
+
i += 3;
|
|
262
|
+
} else {
|
|
263
|
+
add(tokens[i + 1], status[0]);
|
|
264
|
+
i += 2;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return [...entries].map(([path, status]) => ({ path, status }));
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Validate the parsed policy shape strictly. Returns an error string or null.
|
|
272
|
+
* A malformed catalog field must never degrade to "no rule" (fail closed).
|
|
273
|
+
*/
|
|
274
|
+
function validatePolicyShape(parsed) {
|
|
275
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
276
|
+
return 'policy is not a JSON object';
|
|
277
|
+
}
|
|
278
|
+
if (parsed.attribution !== 'allow' && parsed.attribution !== 'human-only') {
|
|
279
|
+
return 'attribution must be "allow" or "human-only"';
|
|
280
|
+
}
|
|
281
|
+
const isStringList = (value) =>
|
|
282
|
+
Array.isArray(value) && value.every((entry) => typeof entry === 'string' && entry.length > 0);
|
|
283
|
+
if (parsed.botAllow !== undefined && !isStringList(parsed.botAllow)) {
|
|
284
|
+
return 'botAllow must be an array of non-empty strings';
|
|
285
|
+
}
|
|
286
|
+
if (!parsed.catalog || typeof parsed.catalog !== 'object' || Array.isArray(parsed.catalog)) {
|
|
287
|
+
return 'catalog must be an object';
|
|
288
|
+
}
|
|
289
|
+
for (const key of ['identities', 'trailerKeys', 'bylines', 'bylineRegexSources']) {
|
|
290
|
+
if (parsed.catalog[key] !== undefined && !isStringList(parsed.catalog[key])) {
|
|
291
|
+
return `catalog.${key} must be an array of non-empty strings`;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Load the attribution policy from its TRUSTED source. The base ref's committed
|
|
299
|
+
* policy.json governs: a pull request cannot relax the rule for itself by
|
|
300
|
+
* editing the file, whichever guard dir BUILD_GUARD_DIR points at. When the
|
|
301
|
+
* base ref has no policy.json (the kit there predates 0.5.0):
|
|
302
|
+
* - guard files unchanged in this diff -> the guard-dir copy equals the base
|
|
303
|
+
* copy, so it is read; a 0.5.0 gate with no policy at all is a partial kit
|
|
304
|
+
* and fails closed;
|
|
305
|
+
* - guard files changed -> the branch copy is untrusted; attribution is not
|
|
306
|
+
* evaluated (returned policy null) and guard-integrity already forces a
|
|
307
|
+
* human merge (exit 2).
|
|
308
|
+
* Returns { policy } (policy may be null with `skipped` set) or { error }.
|
|
309
|
+
*/
|
|
310
|
+
function loadPolicy(baseRef, guardDirRel, trustBranchConfig) {
|
|
311
|
+
// A null baseRef (--message mode) reads this checkout's policy.json directly.
|
|
312
|
+
let raw =
|
|
313
|
+
baseRef === null
|
|
314
|
+
? null
|
|
315
|
+
: git(['show', `${baseRef}:${guardDirRel}policy.json`], { allowFailure: true });
|
|
316
|
+
let origin = `${baseRef}:${guardDirRel}policy.json`;
|
|
317
|
+
if (raw === null) {
|
|
318
|
+
if (!trustBranchConfig) {
|
|
319
|
+
return {
|
|
320
|
+
policy: null,
|
|
321
|
+
skipped: `base ref ${baseRef} has no policy.json and guard files changed in this diff; attribution not evaluated (guard-integrity requires a human merge).`,
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
const policyPath = join(SCRIPT_DIR, 'policy.json');
|
|
325
|
+
if (!existsSync(policyPath)) {
|
|
326
|
+
return {
|
|
327
|
+
error: `policy.json missing at ${policyPath}${baseRef === null ? '' : ` and absent at ${baseRef}`}`,
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
try {
|
|
331
|
+
raw = readFileSync(policyPath, 'utf8');
|
|
332
|
+
} catch (error) {
|
|
333
|
+
return { error: `policy.json unreadable at ${policyPath}: ${error.message}` };
|
|
334
|
+
}
|
|
335
|
+
origin = policyPath;
|
|
336
|
+
}
|
|
337
|
+
let parsed;
|
|
338
|
+
try {
|
|
339
|
+
parsed = JSON.parse(raw);
|
|
340
|
+
} catch (error) {
|
|
341
|
+
return { error: `policy.json at ${origin} is not valid JSON: ${error.message}` };
|
|
342
|
+
}
|
|
343
|
+
const shapeError = validatePolicyShape(parsed);
|
|
344
|
+
if (shapeError) {
|
|
345
|
+
return { error: `policy.json at ${origin} is malformed (${shapeError})` };
|
|
346
|
+
}
|
|
347
|
+
const lower = (values) => (values ?? []).map((value) => value.toLowerCase());
|
|
348
|
+
const catalog = parsed.catalog;
|
|
349
|
+
try {
|
|
350
|
+
return {
|
|
351
|
+
policy: {
|
|
352
|
+
attribution: parsed.attribution,
|
|
353
|
+
botAllow: lower(parsed.botAllow),
|
|
354
|
+
identities: lower(catalog.identities),
|
|
355
|
+
trailerKeys: lower(catalog.trailerKeys),
|
|
356
|
+
bylines: lower(catalog.bylines),
|
|
357
|
+
bylineRegexes: (catalog.bylineRegexSources ?? []).map((source) => new RegExp(source, 'i')),
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
} catch (error) {
|
|
361
|
+
return { error: `policy.json at ${origin} has an invalid catalog regex: ${error.message}` };
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const ATTRIBUTION_FIX =
|
|
366
|
+
'Under git.attribution=human-only, remove the AI attribution (amend or rebase the commit, edit the PR body) and run build guard sync so the agent CLIs stop adding it.';
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* Bot login for a git identity, lower-cased, or null. Recognises the
|
|
370
|
+
* `<login>[bot]` display name and the GitHub bot address
|
|
371
|
+
* `<id>+<login>[bot]@users.noreply.github.com`.
|
|
372
|
+
*/
|
|
373
|
+
function botLogin(name, email) {
|
|
374
|
+
const trimmedName = (name || '').trim();
|
|
375
|
+
if (/\[bot\]$/i.test(trimmedName)) {
|
|
376
|
+
return trimmedName.toLowerCase();
|
|
377
|
+
}
|
|
378
|
+
const match = /^(?:\d+\+)?([^@]+\[bot\])@users\.noreply\.github\.com$/i.exec((email || '').trim());
|
|
379
|
+
return match ? match[1].toLowerCase() : null;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/** Scan free text (a commit body or PR body) for attribution signatures. */
|
|
383
|
+
function scanAttributionText(policy, text, file, addFinding) {
|
|
384
|
+
const lowerText = text.toLowerCase();
|
|
385
|
+
for (const rawLine of text.split('\n')) {
|
|
386
|
+
const line = rawLine.trim();
|
|
387
|
+
if (!line) continue;
|
|
388
|
+
const lowerLine = line.toLowerCase();
|
|
389
|
+
const coauthor = /^co-authored-by:\s*(.*)$/i.exec(line);
|
|
390
|
+
if (coauthor) {
|
|
391
|
+
addFinding('attribution', 'co-authored-by', file, `Co-authored-by trailer present (${coauthor[1].trim()})`, ATTRIBUTION_FIX);
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
for (const key of policy.trailerKeys) {
|
|
395
|
+
if (lowerLine.startsWith(`${key}:`)) {
|
|
396
|
+
addFinding('attribution', 'agent-trailer', file, `agent trailer present (${line})`, ATTRIBUTION_FIX);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
for (const regex of policy.bylineRegexes) {
|
|
400
|
+
if (regex.test(line)) {
|
|
401
|
+
addFinding('attribution', 'agent-byline', file, `agent byline present (${line})`, ATTRIBUTION_FIX);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
for (const byline of policy.bylines) {
|
|
406
|
+
if (lowerText.includes(byline)) {
|
|
407
|
+
addFinding('attribution', 'agent-byline', file, `agent byline present (${byline})`, ATTRIBUTION_FIX);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
for (const identity of policy.identities) {
|
|
411
|
+
if (lowerText.includes(identity)) {
|
|
412
|
+
addFinding('attribution', 'agent-identity', file, `agent identity present (${identity})`, ATTRIBUTION_FIX);
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Scan every non-merge commit in mergeBase..HEAD: identities and message.
|
|
419
|
+
* Fields and records are NUL-separated: git refuses NUL bytes in commit
|
|
420
|
+
* messages and identities, so no message content can forge a boundary (a
|
|
421
|
+
* printable separator such as U+001E could). Each record is exactly six
|
|
422
|
+
* fields; the hex object id (SHA-1 or SHA-256) guards alignment.
|
|
423
|
+
*/
|
|
424
|
+
function scanAttributionCommits(policy, mergeBase, addFinding) {
|
|
425
|
+
const raw =
|
|
426
|
+
git([
|
|
427
|
+
'log',
|
|
428
|
+
'-z',
|
|
429
|
+
'--no-merges',
|
|
430
|
+
'--format=%H%x00%an%x00%ae%x00%cn%x00%ce%x00%B',
|
|
431
|
+
`${mergeBase}..HEAD`,
|
|
432
|
+
]) ?? '';
|
|
433
|
+
const tokens = raw.split('\u0000');
|
|
434
|
+
for (let index = 0; index + 5 < tokens.length; index += 6) {
|
|
435
|
+
const [sha, authorName, authorEmail, committerName, committerEmail, body] = tokens.slice(
|
|
436
|
+
index,
|
|
437
|
+
index + 6
|
|
438
|
+
);
|
|
439
|
+
// SHA-1 (40) or SHA-256 (64) object ids.
|
|
440
|
+
if (!/^[0-9a-f]{40}(?:[0-9a-f]{24})?$/.test(sha)) {
|
|
441
|
+
throw new Error(`unexpected git log record alignment at token ${index}`);
|
|
442
|
+
}
|
|
443
|
+
const file = `commit ${sha.slice(0, 12)}`;
|
|
444
|
+
for (const [role, name, email] of [
|
|
445
|
+
['author', authorName, authorEmail],
|
|
446
|
+
['committer', committerName, committerEmail],
|
|
447
|
+
]) {
|
|
448
|
+
const lowerEmail = (email || '').trim().toLowerCase();
|
|
449
|
+
if (policy.identities.includes(lowerEmail)) {
|
|
450
|
+
addFinding('attribution', 'agent-identity', file, `${role} ${lowerEmail} is an AI agent identity`, ATTRIBUTION_FIX);
|
|
451
|
+
}
|
|
452
|
+
const bot = botLogin(name, email);
|
|
453
|
+
if (bot && !policy.botAllow.includes(bot)) {
|
|
454
|
+
addFinding('attribution', 'bot-identity', file, `${role} ${bot} is a bot identity not in policy.botAllow`, ATTRIBUTION_FIX);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
scanAttributionText(policy, body, file, addFinding);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Pull-request body for the hosted run: BUILD_GUARD_PR_BODY_FILE (any CI), else
|
|
463
|
+
* the GitHub event payload. Null when neither is available (local runs, merge
|
|
464
|
+
* queues); the PR event re-runs on `edited`, so body enforcement lives there.
|
|
465
|
+
*/
|
|
466
|
+
function loadPullRequestBody() {
|
|
467
|
+
const bodyFile = process.env.BUILD_GUARD_PR_BODY_FILE;
|
|
468
|
+
if (bodyFile && existsSync(bodyFile)) {
|
|
469
|
+
return readFileSync(bodyFile, 'utf8');
|
|
470
|
+
}
|
|
471
|
+
const eventPath = process.env.GITHUB_EVENT_PATH;
|
|
472
|
+
if (eventPath && existsSync(eventPath)) {
|
|
473
|
+
try {
|
|
474
|
+
const event = JSON.parse(readFileSync(eventPath, 'utf8'));
|
|
475
|
+
const body = event?.pull_request?.body;
|
|
476
|
+
if (typeof body === 'string') return body;
|
|
477
|
+
} catch {
|
|
478
|
+
// A malformed event payload only means no body is available.
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
return null;
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
function compileSecretMatchers(config) {
|
|
485
|
+
const matchers = SECRET_PATTERNS.map((entry) => ({
|
|
486
|
+
rule: entry.rule,
|
|
487
|
+
regex: new RegExp(entry.source, entry.caseInsensitive ? 'i' : ''),
|
|
488
|
+
}));
|
|
489
|
+
const extra = Array.isArray(config.extraSecretPatterns) ? config.extraSecretPatterns : [];
|
|
490
|
+
for (const source of extra) {
|
|
491
|
+
matchers.push({ rule: `config-secret:${source}`, regex: new RegExp(source) });
|
|
492
|
+
}
|
|
493
|
+
return matchers;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
function scanAddedLines(diff, matchers, addFinding) {
|
|
497
|
+
let currentFile = '';
|
|
498
|
+
let inFileHeader = false;
|
|
499
|
+
let sawSourceHeader = false;
|
|
500
|
+
for (const rawLine of diff.split('\n')) {
|
|
501
|
+
if (rawLine.startsWith('diff --git ')) {
|
|
502
|
+
currentFile = '';
|
|
503
|
+
inFileHeader = true;
|
|
504
|
+
sawSourceHeader = false;
|
|
505
|
+
continue;
|
|
506
|
+
}
|
|
507
|
+
if (inFileHeader && rawLine.startsWith('--- ')) {
|
|
508
|
+
sawSourceHeader = true;
|
|
509
|
+
continue;
|
|
510
|
+
}
|
|
511
|
+
if (inFileHeader && sawSourceHeader && rawLine.startsWith('+++ ')) {
|
|
512
|
+
const next = rawLine.slice(4);
|
|
513
|
+
currentFile =
|
|
514
|
+
next === '/dev/null' ? '' : normalizePath(next.startsWith('b/') ? next.slice(2) : next);
|
|
515
|
+
sawSourceHeader = false;
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
if (rawLine.startsWith('@@ ')) {
|
|
519
|
+
inFileHeader = false;
|
|
520
|
+
sawSourceHeader = false;
|
|
521
|
+
continue;
|
|
522
|
+
}
|
|
523
|
+
if (!currentFile || !rawLine.startsWith('+')) {
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
const line = rawLine.slice(1);
|
|
527
|
+
for (const matcher of matchers) {
|
|
528
|
+
matcher.regex.lastIndex = 0;
|
|
529
|
+
if (matcher.regex.test(line)) {
|
|
530
|
+
addFinding(
|
|
531
|
+
'secret-scan',
|
|
532
|
+
matcher.rule,
|
|
533
|
+
currentFile,
|
|
534
|
+
`potential secret in an added line (${matcher.rule})`,
|
|
535
|
+
'Remove the credential and rotate it; never commit secrets.'
|
|
536
|
+
);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/**
|
|
543
|
+
* Restricted glob matcher for deny PATHS: `*` matches within a path segment,
|
|
544
|
+
* `**` matches across segments. Deliberately tiny — no npm glob library at
|
|
545
|
+
* gate time.
|
|
546
|
+
*/
|
|
547
|
+
function globToRegex(pattern) {
|
|
548
|
+
// `**/` matches zero or more whole directories (so `**/*.log` matches a
|
|
549
|
+
// root-level `debug.log`); a bare `**` matches anything including slashes.
|
|
550
|
+
const parts = pattern.split(/\*\*\//);
|
|
551
|
+
const segment = (part) =>
|
|
552
|
+
part
|
|
553
|
+
.split('**')
|
|
554
|
+
.map((piece) =>
|
|
555
|
+
piece
|
|
556
|
+
.split('*')
|
|
557
|
+
.map((literal) => literal.replace(/[.+^${}()|[\]\\?]/g, '\\$&'))
|
|
558
|
+
.join('[^/]*')
|
|
559
|
+
)
|
|
560
|
+
.join('.*');
|
|
561
|
+
const source = parts.map(segment).join('(?:[^/]+/)*');
|
|
562
|
+
return new RegExp(`^${source}$`);
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
function compileArtifactMatchers(config) {
|
|
566
|
+
// defaultDenyPaths and extraDenyPaths are GLOBS (path patterns);
|
|
567
|
+
// extraArtifactPatterns are raw regex sources for advanced consumers.
|
|
568
|
+
// `origin` records whether a matcher came from the generated defaults or the
|
|
569
|
+
// consumer's own extras: allowPaths may exempt a path from a DEFAULT deny
|
|
570
|
+
// (a repo that commits dist/ on purpose) but never from an extra the
|
|
571
|
+
// consumer added itself.
|
|
572
|
+
const matchers = [];
|
|
573
|
+
for (const source of Array.isArray(MANIFEST.defaultDenyPaths) ? MANIFEST.defaultDenyPaths : []) {
|
|
574
|
+
matchers.push({ source, regex: globToRegex(source), origin: 'default' });
|
|
575
|
+
}
|
|
576
|
+
for (const source of Array.isArray(config.extraDenyPaths) ? config.extraDenyPaths : []) {
|
|
577
|
+
matchers.push({ source, regex: globToRegex(source), origin: 'extra' });
|
|
578
|
+
}
|
|
579
|
+
for (const source of Array.isArray(config.extraArtifactPatterns)
|
|
580
|
+
? config.extraArtifactPatterns
|
|
581
|
+
: []) {
|
|
582
|
+
matchers.push({ source, regex: new RegExp(source), origin: 'extra' });
|
|
583
|
+
}
|
|
584
|
+
return matchers;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
function compileAllowMatchers(config) {
|
|
588
|
+
const globs = Array.isArray(config.allowPaths) ? config.allowPaths : [];
|
|
589
|
+
return globs
|
|
590
|
+
.filter((source) => typeof source === 'string' && source.length > 0)
|
|
591
|
+
.map((source) => ({ source, regex: globToRegex(source) }));
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
function renderHuman(baseRef, findings, changedCount) {
|
|
595
|
+
const lines = [];
|
|
596
|
+
for (const finding of findings) {
|
|
597
|
+
const label = finding.check === 'guard-integrity' ? 'Warning' : 'Error';
|
|
598
|
+
lines.push(`${label}: [${finding.check}] ${finding.file}: ${finding.message}`);
|
|
599
|
+
if (finding.fix) {
|
|
600
|
+
lines.push(` fix: ${finding.fix}`);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
if (findings.length === 0) {
|
|
604
|
+
lines.push(`OK: guard checks passed (${changedCount} changed file(s) vs ${baseRef}).`);
|
|
605
|
+
}
|
|
606
|
+
return lines.join('\n');
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
function main() {
|
|
610
|
+
const args = parseArgs(process.argv.slice(2));
|
|
611
|
+
|
|
612
|
+
if (args.listChecks) {
|
|
613
|
+
process.stdout.write(`${JSON.stringify(MANIFEST, null, 2)}\n`);
|
|
614
|
+
process.exit(0);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
const config = loadConfig();
|
|
618
|
+
if (args.staged) {
|
|
619
|
+
const findings = [];
|
|
620
|
+
const addFinding = (check, rule, file, message, fix) => {
|
|
621
|
+
findings.push({ check, rule, file, message, fix });
|
|
622
|
+
};
|
|
623
|
+
if (MANIFEST.checks.secretScan) {
|
|
624
|
+
const stagedDiff = git([
|
|
625
|
+
'diff',
|
|
626
|
+
'--cached',
|
|
627
|
+
'--no-ext-diff',
|
|
628
|
+
'--no-color',
|
|
629
|
+
'--src-prefix=a/',
|
|
630
|
+
'--dst-prefix=b/',
|
|
631
|
+
'--unified=0',
|
|
632
|
+
'--diff-filter=ACMR',
|
|
633
|
+
]);
|
|
634
|
+
// Staged checks use only the generated catalog. Branch-owned custom
|
|
635
|
+
// regexes are reserved for the hosted path, where guard changes make
|
|
636
|
+
// config untrusted before regex compilation.
|
|
637
|
+
scanAddedLines(stagedDiff, compileSecretMatchers({}), addFinding);
|
|
638
|
+
}
|
|
639
|
+
const deduped = [...new Map(findings.map((finding) => [
|
|
640
|
+
`${finding.check}\u0000${finding.rule}\u0000${finding.file}`,
|
|
641
|
+
finding,
|
|
642
|
+
])).values()];
|
|
643
|
+
if (args.formatJson) {
|
|
644
|
+
process.stdout.write(
|
|
645
|
+
`${JSON.stringify({ baseRef: 'staged-index', mergeBase: null, findings: deduped }, null, 2)}\n`
|
|
646
|
+
);
|
|
647
|
+
} else if (deduped.length === 0) {
|
|
648
|
+
process.stdout.write('OK: guard staged secret scan passed.\n');
|
|
649
|
+
} else {
|
|
650
|
+
process.stderr.write(`${renderHuman('staged index', deduped, 0)}\n`);
|
|
651
|
+
}
|
|
652
|
+
process.exit(deduped.length === 0 ? 0 : 1);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
if (args.message !== null) {
|
|
656
|
+
const findings = [];
|
|
657
|
+
const addFinding = (check, rule, file, message, fix) => {
|
|
658
|
+
findings.push({ check, rule, file, message, fix });
|
|
659
|
+
};
|
|
660
|
+
if (MANIFEST.checks.attribution) {
|
|
661
|
+
const loaded = loadPolicy(null, '', true);
|
|
662
|
+
if (loaded.error) {
|
|
663
|
+
addFinding(
|
|
664
|
+
'attribution',
|
|
665
|
+
'policy-unusable',
|
|
666
|
+
'policy.json',
|
|
667
|
+
`guard policy is unusable (${loaded.error}).`,
|
|
668
|
+
'Re-run: build init --guardrails --reinstall-guard, then build guard sync, and commit .build-project/guard/.'
|
|
669
|
+
);
|
|
670
|
+
} else if (loaded.policy.attribution === 'human-only') {
|
|
671
|
+
const text = readFileSync(args.message === '-' ? 0 : args.message, 'utf8');
|
|
672
|
+
scanAttributionText(loaded.policy, text, 'commit message', addFinding);
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
const deduped = [...new Map(findings.map((finding) => [
|
|
676
|
+
`${finding.check}\u0000${finding.rule}\u0000${finding.file}`,
|
|
677
|
+
finding,
|
|
678
|
+
])).values()];
|
|
679
|
+
if (args.formatJson) {
|
|
680
|
+
process.stdout.write(
|
|
681
|
+
`${JSON.stringify({ baseRef: 'commit-message', mergeBase: null, findings: deduped }, null, 2)}\n`
|
|
682
|
+
);
|
|
683
|
+
} else if (deduped.length === 0) {
|
|
684
|
+
process.stdout.write('OK: guard commit message check passed.\n');
|
|
685
|
+
} else {
|
|
686
|
+
process.stderr.write(`${renderHuman('commit message', deduped, 0)}\n`);
|
|
687
|
+
}
|
|
688
|
+
process.exit(deduped.length === 0 ? 0 : 1);
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
const emitFailure = (rule, message, fix, check = 'git') => {
|
|
692
|
+
process.stderr.write(`Error: ${message}\n`);
|
|
693
|
+
process.stderr.write(` fix: ${fix}\n`);
|
|
694
|
+
if (args.formatJson) {
|
|
695
|
+
process.stdout.write(
|
|
696
|
+
`${JSON.stringify(
|
|
697
|
+
{ baseRef: null, mergeBase: null, findings: [{ check, rule, file: '', message, fix }] },
|
|
698
|
+
null,
|
|
699
|
+
2
|
|
700
|
+
)}\n`
|
|
701
|
+
);
|
|
702
|
+
}
|
|
703
|
+
process.exit(1);
|
|
704
|
+
};
|
|
705
|
+
|
|
706
|
+
const baseRef = resolveBaseRef(config, args.base);
|
|
707
|
+
if (!baseRef) {
|
|
708
|
+
emitFailure(
|
|
709
|
+
'base-resolution',
|
|
710
|
+
'cannot determine a base ref (fail closed).',
|
|
711
|
+
'Pass --base <ref>, set BUILD_GUARD_BASE_REF, set config.json baseRef, or ensure origin/HEAD resolves.'
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
if (git(['rev-parse', '--verify', '--quiet', baseRef], { allowFailure: true }) === null) {
|
|
716
|
+
emitFailure(
|
|
717
|
+
'base-resolution',
|
|
718
|
+
`cannot resolve base ref '${baseRef}' (fail closed).`,
|
|
719
|
+
`Fetch the base branch (git fetch origin) or set BUILD_GUARD_BASE_REF / config.json baseRef to a resolvable ref.`
|
|
720
|
+
);
|
|
721
|
+
}
|
|
722
|
+
|
|
723
|
+
const mergeBaseRaw = git(['merge-base', baseRef, 'HEAD'], { allowFailure: true });
|
|
724
|
+
const mergeBase = mergeBaseRaw ? mergeBaseRaw.trim() : '';
|
|
725
|
+
if (!mergeBase) {
|
|
726
|
+
emitFailure(
|
|
727
|
+
'shallow-clone',
|
|
728
|
+
`no merge base between '${baseRef}' and HEAD (likely a shallow clone).`,
|
|
729
|
+
'Use fetch-depth: 0 in your CI checkout, or run git fetch --unshallow, then retry.'
|
|
730
|
+
);
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
const repoRoot = normalizePath(git(['rev-parse', '--show-toplevel']).trim());
|
|
734
|
+
const guardDir = `${normalizePath(relative(repoRoot, SCRIPT_DIR))}/`;
|
|
735
|
+
|
|
736
|
+
// Deletions (D) are included: deleting a guard file is a change the
|
|
737
|
+
// guard-integrity check must see. Per-check policy on deletions:
|
|
738
|
+
// guard-integrity: sees them (that is the point);
|
|
739
|
+
// artifact-paths: skips them (removing a committed artifact is cleanup);
|
|
740
|
+
// secret-scan: skips naturally (deleted files add no lines).
|
|
741
|
+
const changedEntries = parseNameStatusZ(
|
|
742
|
+
git(['diff', '--name-status', '-z', '-M', '--diff-filter=ACDMRT', mergeBase, 'HEAD']) ?? ''
|
|
743
|
+
);
|
|
744
|
+
const changedFiles = changedEntries.map((entry) => entry.path);
|
|
745
|
+
const presentFiles = changedEntries
|
|
746
|
+
.filter((entry) => entry.status !== 'D')
|
|
747
|
+
.map((entry) => entry.path);
|
|
748
|
+
|
|
749
|
+
const findings = [];
|
|
750
|
+
const addFinding = (check, rule, file, message, fix) => {
|
|
751
|
+
findings.push({ check, rule, file, message, fix });
|
|
752
|
+
};
|
|
753
|
+
|
|
754
|
+
// Check 3 (guard integrity) runs FIRST, before any consumer-config-derived
|
|
755
|
+
// matcher executes: config.json is branch-owned, so a PR could plant a
|
|
756
|
+
// pathological regex (ReDoS) in extraSecretPatterns to hang or hard-fail
|
|
757
|
+
// the run before the guard-change verdict is reached. When guard files
|
|
758
|
+
// changed, the branch config is untrusted — content checks still run, but
|
|
759
|
+
// with BUILT-IN matchers only.
|
|
760
|
+
const guardChanged = [];
|
|
761
|
+
if (MANIFEST.checks.guardIntegrity) {
|
|
762
|
+
for (const entry of changedEntries) {
|
|
763
|
+
if (!isUnderGuardNamespace(entry.path, guardDir)) {
|
|
764
|
+
continue;
|
|
765
|
+
}
|
|
766
|
+
guardChanged.push(entry.path);
|
|
767
|
+
const caseVariant = !entry.path.startsWith(guardDir);
|
|
768
|
+
addFinding(
|
|
769
|
+
'guard-integrity',
|
|
770
|
+
caseVariant ? 'guard-namespace-case-variant' : 'guard-change',
|
|
771
|
+
entry.path,
|
|
772
|
+
caseVariant
|
|
773
|
+
? 'case-variant path collides with the guard directory namespace'
|
|
774
|
+
: 'gate machinery changed under the guard directory',
|
|
775
|
+
caseVariant
|
|
776
|
+
? 'Remove the path; on case-insensitive filesystems it materializes inside the guard directory.'
|
|
777
|
+
: 'Land guard changes via build init --guardrails, or require a human merge.'
|
|
778
|
+
);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
const trustBranchConfig = guardChanged.length === 0;
|
|
782
|
+
const effectiveConfig = trustBranchConfig ? config : {};
|
|
783
|
+
if (!trustBranchConfig) {
|
|
784
|
+
process.stderr.write(
|
|
785
|
+
'Info: guard files changed in this diff; consumer config.json is untrusted for this run (built-in checks only).\n'
|
|
786
|
+
);
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
// Attribution policy from its trusted source (the base ref's copy; see
|
|
790
|
+
// loadPolicy). Unusable policy fails closed; absent-at-base with guard
|
|
791
|
+
// changes is skipped because guard-integrity already forces a human merge.
|
|
792
|
+
let policy = null;
|
|
793
|
+
if (MANIFEST.checks.attribution) {
|
|
794
|
+
const loaded = loadPolicy(baseRef, guardDir, trustBranchConfig);
|
|
795
|
+
if (loaded.error) {
|
|
796
|
+
emitFailure(
|
|
797
|
+
'policy-unusable',
|
|
798
|
+
`guard policy is unusable (${loaded.error}).`,
|
|
799
|
+
'Re-run: build init --guardrails --reinstall-guard, then build guard sync, and commit .build-project/guard/.',
|
|
800
|
+
'attribution'
|
|
801
|
+
);
|
|
802
|
+
}
|
|
803
|
+
policy = loaded.policy;
|
|
804
|
+
if (loaded.skipped && !args.formatJson) {
|
|
805
|
+
process.stderr.write(`Info: ${loaded.skipped}\n`);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
// Check 1: secrets in every commit addition in the PR range. Scanning the
|
|
810
|
+
// commit history, rather than only the endpoint diff, catches credentials
|
|
811
|
+
// that were committed and removed before the branch reached its final tree.
|
|
812
|
+
if (MANIFEST.checks.secretScan) {
|
|
813
|
+
const matchers = compileSecretMatchers(effectiveConfig);
|
|
814
|
+
const historyDiff = git([
|
|
815
|
+
'log',
|
|
816
|
+
'--format=',
|
|
817
|
+
'--no-ext-diff',
|
|
818
|
+
'--no-color',
|
|
819
|
+
'--no-merges',
|
|
820
|
+
'--src-prefix=a/',
|
|
821
|
+
'--dst-prefix=b/',
|
|
822
|
+
'-p',
|
|
823
|
+
`${mergeBase}..HEAD`,
|
|
824
|
+
]);
|
|
825
|
+
scanAddedLines(historyDiff, matchers, addFinding);
|
|
826
|
+
const endpointDiff = git([
|
|
827
|
+
'diff',
|
|
828
|
+
'--no-ext-diff',
|
|
829
|
+
'--no-color',
|
|
830
|
+
'--src-prefix=a/',
|
|
831
|
+
'--dst-prefix=b/',
|
|
832
|
+
mergeBase,
|
|
833
|
+
'HEAD',
|
|
834
|
+
]);
|
|
835
|
+
scanAddedLines(endpointDiff, matchers, addFinding);
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// Check 2: artifact paths.
|
|
839
|
+
if (MANIFEST.checks.artifactPaths) {
|
|
840
|
+
const matchers = compileArtifactMatchers(effectiveConfig);
|
|
841
|
+
const allowMatchers = compileAllowMatchers(effectiveConfig);
|
|
842
|
+
// Deletions skipped: removing a committed artifact is cleanup, not a
|
|
843
|
+
// violation.
|
|
844
|
+
for (const file of presentFiles) {
|
|
845
|
+
const allowed = allowMatchers.some((matcher) => matcher.regex.test(file));
|
|
846
|
+
for (const matcher of matchers) {
|
|
847
|
+
if (allowed && matcher.origin === 'default') {
|
|
848
|
+
continue;
|
|
849
|
+
}
|
|
850
|
+
if (matcher.regex.test(file)) {
|
|
851
|
+
addFinding(
|
|
852
|
+
'artifact-paths',
|
|
853
|
+
`deny:${matcher.source}`,
|
|
854
|
+
file,
|
|
855
|
+
'artifact/generated path must not be committed',
|
|
856
|
+
'Remove the path from the commit and add it to .gitignore.'
|
|
857
|
+
);
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
|
|
863
|
+
// Check 4: attribution (human-only only). Uses the trusted policy loaded
|
|
864
|
+
// from the guard dir, never branch config, so a PR cannot relax it.
|
|
865
|
+
if (MANIFEST.checks.attribution && policy && policy.attribution === 'human-only') {
|
|
866
|
+
scanAttributionCommits(policy, mergeBase, addFinding);
|
|
867
|
+
const prBody = loadPullRequestBody();
|
|
868
|
+
if (prBody !== null) {
|
|
869
|
+
scanAttributionText(policy, prBody, 'pull-request-body', addFinding);
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
// De-duplicate findings by (check, rule, file).
|
|
874
|
+
const seen = new Set();
|
|
875
|
+
let deduped = [];
|
|
876
|
+
for (const finding of findings) {
|
|
877
|
+
const key = `${finding.check}\u0000${finding.rule}\u0000${finding.file}`;
|
|
878
|
+
if (seen.has(key)) {
|
|
879
|
+
continue;
|
|
880
|
+
}
|
|
881
|
+
seen.add(key);
|
|
882
|
+
deduped.push(finding);
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
// Guard self-change escape hatch: honored only outside CI.
|
|
886
|
+
const allowSelfChange = process.env.BUILD_GUARD_ALLOW_SELF_CHANGE === '1' && !isCI();
|
|
887
|
+
let selfChangeSuppressed = false;
|
|
888
|
+
if (allowSelfChange) {
|
|
889
|
+
const before = deduped.length;
|
|
890
|
+
deduped = deduped.filter((finding) => finding.check !== 'guard-integrity');
|
|
891
|
+
selfChangeSuppressed = deduped.length !== before;
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
const guardFindings = deduped.filter((finding) => finding.check === 'guard-integrity');
|
|
895
|
+
const hardFindings = deduped.filter((finding) => finding.check !== 'guard-integrity');
|
|
896
|
+
|
|
897
|
+
let exitCode = 0;
|
|
898
|
+
if (hardFindings.length > 0) {
|
|
899
|
+
exitCode = 1;
|
|
900
|
+
} else if (guardFindings.length > 0) {
|
|
901
|
+
exitCode = 2;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
if (args.formatJson) {
|
|
905
|
+
process.stdout.write(`${JSON.stringify({ baseRef, mergeBase, findings: deduped }, null, 2)}\n`);
|
|
906
|
+
process.exit(exitCode);
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
if (selfChangeSuppressed) {
|
|
910
|
+
process.stderr.write('Info: guard self-change allowed (BUILD_GUARD_ALLOW_SELF_CHANGE=1, not CI).\n');
|
|
911
|
+
}
|
|
912
|
+
const rendered = renderHuman(baseRef, deduped, changedFiles.length);
|
|
913
|
+
const stream = exitCode === 0 ? process.stdout : process.stderr;
|
|
914
|
+
stream.write(`${rendered}\n`);
|
|
915
|
+
if (exitCode === 2) {
|
|
916
|
+
stream.write('Guard machinery changed: this requires a human merge (exit 2).\n');
|
|
917
|
+
}
|
|
918
|
+
process.exit(exitCode);
|
|
919
|
+
}
|
|
920
|
+
|
|
921
|
+
// This module is an EXECUTABLE gate, not a library: it runs main() (which calls
|
|
922
|
+
// process.exit) at import time. Do not export or import its helpers — any
|
|
923
|
+
// import would execute the gate. Tests exercise it via subprocess execution
|
|
924
|
+
// (see tests/unit/guard-kit/check-script.test.ts), never by importing.
|
|
925
|
+
try {
|
|
926
|
+
main();
|
|
927
|
+
} catch (error) {
|
|
928
|
+
process.stderr.write(
|
|
929
|
+
`Error: guard check failed - ${error instanceof Error ? error.message : String(error)}\n`
|
|
930
|
+
);
|
|
931
|
+
process.exit(1);
|
|
932
|
+
}
|