@iowarp/clio-coder 0.4.2 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +98 -0
- package/CONTRIBUTING.md +86 -19
- package/README.md +35 -6
- package/dist/{acp-TMDQZDIG.js → acp-WNAYYF4F.js} +12 -13
- package/dist/{agents-5N5NG3XG.js → agents-3OKXHLOI.js} +60 -57
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-Z5CCBXKQ.js → auth-VKNNMGPU.js} +21 -19
- package/dist/{builtins-K6TNDT24.js → builtins-WGALA46I.js} +9 -4
- package/dist/{chunk-XE3PCIXH.js → chunk-23L32XTI.js} +12 -9
- package/dist/{chunk-I64IFBLB.js → chunk-25QBEXRS.js} +18 -11
- package/dist/{chunk-CDNVLKUX.js → chunk-26QSH3EJ.js} +13 -7
- package/dist/{chunk-QQLGQY2A.js → chunk-2ASED4PZ.js} +22 -22
- package/dist/{chunk-MCEPRMZW.js → chunk-2CU2H6KE.js} +2 -2
- package/dist/chunk-2DSOYNFC.js +108 -0
- package/dist/{chunk-72GZI5EV.js → chunk-2JH2WHGE.js} +2 -2
- package/dist/{chunk-I66EAJFY.js → chunk-2WZ546HR.js} +267 -232
- package/dist/{chunk-O3YUNJZ2.js → chunk-2ZSONWVL.js} +82 -25
- package/dist/{chunk-2NHR3NAY.js → chunk-36CT5VVL.js} +331 -42
- package/dist/{chunk-2X4RYJTJ.js → chunk-3GY4F45V.js} +3 -3
- package/dist/{chunk-ZW55JB7N.js → chunk-3ODX73FK.js} +4 -6
- package/dist/{chunk-PBP4B7XR.js → chunk-3UNOLWNZ.js} +3 -3
- package/dist/{chunk-4JDLP6ZS.js → chunk-3UUXNFEX.js} +14 -10
- package/dist/{chunk-RKSR6VSF.js → chunk-4IUZQIJ3.js} +29 -1
- package/dist/{chunk-ZW4HH5JJ.js → chunk-4M6Z5QVF.js} +6 -6
- package/dist/{chunk-K6BSR66V.js → chunk-4NSRCOYP.js} +4 -1
- package/dist/{chunk-M2DAX4F6.js → chunk-4WR7VSYB.js} +2 -2
- package/dist/{chunk-FSP7CMNU.js → chunk-54X7T7DK.js} +61 -6
- package/dist/{chunk-54ODD65L.js → chunk-5636DCO5.js} +4 -4
- package/dist/chunk-57XXR6DR.js +3763 -0
- package/dist/{chunk-3KIPBMUA.js → chunk-5ICU3EUH.js} +2 -2
- package/dist/{chunk-77QIVUZB.js → chunk-5MEZN6CB.js} +4 -4
- package/dist/{chunk-O42A54GG.js → chunk-5OIVVPHF.js} +2 -2
- package/dist/{chunk-YJISEZKC.js → chunk-5TUB6SLS.js} +6 -6
- package/dist/{chunk-IMXMHHMQ.js → chunk-6OSVSQL5.js} +341 -57
- package/dist/{chunk-Q4XWMHX6.js → chunk-6PAZTBPA.js} +14 -2
- package/dist/{chunk-FVDGR2ZL.js → chunk-6Q3CYFD3.js} +112 -39
- package/dist/{chunk-IDNA72AH.js → chunk-6QOTUPRG.js} +155 -36
- package/dist/{chunk-X7IARSHT.js → chunk-6UINWWS6.js} +16 -10
- package/dist/{chunk-CYZW7JHJ.js → chunk-72YIHOZQ.js} +9 -9
- package/dist/{chunk-IKSLQ4XV.js → chunk-75W7L2E2.js} +752 -861
- package/dist/{chunk-CRFOIAX3.js → chunk-7UGL4MB5.js} +6 -6
- package/dist/{chunk-HIICAHCJ.js → chunk-AUPNRN7C.js} +2 -2
- package/dist/{chunk-7BHIY2MW.js → chunk-BJVFZO5U.js} +8 -50
- package/dist/{chunk-B74PXLU7.js → chunk-CUSRQKPU.js} +65 -3
- package/dist/chunk-DQOVN6KV.js +386 -0
- package/dist/{chunk-E7GT7O5N.js → chunk-DT3LWJOB.js} +7 -4
- package/dist/chunk-DXKJURES.js +671 -0
- package/dist/{chunk-JBCS7CRR.js → chunk-EL24TAU4.js} +10 -10
- package/dist/{chunk-TPEQIQIE.js → chunk-ELWDPP3Y.js} +8 -8
- package/dist/{chunk-NDINPTJ4.js → chunk-ELZVTCGV.js} +5 -4
- package/dist/chunk-EXLD33WO.js +381 -0
- package/dist/chunk-FEAXX7B6.js +101 -0
- package/dist/{chunk-RLYRBIYQ.js → chunk-FFUPXJC4.js} +90 -331
- package/dist/{chunk-5PFYMY2V.js → chunk-FTMGRKEF.js} +2 -2
- package/dist/{chunk-34BHNEE3.js → chunk-GHS5EBTQ.js} +58 -7
- package/dist/{chunk-DYHAXKHD.js → chunk-GWZNEVM2.js} +12 -8
- package/dist/chunk-GX5WYQO4.js +59 -0
- package/dist/chunk-GYV6VZOC.js +26 -0
- package/dist/{chunk-MQXIVJ35.js → chunk-HAXOFFRH.js} +5 -5
- package/dist/chunk-I2DWJ4GM.js +390 -0
- package/dist/{chunk-TXOTCRLG.js → chunk-I5FWO7L5.js} +5 -5
- package/dist/{chunk-WNP7O5WZ.js → chunk-ID64D7PE.js} +4 -4
- package/dist/{chunk-XQRY4DTA.js → chunk-IGLP3ODT.js} +10 -10
- package/dist/chunk-IRXAATOX.js +539 -0
- package/dist/chunk-IXIY2H4R.js +44 -0
- package/dist/{chunk-SSEYRH53.js → chunk-IZXGRF7P.js} +92 -147
- package/dist/{chunk-5TSRNF4G.js → chunk-JCI2ROMZ.js} +164 -6
- package/dist/{chunk-JWJGP5DQ.js → chunk-JEIYHLOR.js} +7 -7
- package/dist/{chunk-F2I26BDK.js → chunk-JQLNNIKT.js} +4 -4
- package/dist/{chunk-BYMNWQ7O.js → chunk-JSD46VO2.js} +315 -63
- package/dist/{chunk-AK5XEFVZ.js → chunk-JT2RFCC5.js} +64 -14
- package/dist/{chunk-MCMZMDAC.js → chunk-K6T2ZAMZ.js} +168 -6
- package/dist/{chunk-PGF63K6I.js → chunk-KFV5L5SK.js} +73 -4
- package/dist/{chunk-IHXBNWMM.js → chunk-KXDSS5WJ.js} +7 -3
- package/dist/{chunk-PJX3WQUQ.js → chunk-LLXSDWXS.js} +3 -3
- package/dist/{chunk-DZAW46HP.js → chunk-LTIKRKFL.js} +3 -3
- package/dist/{chunk-DZEK6CJN.js → chunk-N56KALIC.js} +21 -21
- package/dist/{chunk-B7HM5Z7T.js → chunk-NAI6ZFCY.js} +9 -5
- package/dist/{chunk-I66ZTYNP.js → chunk-NRO2BJRH.js} +2656 -2213
- package/dist/{chunk-ZGNYYXQ6.js → chunk-NXIMQY5W.js} +3 -3
- package/dist/{chunk-IKOZFYBN.js → chunk-NXYCB2VD.js} +149 -106
- package/dist/{chunk-CWVRRIEI.js → chunk-NZMNUPZZ.js} +2 -2
- package/dist/{chunk-462T4EGZ.js → chunk-O5CVSAG5.js} +2 -2
- package/dist/chunk-ODGTEFFI.js +50 -0
- package/dist/{chunk-3F7VUY77.js → chunk-OEJSLEPW.js} +2 -2
- package/dist/{chunk-KKOJXO6R.js → chunk-OMQNJVKW.js} +4 -2
- package/dist/{chunk-5KW52TEP.js → chunk-Q4WO54TA.js} +132 -77
- package/dist/{chunk-W6NIE6OW.js → chunk-QUFRYSWI.js} +13 -7
- package/dist/{chunk-42FMPA75.js → chunk-QZWQA4DE.js} +2 -2
- package/dist/chunk-R6Q67RJH.js +134 -0
- package/dist/{chunk-W4YEMFBX.js → chunk-RAY4OVGZ.js} +3 -3
- package/dist/{chunk-ZNT2M6TG.js → chunk-RQCKCSRL.js} +17 -17
- package/dist/{chunk-LJID3DYZ.js → chunk-RXTN6AKH.js} +3 -3
- package/dist/{chunk-P75RZCJW.js → chunk-RZDWV63N.js} +3 -3
- package/dist/{chunk-UH632ZYL.js → chunk-S6PYF2XF.js} +2 -2
- package/dist/{chunk-HJWWJ6IL.js → chunk-TOIVGRUX.js} +17 -5
- package/dist/{chunk-HLAFFSEK.js → chunk-TQAHXW6Y.js} +2 -2
- package/dist/{chunk-JIEGK6UF.js → chunk-U6TMQNSI.js} +48 -4
- package/dist/{chunk-2HFQNRV3.js → chunk-UEPWCCTY.js} +12 -12
- package/dist/chunk-UOIZ7DA4.js +41 -0
- package/dist/{chunk-UH347SHR.js → chunk-USR47QNF.js} +11 -11
- package/dist/{chunk-AZ4WMN4W.js → chunk-V6HJFQZE.js} +2 -2
- package/dist/chunk-V76WTFTW.js +318 -0
- package/dist/{chunk-NMJXSHBJ.js → chunk-W54I7H25.js} +2 -2
- package/dist/{chunk-KPXDY6QF.js → chunk-XRZT5WY5.js} +2 -2
- package/dist/{chunk-UBRFI4HS.js → chunk-XULDXHTN.js} +142 -50
- package/dist/chunk-XXYSBZIQ.js +283 -0
- package/dist/{chunk-HKMD33FO.js → chunk-Y55JBDO5.js} +405 -122
- package/dist/{chunk-XOXV5GKE.js → chunk-YD5GIKET.js} +17 -8
- package/dist/{chunk-XGDPUNND.js → chunk-YECAMM3D.js} +2 -2
- package/dist/{chunk-BO7Y52RY.js → chunk-YNFKXPEC.js} +7 -7
- package/dist/{chunk-VXMFAE2W.js → chunk-YPC6ZR5L.js} +19 -6
- package/dist/{chunk-M2WXEHER.js → chunk-ZA4VCIGV.js} +2 -2
- package/dist/cli/index.js +42 -40
- package/dist/{clio-7VB377CC.js → clio-QLICPCF5.js} +7 -7
- package/dist/{code-nav-YVLCYA7V.js → code-nav-IJR2DBPR.js} +9 -9
- package/dist/{components-UBWCQSRW.js → components-2TGAI2RC.js} +5 -6
- package/dist/{config-4HVOS65E.js → config-IUA6OYNS.js} +88 -81
- package/dist/{configure-PIWO7B24.js → configure-VEPX4NMX.js} +26 -25
- package/dist/{context-KQYIWPWT.js → context-2DKHWH2T.js} +60 -45
- package/dist/{context-IYEHL3WQ.js → context-4MPR7WKB.js} +78 -69
- package/dist/{context-N6ZE3LGJ.js → context-BOYF5EJM.js} +15 -11
- package/dist/{context-clear-G4OGZJDS.js → context-clear-S4ZJCQUX.js} +73 -65
- package/dist/context-map-COB37XXN.js +505 -0
- package/dist/{context-working-set-BWLF6LJP.js → context-working-set-3I3FYX6Y.js} +18 -17
- package/dist/detail-A7JAVSIG.js +98 -0
- package/dist/{dispatch-runner-2QQAITS3.js → dispatch-runner-RJ5I2F2O.js} +99 -75
- package/dist/{docs-PD3EXDKU.js → docs-SPOV3BAN.js} +3 -5
- package/dist/{doctor-LHBD36VU.js → doctor-DKICC2SN.js} +71 -48
- package/dist/{eval-C45FYRJ6.js → eval-OQOQUDHK.js} +308 -146
- package/dist/{eval-inventory-6DEJPLBF.js → eval-inventory-Y6QRFOH5.js} +4 -4
- package/dist/{evidence-6SHONYAF.js → evidence-4DQ25GUQ.js} +79 -175
- package/dist/evidence-4F5USFKH.js +208 -0
- package/dist/{evolve-KRKMV72X.js → evolve-GSS52E5J.js} +71 -67
- package/dist/{extensions-KPZ2UHBB.js → extensions-G7MFLYHT.js} +8 -9
- package/dist/{fleet-IVTCKDHT.js → fleet-Q37YHHAQ.js} +126 -118
- package/dist/{fleet-commands-EDWL3IT7.js → fleet-commands-G7E4N7SM.js} +16 -13
- package/dist/{fleet-decisions-YP3YEFGK.js → fleet-decisions-O7M6QBA2.js} +9 -8
- package/dist/{fleet-graph-ZFWKHY2M.js → fleet-graph-TOUBW6OW.js} +21 -20
- package/dist/{fleet-inspect-FVUNCBML.js → fleet-inspect-SW33JJNI.js} +65 -60
- package/dist/{fleet-preflight-UN5XED4R.js → fleet-preflight-CV2655TW.js} +4 -5
- package/dist/{fleet-validate-XOWC4HSX.js → fleet-validate-KESZX2YH.js} +25 -24
- package/dist/{fleet-verify-UN3SODEL.js → fleet-verify-UQPMTVE3.js} +66 -61
- package/dist/{fleet-view-TWHJKCN6.js → fleet-view-MN2VG4MR.js} +65 -60
- package/dist/{init-T2QORQ3Y.js → init-PXEXQSBF.js} +90 -82
- package/dist/{interop-IN5I2A66.js → interop-ZG5T62U3.js} +12 -13
- package/dist/inventory-C26CFDRR.js +101 -0
- package/dist/{library-LSCATDLZ.js → library-B2W4N74O.js} +29 -29
- package/dist/{memory-HYOKAGGJ.js → memory-YCANYS5A.js} +73 -69
- package/dist/{models-2GPMFYCM.js → models-GERTU3YI.js} +51 -47
- package/dist/{monitor-E4ASVUJH.js → monitor-CPNIUULB.js} +74 -67
- package/dist/{orchestrator-DDMPR3PY.js → orchestrator-J4BSH4WQ.js} +1288 -1606
- package/dist/{panes-E3RUXOW5.js → panes-BOHAEGYC.js} +4 -4
- package/dist/{panes-IXKLOKA2.js → panes-NXSLDQZ2.js} +10 -11
- package/dist/{paths-L7LGY6RN.js → paths-VSUWNC22.js} +6 -7
- package/dist/reset-TNWTB5LU.js +343 -0
- package/dist/{resources-OTRSN34L.js → resources-4PXNMD5G.js} +29 -22
- package/dist/{run-5DEYH5QK.js → run-D6XJ34CN.js} +132 -132
- package/dist/{share-IHWTLO3M.js → share-2NWMJJEE.js} +27 -27
- package/dist/{skills-IYMXMKW4.js → skills-KR7WON5G.js} +40 -33
- package/dist/{skills-eval-DROHSJAR.js → skills-eval-O2ZNOLDS.js} +81 -77
- package/dist/{skills-inventory-D7X4L4ZX.js → skills-inventory-ZZOUBK7O.js} +23 -22
- package/dist/{slash-commands-QBM7UZ3B.js → slash-commands-ZXPJD64J.js} +47 -37
- package/dist/{steer-Z5DO23FJ.js → steer-XA25PSCS.js} +4 -4
- package/dist/{support-U7QOWY26.js → support-7EMVWYG2.js} +6 -6
- package/dist/{targets-P2FUC4IL.js → targets-OMH2XCSN.js} +50 -49
- package/dist/tasks-IPAGMEIX.js +36 -0
- package/dist/{terminal-lease-YREJ3JX2.js → terminal-lease-C2J3JYRE.js} +4 -4
- package/dist/{tools-5B7RO6MV.js → tools-EFFEAIDP.js} +8 -9
- package/dist/{trace-YMGMUM6A.js → trace-FXMXUZUF.js} +7 -7
- package/dist/uninstall-HALS6BLF.js +407 -0
- package/dist/upgrade-MS72RJEP.js +306 -0
- package/dist/{usage-ME5MPXGX.js → usage-NHG6MCJM.js} +162 -108
- package/dist/{verifiers-BVZ7IWOO.js → verifiers-7AUNVXDY.js} +155 -22
- package/dist/{verify-5K7ZKQFC.js → verify-FWYGPKMR.js} +14 -12
- package/dist/{web-fetch-MPARV2K7.js → web-fetch-V4FKSDAV.js} +4 -4
- package/dist/{wiki-generate-F5W5QTYY.js → wiki-generate-743CIGJW.js} +99 -90
- package/dist/{with-panes-BYOJCLAM.js → with-panes-BDQEWBRT.js} +10 -10
- package/dist/worker/entry.js +72 -68
- package/docs/README.md +3 -2
- package/docs/architecture/acp.md +17 -0
- package/docs/architecture/artifact-placement.md +1 -0
- package/docs/architecture/artifact-versions.md +2 -2
- package/docs/architecture/context-engine.md +4 -0
- package/docs/architecture/dispatch-typed-intent.md +1 -1
- package/docs/architecture/evidence-and-memory.md +1 -1
- package/docs/architecture/middleware-and-components.md +1 -1
- package/docs/architecture/model-catalog.md +21 -10
- package/docs/architecture/observability.md +19 -2
- package/docs/architecture/prompt-envelope-and-tools.md +17 -5
- package/docs/architecture/provider-adapter-cookbook.md +63 -0
- package/docs/architecture/safety-model.md +25 -22
- package/docs/architecture/tui-design.md +1 -1
- package/docs/guide/built-in-agents.md +25 -11
- package/docs/guide/commands-and-modes.md +18 -3
- package/docs/guide/configuration-and-targets.md +100 -10
- package/docs/guide/configuration-reference.md +17 -7
- package/docs/guide/environment-variables.md +4 -2
- package/docs/guide/installation-and-lifecycle.md +37 -4
- package/docs/guide/proactive-memory.md +66 -55
- package/docs/guide/skills-marketplace.md +18 -0
- package/docs/guide/tool-usage.md +78 -3
- package/docs/history/config-knobs-audit.md +2 -2
- package/docs/process/development-pipeline.md +40 -2
- package/docs/process/eval-runner.md +67 -3
- package/docs/process/git-commit-provenance.md +15 -0
- package/docs/process/release-cut-checklist.md +207 -0
- package/docs/process/scientific-validation.md +18 -17
- package/evals/behavioral-machinery-support.ts +1 -0
- package/evals/behavioral-machinery.yaml +1 -1
- package/evals/behavioral-model.yaml +3 -2
- package/package.json +2 -2
- package/skills/README.md +7 -5
- package/skills/coding/ast-grep/SKILL.md +101 -30
- package/skills/coding/ast-grep/evals.md +26 -0
- package/skills/coding/coding-standards/SKILL.md +47 -2
- package/skills/coding/coding-standards/evals.md +23 -0
- package/skills/coding/prototype/SKILL.md +87 -28
- package/skills/coding/prototype/evals.md +19 -0
- package/skills/coding/tdd/SKILL.md +80 -53
- package/skills/coding/tdd/evals.md +20 -0
- package/skills/context/context-handoff/SKILL.md +43 -2
- package/skills/context/context-handoff/evals.md +44 -0
- package/skills/context/context-prime/SKILL.md +45 -15
- package/skills/context/context-prime/evals.md +45 -0
- package/skills/git/branch-closeout/SKILL.md +132 -0
- package/skills/git/branch-closeout/evals.md +133 -0
- package/skills/git/branch-closeout/references/closeout-checklist.md +81 -0
- package/skills/git/file-ticket/SKILL.md +77 -63
- package/skills/git/file-ticket/assets/issue-template.md +22 -0
- package/skills/git/file-ticket/evals.md +31 -26
- package/skills/git/file-ticket/references/issue-discovery.md +49 -0
- package/skills/git/fix-issue/SKILL.md +87 -64
- package/skills/git/fix-issue/evals.md +35 -31
- package/skills/git/fix-issue/references/diagnosis-and-rca.md +46 -0
- package/skills/git/resolve-merge-conflicts/SKILL.md +100 -51
- package/skills/git/resolve-merge-conflicts/evals.md +52 -25
- package/skills/git/resolve-merge-conflicts/references/conflict-matrix.md +126 -0
- package/skills/git/ship/SKILL.md +103 -67
- package/skills/git/ship/assets/pr-template.md +21 -0
- package/skills/git/ship/evals.md +44 -28
- package/skills/git/ship/references/remote-and-branch-policy.md +62 -0
- package/skills/git/worktree-create/SKILL.md +80 -50
- package/skills/git/worktree-create/evals.md +40 -33
- package/skills/git/worktree-create/references/worktree-setup.md +62 -66
- package/skills/git/worktree-merge/SKILL.md +112 -65
- package/skills/git/worktree-merge/evals.md +42 -34
- package/skills/git/worktree-merge/references/merge-strategies.md +52 -0
- package/skills/planning/archify/SKILL.md +196 -0
- package/skills/planning/archify/evals.md +65 -0
- package/skills/planning/architecture/SKILL.md +61 -12
- package/skills/planning/architecture/evals.md +65 -0
- package/skills/planning/backlog/SKILL.md +130 -14
- package/skills/planning/backlog/evals.md +142 -0
- package/skills/planning/prd/SKILL.md +47 -6
- package/skills/planning/prd/evals.md +54 -0
- package/skills/planning/product-intent/SKILL.md +57 -2
- package/skills/planning/product-intent/evals.md +70 -0
- package/skills/planning/tech-spec/SKILL.md +53 -2
- package/skills/planning/tech-spec/evals.md +73 -0
- package/skills/registry.yaml +58 -50
- package/skills/remote.yaml +13 -0
- package/skills/research/arxiv-literature/SKILL.md +76 -18
- package/skills/research/arxiv-literature/evals.md +50 -0
- package/skills/research/experiment-protocol/SKILL.md +20 -1
- package/skills/research/experiment-protocol/evals.md +23 -0
- package/skills/research/scientific-debugging/SKILL.md +24 -1
- package/skills/research/scientific-debugging/evals.md +18 -0
- package/skills/research/scientific-modernization/SKILL.md +26 -1
- package/skills/research/scientific-modernization/evals.md +27 -0
- package/skills/skill-marketplace.json +63 -28
- package/skills/workflow/cut-it/SKILL.md +64 -5
- package/skills/workflow/cut-it/evals.md +101 -0
- package/skills/workflow/design-council/SKILL.md +112 -27
- package/skills/workflow/design-council/evals.md +161 -0
- package/skills/workflow/grill-me/SKILL.md +85 -10
- package/skills/workflow/grill-me/evals.md +153 -0
- package/skills/workflow/workflow-distiller/SKILL.md +76 -17
- package/skills/workflow/workflow-distiller/evals.md +118 -0
- package/src/cli/args.ts +0 -8
- package/src/cli/configure-interop.ts +105 -13
- package/src/cli/configure-oauth.ts +57 -0
- package/src/cli/configure-onboarding.ts +980 -0
- package/src/cli/configure-target.ts +594 -0
- package/src/cli/configure.ts +1084 -529
- package/src/cli/context-map.ts +114 -0
- package/src/cli/context.ts +4 -0
- package/src/cli/doctor-state-size.ts +1 -12
- package/src/cli/doctor-validation-contract.ts +28 -0
- package/src/cli/doctor.ts +5 -0
- package/src/cli/evidence-detail.ts +1 -75
- package/src/cli/evidence-inventory.ts +1 -167
- package/src/cli/index.ts +3 -0
- package/src/cli/lifecycle-presenter.ts +436 -0
- package/src/cli/models.ts +10 -2
- package/src/cli/modes/print.ts +5 -1
- package/src/cli/reset.ts +228 -106
- package/src/cli/run.ts +7 -4
- package/src/cli/select.ts +664 -0
- package/src/cli/skills.ts +9 -2
- package/src/cli/targets.ts +3 -0
- package/src/cli/tasks.ts +84 -0
- package/src/cli/uninstall.ts +233 -165
- package/src/cli/upgrade.ts +210 -150
- package/src/cli/usage.ts +92 -27
- package/src/cli/validate-model.ts +3 -3
- package/src/cli/verifiers.ts +147 -1
- package/src/cli/wiki-generate.ts +1 -0
- package/src/core/commit-attribution.ts +41 -1
- package/src/core/config.ts +56 -0
- package/src/core/external-diagnostic.ts +44 -0
- package/src/core/gateway-routing.ts +157 -0
- package/src/core/git-commit-attribution.ts +46 -3
- package/src/core/run-overrides.ts +0 -5
- package/src/core/safe-exec.ts +17 -2
- package/src/core/skill-activation.ts +92 -2
- package/src/core/tool-names.ts +5 -2
- package/src/domains/agents/builtins/architect.md +1 -1
- package/src/domains/agents/builtins/coder.md +1 -1
- package/src/domains/agents/builtins/documenter.md +1 -1
- package/src/domains/agents/builtins/git-master.md +1 -1
- package/src/domains/agents/builtins/provenance.md +7 -7
- package/src/domains/agents/builtins/tester.md +1 -1
- package/src/domains/agents/builtins/verifier.md +2 -2
- package/src/domains/agents/builtins/wiki-writer.md +4 -3
- package/src/domains/agents/builtins/world-knowledge.md +31 -0
- package/src/domains/agents/catalog.ts +1 -1
- package/src/domains/agents/result-contract.ts +70 -0
- package/src/domains/context/extension.ts +31 -7
- package/src/domains/context/refresh.ts +3 -0
- package/src/domains/context/wiki/frontmatter.ts +5 -2
- package/src/domains/context/wiki/generate.ts +6 -0
- package/src/domains/context/wiki/map-seed.ts +589 -0
- package/src/domains/context/wiki/plan.ts +2 -2
- package/src/domains/context/wiki/prompts.ts +43 -0
- package/src/domains/dispatch/active-route-planner.ts +4 -0
- package/src/domains/dispatch/admission.ts +29 -0
- package/src/domains/dispatch/agent-candidates.ts +10 -0
- package/src/domains/dispatch/budget-envelope.ts +86 -1
- package/src/domains/dispatch/capability-match.ts +1 -0
- package/src/domains/dispatch/capacity-lease.ts +17 -0
- package/src/domains/dispatch/code-step.ts +11 -4
- package/src/domains/dispatch/contract.ts +42 -8
- package/src/domains/dispatch/execution-scheduler.ts +2 -0
- package/src/domains/dispatch/extension.ts +184 -56
- package/src/domains/dispatch/fleet-commit-attribution.ts +5 -0
- package/src/domains/dispatch/fleet-run.ts +1 -0
- package/src/domains/dispatch/host-verification.ts +114 -13
- package/src/domains/dispatch/intent.ts +28 -18
- package/src/domains/dispatch/orphan-recovery.ts +2 -0
- package/src/domains/dispatch/receipt-integrity.ts +4 -0
- package/src/domains/dispatch/reservation-store.ts +5 -3
- package/src/domains/dispatch/state.ts +15 -2
- package/src/domains/dispatch/types.ts +20 -2
- package/src/domains/dispatch/worker-model-metadata.ts +38 -0
- package/src/domains/eval/metrics/call-ledger-stream.ts +34 -11
- package/src/domains/eval/metrics/token-stream.ts +201 -31
- package/src/domains/eval/metrics/tracked.ts +40 -4
- package/src/domains/eval/runners/clio-run.ts +17 -11
- package/src/domains/eval/runners/context-index.ts +2 -7
- package/src/domains/eval/runners/context-init.ts +3 -6
- package/src/domains/eval/runners/external-command.ts +29 -11
- package/src/domains/eval/schema/suite.ts +28 -0
- package/src/domains/eval/schema/verdict.ts +2 -2
- package/src/domains/eval/suites/resolve.ts +13 -1
- package/src/domains/eval/suites/run.ts +24 -3
- package/src/domains/evidence/build.ts +102 -15
- package/src/domains/evidence/detail.ts +69 -0
- package/src/domains/evidence/eval.ts +13 -1
- package/src/domains/evidence/finish-contract-map.ts +5 -1
- package/src/domains/evidence/inventory.ts +167 -0
- package/src/domains/evidence/store.ts +16 -0
- package/src/domains/evidence/types.ts +12 -0
- package/src/domains/extensions/resources.ts +7 -0
- package/src/domains/interop/registry.ts +6 -2
- package/src/domains/interop/types.ts +4 -0
- package/src/domains/lifecycle/migrations/index.ts +4 -0
- package/src/domains/memory/task-memory-policy.ts +70 -26
- package/src/domains/memory/task-memory-telemetry.ts +1 -0
- package/src/domains/middleware/index.ts +0 -1
- package/src/domains/middleware/marketplace-offer.ts +22 -35
- package/src/domains/middleware/memory-intervention.ts +127 -32
- package/src/domains/middleware/memory-step-endpoint.ts +3 -2
- package/src/domains/middleware/runtime.ts +7 -3
- package/src/domains/middleware/skills-reminder.ts +31 -2
- package/src/domains/mux/detect.ts +3 -6
- package/src/domains/observability/accountability.ts +15 -1
- package/src/domains/observability/compaction-usage.ts +118 -0
- package/src/domains/observability/contract.ts +52 -7
- package/src/domains/observability/cost.ts +1 -1
- package/src/domains/observability/evidence-index.ts +10 -0
- package/src/domains/observability/extension.ts +15 -6
- package/src/domains/observability/out-of-turn-usage.ts +52 -21
- package/src/domains/observability/projection.ts +394 -45
- package/src/{interactive → domains/observability}/worker-progress.ts +3 -3
- package/src/domains/prompts/fragments/operating/contract.md +2 -0
- package/src/domains/prompts/fragments/wiki/page.md +8 -0
- package/src/domains/providers/contract.ts +4 -1
- package/src/domains/providers/extension.ts +40 -9
- package/src/domains/providers/model-capabilities.ts +9 -0
- package/src/domains/providers/model-discovery.ts +3 -4
- package/src/domains/providers/model-runtime-capabilities.ts +15 -5
- package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +48 -26
- package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +225 -45
- package/src/domains/providers/runtimes/claude/claude-code.ts +9 -0
- package/src/domains/providers/runtimes/common/lmstudio-http.ts +6 -2
- package/src/domains/providers/runtimes/common/local-synth.ts +2 -0
- package/src/domains/providers/runtimes/protocol/litellm.ts +119 -29
- package/src/domains/providers/support.ts +11 -5
- package/src/domains/providers/target-model-cache.ts +25 -2
- package/src/domains/providers/types/capability-flags.ts +2 -0
- package/src/domains/providers/types/runtime-descriptor.ts +20 -1
- package/src/domains/providers/types/target-descriptor.ts +19 -0
- package/src/domains/resources/index.ts +3 -0
- package/src/domains/resources/skills/install.ts +72 -7
- package/src/domains/resources/skills/loader.ts +7 -0
- package/src/domains/resources/skills/marketplace.ts +63 -11
- package/src/domains/safety/action-classifier.ts +7 -0
- package/src/domains/safety/autonomy.ts +15 -0
- package/src/domains/safety/default-path-policy.ts +2 -0
- package/src/domains/safety/finish-contract-registration.ts +29 -14
- package/src/domains/safety/finish-contract.ts +252 -40
- package/src/domains/safety/index.ts +21 -1
- package/src/domains/safety/path-policy.ts +1 -1
- package/src/domains/safety/policy-engine.ts +60 -17
- package/src/domains/safety/protected-artifacts.ts +191 -88
- package/src/domains/safety/rigor.ts +53 -39
- package/src/domains/safety/run-effects.ts +2 -22
- package/src/domains/safety/skill-authority.ts +55 -0
- package/src/domains/safety/validation-contract.ts +388 -0
- package/src/domains/session/archive-readers.ts +10 -1
- package/src/domains/session/compaction/compact.ts +72 -22
- package/src/domains/session/decision-board.ts +101 -2
- package/src/domains/session/entries.ts +50 -7
- package/src/domains/session/extension.ts +4 -4
- package/src/domains/session/handoff.ts +2 -1
- package/src/domains/session/manager.ts +2 -3
- package/src/domains/session/task-board.ts +14 -1
- package/src/domains/session/tree/fork.ts +1 -2
- package/src/domains/session/tree/navigator.ts +1 -1
- package/src/domains/session/usage.ts +3 -3
- package/src/domains/user-tasks/acceptance.ts +56 -0
- package/src/domains/user-tasks/active-acceptance.ts +40 -0
- package/src/domains/user-tasks/store.ts +34 -3
- package/src/engine/acp/adapter.ts +24 -6
- package/src/engine/acp/server.ts +21 -4
- package/src/engine/acp/transport.ts +53 -8
- package/src/engine/acp/types.ts +4 -0
- package/src/engine/agent.ts +13 -3
- package/src/engine/ai.ts +26 -8
- package/src/engine/antigravity/subprocess-runtime.ts +386 -120
- package/src/engine/api-registry.ts +3 -0
- package/src/engine/apis/ollama-native.ts +15 -0
- package/src/engine/apis/openai-completions.ts +117 -14
- package/src/engine/claude/subprocess-runtime.ts +107 -60
- package/src/engine/external-subprocess.ts +122 -6
- package/src/entry/background-model-metadata.ts +18 -0
- package/src/entry/compaction-prompt.ts +57 -0
- package/src/entry/orchestrator.ts +416 -218
- package/src/entry/task-memory-lifecycle.ts +35 -0
- package/src/interactive/chat-loop-messages.ts +13 -4
- package/src/interactive/chat-loop.ts +65 -2
- package/src/interactive/chat-renderer.ts +1 -0
- package/src/interactive/cost-overlay.ts +26 -2
- package/src/interactive/dispatch-board.ts +46 -717
- package/src/interactive/fleet-run-preview.ts +2 -1
- package/src/interactive/interactive-application.ts +3 -2
- package/src/interactive/interactive-presentation.ts +55 -12
- package/src/interactive/interactive-slash-runtime.ts +4 -2
- package/src/interactive/oracle.ts +5 -2
- package/src/interactive/overlays/fleet-run-approval.ts +3 -2
- package/src/interactive/overlays/message-picker.ts +2 -2
- package/src/interactive/overlays/settings.ts +2 -2
- package/src/interactive/overlays/tree-selector.ts +2 -2
- package/src/interactive/renderers/branch-summary.ts +1 -1
- package/src/interactive/renderers/worker-entry.ts +32 -0
- package/src/interactive/slash-autocomplete.ts +4 -6
- package/src/interactive/slash-commands.ts +49 -45
- package/src/interactive/slash-spec.ts +28 -0
- package/src/interactive/theme/labels.ts +19 -13
- package/src/interactive/turn-context.ts +9 -5
- package/src/interactive/turn-recovery.ts +8 -0
- package/src/interactive/turn-runtime.ts +27 -11
- package/src/interactive/turn-state.ts +7 -0
- package/src/interactive/view/artifacts.ts +2 -0
- package/src/interactive/worker-receipts.ts +1 -0
- package/src/interactive/worker-stream.ts +13 -4
- package/src/tools/bootstrap.ts +4 -0
- package/src/tools/builtin-tool-catalog.ts +31 -0
- package/src/tools/compete-worktrees.ts +7 -1
- package/src/tools/context/index.ts +30 -9
- package/src/tools/core-bootstrap.ts +16 -0
- package/src/tools/decide.ts +136 -0
- package/src/tools/dispatch-admission.ts +21 -0
- package/src/tools/dispatch-arguments.ts +1 -0
- package/src/tools/dispatch-event-text.ts +10 -0
- package/src/tools/dispatch-plan.ts +6 -2
- package/src/tools/dispatch-runner.ts +27 -1
- package/src/tools/dispatch-types.ts +6 -0
- package/src/tools/evidence.ts +96 -0
- package/src/tools/limitation.ts +76 -0
- package/src/tools/policy.ts +9 -0
- package/src/tools/presentation.ts +3 -0
- package/src/tools/registry.ts +11 -5
- package/src/tools/result-shaping.ts +17 -5
- package/src/tools/task-worktree.ts +13 -3
- package/src/tools/tasks.ts +10 -1
- package/src/tools/verify/authoring.ts +170 -83
- package/src/tools/verify/catalog.ts +122 -5
- package/src/tools/verify/index.ts +2 -1
- package/src/tools/verify/numeric.ts +298 -0
- package/src/tools/verify/perf.ts +143 -0
- package/src/tools/verify/scripts.ts +229 -2
- package/src/tools/worker-evidence.ts +3 -1
- package/src/worker/spec-contract.ts +4 -0
- package/dist/chunk-2Z2IKEXI.js +0 -1554
- package/dist/chunk-RVG5JXAL.js +0 -41
- package/dist/chunk-T56WDKA5.js +0 -183
- package/dist/chunk-VN3SHNBN.js +0 -313
- package/dist/chunk-VPKWYKEY.js +0 -169
- package/dist/reset-OAQP3W4O.js +0 -230
- package/dist/uninstall-N34PCTGJ.js +0 -331
- package/dist/upgrade-PXK3S2YM.js +0 -325
|
@@ -1,14 +1,18 @@
|
|
|
1
|
+
import { resolve } from "node:path";
|
|
1
2
|
import { ToolNames } from "../../core/tool-names.js";
|
|
2
3
|
import { isProjectVerifierCheckId, isVerificationScriptName } from "../../core/verification-scripts.js";
|
|
4
|
+
import { type DeclaredCheckSourceRef, PROJECT_VERIFIER_CATALOG_RELATIVE_PATH } from "../../tools/verify/catalog.js";
|
|
5
|
+
import type { UserTaskAcceptance } from "../user-tasks/acceptance.js";
|
|
3
6
|
import {
|
|
4
7
|
detectValidationCommand,
|
|
5
8
|
extractCommandDeleteTargets,
|
|
6
9
|
extractCommandWriteTargets,
|
|
7
10
|
toolMutationPaths,
|
|
8
11
|
} from "./protected-artifacts.js";
|
|
12
|
+
import type { Rigor } from "./rigor.js";
|
|
9
13
|
|
|
10
14
|
export const FINISH_CONTRACT_ADVISORY_MESSAGE =
|
|
11
|
-
"[Clio Coder] finish-contract advisory: you changed files this turn without recording validation evidence or
|
|
15
|
+
"[Clio Coder] finish-contract advisory: you changed files this turn without recording validation evidence or a limitation receipt. Run a verification command or call limitation with the scope and reason.";
|
|
12
16
|
|
|
13
17
|
/**
|
|
14
18
|
* The recent-window cap (entries since the last user message). Exported so a
|
|
@@ -17,11 +21,24 @@ export const FINISH_CONTRACT_ADVISORY_MESSAGE =
|
|
|
17
21
|
*/
|
|
18
22
|
export const DEFAULT_RECENT_ENTRY_LIMIT = 80;
|
|
19
23
|
|
|
20
|
-
export type FinishContractEvidenceKind =
|
|
24
|
+
export type FinishContractEvidenceKind =
|
|
25
|
+
| "validation_command"
|
|
26
|
+
| "protected_artifact"
|
|
27
|
+
| "dispatch_receipt"
|
|
28
|
+
| "limitation";
|
|
29
|
+
|
|
30
|
+
interface ValidationExecutionEvidence {
|
|
31
|
+
source?: DeclaredCheckSourceRef;
|
|
32
|
+
cwd?: string;
|
|
33
|
+
argv?: ReadonlyArray<string>;
|
|
34
|
+
durationMs?: number;
|
|
35
|
+
}
|
|
21
36
|
|
|
22
|
-
export interface FinishContractEvidence {
|
|
37
|
+
export interface FinishContractEvidence extends ValidationExecutionEvidence {
|
|
23
38
|
kind: FinishContractEvidenceKind;
|
|
24
39
|
summary: string;
|
|
40
|
+
check?: string;
|
|
41
|
+
paths?: ReadonlyArray<string>;
|
|
25
42
|
turnId?: string;
|
|
26
43
|
}
|
|
27
44
|
|
|
@@ -48,16 +65,22 @@ export type FinishContractAssessment =
|
|
|
48
65
|
};
|
|
49
66
|
|
|
50
67
|
export interface FinishContractInput {
|
|
51
|
-
assistantText: string;
|
|
52
68
|
sessionEntries?: ReadonlyArray<unknown>;
|
|
53
69
|
assistantTurnId?: string | null;
|
|
54
70
|
recentEntryLimit?: number;
|
|
71
|
+
rigor?: Rigor;
|
|
72
|
+
activeAcceptance?: UserTaskAcceptance;
|
|
73
|
+
/** Owning session workspace, supplied by the finish registration. */
|
|
74
|
+
workspaceRoot?: string;
|
|
55
75
|
}
|
|
56
76
|
|
|
57
77
|
interface ToolCallEvidenceCandidate {
|
|
58
78
|
turnId?: string;
|
|
59
79
|
toolCallId: string;
|
|
60
80
|
command: string;
|
|
81
|
+
check?: string;
|
|
82
|
+
paths?: string[];
|
|
83
|
+
execution?: ValidationExecutionEvidence;
|
|
61
84
|
}
|
|
62
85
|
|
|
63
86
|
interface MutationCandidate {
|
|
@@ -65,32 +88,26 @@ interface MutationCandidate {
|
|
|
65
88
|
paths: string[];
|
|
66
89
|
}
|
|
67
90
|
|
|
68
|
-
const LIMITATION_PATTERNS: ReadonlyArray<RegExp> = [
|
|
69
|
-
/\b(?:blocked by|blocker|blockers|unable to|not able to|could not|couldn't|cannot|can't)\b/i,
|
|
70
|
-
/\b(?:did not|didn't|have not|haven't|has not|hasn't|was not able|wasn't able)\b/i,
|
|
71
|
-
/\b(?:not complete|incomplete)\b/i,
|
|
72
|
-
/\b(?:not|un)(?:\s|-)?(?:validated|verified|tested)\b/i,
|
|
73
|
-
/^\s*Tests\s*:\s*(?:not run|not executed|not available|failed|blocked|skipped)\b/im,
|
|
74
|
-
/^\s*Known gaps?\s*:\s*(?!\s*(?:none|no\b|n\/a|not applicable)\b).+/im,
|
|
75
|
-
/\bremaining(?:\s+\w+){0,3}\s+(?:work|issue|issues|gap|gaps|blocker|blockers)\b/i,
|
|
76
|
-
];
|
|
77
|
-
|
|
78
91
|
/**
|
|
79
92
|
* Action-scoped completion contract. The engine keys off what the turn actually
|
|
80
93
|
* DID, not how the prompt was phrased: it engages only when the recent window
|
|
81
94
|
* mutated workspace state and then settled (turn_end) without recording
|
|
82
|
-
* validation evidence or
|
|
95
|
+
* validation evidence or a limitation receipt. The turn settling is itself
|
|
83
96
|
* the completion signal, so the model never has to type "done" to be gated, and
|
|
84
97
|
* a work request phrased as a question cannot bypass the gate.
|
|
85
98
|
*
|
|
86
99
|
* Decision order (pure function of ledger receipts):
|
|
87
100
|
* 1. no mutating receipt in the window -> ok/no_mutation
|
|
88
101
|
* 2. validation evidence present -> ok/validation_evidence
|
|
89
|
-
* 3.
|
|
102
|
+
* 3. successful `limitation` receipt present -> ok/explicit_limitation
|
|
90
103
|
* 4. otherwise -> engage/unvalidated_mutation
|
|
104
|
+
*
|
|
105
|
+
* The assistant's prose never enters the decision. A limitation counts only
|
|
106
|
+
* as a `limitation` tool_call paired with a non-error tool_result inside the
|
|
107
|
+
* same window the mutation scan uses, so a run cannot satisfy the contract by
|
|
108
|
+
* wording alone and a real limitation is never missed for its phrasing.
|
|
91
109
|
*/
|
|
92
110
|
export function assessFinishContract(input: FinishContractInput): FinishContractAssessment {
|
|
93
|
-
const assistantText = input.assistantText.trim();
|
|
94
111
|
const sessionEntries = input.sessionEntries ?? [];
|
|
95
112
|
const assistantTurnId = input.assistantTurnId ?? null;
|
|
96
113
|
const window = recentEntries(sessionEntries, assistantTurnId, input.recentEntryLimit ?? DEFAULT_RECENT_ENTRY_LIMIT);
|
|
@@ -100,13 +117,39 @@ export function assessFinishContract(input: FinishContractInput): FinishContract
|
|
|
100
117
|
return { kind: "ok", reason: "no_mutation", evidence: [], mutatedPaths };
|
|
101
118
|
}
|
|
102
119
|
|
|
103
|
-
const
|
|
120
|
+
const acceptanceChecks = new Set(input.activeAcceptance?.verification.map((item) => item.check) ?? []);
|
|
121
|
+
const evidence = collectValidationEvidence(window, acceptanceChecks, input.workspaceRoot);
|
|
122
|
+
const limitations = collectLimitationEvidence(window);
|
|
123
|
+
const required = input.rigor === "high" ? (input.activeAcceptance?.verification ?? []) : [];
|
|
124
|
+
if (required.length > 0) {
|
|
125
|
+
const passes = new Set(
|
|
126
|
+
required.filter((check) => evidence.some((item) => acceptanceCheckPassed(item, check, input.workspaceRoot))),
|
|
127
|
+
);
|
|
128
|
+
const limited = new Set(limitations.flatMap((item) => item.paths ?? []));
|
|
129
|
+
const missing = [
|
|
130
|
+
...new Set(required.filter((check) => !passes.has(check) && !limited.has(check.check)).map((item) => item.check)),
|
|
131
|
+
];
|
|
132
|
+
if (missing.length > 0)
|
|
133
|
+
return {
|
|
134
|
+
kind: "engage",
|
|
135
|
+
reason: "unvalidated_mutation",
|
|
136
|
+
message: `[Clio Coder] high-rigor finish gate: operator acceptance still requires passing validation for: ${missing.join(", ")}. Run each named check or include its exact id in limitation.paths.`,
|
|
137
|
+
evidence: [...evidence, ...limitations],
|
|
138
|
+
mutatedPaths,
|
|
139
|
+
};
|
|
140
|
+
return {
|
|
141
|
+
kind: "ok",
|
|
142
|
+
reason: passes.size === required.length ? "validation_evidence" : "explicit_limitation",
|
|
143
|
+
evidence: [...evidence, ...limitations],
|
|
144
|
+
mutatedPaths,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
104
147
|
if (evidence.length > 0) {
|
|
105
148
|
return { kind: "ok", reason: "validation_evidence", evidence, mutatedPaths };
|
|
106
149
|
}
|
|
107
150
|
|
|
108
|
-
if (
|
|
109
|
-
return { kind: "ok", reason: "explicit_limitation", evidence:
|
|
151
|
+
if (limitations.length > 0) {
|
|
152
|
+
return { kind: "ok", reason: "explicit_limitation", evidence: limitations, mutatedPaths };
|
|
110
153
|
}
|
|
111
154
|
|
|
112
155
|
return {
|
|
@@ -118,16 +161,80 @@ export function assessFinishContract(input: FinishContractInput): FinishContract
|
|
|
118
161
|
};
|
|
119
162
|
}
|
|
120
163
|
|
|
164
|
+
function acceptanceCheckPassed(
|
|
165
|
+
evidence: FinishContractEvidence,
|
|
166
|
+
required: UserTaskAcceptance["verification"][number],
|
|
167
|
+
workspaceRoot: string | undefined,
|
|
168
|
+
): boolean {
|
|
169
|
+
if (evidence.kind !== "validation_command" || evidence.check !== required.check || !workspaceRoot || !evidence.source)
|
|
170
|
+
return false;
|
|
171
|
+
if (evidence.durationMs !== undefined && evidence.durationMs > required.timeoutMs) return false;
|
|
172
|
+
const root = resolve(workspaceRoot);
|
|
173
|
+
if (evidence.source.kind === "project-catalog")
|
|
174
|
+
return evidence.source.path === resolve(root, PROJECT_VERIFIER_CATALOG_RELATIVE_PATH);
|
|
175
|
+
return (
|
|
176
|
+
evidence.source.path === resolve(root, "package.json") &&
|
|
177
|
+
evidence.cwd === root &&
|
|
178
|
+
validationCheckId(evidence.argv?.join(" ") ?? "") === required.check
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
121
182
|
/**
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
125
|
-
*
|
|
183
|
+
* Successful `limitation` receipts over the recent window. A receipt is a
|
|
184
|
+
* `limitation` tool_call whose tool_result in the same window is not an
|
|
185
|
+
* error, judged by the same `successfulToolResultId` rule the mutation and
|
|
186
|
+
* validation scans use. A call the tool rejected (bad reason, empty scope)
|
|
187
|
+
* leaves no receipt, so it cannot settle the contract.
|
|
126
188
|
*/
|
|
127
|
-
function
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
189
|
+
function collectLimitationEvidence(recent: ReadonlyArray<unknown>): FinishContractEvidence[] {
|
|
190
|
+
const evidence: FinishContractEvidence[] = [];
|
|
191
|
+
const calls = new Map<string, ToolCallEvidenceCandidate>();
|
|
192
|
+
const seen = new Set<string>();
|
|
193
|
+
|
|
194
|
+
for (const entry of recent) {
|
|
195
|
+
const call = limitationToolCall(entry);
|
|
196
|
+
if (call !== null) {
|
|
197
|
+
calls.set(call.toolCallId, call);
|
|
198
|
+
continue;
|
|
199
|
+
}
|
|
200
|
+
const resultId = successfulToolResultId(entry);
|
|
201
|
+
if (resultId === null) continue;
|
|
202
|
+
const candidate = calls.get(resultId);
|
|
203
|
+
if (candidate === undefined) continue;
|
|
204
|
+
const item: FinishContractEvidence = {
|
|
205
|
+
kind: "limitation",
|
|
206
|
+
summary: candidate.command,
|
|
207
|
+
...(candidate.paths ? { paths: candidate.paths } : {}),
|
|
208
|
+
};
|
|
209
|
+
if (candidate.turnId !== undefined) item.turnId = candidate.turnId;
|
|
210
|
+
pushEvidence(evidence, seen, item);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return evidence;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function limitationToolCall(entry: unknown): ToolCallEvidenceCandidate | null {
|
|
217
|
+
const record = asRecord(entry);
|
|
218
|
+
if (record?.kind !== "message" || record.role !== "tool_call") return null;
|
|
219
|
+
const payload = asRecord(record.payload);
|
|
220
|
+
if (payload === null) return null;
|
|
221
|
+
const toolName = stringFromFirst(payload, ["name", "toolName", "tool"]);
|
|
222
|
+
if (toolName !== ToolNames.Limitation) return null;
|
|
223
|
+
const toolCallId = stringFromFirst(payload, ["toolCallId", "tool_call_id", "id"]) ?? turnIdOf(entry);
|
|
224
|
+
if (toolCallId === null) return null;
|
|
225
|
+
const args = asRecord(payload.args ?? payload.arguments ?? payload.input);
|
|
226
|
+
const scope = typeof args?.scope === "string" ? args.scope.trim() : "";
|
|
227
|
+
const reason = typeof args?.reason === "string" ? args.reason.trim() : "";
|
|
228
|
+
const candidate: ToolCallEvidenceCandidate = {
|
|
229
|
+
toolCallId,
|
|
230
|
+
paths: Array.isArray(args?.paths)
|
|
231
|
+
? args.paths.filter((item): item is string => typeof item === "string").map((item) => item.trim())
|
|
232
|
+
: [],
|
|
233
|
+
command: `limitation recorded: ${scope.length > 0 ? scope : "unspecified"} (reason=${reason.length > 0 ? reason : "unspecified"})`,
|
|
234
|
+
};
|
|
235
|
+
const turnId = turnIdOf(entry);
|
|
236
|
+
if (turnId !== null) candidate.turnId = turnId;
|
|
237
|
+
return candidate;
|
|
131
238
|
}
|
|
132
239
|
|
|
133
240
|
/**
|
|
@@ -226,7 +333,11 @@ function pushPath(paths: string[], seen: Set<string>, path: string): void {
|
|
|
226
333
|
* Inspection was removed because inspecting the repo is never a mutation, so it
|
|
227
334
|
* can no longer be on the path to engaging the contract.
|
|
228
335
|
*/
|
|
229
|
-
function collectValidationEvidence(
|
|
336
|
+
function collectValidationEvidence(
|
|
337
|
+
recent: ReadonlyArray<unknown>,
|
|
338
|
+
acceptanceChecks: ReadonlySet<string>,
|
|
339
|
+
workspaceRoot: string | undefined,
|
|
340
|
+
): FinishContractEvidence[] {
|
|
230
341
|
const evidence: FinishContractEvidence[] = [];
|
|
231
342
|
const toolCalls = new Map<string, ToolCallEvidenceCandidate>();
|
|
232
343
|
const dispatchCalls = new Map<string, ToolCallEvidenceCandidate>();
|
|
@@ -239,7 +350,7 @@ function collectValidationEvidence(recent: ReadonlyArray<unknown>): FinishContra
|
|
|
239
350
|
continue;
|
|
240
351
|
}
|
|
241
352
|
|
|
242
|
-
const call = bashValidationCall(entry);
|
|
353
|
+
const call = bashValidationCall(entry, acceptanceChecks, workspaceRoot);
|
|
243
354
|
if (call !== null) {
|
|
244
355
|
toolCalls.set(call.toolCallId, call);
|
|
245
356
|
continue;
|
|
@@ -267,19 +378,19 @@ function collectValidationEvidence(recent: ReadonlyArray<unknown>): FinishContra
|
|
|
267
378
|
}
|
|
268
379
|
const candidate = toolCalls.get(resultId);
|
|
269
380
|
if (candidate !== undefined) {
|
|
270
|
-
pushEvidence(evidence, seen, validationEvidence(candidate));
|
|
381
|
+
pushEvidence(evidence, seen, validationEvidence(candidate, entry));
|
|
271
382
|
}
|
|
272
383
|
continue;
|
|
273
384
|
}
|
|
274
385
|
|
|
275
|
-
const bashExecution = bashExecutionEvidence(entry);
|
|
386
|
+
const bashExecution = bashExecutionEvidence(entry, acceptanceChecks, workspaceRoot);
|
|
276
387
|
if (bashExecution !== null) pushEvidence(evidence, seen, bashExecution);
|
|
277
388
|
}
|
|
278
389
|
|
|
279
390
|
return evidence;
|
|
280
391
|
}
|
|
281
392
|
|
|
282
|
-
function recentEntries(
|
|
393
|
+
export function recentEntries(
|
|
283
394
|
entries: ReadonlyArray<unknown>,
|
|
284
395
|
assistantTurnId: string | null,
|
|
285
396
|
recentEntryLimit: number,
|
|
@@ -299,7 +410,11 @@ function recentEntries(
|
|
|
299
410
|
return entries.slice(startInclusive, endExclusive);
|
|
300
411
|
}
|
|
301
412
|
|
|
302
|
-
function bashValidationCall(
|
|
413
|
+
function bashValidationCall(
|
|
414
|
+
entry: unknown,
|
|
415
|
+
acceptanceChecks: ReadonlySet<string>,
|
|
416
|
+
workspaceRoot: string | undefined,
|
|
417
|
+
): ToolCallEvidenceCandidate | null {
|
|
303
418
|
const record = asRecord(entry);
|
|
304
419
|
if (record?.kind !== "message" || record.role !== "tool_call") return null;
|
|
305
420
|
const payload = asRecord(record.payload);
|
|
@@ -309,13 +424,15 @@ function bashValidationCall(entry: unknown): ToolCallEvidenceCandidate | null {
|
|
|
309
424
|
const args = asRecord(payload.args ?? payload.arguments ?? payload.input);
|
|
310
425
|
const command = typeof args?.command === "string" ? args.command : null;
|
|
311
426
|
if (command === null) return null;
|
|
312
|
-
const detected =
|
|
427
|
+
const detected = acceptanceValidationCommand(command, acceptanceChecks);
|
|
313
428
|
if (detected.kind !== "validation") return null;
|
|
314
429
|
const toolCallId = stringFromFirst(payload, ["toolCallId", "tool_call_id", "id"]) ?? turnIdOf(entry);
|
|
315
430
|
if (toolCallId === null) return null;
|
|
316
431
|
const candidate: ToolCallEvidenceCandidate = {
|
|
317
432
|
toolCallId,
|
|
318
433
|
command: detected.matched,
|
|
434
|
+
...validationCheckFields(detected.matched),
|
|
435
|
+
execution: packageCommandExecution(command, args?.cwd, workspaceRoot),
|
|
319
436
|
};
|
|
320
437
|
const turnId = turnIdOf(entry);
|
|
321
438
|
if (turnId !== null) candidate.turnId = turnId;
|
|
@@ -380,6 +497,7 @@ function validationToolCall(entry: unknown): ToolCallEvidenceCandidate | null {
|
|
|
380
497
|
const candidate: ToolCallEvidenceCandidate = {
|
|
381
498
|
toolCallId,
|
|
382
499
|
command: summary,
|
|
500
|
+
...validationCheckFields(summary),
|
|
383
501
|
};
|
|
384
502
|
const turnId = turnIdOf(entry);
|
|
385
503
|
if (turnId !== null) candidate.turnId = turnId;
|
|
@@ -414,7 +532,8 @@ function successfulToolResultId(entry: unknown): string | null {
|
|
|
414
532
|
if (payload.isError === true || payload.error === true) return null;
|
|
415
533
|
const result = asRecord(payload.result);
|
|
416
534
|
const details = asRecord(result?.details);
|
|
417
|
-
if (details?.kind === "error") return null;
|
|
535
|
+
if (result?.kind === "error" || details?.kind === "error") return null;
|
|
536
|
+
if (typeof details?.exitCode === "number" && details.exitCode !== 0) return null;
|
|
418
537
|
return stringFromFirst(payload, ["toolCallId", "tool_call_id", "id"]);
|
|
419
538
|
}
|
|
420
539
|
|
|
@@ -482,18 +601,24 @@ function dispatchReceiptAgentId(
|
|
|
482
601
|
return candidate?.command.match(/^agent=([^\s]+)/)?.[1] ?? "unknown";
|
|
483
602
|
}
|
|
484
603
|
|
|
485
|
-
function bashExecutionEvidence(
|
|
604
|
+
function bashExecutionEvidence(
|
|
605
|
+
entry: unknown,
|
|
606
|
+
acceptanceChecks: ReadonlySet<string>,
|
|
607
|
+
workspaceRoot: string | undefined,
|
|
608
|
+
): FinishContractEvidence | null {
|
|
486
609
|
const record = asRecord(entry);
|
|
487
610
|
if (record?.kind !== "bashExecution") return null;
|
|
488
611
|
if (typeof record.command !== "string") return null;
|
|
489
612
|
if (record.cancelled === true) return null;
|
|
490
613
|
if (record.exitCode !== 0) return null;
|
|
491
|
-
const detected =
|
|
614
|
+
const detected = acceptanceValidationCommand(record.command, acceptanceChecks);
|
|
492
615
|
if (detected.kind !== "validation") return null;
|
|
493
616
|
const contextMarker = record.excludeFromContext === true ? " [not sent to model]" : "";
|
|
494
617
|
const evidence: FinishContractEvidence = {
|
|
495
618
|
kind: "validation_command",
|
|
496
619
|
summary: `validation command passed: ${detected.matched}${contextMarker}`,
|
|
620
|
+
...validationCheckFields(detected.matched),
|
|
621
|
+
...packageCommandExecution(record.command, record.cwd, workspaceRoot),
|
|
497
622
|
};
|
|
498
623
|
const turnId = turnIdOf(entry);
|
|
499
624
|
if (turnId !== null) evidence.turnId = turnId;
|
|
@@ -515,17 +640,80 @@ function protectedArtifactEvidence(entry: unknown): FinishContractEvidence | nul
|
|
|
515
640
|
return evidence;
|
|
516
641
|
}
|
|
517
642
|
|
|
518
|
-
function validationEvidence(candidate: ToolCallEvidenceCandidate): FinishContractEvidence {
|
|
643
|
+
function validationEvidence(candidate: ToolCallEvidenceCandidate, entry: unknown): FinishContractEvidence {
|
|
519
644
|
const evidence: FinishContractEvidence = {
|
|
520
645
|
kind: "validation_command",
|
|
521
646
|
summary: `validation command passed: ${candidate.command}`,
|
|
647
|
+
...(candidate.check ? { check: candidate.check } : {}),
|
|
648
|
+
...(candidate.execution ?? declaredCheckExecution(entry, candidate.check)),
|
|
522
649
|
};
|
|
523
650
|
if (candidate.turnId !== undefined) evidence.turnId = candidate.turnId;
|
|
524
651
|
return evidence;
|
|
525
652
|
}
|
|
526
653
|
|
|
654
|
+
/** Preserve the verifier's execution facts only when they identify the declared check. */
|
|
655
|
+
function declaredCheckExecution(entry: unknown, check: string | undefined): ValidationExecutionEvidence {
|
|
656
|
+
const payload = asRecord(asRecord(entry)?.payload);
|
|
657
|
+
const details = asRecord(asRecord(payload?.result)?.details);
|
|
658
|
+
const source = asRecord(details?.source);
|
|
659
|
+
if (
|
|
660
|
+
!details ||
|
|
661
|
+
details.check !== check ||
|
|
662
|
+
details.exitCode !== 0 ||
|
|
663
|
+
details.aborted === true ||
|
|
664
|
+
details.timedOut === true ||
|
|
665
|
+
details.outputCapped === true ||
|
|
666
|
+
(source?.kind !== "package.json" && source?.kind !== "project-catalog") ||
|
|
667
|
+
typeof source.path !== "string" ||
|
|
668
|
+
typeof details.cwd !== "string" ||
|
|
669
|
+
!Array.isArray(details.argv) ||
|
|
670
|
+
!details.argv.every((arg): arg is string => typeof arg === "string")
|
|
671
|
+
)
|
|
672
|
+
return {};
|
|
673
|
+
if (source.kind === "project-catalog") {
|
|
674
|
+
const argv = details.argv;
|
|
675
|
+
if (
|
|
676
|
+
!Array.isArray(details.declaredCommand) ||
|
|
677
|
+
details.declaredCommand.length !== details.argv.length ||
|
|
678
|
+
!details.declaredCommand.every((arg, index) => arg === argv[index]) ||
|
|
679
|
+
typeof details.declaredCwd !== "string" ||
|
|
680
|
+
typeof details.declaredTimeoutMs !== "number" ||
|
|
681
|
+
typeof details.durationMs !== "number" ||
|
|
682
|
+
details.durationMs > details.declaredTimeoutMs ||
|
|
683
|
+
resolve(source.path, "../..", details.declaredCwd) !== details.cwd
|
|
684
|
+
)
|
|
685
|
+
return {};
|
|
686
|
+
}
|
|
687
|
+
return {
|
|
688
|
+
source: { kind: source.kind, path: source.path },
|
|
689
|
+
cwd: details.cwd,
|
|
690
|
+
argv: details.argv,
|
|
691
|
+
...(typeof details.durationMs === "number" ? { durationMs: details.durationMs } : {}),
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
/** Exact package commands retain their execution cwd; a matched substring proves no project identity. */
|
|
696
|
+
function packageCommandExecution(
|
|
697
|
+
command: string,
|
|
698
|
+
cwd: unknown,
|
|
699
|
+
workspaceRoot: string | undefined,
|
|
700
|
+
): ValidationExecutionEvidence {
|
|
701
|
+
if (
|
|
702
|
+
!workspaceRoot ||
|
|
703
|
+
!/^(?:npm|pnpm|yarn|bun) /u.test(command.trim()) ||
|
|
704
|
+
validationCheckId(command.trim()) === undefined
|
|
705
|
+
)
|
|
706
|
+
return {};
|
|
707
|
+
const executionCwd = resolve(workspaceRoot, typeof cwd === "string" ? cwd : ".");
|
|
708
|
+
return {
|
|
709
|
+
source: { kind: "package.json", path: resolve(executionCwd, "package.json") },
|
|
710
|
+
cwd: executionCwd,
|
|
711
|
+
argv: command.trim().split(/\s+/u),
|
|
712
|
+
};
|
|
713
|
+
}
|
|
714
|
+
|
|
527
715
|
function pushEvidence(evidence: FinishContractEvidence[], seen: Set<string>, item: FinishContractEvidence): void {
|
|
528
|
-
const key =
|
|
716
|
+
const key = JSON.stringify(item);
|
|
529
717
|
if (seen.has(key)) return;
|
|
530
718
|
seen.add(key);
|
|
531
719
|
evidence.push(item);
|
|
@@ -554,3 +742,27 @@ function stringFromFirst(record: Record<string, unknown>, keys: ReadonlyArray<st
|
|
|
554
742
|
function asRecord(value: unknown): Record<string, unknown> | null {
|
|
555
743
|
return value !== null && typeof value === "object" ? (value as Record<string, unknown>) : null;
|
|
556
744
|
}
|
|
745
|
+
|
|
746
|
+
/** Exact check ids, never substring matches against rendered evidence summaries. */
|
|
747
|
+
function validationCheckId(command: string): string | undefined {
|
|
748
|
+
return (
|
|
749
|
+
/^(?:npm|pnpm|yarn|bun) (?:run )?([a-z0-9][a-z0-9._:-]*)$/.exec(command)?.[1] ??
|
|
750
|
+
/^verify ([a-z0-9][a-z0-9._:-]*)$/.exec(command)?.[1]
|
|
751
|
+
);
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
function validationCheckFields(command: string): { check?: string } {
|
|
755
|
+
const check = validationCheckId(command);
|
|
756
|
+
return check ? { check } : {};
|
|
757
|
+
}
|
|
758
|
+
|
|
759
|
+
/** Additional package scripts are admitted only by the operator's typed acceptance. */
|
|
760
|
+
function acceptanceValidationCommand(
|
|
761
|
+
command: string,
|
|
762
|
+
checks: ReadonlySet<string>,
|
|
763
|
+
): ReturnType<typeof detectValidationCommand> {
|
|
764
|
+
const exact = command.trim();
|
|
765
|
+
const check = /^npm run ([a-z0-9][a-z0-9._:-]*)$/.exec(exact)?.[1];
|
|
766
|
+
if (check && checks.has(check)) return { kind: "validation", matched: exact };
|
|
767
|
+
return detectValidationCommand(command);
|
|
768
|
+
}
|
|
@@ -19,6 +19,7 @@ export {
|
|
|
19
19
|
DEFAULT_AUTONOMY_LEVEL,
|
|
20
20
|
isAutonomyLevel,
|
|
21
21
|
mapAutonomy,
|
|
22
|
+
modelMayActivateSkills,
|
|
22
23
|
} from "./autonomy.js";
|
|
23
24
|
export type { SafetyContract, SafetyDecision } from "./contract.js";
|
|
24
25
|
export type {
|
|
@@ -41,4 +42,23 @@ export {
|
|
|
41
42
|
type PathPolicyKind,
|
|
42
43
|
type PathPolicyOperation,
|
|
43
44
|
} from "./path-policy.js";
|
|
44
|
-
export {
|
|
45
|
+
export {
|
|
46
|
+
parseRigorOverride,
|
|
47
|
+
type Rigor,
|
|
48
|
+
type RigorResolution,
|
|
49
|
+
type RigorSource,
|
|
50
|
+
resolveRigor,
|
|
51
|
+
rigorResolution,
|
|
52
|
+
} from "./rigor.js";
|
|
53
|
+
export {
|
|
54
|
+
describeValidationContract,
|
|
55
|
+
loadValidationContract,
|
|
56
|
+
parseValidationContractText,
|
|
57
|
+
VALIDATION_CONTRACT_CAPS,
|
|
58
|
+
VALIDATION_CONTRACT_MARKDOWN_PATH,
|
|
59
|
+
VALIDATION_CONTRACT_YAML_PATHS,
|
|
60
|
+
type ValidationContract,
|
|
61
|
+
type ValidationContractArtifact,
|
|
62
|
+
type ValidationContractLoadResult,
|
|
63
|
+
type ValidationContractRuntime,
|
|
64
|
+
} from "./validation-contract.js";
|
|
@@ -41,7 +41,7 @@ export function isSameOrDescendant(candidatePath: string, policyPath: string): b
|
|
|
41
41
|
const candidate = path.resolve(candidatePath);
|
|
42
42
|
const policy = path.resolve(policyPath);
|
|
43
43
|
const relative = path.relative(policy, candidate);
|
|
44
|
-
return relative === "" || (!relative.startsWith(
|
|
44
|
+
return relative === "" || (relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative));
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
function expandTilde(rawPath: string): string {
|
|
@@ -25,10 +25,12 @@ import {
|
|
|
25
25
|
extractCommandDeleteTargets,
|
|
26
26
|
extractCommandWriteTargets,
|
|
27
27
|
inlineShellScript,
|
|
28
|
-
|
|
28
|
+
invokesClioSkillMutation,
|
|
29
|
+
scanShellLike,
|
|
29
30
|
} from "./protected-artifacts.js";
|
|
30
31
|
import { formatRejection, type RejectionMessage } from "./rejection-feedback.js";
|
|
31
32
|
import { getCachedDefaultRulePacks, type PackId, type RulePacks } from "./rule-pack-loader.js";
|
|
33
|
+
import { activeClioSkillRoots, skillMutationReason } from "./skill-authority.js";
|
|
32
34
|
|
|
33
35
|
export type SafetyPolicySource =
|
|
34
36
|
| "damage-control:base"
|
|
@@ -194,6 +196,7 @@ export function createSafetyPolicyEngine(options: SafetyPolicyEngineOptions = {}
|
|
|
194
196
|
// cwd and roots to compare like against like (the design mandates no symlink chasing).
|
|
195
197
|
const writeRootCwd = path.resolve(options.cwd ?? process.cwd());
|
|
196
198
|
const writeRoots = (options.writeRoots ?? []).map((root) => resolvePathBoundary(writeRootCwd, root));
|
|
199
|
+
const skillRoots = activeClioSkillRoots(cwd);
|
|
197
200
|
const packs = options.rulePacks ?? getCachedDefaultRulePacks();
|
|
198
201
|
const projectPolicy = options.projectPolicy ?? loadProjectSafetyPolicy(cwd);
|
|
199
202
|
const projectPolicyRoot =
|
|
@@ -201,12 +204,15 @@ export function createSafetyPolicyEngine(options: SafetyPolicyEngineOptions = {}
|
|
|
201
204
|
const pathPolicyInput = projectPolicy.disableDefaultPathPolicy
|
|
202
205
|
? projectPolicy.pathPolicy
|
|
203
206
|
: mergePathPolicyInputs(DEFAULT_DAMAGE_CONTROL_PATH_POLICY, projectPolicy.pathPolicy);
|
|
204
|
-
// Clio's own secret store, by absolute path.
|
|
205
|
-
//
|
|
207
|
+
// Clio's own secret store and user skills, by absolute path.
|
|
208
|
+
// Config directory expansion has to happen here because
|
|
206
209
|
// the list cannot call config helpers at module scope.
|
|
207
210
|
const expandedDefaults = projectPolicy.disableDefaultPathPolicy
|
|
208
211
|
? pathPolicyInput
|
|
209
|
-
: mergePathPolicyInputs(pathPolicyInput, {
|
|
212
|
+
: mergePathPolicyInputs(pathPolicyInput, {
|
|
213
|
+
zeroAccessPaths: clioCredentialStorePaths(),
|
|
214
|
+
readOnlyPaths: clioSkillsRootPaths(),
|
|
215
|
+
});
|
|
210
216
|
const pathPolicy = compilePathPolicy(expandedDefaults, projectPolicyRoot);
|
|
211
217
|
// Bash-read scanning tests argument tokens against zero-access entries only:
|
|
212
218
|
// read-only paths stay readable from bash by design, secrets do not.
|
|
@@ -308,6 +314,27 @@ export function createSafetyPolicyEngine(options: SafetyPolicyEngineOptions = {}
|
|
|
308
314
|
return blockDecision(base, blockInput);
|
|
309
315
|
}
|
|
310
316
|
|
|
317
|
+
// Editing active instructions is an operator privilege at every autonomy
|
|
318
|
+
// level, in both the coordinator and the shared worker safety contract.
|
|
319
|
+
const mutationCommand = call.tool === ToolNames.Bash ? command : catalogCommand;
|
|
320
|
+
const skillReason =
|
|
321
|
+
mutationCommand !== null && invokesClioSkillMutation(mutationCommand)
|
|
322
|
+
? "skill installation and updates require the operator CLI or an explicit operator install choice; draft outside active skill roots"
|
|
323
|
+
: skillMutationReason(
|
|
324
|
+
skillRoots,
|
|
325
|
+
pathPolicyTargets(catalogCommand === null ? call : { tool: ToolNames.Bash, args: { command: catalogCommand } }),
|
|
326
|
+
callCwd,
|
|
327
|
+
mutationCommand,
|
|
328
|
+
);
|
|
329
|
+
if (skillReason !== null) {
|
|
330
|
+
return blockDecision(base, {
|
|
331
|
+
ruleId: "skill-authority",
|
|
332
|
+
reasonCode: "skill-authority",
|
|
333
|
+
reasons: [skillReason],
|
|
334
|
+
policySource: "builtin-classifier",
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
|
|
311
338
|
// The path policy runs regardless of project policy validity. When
|
|
312
339
|
// `.clio-coder/safety.yaml` is invalid, the loader has already dropped every
|
|
313
340
|
// project-authored path entry and forced `disableDefaultPathPolicy`
|
|
@@ -454,6 +481,15 @@ function clioCredentialStorePaths(): string[] {
|
|
|
454
481
|
}
|
|
455
482
|
}
|
|
456
483
|
|
|
484
|
+
/** Absolute path of Clio's user skills, when resolvable. */
|
|
485
|
+
function clioSkillsRootPaths(): string[] {
|
|
486
|
+
try {
|
|
487
|
+
return [path.join(clioConfigDir(), "skills")];
|
|
488
|
+
} catch {
|
|
489
|
+
return [];
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
457
493
|
/**
|
|
458
494
|
* The exact safe presence form: `grep -q` or `grep -sq` (either flag order)
|
|
459
495
|
* with a `^NAME=`-shaped pattern and a single file argument. Exit code only;
|
|
@@ -488,10 +524,10 @@ function stripQuotes(token: string): string {
|
|
|
488
524
|
*/
|
|
489
525
|
function bashPathTokenCandidates(command: string): string[] {
|
|
490
526
|
const candidates: string[] = [];
|
|
491
|
-
for (const
|
|
527
|
+
for (const scanned of scanShellLike(command)) {
|
|
528
|
+
if (scanned.operator) continue;
|
|
529
|
+
const token = scanned.value;
|
|
492
530
|
if (token.length === 0) continue;
|
|
493
|
-
if (token === ";" || token === "&&" || token === "||" || token === "|" || token === ">" || token === ">>") continue;
|
|
494
|
-
if (token === "<" || token === "<<") continue;
|
|
495
531
|
// A token containing whitespace came from a quoted string of prose, not
|
|
496
532
|
// a path argument; and flags are not paths unless they embed one
|
|
497
533
|
// (--file=~/.aws/credentials).
|
|
@@ -821,9 +857,6 @@ function matchingProjectCommand(
|
|
|
821
857
|
return null;
|
|
822
858
|
}
|
|
823
859
|
|
|
824
|
-
/** Operators that end chain recognition; only `&&` keeps a chain readable. */
|
|
825
|
-
const CHAIN_BREAKING_TOKENS: ReadonlySet<string> = new Set([";", "|", "||", ">", ">>", "<", "<<"]);
|
|
826
|
-
|
|
827
860
|
/** Chain length ceiling. Real compound calls are two or three steps. */
|
|
828
861
|
const CHAIN_MAX_SEGMENTS = 6;
|
|
829
862
|
|
|
@@ -856,14 +889,16 @@ function recognizeCommandChain(
|
|
|
856
889
|
): ChainRecognition | null {
|
|
857
890
|
const segments: string[][] = [];
|
|
858
891
|
let current: string[] = [];
|
|
859
|
-
for (const token of
|
|
860
|
-
if (token === "&&") {
|
|
892
|
+
for (const token of scanShellLike(command)) {
|
|
893
|
+
if (token.operator && token.value === "&&") {
|
|
861
894
|
segments.push(current);
|
|
862
895
|
current = [];
|
|
863
896
|
continue;
|
|
864
897
|
}
|
|
865
|
-
|
|
866
|
-
|
|
898
|
+
// Only an actual && operator joins recognizable commands. Quoted words
|
|
899
|
+
// remain argv and every other real operator makes this chain unrecognized.
|
|
900
|
+
if (token.operator) return null;
|
|
901
|
+
current.push(token.value);
|
|
867
902
|
}
|
|
868
903
|
segments.push(current);
|
|
869
904
|
if (segments.length < 2 || segments.length > CHAIN_MAX_SEGMENTS) return null;
|
|
@@ -943,10 +978,16 @@ function cwdArg(args: Record<string, unknown> | undefined, fallback: string): st
|
|
|
943
978
|
}
|
|
944
979
|
|
|
945
980
|
/**
|
|
946
|
-
* Tools whose arguments
|
|
947
|
-
* Their damage-control scan is the destination path alone.
|
|
981
|
+
* Tools whose arguments carry file contents or task prose, not command lines.
|
|
982
|
+
* Their damage-control scan is the destination path alone, when present.
|
|
948
983
|
*/
|
|
949
|
-
const CONTENT_BEARING_TOOLS: ReadonlySet<string> = new Set([
|
|
984
|
+
const CONTENT_BEARING_TOOLS: ReadonlySet<string> = new Set([
|
|
985
|
+
ToolNames.Write,
|
|
986
|
+
ToolNames.Edit,
|
|
987
|
+
ToolNames.Artifact,
|
|
988
|
+
ToolNames.Dispatch,
|
|
989
|
+
ToolNames.Tasks,
|
|
990
|
+
]);
|
|
950
991
|
|
|
951
992
|
/**
|
|
952
993
|
* The text damage-control rules are matched against.
|
|
@@ -968,6 +1009,8 @@ const CONTENT_BEARING_TOOLS: ReadonlySet<string> = new Set([ToolNames.Write, Too
|
|
|
968
1009
|
* full. Only the destination path is scanned for a mutation tool, which keeps
|
|
969
1010
|
* any path-shaped rule working; where the file may land is the write tool's own
|
|
970
1011
|
* gate in `writePathClass`.
|
|
1012
|
+
* Dispatch and task-board prose likewise does not execute; worker commands
|
|
1013
|
+
* are scanned when the worker calls an execute-class tool.
|
|
971
1014
|
*/
|
|
972
1015
|
function damageControlScan(call: ClassifierCall): string {
|
|
973
1016
|
if (!CONTENT_BEARING_TOOLS.has(call.tool)) return serializeArgs(call.args);
|