@iowarp/clio-coder 0.4.3 → 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 +63 -0
- package/README.md +1 -1
- package/dist/{acp-H2NGRPWO.js → acp-WNAYYF4F.js} +4 -5
- package/dist/{agents-TL5LLUQP.js → agents-3OKXHLOI.js} +33 -31
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-E5SW4HMS.js → auth-VKNNMGPU.js} +10 -11
- package/dist/{builtins-IA7V7FUC.js → builtins-WGALA46I.js} +4 -4
- package/dist/{chunk-F5JHEYZM.js → chunk-23L32XTI.js} +10 -7
- package/dist/{chunk-DWUOQKRU.js → chunk-25QBEXRS.js} +2 -2
- package/dist/{chunk-LLDJM5XK.js → chunk-26QSH3EJ.js} +2 -2
- package/dist/{chunk-N2Z7HLVY.js → chunk-2ASED4PZ.js} +10 -10
- package/dist/{chunk-MCEPRMZW.js → chunk-2CU2H6KE.js} +2 -2
- package/dist/chunk-2DSOYNFC.js +108 -0
- package/dist/{chunk-LDJG7DW3.js → chunk-2ZSONWVL.js} +4 -4
- package/dist/{chunk-GI7YYQ3F.js → chunk-36CT5VVL.js} +324 -41
- package/dist/{chunk-4UVU7BJ5.js → chunk-3GY4F45V.js} +2 -2
- package/dist/{chunk-PUVDKJ2Y.js → chunk-3ODX73FK.js} +3 -5
- package/dist/{chunk-IUE3Y34X.js → chunk-3UNOLWNZ.js} +2 -2
- package/dist/{chunk-6PTFB5VS.js → chunk-3UUXNFEX.js} +8 -4
- package/dist/{chunk-2APPQIER.js → chunk-4M6Z5QVF.js} +4 -4
- package/dist/{chunk-K6BSR66V.js → chunk-4NSRCOYP.js} +4 -1
- package/dist/{chunk-JGRC33J2.js → chunk-54X7T7DK.js} +12 -3
- package/dist/{chunk-YQWYVTMC.js → chunk-5636DCO5.js} +4 -4
- package/dist/{chunk-7E7I3WLS.js → chunk-57XXR6DR.js} +23 -22
- package/dist/{chunk-7ZYNNDKC.js → chunk-5TUB6SLS.js} +2 -2
- package/dist/{chunk-VW6DOEDG.js → chunk-6OSVSQL5.js} +11 -2
- package/dist/{chunk-L47TF46W.js → chunk-6PAZTBPA.js} +14 -2
- package/dist/{chunk-XIVNBFZS.js → chunk-6Q3CYFD3.js} +34 -16
- package/dist/{chunk-RSJ25QSL.js → chunk-6QOTUPRG.js} +155 -36
- package/dist/{chunk-JKKCYP3C.js → chunk-6UINWWS6.js} +10 -4
- package/dist/{chunk-WBKFA554.js → chunk-72YIHOZQ.js} +2 -2
- package/dist/{chunk-PAJQJ7BS.js → chunk-75W7L2E2.js} +246 -697
- package/dist/{chunk-RRNP2ANY.js → chunk-7UGL4MB5.js} +4 -4
- package/dist/{chunk-EKCHAPYA.js → chunk-AUPNRN7C.js} +2 -2
- package/dist/{chunk-ZDN3Y73Y.js → chunk-BJVFZO5U.js} +6 -48
- package/dist/{chunk-IWT4SF4R.js → chunk-CUSRQKPU.js} +64 -2
- package/dist/{chunk-SKHCAU7K.js → chunk-DQOVN6KV.js} +3 -2
- package/dist/{chunk-ZWPRK62N.js → chunk-DT3LWJOB.js} +4 -4
- package/dist/chunk-DXKJURES.js +671 -0
- package/dist/{chunk-BEPZRGGU.js → chunk-EL24TAU4.js} +2 -2
- package/dist/{chunk-OML5D5V5.js → chunk-ELWDPP3Y.js} +5 -5
- package/dist/{chunk-NDINPTJ4.js → chunk-ELZVTCGV.js} +5 -4
- package/dist/chunk-EXLD33WO.js +381 -0
- package/dist/{chunk-IJNZMHLA.js → chunk-FEAXX7B6.js} +2 -2
- package/dist/{chunk-TM6LQDI3.js → chunk-FFUPXJC4.js} +74 -323
- package/dist/chunk-GX5WYQO4.js +59 -0
- package/dist/chunk-I2DWJ4GM.js +390 -0
- package/dist/{chunk-TXOTCRLG.js → chunk-I5FWO7L5.js} +5 -5
- package/dist/chunk-IRXAATOX.js +539 -0
- package/dist/chunk-IXIY2H4R.js +44 -0
- package/dist/{chunk-KK4JZPBQ.js → chunk-IZXGRF7P.js} +76 -10
- package/dist/{chunk-5TSRNF4G.js → chunk-JCI2ROMZ.js} +164 -6
- package/dist/{chunk-INY6HTFL.js → chunk-JEIYHLOR.js} +2 -2
- package/dist/{chunk-MUW2BDDH.js → chunk-JQLNNIKT.js} +2 -2
- package/dist/{chunk-XPWWI35G.js → chunk-JSD46VO2.js} +19 -8
- package/dist/{chunk-VA5FNYMT.js → chunk-JT2RFCC5.js} +39 -2
- package/dist/{chunk-V2ANDPVT.js → chunk-K6T2ZAMZ.js} +168 -6
- package/dist/{chunk-B4OAX3SI.js → chunk-KFV5L5SK.js} +13 -6
- package/dist/{chunk-JEQ3XTHC.js → chunk-LLXSDWXS.js} +2 -2
- package/dist/{chunk-E3TPLWFX.js → chunk-LTIKRKFL.js} +3 -3
- package/dist/{chunk-NIQJ66N4.js → chunk-N56KALIC.js} +17 -17
- package/dist/{chunk-JDAY6FIL.js → chunk-NAI6ZFCY.js} +13 -9
- package/dist/{chunk-AF4YM7Z4.js → chunk-NRO2BJRH.js} +2490 -2182
- package/dist/{chunk-WRBAGUNF.js → chunk-NXIMQY5W.js} +2 -2
- package/dist/{chunk-I7ZPNEJM.js → chunk-NXYCB2VD.js} +5 -5
- package/dist/chunk-ODGTEFFI.js +50 -0
- package/dist/{chunk-2VIKGWFZ.js → chunk-OEJSLEPW.js} +2 -2
- package/dist/{chunk-KKOJXO6R.js → chunk-OMQNJVKW.js} +4 -2
- package/dist/{chunk-54CBCGIR.js → chunk-Q4WO54TA.js} +132 -77
- package/dist/{chunk-B4VEBZKF.js → chunk-QUFRYSWI.js} +12 -6
- package/dist/{chunk-42FMPA75.js → chunk-QZWQA4DE.js} +2 -2
- package/dist/{chunk-HEQY7ZFI.js → chunk-RAY4OVGZ.js} +2 -2
- package/dist/{chunk-G76U63X4.js → chunk-RQCKCSRL.js} +7 -7
- package/dist/{chunk-64I3JVYM.js → chunk-RXTN6AKH.js} +2 -2
- package/dist/{chunk-UPZU6GE4.js → chunk-RZDWV63N.js} +3 -3
- package/dist/{chunk-2UH2KFUP.js → chunk-S6PYF2XF.js} +2 -2
- package/dist/{chunk-JSC3U7TI.js → chunk-TOIVGRUX.js} +2 -2
- package/dist/{chunk-7DRAWPTZ.js → chunk-TQAHXW6Y.js} +1 -1
- package/dist/{chunk-JIEGK6UF.js → chunk-U6TMQNSI.js} +48 -4
- package/dist/{chunk-AX2THNSA.js → chunk-UEPWCCTY.js} +4 -4
- package/dist/{chunk-QWGDJJYJ.js → chunk-USR47QNF.js} +4 -4
- package/dist/{chunk-Y3CBHOR6.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-2UG5F4C5.js → chunk-XULDXHTN.js} +24 -12
- package/dist/chunk-XXYSBZIQ.js +283 -0
- package/dist/{chunk-MWUZBSAQ.js → chunk-Y55JBDO5.js} +331 -51
- package/dist/{chunk-W6RRQCPQ.js → chunk-YD5GIKET.js} +4 -4
- package/dist/{chunk-CE5AX47J.js → chunk-YECAMM3D.js} +2 -2
- package/dist/{chunk-WCXUNS7U.js → chunk-YNFKXPEC.js} +6 -6
- package/dist/cli/index.js +36 -35
- package/dist/{clio-CMMK4KRR.js → clio-QLICPCF5.js} +2 -2
- package/dist/{code-nav-MDZNQS33.js → code-nav-IJR2DBPR.js} +6 -6
- package/dist/{components-UCUQ4QXW.js → components-2TGAI2RC.js} +3 -4
- package/dist/{config-SVM5P5YI.js → config-IUA6OYNS.js} +52 -47
- package/dist/{configure-LE3IK2TJ.js → configure-VEPX4NMX.js} +14 -15
- package/dist/{context-VNCR7KAG.js → context-2DKHWH2T.js} +23 -23
- package/dist/{context-2OHRKS42.js → context-4MPR7WKB.js} +48 -42
- package/dist/{context-E3VC7RX5.js → context-BOYF5EJM.js} +11 -11
- package/dist/{context-clear-BW4O37TG.js → context-clear-S4ZJCQUX.js} +48 -42
- package/dist/{context-working-set-VDS25HXZ.js → context-working-set-3I3FYX6Y.js} +8 -8
- package/dist/detail-A7JAVSIG.js +98 -0
- package/dist/{dispatch-runner-5AHT53RF.js → dispatch-runner-RJ5I2F2O.js} +71 -58
- package/dist/{docs-PD3EXDKU.js → docs-SPOV3BAN.js} +3 -5
- package/dist/{doctor-WNNVO6FY.js → doctor-DKICC2SN.js} +54 -31
- package/dist/{eval-7G7SGAYO.js → eval-OQOQUDHK.js} +47 -56
- package/dist/{evidence-VD6736FQ.js → evidence-4DQ25GUQ.js} +53 -150
- package/dist/evidence-4F5USFKH.js +208 -0
- package/dist/{evolve-AL3NGVRL.js → evolve-GSS52E5J.js} +44 -41
- package/dist/{extensions-MOVJ32NM.js → extensions-G7MFLYHT.js} +4 -5
- package/dist/{fleet-QZHUMAGI.js → fleet-Q37YHHAQ.js} +74 -68
- package/dist/{fleet-commands-BAYT5FJZ.js → fleet-commands-G7E4N7SM.js} +14 -11
- package/dist/{fleet-decisions-IREVMRU4.js → fleet-decisions-O7M6QBA2.js} +6 -6
- package/dist/{fleet-graph-YCTT3HTI.js → fleet-graph-TOUBW6OW.js} +13 -13
- package/dist/{fleet-inspect-QVJTDAVB.js → fleet-inspect-SW33JJNI.js} +43 -39
- package/dist/{fleet-preflight-25QAFPK4.js → fleet-preflight-CV2655TW.js} +2 -3
- package/dist/{fleet-validate-5O57AAJ7.js → fleet-validate-KESZX2YH.js} +16 -16
- package/dist/{fleet-verify-CPH2W2T6.js → fleet-verify-UQPMTVE3.js} +42 -38
- package/dist/{fleet-view-SWBR3VGQ.js → fleet-view-MN2VG4MR.js} +43 -39
- package/dist/{init-J477LKZH.js → init-PXEXQSBF.js} +60 -54
- package/dist/{interop-3FCM6XLG.js → interop-ZG5T62U3.js} +6 -7
- package/dist/inventory-C26CFDRR.js +101 -0
- package/dist/{library-QUQEIUG6.js → library-B2W4N74O.js} +16 -17
- package/dist/{memory-SGGSEP65.js → memory-YCANYS5A.js} +45 -42
- package/dist/{models-HEKUAXXK.js → models-GERTU3YI.js} +20 -22
- package/dist/{monitor-HKU57TYQ.js → monitor-CPNIUULB.js} +50 -44
- package/dist/{orchestrator-VDFAEFAI.js → orchestrator-J4BSH4WQ.js} +491 -1182
- package/dist/{panes-DN2SSFOH.js → panes-BOHAEGYC.js} +3 -3
- package/dist/{panes-TALGNPZT.js → panes-NXSLDQZ2.js} +5 -6
- package/dist/{paths-NBMFAIEZ.js → paths-VSUWNC22.js} +3 -4
- package/dist/{reset-EAJFFJVB.js → reset-TNWTB5LU.js} +5 -6
- package/dist/{resources-OVKSEFVE.js → resources-4PXNMD5G.js} +14 -14
- package/dist/{run-7DP7ZF2J.js → run-D6XJ34CN.js} +79 -83
- package/dist/{share-WML67FT3.js → share-2NWMJJEE.js} +14 -15
- package/dist/{skills-SG662R2K.js → skills-KR7WON5G.js} +18 -19
- package/dist/{skills-eval-VVZEUU46.js → skills-eval-O2ZNOLDS.js} +49 -46
- package/dist/{skills-inventory-I2E23GET.js → skills-inventory-ZZOUBK7O.js} +14 -14
- package/dist/{slash-commands-S7MBJDQK.js → slash-commands-ZXPJD64J.js} +32 -23
- package/dist/{steer-2LQOMCPB.js → steer-XA25PSCS.js} +3 -3
- package/dist/{support-CC2UJBJ6.js → support-7EMVWYG2.js} +2 -2
- package/dist/{targets-4QC3HIEW.js → targets-OMH2XCSN.js} +25 -27
- package/dist/tasks-IPAGMEIX.js +36 -0
- package/dist/{terminal-lease-TUHIJ6Y2.js → terminal-lease-C2J3JYRE.js} +4 -4
- package/dist/{tools-TFGJICCU.js → tools-EFFEAIDP.js} +5 -6
- package/dist/{uninstall-5PEVOE5B.js → uninstall-HALS6BLF.js} +7 -8
- package/dist/{upgrade-M4WXY6KN.js → upgrade-MS72RJEP.js} +14 -11
- package/dist/{usage-N7ZNVLEM.js → usage-NHG6MCJM.js} +60 -51
- package/dist/{verifiers-DJTP4XX6.js → verifiers-7AUNVXDY.js} +150 -17
- package/dist/{verify-RWE4PPEK.js → verify-FWYGPKMR.js} +12 -10
- package/dist/{web-fetch-MPARV2K7.js → web-fetch-V4FKSDAV.js} +4 -4
- package/dist/{wiki-generate-C7IQOXSP.js → wiki-generate-743CIGJW.js} +63 -56
- package/dist/{with-panes-4GCGSL7J.js → with-panes-BDQEWBRT.js} +2 -2
- package/dist/worker/entry.js +36 -33
- package/docs/README.md +3 -2
- package/docs/architecture/acp.md +17 -0
- package/docs/architecture/artifact-versions.md +1 -1
- package/docs/architecture/dispatch-typed-intent.md +1 -1
- package/docs/architecture/evidence-and-memory.md +1 -1
- package/docs/architecture/observability.md +7 -1
- package/docs/architecture/prompt-envelope-and-tools.md +15 -5
- package/docs/architecture/safety-model.md +10 -17
- package/docs/architecture/tui-design.md +1 -1
- package/docs/guide/built-in-agents.md +8 -8
- package/docs/guide/commands-and-modes.md +17 -2
- package/docs/guide/configuration-and-targets.md +3 -1
- package/docs/guide/configuration-reference.md +10 -5
- package/docs/guide/environment-variables.md +2 -2
- package/docs/guide/tool-usage.md +78 -3
- package/docs/history/config-knobs-audit.md +2 -2
- package/docs/process/development-pipeline.md +6 -1
- 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/package.json +1 -1
- package/skills/coding/coding-standards/SKILL.md +14 -4
- package/skills/context/context-handoff/SKILL.md +3 -3
- package/skills/context/context-prime/SKILL.md +3 -3
- package/skills/planning/architecture/SKILL.md +5 -5
- package/skills/planning/backlog/SKILL.md +4 -4
- package/skills/planning/prd/SKILL.md +4 -3
- package/skills/planning/product-intent/SKILL.md +8 -8
- package/skills/planning/tech-spec/SKILL.md +4 -4
- package/skills/registry.yaml +32 -32
- package/skills/research/arxiv-literature/SKILL.md +3 -3
- package/skills/research/experiment-protocol/SKILL.md +3 -3
- package/skills/research/scientific-debugging/SKILL.md +3 -2
- package/skills/research/scientific-modernization/SKILL.md +3 -3
- package/skills/skill-marketplace.json +16 -16
- package/skills/workflow/cut-it/SKILL.md +3 -4
- package/skills/workflow/design-council/SKILL.md +5 -10
- package/skills/workflow/grill-me/SKILL.md +14 -15
- package/skills/workflow/workflow-distiller/SKILL.md +4 -4
- package/src/cli/args.ts +0 -8
- package/src/cli/configure.ts +2 -1
- 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 +2 -0
- package/src/cli/run.ts +0 -2
- package/src/cli/targets.ts +1 -1
- package/src/cli/tasks.ts +84 -0
- package/src/cli/upgrade.ts +10 -5
- package/src/cli/usage.ts +6 -0
- 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/git-commit-attribution.ts +46 -3
- package/src/core/run-overrides.ts +0 -5
- package/src/core/skill-activation.ts +3 -0
- 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/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/prompts.ts +43 -0
- package/src/domains/dispatch/active-route-planner.ts +4 -0
- package/src/domains/dispatch/code-step.ts +11 -4
- package/src/domains/dispatch/contract.ts +31 -7
- package/src/domains/dispatch/execution-scheduler.ts +2 -0
- package/src/domains/dispatch/extension.ts +50 -27
- 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 +17 -2
- package/src/domains/eval/runners/clio-run.ts +12 -9
- 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/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/middleware/marketplace-offer.ts +20 -1
- package/src/domains/middleware/runtime.ts +7 -3
- package/src/domains/mux/detect.ts +3 -6
- package/src/domains/observability/accountability.ts +15 -1
- package/src/domains/observability/contract.ts +52 -7
- package/src/domains/observability/evidence-index.ts +10 -0
- package/src/domains/observability/extension.ts +9 -5
- 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/model-discovery.ts +1 -4
- package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +16 -14
- package/src/domains/providers/runtimes/claude/claude-code.ts +9 -0
- package/src/domains/providers/support.ts +1 -1
- package/src/domains/providers/types/runtime-descriptor.ts +1 -1
- package/src/domains/safety/action-classifier.ts +7 -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 +20 -1
- package/src/domains/safety/policy-engine.ts +26 -6
- package/src/domains/safety/rigor.ts +53 -39
- package/src/domains/safety/validation-contract.ts +388 -0
- package/src/domains/session/archive-readers.ts +10 -1
- package/src/domains/session/decision-board.ts +101 -2
- package/src/domains/session/entries.ts +44 -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/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/apis/ollama-native.ts +15 -0
- package/src/engine/claude/subprocess-runtime.ts +107 -60
- package/src/engine/external-subprocess.ts +12 -4
- package/src/entry/orchestrator.ts +11 -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 +2 -1
- 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/slash-autocomplete.ts +4 -6
- package/src/interactive/slash-commands.ts +25 -39
- package/src/interactive/slash-spec.ts +28 -0
- package/src/interactive/view/artifacts.ts +2 -0
- package/src/interactive/worker-stream.ts +7 -3
- 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/core-bootstrap.ts +16 -0
- package/src/tools/decide.ts +136 -0
- package/src/tools/dispatch-admission.ts +21 -0
- package/src/tools/dispatch-plan.ts +5 -2
- package/src/tools/dispatch-runner.ts +15 -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 +1 -1
- 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/dist/chunk-7DICMOS6.js +0 -313
- package/dist/chunk-RVG5JXAL.js +0 -41
- package/dist/chunk-T56WDKA5.js +0 -183
- package/dist/chunk-VPKWYKEY.js +0 -169
package/src/cli/verifiers.ts
CHANGED
|
@@ -6,8 +6,15 @@ import {
|
|
|
6
6
|
runVerifierAuthoringWorkflow,
|
|
7
7
|
type VerifierRevision,
|
|
8
8
|
} from "../tools/verify/authoring.js";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
DECLARED_CHECK_KINDS,
|
|
11
|
+
type DeclaredCheckKind,
|
|
12
|
+
loadProjectVerifierCatalog,
|
|
13
|
+
PROJECT_VERIFIER_CATALOG_RELATIVE_PATH,
|
|
14
|
+
} from "../tools/verify/catalog.js";
|
|
10
15
|
import { verifyTool } from "../tools/verify/index.js";
|
|
16
|
+
import { normalizeNumericTolerance } from "../tools/verify/numeric.js";
|
|
17
|
+
import { recordPerfBaseline } from "../tools/verify/scripts.js";
|
|
11
18
|
import { printError, printOk } from "./argv.js";
|
|
12
19
|
import { runVerifiersInspect } from "./verifiers-inspect.js";
|
|
13
20
|
|
|
@@ -23,11 +30,22 @@ Usage:
|
|
|
23
30
|
clio-coder verifiers edit <id> [--description <text>] [--command <json-argv>] [fields] [--yes]
|
|
24
31
|
clio-coder verifiers rename <old> <new> [--yes]
|
|
25
32
|
clio-coder verifiers remove <id> [--yes]
|
|
33
|
+
clio-coder verifiers baseline <id>
|
|
26
34
|
|
|
27
35
|
Fields:
|
|
28
36
|
--cwd <path> repository-relative working directory (default .)
|
|
29
37
|
--timeout-ms <number> bounded timeout in milliseconds (default 120000)
|
|
30
38
|
--tags <a,b> comma-separated catalog tags
|
|
39
|
+
--kind <kind> command (default), numeric-compare, or perf-budget
|
|
40
|
+
--reference <path> numeric-compare: repository-relative reference JSON of string -> number | number[]
|
|
41
|
+
--tolerance <json> numeric-compare: {"relative"?,"absolute"?,"ulp"?}, at least one;
|
|
42
|
+
perf-budget with --baseline: {"relative"} headroom over the baseline
|
|
43
|
+
--budget-ms <number> perf-budget: wall-time bound in milliseconds
|
|
44
|
+
--budget-relative <r> perf-budget with --budget-ms: fractional headroom over the bound
|
|
45
|
+
--baseline <path> perf-budget: repository-relative baseline JSON written by 'verifiers baseline <id>'
|
|
46
|
+
|
|
47
|
+
baseline runs a perf-budget check once and records its wall time at the check's
|
|
48
|
+
baseline path; a failing or timed-out command records nothing.
|
|
31
49
|
|
|
32
50
|
Discovery and every preview are read-only. Mutating commands write only with
|
|
33
51
|
--yes after printing the exact argv, cwd, timeout, tags, source provenance, and
|
|
@@ -48,6 +66,12 @@ const VALUE_OPTIONS = new Set([
|
|
|
48
66
|
"--exclude",
|
|
49
67
|
"--rename",
|
|
50
68
|
"--dry-run",
|
|
69
|
+
"--kind",
|
|
70
|
+
"--reference",
|
|
71
|
+
"--tolerance",
|
|
72
|
+
"--budget-ms",
|
|
73
|
+
"--budget-relative",
|
|
74
|
+
"--baseline",
|
|
51
75
|
]);
|
|
52
76
|
|
|
53
77
|
interface ParsedAuthoringArgs {
|
|
@@ -124,6 +148,93 @@ function tags(value: string | undefined): string[] {
|
|
|
124
148
|
.filter((tag) => tag.length > 0);
|
|
125
149
|
}
|
|
126
150
|
|
|
151
|
+
type KindFields = Pick<Extract<VerifierRevision, { kind: "add" }>["check"], "kind" | "numeric" | "perf">;
|
|
152
|
+
|
|
153
|
+
function parseJsonObject(value: string, option: string): Record<string, unknown> | Error {
|
|
154
|
+
try {
|
|
155
|
+
const parsed = JSON.parse(value) as unknown;
|
|
156
|
+
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
157
|
+
return new Error(`${option} must be a JSON object`);
|
|
158
|
+
}
|
|
159
|
+
return parsed as Record<string, unknown>;
|
|
160
|
+
} catch (error) {
|
|
161
|
+
return new Error(`${option} must be valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* The kind and its parameters from the option set. Returns `{}` when no kind
|
|
167
|
+
* option was given so a plain command check keeps the version-1 shape, and an
|
|
168
|
+
* Error when the options disagree with the kind the way the catalog parser
|
|
169
|
+
* would refuse them, so the operator reads one message here instead of a
|
|
170
|
+
* rejected preview.
|
|
171
|
+
*/
|
|
172
|
+
function kindFieldsFromArgs(parsed: ParsedAuthoringArgs): KindFields | Error {
|
|
173
|
+
const kindValue = oneValue(parsed, "--kind") ?? "command";
|
|
174
|
+
if (!(DECLARED_CHECK_KINDS as ReadonlyArray<string>).includes(kindValue)) {
|
|
175
|
+
return new Error(`--kind must be one of ${DECLARED_CHECK_KINDS.join(", ")}`);
|
|
176
|
+
}
|
|
177
|
+
const kind = kindValue as DeclaredCheckKind;
|
|
178
|
+
const reference = oneValue(parsed, "--reference");
|
|
179
|
+
const toleranceValue = oneValue(parsed, "--tolerance");
|
|
180
|
+
const budgetMs = oneValue(parsed, "--budget-ms");
|
|
181
|
+
const budgetRelative = oneValue(parsed, "--budget-relative");
|
|
182
|
+
const baseline = oneValue(parsed, "--baseline");
|
|
183
|
+
if (kind === "command") {
|
|
184
|
+
const stray = [
|
|
185
|
+
["--reference", reference],
|
|
186
|
+
["--tolerance", toleranceValue],
|
|
187
|
+
["--budget-ms", budgetMs],
|
|
188
|
+
["--budget-relative", budgetRelative],
|
|
189
|
+
["--baseline", baseline],
|
|
190
|
+
].filter(([, value]) => value !== undefined);
|
|
191
|
+
if (stray.length > 0)
|
|
192
|
+
return new Error(`${stray.map(([name]) => name).join(", ")} require --kind numeric-compare or perf-budget`);
|
|
193
|
+
return {};
|
|
194
|
+
}
|
|
195
|
+
if (kind === "numeric-compare") {
|
|
196
|
+
if (budgetMs !== undefined || budgetRelative !== undefined || baseline !== undefined) {
|
|
197
|
+
return new Error("--budget-ms, --budget-relative, and --baseline belong to --kind perf-budget");
|
|
198
|
+
}
|
|
199
|
+
if (reference === undefined) return new Error("--reference is required for --kind numeric-compare");
|
|
200
|
+
if (toleranceValue === undefined) return new Error("--tolerance is required for --kind numeric-compare");
|
|
201
|
+
const toleranceJson = parseJsonObject(toleranceValue, "--tolerance");
|
|
202
|
+
if (toleranceJson instanceof Error) return toleranceJson;
|
|
203
|
+
const tolerance = normalizeNumericTolerance(toleranceJson);
|
|
204
|
+
if (tolerance instanceof Error) return new Error(`--tolerance ${tolerance.message}`);
|
|
205
|
+
return { kind, numeric: { reference, tolerance } };
|
|
206
|
+
}
|
|
207
|
+
if (reference !== undefined) return new Error("--reference belongs to --kind numeric-compare");
|
|
208
|
+
if ((budgetMs === undefined) === (baseline === undefined)) {
|
|
209
|
+
return new Error("--kind perf-budget requires exactly one of --budget-ms or --baseline");
|
|
210
|
+
}
|
|
211
|
+
if (budgetMs !== undefined) {
|
|
212
|
+
if (toleranceValue !== undefined) return new Error("use --budget-relative for headroom over --budget-ms");
|
|
213
|
+
const wallTimeMs = Number(budgetMs);
|
|
214
|
+
if (!Number.isFinite(wallTimeMs) || wallTimeMs <= 0) return new Error("--budget-ms must be a positive number");
|
|
215
|
+
const budget: NonNullable<KindFields["perf"]>["budget"] = { wallTimeMs };
|
|
216
|
+
if (budgetRelative !== undefined) {
|
|
217
|
+
const relative = Number(budgetRelative);
|
|
218
|
+
if (!Number.isFinite(relative) || relative < 0) return new Error("--budget-relative must be a non-negative number");
|
|
219
|
+
budget.tolerance = { relative };
|
|
220
|
+
}
|
|
221
|
+
return { kind, perf: { budget } };
|
|
222
|
+
}
|
|
223
|
+
if (budgetRelative !== undefined)
|
|
224
|
+
return new Error("--budget-relative belongs with --budget-ms; use --tolerance with --baseline");
|
|
225
|
+
const perf: NonNullable<KindFields["perf"]> = { baseline: baseline as string };
|
|
226
|
+
if (toleranceValue !== undefined) {
|
|
227
|
+
const toleranceJson = parseJsonObject(toleranceValue, "--tolerance");
|
|
228
|
+
if (toleranceJson instanceof Error) return toleranceJson;
|
|
229
|
+
const relative = toleranceJson.relative;
|
|
230
|
+
if (typeof relative !== "number" || !Number.isFinite(relative) || relative < 0) {
|
|
231
|
+
return new Error('--tolerance for a baseline must be {"relative": <non-negative number>}');
|
|
232
|
+
}
|
|
233
|
+
perf.tolerance = { relative };
|
|
234
|
+
}
|
|
235
|
+
return { kind, perf };
|
|
236
|
+
}
|
|
237
|
+
|
|
127
238
|
function requiredValue(parsed: ParsedAuthoringArgs, option: string): string | Error {
|
|
128
239
|
const value = oneValue(parsed, option);
|
|
129
240
|
return value === undefined || value.length === 0 ? new Error(`${option} is required`) : value;
|
|
@@ -151,6 +262,8 @@ function addRevision(parsed: ParsedAuthoringArgs): VerifierRevision | Error {
|
|
|
151
262
|
if (command instanceof Error) return command;
|
|
152
263
|
const timeoutMs = parseTimeout(oneValue(parsed, "--timeout-ms"));
|
|
153
264
|
if (timeoutMs instanceof Error) return timeoutMs;
|
|
265
|
+
const kindFields = kindFieldsFromArgs(parsed);
|
|
266
|
+
if (kindFields instanceof Error) return kindFields;
|
|
154
267
|
return {
|
|
155
268
|
kind: "add",
|
|
156
269
|
check: {
|
|
@@ -160,6 +273,7 @@ function addRevision(parsed: ParsedAuthoringArgs): VerifierRevision | Error {
|
|
|
160
273
|
cwd: oneValue(parsed, "--cwd") ?? ".",
|
|
161
274
|
timeoutMs,
|
|
162
275
|
tags: tags(oneValue(parsed, "--tags")),
|
|
276
|
+
...kindFields,
|
|
163
277
|
},
|
|
164
278
|
};
|
|
165
279
|
}
|
|
@@ -186,6 +300,13 @@ function editRevision(parsed: ParsedAuthoringArgs): VerifierRevision | Error {
|
|
|
186
300
|
}
|
|
187
301
|
const tagValue = oneValue(parsed, "--tags");
|
|
188
302
|
if (tagValue !== undefined) changes.tags = tags(tagValue);
|
|
303
|
+
if (oneValue(parsed, "--kind") !== undefined) {
|
|
304
|
+
const kindFields = kindFieldsFromArgs(parsed);
|
|
305
|
+
if (kindFields instanceof Error) return kindFields;
|
|
306
|
+
changes.kind = kindFields.kind ?? "command";
|
|
307
|
+
if (kindFields.numeric !== undefined) changes.numeric = kindFields.numeric;
|
|
308
|
+
if (kindFields.perf !== undefined) changes.perf = kindFields.perf;
|
|
309
|
+
}
|
|
189
310
|
if (Object.keys(changes).length === 0) return new Error("edit requires at least one changed field");
|
|
190
311
|
return { kind: "edit", id, changes };
|
|
191
312
|
}
|
|
@@ -260,6 +381,30 @@ async function executeWorkflow(
|
|
|
260
381
|
return code;
|
|
261
382
|
}
|
|
262
383
|
|
|
384
|
+
async function baselineCommand(id: string | undefined): Promise<number> {
|
|
385
|
+
if (id === undefined) {
|
|
386
|
+
printError("baseline requires a check ID");
|
|
387
|
+
return 2;
|
|
388
|
+
}
|
|
389
|
+
const loaded = loadProjectVerifierCatalog(process.cwd());
|
|
390
|
+
if (!loaded.ok) {
|
|
391
|
+
printError(`production catalog parser rejected ${loaded.reason}`);
|
|
392
|
+
return 1;
|
|
393
|
+
}
|
|
394
|
+
const check = loaded.source?.checks.find((candidate) => candidate.id === id);
|
|
395
|
+
if (check === undefined) {
|
|
396
|
+
printError(`no catalog check '${id}' in ${PROJECT_VERIFIER_CATALOG_RELATIVE_PATH}`);
|
|
397
|
+
return 1;
|
|
398
|
+
}
|
|
399
|
+
const recorded = await recordPerfBaseline(check);
|
|
400
|
+
if (!recorded.ok) {
|
|
401
|
+
printError(`baseline '${id}' not recorded: ${recorded.message}`);
|
|
402
|
+
return 1;
|
|
403
|
+
}
|
|
404
|
+
printOk(`recorded baseline for '${id}': ${Math.round(recorded.wallTimeMs)}ms at ${recorded.path}`);
|
|
405
|
+
return 0;
|
|
406
|
+
}
|
|
407
|
+
|
|
263
408
|
async function discoverCommand(): Promise<number> {
|
|
264
409
|
const discovery = discoverVerifierAuthoring();
|
|
265
410
|
if (!discovery.ok) {
|
|
@@ -304,6 +449,7 @@ export async function runVerifiersCommand(argv: string[]): Promise<number> {
|
|
|
304
449
|
const command = parsed.positional[0];
|
|
305
450
|
if (command === "discover") return discoverCommand();
|
|
306
451
|
if (command === "validate") return validateCommand();
|
|
452
|
+
if (command === "baseline") return baselineCommand(parsed.positional[1]);
|
|
307
453
|
if (command === "dry-run") {
|
|
308
454
|
const id = parsed.positional[1];
|
|
309
455
|
if (id === undefined) {
|
package/src/cli/wiki-generate.ts
CHANGED
|
@@ -15,6 +15,21 @@ export const CLIO_COMMIT_TRAILERS = {
|
|
|
15
15
|
coAuthored: `Co-authored-by: ${CLIO_COMMIT_IDENTITY}`,
|
|
16
16
|
} as const;
|
|
17
17
|
|
|
18
|
+
export const CLIO_DECISION_TRAILER_KEY = "Clio-Decision";
|
|
19
|
+
|
|
20
|
+
/** Most `Clio-Decision:` trailers one commit carries; matches the receipt cap. */
|
|
21
|
+
export const CLIO_DECISION_TRAILER_CAP = 32;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A decision ref is `<interviewId>/<key>`: an `ask_user` interview id or an
|
|
25
|
+
* `agent:<uuid>` decision-set id, then the decision key. Operator keys are
|
|
26
|
+
* snake_case and agent keys are kebab-case, the same shape `isDecisionRecord`
|
|
27
|
+
* admits. Only refs of this shape become trailers, so a malformed value can
|
|
28
|
+
* never inject a second trailer line or a stray control character into a
|
|
29
|
+
* commit message.
|
|
30
|
+
*/
|
|
31
|
+
export const DECISION_REF_PATTERN = /^[A-Za-z0-9][A-Za-z0-9:._-]{0,127}\/[a-z0-9]+(?:[_-][a-z0-9]+)*$/u;
|
|
32
|
+
|
|
18
33
|
export interface CommitReceiptEvidence {
|
|
19
34
|
version: 20;
|
|
20
35
|
algorithm: "sha256";
|
|
@@ -37,6 +52,12 @@ export interface CommitAttributionEvidence {
|
|
|
37
52
|
materiallyAuthored?: boolean;
|
|
38
53
|
/** Optional sealed receipt for a directly relevant fact above. */
|
|
39
54
|
receipt?: CommitReceiptEvidence;
|
|
55
|
+
/**
|
|
56
|
+
* Decision refs (`<interviewId>/<key>`) the committed work was done under,
|
|
57
|
+
* read from the session decision board or a sealed receipt's
|
|
58
|
+
* `decisionRefs`. Each becomes one `Clio-Decision:` trailer.
|
|
59
|
+
*/
|
|
60
|
+
decisions?: ReadonlyArray<string>;
|
|
40
61
|
}
|
|
41
62
|
|
|
42
63
|
const TRAILER_LINE = /^([A-Za-z0-9][A-Za-z0-9-]*):[ \t]+(.+)$/u;
|
|
@@ -58,7 +79,25 @@ const KNOWN_CLIO_TRAILERS = new Set(
|
|
|
58
79
|
);
|
|
59
80
|
|
|
60
81
|
function isClioTrailer(key: string): boolean {
|
|
61
|
-
return
|
|
82
|
+
return (
|
|
83
|
+
KNOWN_CLIO_TRAILERS.has(key) ||
|
|
84
|
+
key.startsWith("clio-evidence:receipt-v20/sha256:") ||
|
|
85
|
+
key.startsWith(`${CLIO_DECISION_TRAILER_KEY.toLowerCase()}:`)
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Well-formed decision refs from the evidence, deduplicated, sorted, and capped. */
|
|
90
|
+
export function decisionTrailerRefs(decisions: ReadonlyArray<string> | undefined): string[] {
|
|
91
|
+
if (decisions === undefined) return [];
|
|
92
|
+
const refs = new Set<string>();
|
|
93
|
+
for (const ref of decisions) {
|
|
94
|
+
if (typeof ref === "string" && DECISION_REF_PATTERN.test(ref)) refs.add(ref);
|
|
95
|
+
}
|
|
96
|
+
return [...refs].sort().slice(0, CLIO_DECISION_TRAILER_CAP);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function decisionTrailer(ref: string): string {
|
|
100
|
+
return `${CLIO_DECISION_TRAILER_KEY}: ${ref}`;
|
|
62
101
|
}
|
|
63
102
|
|
|
64
103
|
/**
|
|
@@ -138,6 +177,7 @@ export function attributeCommitMessage(
|
|
|
138
177
|
if (evidence.materiallyAuthored === true) desired.push(CLIO_COMMIT_TRAILERS.coAuthored);
|
|
139
178
|
const receipt = receiptTrailer(evidence.receipt);
|
|
140
179
|
if (receipt !== null) desired.push(receipt);
|
|
180
|
+
for (const ref of decisionTrailerRefs(evidence.decisions)) desired.push(decisionTrailer(ref));
|
|
141
181
|
|
|
142
182
|
const existing = new Set(
|
|
143
183
|
(blockStart === null ? [] : retained.slice(blockStart))
|
|
@@ -12,17 +12,24 @@ import {
|
|
|
12
12
|
} from "node:fs";
|
|
13
13
|
import { join, resolve } from "node:path";
|
|
14
14
|
import { AI_AGENT_NAME } from "./agent-environment.js";
|
|
15
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
CLIO_COMMIT_TRAILERS,
|
|
17
|
+
CLIO_DECISION_TRAILER_KEY,
|
|
18
|
+
type CommitAttributionEvidence,
|
|
19
|
+
decisionTrailerRefs,
|
|
20
|
+
} from "./commit-attribution.js";
|
|
16
21
|
import { clioStateDir } from "./xdg.js";
|
|
17
22
|
|
|
18
23
|
/** Effective `attribution.gitCommits` for child-process seams. Internal state, not an operator override. */
|
|
19
24
|
export const CLIO_GIT_COMMITS_ENABLED_ENV = "CLIO_CODER_GIT_COMMITS_ENABLED";
|
|
20
25
|
const ASSISTED_ENV = "CLIO_CODER_COMMIT_ASSISTED";
|
|
21
26
|
const AUTHORED_ENV = "CLIO_CODER_COMMIT_AUTHORED";
|
|
27
|
+
/** Space-separated decision refs the spawn was made under; each becomes one `Clio-Decision:` trailer. */
|
|
28
|
+
const DECISIONS_ENV = "CLIO_CODER_COMMIT_DECISIONS";
|
|
22
29
|
/** Present iff this environment carries Clio's command-scope core.hooksPath pair; holds the count below it. */
|
|
23
30
|
const CONFIG_BASE_COUNT_ENV = "CLIO_CODER_GIT_CONFIG_BASE_COUNT";
|
|
24
31
|
const DEFAULT_HOOKS_EQUIVALENT_ENV = "CLIO_CODER_GIT_DEFAULT_HOOKS_EQUIVALENT";
|
|
25
|
-
const MANAGED_HOOK_VERSION =
|
|
32
|
+
const MANAGED_HOOK_VERSION = 3;
|
|
26
33
|
const DIAGNOSTIC_MAX_CHARS = 300;
|
|
27
34
|
const COUNT = /^(?:0|[1-9][0-9]*)$/u;
|
|
28
35
|
const reportedDiagnostics = new Set<string>();
|
|
@@ -45,7 +52,33 @@ type RepositoryProbe =
|
|
|
45
52
|
const probeCache = new Map<string, { at: number; probe: RepositoryProbe }>();
|
|
46
53
|
let installedHooksDirectory: string | null = null;
|
|
47
54
|
|
|
48
|
-
const PER_SPAWN_ENV_NAMES = [
|
|
55
|
+
const PER_SPAWN_ENV_NAMES = [
|
|
56
|
+
ASSISTED_ENV,
|
|
57
|
+
AUTHORED_ENV,
|
|
58
|
+
DECISIONS_ENV,
|
|
59
|
+
CONFIG_BASE_COUNT_ENV,
|
|
60
|
+
DEFAULT_HOOKS_EQUIVALENT_ENV,
|
|
61
|
+
] as const;
|
|
62
|
+
|
|
63
|
+
let decisionRefsProvider: (() => ReadonlyArray<string>) | null = null;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Register the live decision board's active refs for the session seam. Each
|
|
67
|
+
* Clio-spawned commit is then stamped with the decisions it was made under,
|
|
68
|
+
* the same way `ASSISTED_ENV` carries assistance. Explicit `evidence.decisions`
|
|
69
|
+
* on a spawn still wins over the provider.
|
|
70
|
+
*/
|
|
71
|
+
export function setCommitDecisionRefsProvider(provider: (() => ReadonlyArray<string>) | null): void {
|
|
72
|
+
decisionRefsProvider = provider;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function providedDecisionRefs(): ReadonlyArray<string> {
|
|
76
|
+
try {
|
|
77
|
+
return decisionRefsProvider?.() ?? [];
|
|
78
|
+
} catch {
|
|
79
|
+
return [];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
49
82
|
|
|
50
83
|
export interface ManagedCommitAttributionOptions {
|
|
51
84
|
cwd?: string;
|
|
@@ -242,6 +275,14 @@ if [ "$${ASSISTED_ENV}" = '1' ] || [ "$${AUTHORED_ENV}" = '1' ]; then
|
|
|
242
275
|
append_trailer '${CLIO_COMMIT_TRAILERS.assisted}'
|
|
243
276
|
fi
|
|
244
277
|
if [ "$${AUTHORED_ENV}" = '1' ]; then append_trailer '${CLIO_COMMIT_TRAILERS.coAuthored}'; fi
|
|
278
|
+
# Decision refs are validated again here: only <id>/<key> shapes become
|
|
279
|
+
# trailers, so a stray value cannot inject a second line into the message.
|
|
280
|
+
for decision_ref in $${DECISIONS_ENV}; do
|
|
281
|
+
case "$decision_ref" in
|
|
282
|
+
*[!A-Za-z0-9:._/-]* | */*/* | /* | */ | *-*-) continue ;;
|
|
283
|
+
*/*) append_trailer "${CLIO_DECISION_TRAILER_KEY}: $decision_ref" ;;
|
|
284
|
+
esac
|
|
285
|
+
done
|
|
245
286
|
exit 0
|
|
246
287
|
`;
|
|
247
288
|
|
|
@@ -344,6 +385,8 @@ export function withManagedGitCommitAttributionEnvironment(
|
|
|
344
385
|
const evidence = options.evidence ?? { materiallyAssisted: true, materiallyAuthored: true };
|
|
345
386
|
env[ASSISTED_ENV] = evidence.materiallyAssisted === true ? "1" : "0";
|
|
346
387
|
env[AUTHORED_ENV] = evidence.materiallyAuthored === true ? "1" : "0";
|
|
388
|
+
const decisions = decisionTrailerRefs(evidence.decisions ?? providedDecisionRefs());
|
|
389
|
+
if (decisions.length > 0) env[DECISIONS_ENV] = decisions.join(" ");
|
|
347
390
|
|
|
348
391
|
const countRaw = env.GIT_CONFIG_COUNT;
|
|
349
392
|
const count = countRaw === undefined ? 0 : COUNT.test(countRaw) ? Number(countRaw) : Number.NaN;
|
|
@@ -18,8 +18,6 @@ export const RUN_OVERRIDES_ENV = "CLIO_CODER_RUN_OVERRIDES";
|
|
|
18
18
|
export interface RunOverrides {
|
|
19
19
|
/** One-run context-window override for supported local runtimes. */
|
|
20
20
|
maxContextTokens?: number;
|
|
21
|
-
/** One-run KV-cache quantization mode; the consuming runtime validates it. */
|
|
22
|
-
kvCacheMode?: string;
|
|
23
21
|
/**
|
|
24
22
|
* One-run sampling parameter overrides. Kept as a loose numeric record
|
|
25
23
|
* here (undefined fields are dropped at serialization);
|
|
@@ -45,9 +43,6 @@ export function runOverrides(env: NodeJS.ProcessEnv = process.env): RunOverrides
|
|
|
45
43
|
if (typeof maxContextTokens === "number" && Number.isInteger(maxContextTokens) && maxContextTokens > 0) {
|
|
46
44
|
out.maxContextTokens = maxContextTokens;
|
|
47
45
|
}
|
|
48
|
-
if (typeof record.kvCacheMode === "string" && record.kvCacheMode.length > 0) {
|
|
49
|
-
out.kvCacheMode = record.kvCacheMode;
|
|
50
|
-
}
|
|
51
46
|
const sampling = record.sampling;
|
|
52
47
|
if (sampling !== null && typeof sampling === "object" && !Array.isArray(sampling)) {
|
|
53
48
|
const numeric: Record<string, number> = {};
|
|
@@ -189,6 +189,9 @@ export function evaluateSkillToolSurface(
|
|
|
189
189
|
.filter(([, declared]) => declared.disallowedTools?.includes(tool) === true)
|
|
190
190
|
.map(([name]) => name);
|
|
191
191
|
if (disallowedBy.length > 0) return { skills, mergedAllowedTools: null, disallowedBy, carriedSurface };
|
|
192
|
+
// A finish receipt records a limitation without performing another action.
|
|
193
|
+
// Keep it available under allow-narrowing, while honoring explicit denials.
|
|
194
|
+
if (tool === "limitation") return null;
|
|
192
195
|
const allowLists = entries.map(([, declared]) => declared.allowedTools);
|
|
193
196
|
if (allowLists.some((list) => list === undefined || list.length === 0)) return null;
|
|
194
197
|
const merged = [...new Set(allowLists.flatMap((list) => [...(list ?? [])]))];
|
package/src/core/tool-names.ts
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
*
|
|
5
5
|
* The surface is organized in seven planes; each plane is one policy unit
|
|
6
6
|
* (action class, size posture, details schema, concurrency rule):
|
|
7
|
-
* OBSERVE read, grep, find, ls, code_nav, context, credential_present
|
|
7
|
+
* OBSERVE evidence, read, grep, find, ls, code_nav, context, credential_present
|
|
8
8
|
* MUTATE write, edit
|
|
9
9
|
* EXECUTE bash, git, verify
|
|
10
|
-
* ORCHESTRATE dispatch, monitor, steer, tasks, panes
|
|
10
|
+
* ORCHESTRATE dispatch, monitor, steer, tasks, ledger, panes, limitation, decide
|
|
11
11
|
* RETRIEVE web_fetch
|
|
12
12
|
* INTERACT ask_user
|
|
13
13
|
* ARTIFACT artifact
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
export const ToolNames = {
|
|
17
17
|
// OBSERVE
|
|
18
18
|
Read: "read",
|
|
19
|
+
Evidence: "evidence",
|
|
19
20
|
Grep: "grep",
|
|
20
21
|
Find: "find",
|
|
21
22
|
Ls: "ls",
|
|
@@ -36,6 +37,8 @@ export const ToolNames = {
|
|
|
36
37
|
Tasks: "tasks",
|
|
37
38
|
Ledger: "ledger",
|
|
38
39
|
Panes: "panes",
|
|
40
|
+
Limitation: "limitation",
|
|
41
|
+
Decide: "decide",
|
|
39
42
|
// RETRIEVE
|
|
40
43
|
WebFetch: "web_fetch",
|
|
41
44
|
// INTERACT
|
|
@@ -4,7 +4,7 @@ name: Architect
|
|
|
4
4
|
description: Designs a change across boundaries and slices it into a sprint. Covers contracts, migrations, and validation gates, and turns an existing plan into a dependency-ordered sprint through its bound cut-it skill.
|
|
5
5
|
tools:
|
|
6
6
|
required: [artifact, context]
|
|
7
|
-
optional: [read, grep, find, ls, code_nav, git, ledger]
|
|
7
|
+
optional: [read, grep, find, ls, code_nav, git, ledger, limitation]
|
|
8
8
|
skills: [cut-it]
|
|
9
9
|
audience: base
|
|
10
10
|
category: plan
|
|
@@ -4,7 +4,7 @@ name: Coder
|
|
|
4
4
|
description: Implements bounded code changes, repairs, and refactors. Behavior-preserving by default.
|
|
5
5
|
tools:
|
|
6
6
|
required: [read, {anyOf: [write, edit]}, context]
|
|
7
|
-
optional: [grep, find, ls, web_fetch, git, verify, code_nav, bash, ledger]
|
|
7
|
+
optional: [grep, find, ls, web_fetch, git, verify, code_nav, bash, ledger, limitation]
|
|
8
8
|
skills: [fix-issue, ship]
|
|
9
9
|
audience: base
|
|
10
10
|
category: implement
|
|
@@ -4,7 +4,7 @@ name: Documenter
|
|
|
4
4
|
description: Updates developer docs, examples, and operational runbooks.
|
|
5
5
|
tools:
|
|
6
6
|
required: [read, {anyOf: [write, edit]}]
|
|
7
|
-
optional: [grep, find, ls, git, verify, code_nav, context, ledger]
|
|
7
|
+
optional: [grep, find, ls, git, verify, code_nav, context, ledger, limitation]
|
|
8
8
|
skills: []
|
|
9
9
|
audience: base
|
|
10
10
|
category: implement
|
|
@@ -4,7 +4,7 @@ name: Git Master
|
|
|
4
4
|
description: Runs bounded git operations end to end. Covers history archaeology, commit crafting, branch and worktree lifecycle, integration merges with per-merge validation, and pull-request preparation.
|
|
5
5
|
tools:
|
|
6
6
|
required: [read, {anyOf: [write, edit]}, context, git]
|
|
7
|
-
optional: [bash, grep, find, ls, code_nav, ledger]
|
|
7
|
+
optional: [bash, grep, find, ls, code_nav, ledger, limitation]
|
|
8
8
|
skills: [fix-issue, ship, worktree-create, worktree-merge]
|
|
9
9
|
audience: base
|
|
10
10
|
category: implement
|
|
@@ -3,8 +3,8 @@ version: 1
|
|
|
3
3
|
name: Provenance
|
|
4
4
|
description: Reads receipts, diffs, and telemetry for evidence. Shadow agent for source-backed handoffs.
|
|
5
5
|
tools:
|
|
6
|
-
required: [
|
|
7
|
-
optional: [grep, find, ls, git, ledger]
|
|
6
|
+
required: [evidence]
|
|
7
|
+
optional: [read, grep, find, ls, git, ledger]
|
|
8
8
|
skills: []
|
|
9
9
|
audience: shadow
|
|
10
10
|
category: operations
|
|
@@ -20,11 +20,11 @@ tags: [receipts, evidence, telemetry]
|
|
|
20
20
|
|
|
21
21
|
You are Provenance, a shadow evidence agent for Clio orchestration.
|
|
22
22
|
Start by restating the receipt, run id, diff, telemetry path, or evidence question.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
Start with `evidence(mode="list")` to find bundles, `evidence(mode="inspect", id="...")` for a named bundle, or `evidence(mode="run", runId="...")` for a run.
|
|
24
|
+
Cite the tool's canonical trust tier, all relevant trust axes, gate decisions, and finding ids when answering evidence questions.
|
|
25
|
+
Keep missing or historical trust status explicit. Do not infer success from file existence or turn unverified claims into confirmed facts.
|
|
26
|
+
Connect each confirmed fact to its evidence id, run id, finding id, or gate decision.
|
|
27
|
+
Fall back to raw artifact reads only when the tool reports the artifact absent. Report those reads as unverified leads, and never use raw receipts to override an integrity failure or canonical trust status.
|
|
28
28
|
Do not edit files, run commands, write plans, write reviews, or approve memory.
|
|
29
29
|
Keep the result compact enough for the main agent to synthesize directly.
|
|
30
30
|
Your entire final response is one JSON object and nothing else, with no prose or code fence around it: `{"confirmedFacts":["..."],"missingEvidence":["..."],"nextInspections":["..."]}`.
|
|
@@ -4,7 +4,7 @@ name: Tester
|
|
|
4
4
|
description: Adds focused deterministic regression and coverage tests.
|
|
5
5
|
tools:
|
|
6
6
|
required: [read, {anyOf: [write, edit]}]
|
|
7
|
-
optional: [grep, find, ls, git, verify, code_nav, ledger]
|
|
7
|
+
optional: [grep, find, ls, git, verify, code_nav, ledger, limitation]
|
|
8
8
|
skills: []
|
|
9
9
|
audience: base
|
|
10
10
|
category: quality
|
|
@@ -4,7 +4,7 @@ name: Verifier
|
|
|
4
4
|
description: Runs test, lint, build, review, and release gates. Reports each gate independently.
|
|
5
5
|
tools:
|
|
6
6
|
required: [verify]
|
|
7
|
-
optional: [read, grep, find, ls, git, code_nav, ledger]
|
|
7
|
+
optional: [evidence, read, grep, find, ls, git, code_nav, ledger]
|
|
8
8
|
skills: []
|
|
9
9
|
audience: base
|
|
10
10
|
category: quality
|
|
@@ -26,7 +26,7 @@ Run only the checks required for the requested confidence level.
|
|
|
26
26
|
Prefer typed validation tools over arbitrary shell execution.
|
|
27
27
|
Call `verify()` before choosing an executable check. It lists package scripts and strict project entries from `.clio-coder/verifiers.yaml` through the same metadata shape.
|
|
28
28
|
Run a project entry only by its listed ID. Do not add args, cwd, timeout, environment, or shell composition; the catalog's exact argv, cwd, and timeout are authoritative.
|
|
29
|
-
|
|
29
|
+
A parsed validation contract's `artifacts` and `validators` are requirements to satisfy, and they are executable only through `.clio-coder/verifiers.yaml` entries.
|
|
30
30
|
Do not edit source files, tests, docs, configs, or generated artifacts from this role.
|
|
31
31
|
When a gate fails, report the exact command, exit status, relevant error lines, and likely owner.
|
|
32
32
|
Distinguish pre-existing failures from introduced failures when the evidence allows.
|
|
@@ -4,7 +4,7 @@ name: Wiki Writer
|
|
|
4
4
|
description: Plans a repository wiki or writes one wiki page. Works against a supplied plan.
|
|
5
5
|
tools:
|
|
6
6
|
required: [read, {anyOf: [write, edit]}]
|
|
7
|
-
optional: [grep, find, ls, code_nav, context, ledger]
|
|
7
|
+
optional: [grep, find, ls, code_nav, context, ledger, limitation]
|
|
8
8
|
skills: []
|
|
9
9
|
audience: base
|
|
10
10
|
category: implement
|
|
@@ -37,5 +37,6 @@ over a batch of parallel guesses. Never read `.env` files or other secret-bearin
|
|
|
37
37
|
Write the file as soon as you can ground it, then improve it in place. A written page is worth
|
|
38
38
|
more than a researched one, and your budget is sized for a single subject, not a repository tour.
|
|
39
39
|
|
|
40
|
-
The file you wrote is your result. When it is on disk,
|
|
41
|
-
|
|
40
|
+
The file you wrote is your result. When it is on disk, call `limitation` with the scope and reason
|
|
41
|
+
for anything you could not ground, then stop and say in one line what you wrote. There is no
|
|
42
|
+
report to file and no JSON to emit.
|
|
@@ -2,8 +2,13 @@ import { existsSync } from "node:fs";
|
|
|
2
2
|
import { isAbsolute, join, relative, resolve } from "node:path";
|
|
3
3
|
import { BusChannels, type ContextActivityPayload } from "../../core/bus-events.js";
|
|
4
4
|
import type { DomainBundle, DomainContext, DomainExtension } from "../../core/domain-loader.js";
|
|
5
|
-
import { clioDataDir } from "../../core/xdg.js";
|
|
5
|
+
import { clioDataDir, clioStateDir } from "../../core/xdg.js";
|
|
6
6
|
import { loadMemoryRecordsSync } from "../memory/index.js";
|
|
7
|
+
import { describeValidationContract, loadValidationContract } from "../safety/index.js";
|
|
8
|
+
import { readSessionEntriesForId } from "../session/archive-readers.js";
|
|
9
|
+
import type { SessionContract } from "../session/contract.js";
|
|
10
|
+
import { foldDecisionBoard } from "../session/decision-board.js";
|
|
11
|
+
import { filterEntriesToActivePath } from "../session/tree/active-path.js";
|
|
7
12
|
import { detectProjectType, type ProjectType } from "../session/workspace/project-type.js";
|
|
8
13
|
import { adoptionSourcesChanged } from "./adoption.js";
|
|
9
14
|
import { runBootstrap } from "./bootstrap.js";
|
|
@@ -148,6 +153,12 @@ function collectStartupHints(cwd: string, options: ContextBundleOptions = {}): s
|
|
|
148
153
|
for (const issue of clio.errors) {
|
|
149
154
|
hints.push(`clio-coder: malformed ${issue.path} ignored: ${issue.error}`);
|
|
150
155
|
}
|
|
156
|
+
// An invalid validation contract leaves rigor at normal; say so once here
|
|
157
|
+
// rather than letting the finish gate quietly behave as if no contract existed.
|
|
158
|
+
const contract = loadValidationContract(cwd);
|
|
159
|
+
if (!contract.ok) {
|
|
160
|
+
hints.push(`clio-coder: validation contract ignored, rigor stays normal: ${describeValidationContract(contract)}`);
|
|
161
|
+
}
|
|
151
162
|
const state = readClioState(cwd);
|
|
152
163
|
if (!state) return hints;
|
|
153
164
|
if (state.contextSources !== undefined && adoptionSourcesChanged(state.contextSources, { cwd })) {
|
|
@@ -290,9 +301,11 @@ export function createContextBundle(
|
|
|
290
301
|
input?.onProgress?.(event);
|
|
291
302
|
};
|
|
292
303
|
try {
|
|
293
|
-
const result = await runContextRefresh(
|
|
294
|
-
|
|
295
|
-
|
|
304
|
+
const result = await runContextRefresh({
|
|
305
|
+
...input,
|
|
306
|
+
...(input?.wiki ? { decisions: input.decisions ?? (await currentDecisions(_context)) } : {}),
|
|
307
|
+
onProgress: emitProgress,
|
|
308
|
+
});
|
|
296
309
|
const cwd = input?.cwd ?? process.cwd();
|
|
297
310
|
contextState.invalidate(cwd);
|
|
298
311
|
if (cwd === lastCwd) startupHints = collectStartupHints(cwd, options);
|
|
@@ -313,9 +326,11 @@ export function createContextBundle(
|
|
|
313
326
|
input?.onProgress?.(event);
|
|
314
327
|
};
|
|
315
328
|
try {
|
|
316
|
-
return await runWikiGenerate(
|
|
317
|
-
|
|
318
|
-
|
|
329
|
+
return await runWikiGenerate({
|
|
330
|
+
...(input ?? { model: "configured-clio-target" }),
|
|
331
|
+
decisions: input?.decisions ?? (await currentDecisions(_context)),
|
|
332
|
+
onProgress: emitProgress,
|
|
333
|
+
});
|
|
319
334
|
} catch (err) {
|
|
320
335
|
emitProgress({
|
|
321
336
|
phase: "done",
|
|
@@ -353,3 +368,12 @@ export function createContextBundle(
|
|
|
353
368
|
|
|
354
369
|
return { extension, contract };
|
|
355
370
|
}
|
|
371
|
+
|
|
372
|
+
async function currentDecisions(context: DomainContext) {
|
|
373
|
+
const session = context.getContract<SessionContract>("session");
|
|
374
|
+
const current = session?.current();
|
|
375
|
+
if (!session || !current) return [];
|
|
376
|
+
session.flushAppends?.();
|
|
377
|
+
const read = await readSessionEntriesForId(clioStateDir(), current.id);
|
|
378
|
+
return foldDecisionBoard(filterEntriesToActivePath(read.entries, session.tree(current.id).leafId ?? undefined));
|
|
379
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { writeFileSync } from "node:fs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
|
+
import type { DecisionLedgerEntry } from "../session/entries.js";
|
|
3
4
|
import { detectProjectType } from "../session/workspace/project-type.js";
|
|
4
5
|
import { type BootstrapIo, type BootstrapProgressSink, codewikiSections } from "./bootstrap.js";
|
|
5
6
|
import { serializeClioMd, tryReadClioMd } from "./clio-md.js";
|
|
@@ -18,6 +19,7 @@ import { wikiCompleteness, wikiStaleness } from "./wiki/staleness.js";
|
|
|
18
19
|
*/
|
|
19
20
|
|
|
20
21
|
export interface RunContextRefreshInput {
|
|
22
|
+
decisions?: ReadonlyArray<DecisionLedgerEntry>;
|
|
21
23
|
cwd?: string;
|
|
22
24
|
io?: BootstrapIo;
|
|
23
25
|
now?: () => Date;
|
|
@@ -146,6 +148,7 @@ export async function runContextRefresh(input: RunContextRefreshInput = {}): Pro
|
|
|
146
148
|
wikiResult = await runWikiGenerate({
|
|
147
149
|
cwd,
|
|
148
150
|
mode: "update",
|
|
151
|
+
...(input.decisions ? { decisions: input.decisions } : {}),
|
|
149
152
|
model: input.wikiModel ?? "unresolved-documenter-target",
|
|
150
153
|
...(input.wikiGenerate ? { generate: input.wikiGenerate } : {}),
|
|
151
154
|
...(input.onProgress ? { onProgress: input.onProgress } : {}),
|