@iowarp/clio-coder 0.4.1 → 0.4.3
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 +127 -0
- package/CONTRIBUTING.md +142 -52
- package/README.md +434 -473
- package/SECURITY.md +2 -1
- package/dist/{acp-ZILU3AUO.js → acp-H2NGRPWO.js} +12 -12
- package/dist/{agents-HYWGBGQR.js → agents-TL5LLUQP.js} +56 -55
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-N3QT7CBO.js → auth-E5SW4HMS.js} +23 -21
- package/dist/builtins-IA7V7FUC.js +22 -0
- package/dist/{chunk-7RY5VZPH.js → chunk-2APPQIER.js} +8 -8
- package/dist/{chunk-72GZI5EV.js → chunk-2JH2WHGE.js} +2 -2
- package/dist/{chunk-JA5QWE4Z.js → chunk-2UG5F4C5.js} +1973 -1664
- package/dist/{chunk-5YHDIDBP.js → chunk-2UH2KFUP.js} +2 -2
- package/dist/{chunk-CTJ4RNAA.js → chunk-2VIKGWFZ.js} +2 -2
- package/dist/{chunk-I66EAJFY.js → chunk-2WZ546HR.js} +267 -232
- package/dist/{chunk-GIZNH63R.js → chunk-35MSIRKH.js} +9 -4
- package/dist/chunk-3EBYEESD.js +314 -0
- package/dist/{chunk-J5LZHVIT.js → chunk-3M6DQK6S.js} +113 -35
- package/dist/{chunk-RKSR6VSF.js → chunk-4IUZQIJ3.js} +29 -1
- package/dist/{chunk-6FN3E6KX.js → chunk-4O6MANBS.js} +2 -2
- package/dist/chunk-4UVU7BJ5.js +39 -0
- package/dist/{chunk-VKRH2TCS.js → chunk-4WR7VSYB.js} +2 -2
- package/dist/{chunk-BBTJOK6Y.js → chunk-54CBCGIR.js} +5 -5
- package/dist/{chunk-AP73CFDC.js → chunk-5ICU3EUH.js} +2 -2
- package/dist/chunk-5MEZN6CB.js +1334 -0
- package/dist/{chunk-O42A54GG.js → chunk-5OIVVPHF.js} +2 -2
- package/dist/{chunk-ABLSQ6JX.js → chunk-64I3JVYM.js} +8 -2
- package/dist/{chunk-AFKWHWXF.js → chunk-6PTFB5VS.js} +39 -22
- package/dist/{chunk-VN3SHNBN.js → chunk-7DICMOS6.js} +2 -2
- package/dist/chunk-7DRAWPTZ.js +360 -0
- package/dist/chunk-7E7I3WLS.js +3762 -0
- package/dist/{chunk-BJGUKIG4.js → chunk-7ZYNNDKC.js} +7 -7
- package/dist/{chunk-XKA2ICR3.js → chunk-AF4YM7Z4.js} +652 -252
- package/dist/{chunk-GVQJ5CCZ.js → chunk-AX2THNSA.js} +12 -12
- package/dist/{chunk-IG7BCQBA.js → chunk-B4OAX3SI.js} +65 -3
- package/dist/{chunk-TD3PGPQA.js → chunk-B4VEBZKF.js} +3 -3
- package/dist/{chunk-74YWRRU5.js → chunk-BEPZRGGU.js} +10 -10
- package/dist/{chunk-FEFIFZTL.js → chunk-CE5AX47J.js} +2 -2
- package/dist/{chunk-UAPGZHYC.js → chunk-DWUOQKRU.js} +25 -11
- package/dist/{chunk-THYWACCR.js → chunk-E3TPLWFX.js} +3 -3
- package/dist/{chunk-7EPLI7VL.js → chunk-EKCHAPYA.js} +2 -2
- package/dist/{chunk-HLW2MRKE.js → chunk-F4EKGO4N.js} +3 -1
- package/dist/{chunk-PJJ6MY27.js → chunk-F5JHEYZM.js} +7 -7
- package/dist/{chunk-6CCS4G3W.js → chunk-FTMGRKEF.js} +3 -3
- package/dist/{chunk-SINK3QR6.js → chunk-G76U63X4.js} +17 -17
- package/dist/{chunk-EIMVLWB3.js → chunk-GHS5EBTQ.js} +64 -9
- package/dist/{chunk-QMXC4JB7.js → chunk-GI7YYQ3F.js} +187 -1419
- package/dist/{chunk-TZSKNMZG.js → chunk-GTUD2WMY.js} +2 -1
- package/dist/{chunk-6HMJX2VU.js → chunk-GWZNEVM2.js} +44 -12
- package/dist/chunk-GYV6VZOC.js +26 -0
- package/dist/{chunk-MQXIVJ35.js → chunk-HAXOFFRH.js} +5 -5
- package/dist/{chunk-UXN6JT4W.js → chunk-HEQY7ZFI.js} +3 -3
- package/dist/{chunk-7PWAODYW.js → chunk-I7XBWTYH.js} +2 -2
- package/dist/{chunk-GCSMB2KY.js → chunk-I7ZPNEJM.js} +145 -102
- package/dist/{chunk-WNP7O5WZ.js → chunk-ID64D7PE.js} +4 -4
- package/dist/{chunk-QTFGO774.js → chunk-IGLP3ODT.js} +29 -16
- package/dist/chunk-IJNZMHLA.js +101 -0
- package/dist/{chunk-BDPT6GTK.js → chunk-INY6HTFL.js} +7 -7
- package/dist/{chunk-PBP4B7XR.js → chunk-IUE3Y34X.js} +2 -2
- package/dist/{chunk-6NJQITNH.js → chunk-IWT4SF4R.js} +6 -3
- package/dist/{chunk-R23Z6K6I.js → chunk-JDAY6FIL.js} +19 -19
- package/dist/chunk-JEQ3XTHC.js +42 -0
- package/dist/{chunk-FSP7CMNU.js → chunk-JGRC33J2.js} +50 -4
- package/dist/{chunk-TVH4ONAM.js → chunk-JKKCYP3C.js} +10 -10
- package/dist/{chunk-HJWWJ6IL.js → chunk-JSC3U7TI.js} +16 -4
- package/dist/{chunk-C537JADH.js → chunk-KK4JZPBQ.js} +19 -141
- package/dist/{chunk-K6BF4U2H.js → chunk-KKOJXO6R.js} +62 -14
- package/dist/{chunk-IHXBNWMM.js → chunk-KXDSS5WJ.js} +7 -3
- package/dist/{chunk-6DWBAZ5U.js → chunk-L47TF46W.js} +5 -7
- package/dist/{chunk-HUAS7ITX.js → chunk-LDJG7DW3.js} +91 -42
- package/dist/{chunk-CDNVLKUX.js → chunk-LLDJM5XK.js} +13 -7
- package/dist/{chunk-YPI3QQCF.js → chunk-MCEPRMZW.js} +2 -4
- package/dist/{chunk-Y4CAGMM6.js → chunk-MNJGS2IN.js} +5 -6
- package/dist/{chunk-VKFQTNDV.js → chunk-MUW2BDDH.js} +4 -4
- package/dist/{chunk-E67WX76H.js → chunk-MWUZBSAQ.js} +104 -152
- package/dist/{chunk-OJTRZGR3.js → chunk-N2Z7HLVY.js} +21 -21
- package/dist/{chunk-TVHHYFHE.js → chunk-NEDJ26B5.js} +2 -2
- package/dist/{chunk-FYUN5KZ3.js → chunk-NIQJ66N4.js} +21 -21
- package/dist/{chunk-U2WB7TZS.js → chunk-NMJXSHBJ.js} +97 -85
- package/dist/{chunk-CWVRRIEI.js → chunk-NZMNUPZZ.js} +2 -2
- package/dist/{chunk-VEGN6WIQ.js → chunk-O5CVSAG5.js} +3 -3
- package/dist/{chunk-MOPSG2X7.js → chunk-OML5D5V5.js} +8 -8
- package/dist/{chunk-2VG7KLYV.js → chunk-PAJQJ7BS.js} +5816 -3255
- package/dist/{chunk-ZW55JB7N.js → chunk-PUVDKJ2Y.js} +2 -2
- package/dist/{chunk-BTGG6BG2.js → chunk-QWGDJJYJ.js} +158 -19
- package/dist/chunk-R6Q67RJH.js +134 -0
- package/dist/{chunk-ZJLUDYFY.js → chunk-RRNP2ANY.js} +6 -6
- package/dist/{chunk-PVAMAVBB.js → chunk-RSJ25QSL.js} +102 -2
- package/dist/{chunk-NLFAQR7Z.js → chunk-S66XZJOF.js} +3 -23
- package/dist/chunk-SKHCAU7K.js +385 -0
- package/dist/chunk-SZAA6XDG.js +30 -0
- package/dist/{chunk-J4HBWF6Y.js → chunk-TM6LQDI3.js} +131 -28
- package/dist/chunk-UOIZ7DA4.js +41 -0
- package/dist/{chunk-MA3H6DM5.js → chunk-UPZU6GE4.js} +25 -3
- package/dist/{chunk-BWW4HLO4.js → chunk-UXCU4E3T.js} +8 -6
- package/dist/{chunk-N5UK64DP.js → chunk-V2ANDPVT.js} +4 -4
- package/dist/{chunk-AK5XEFVZ.js → chunk-VA5FNYMT.js} +26 -13
- package/dist/{chunk-6VC4OV3Z.js → chunk-VIA6RFQZ.js} +3 -11
- package/dist/{chunk-ZAZB4JMW.js → chunk-VKPAQYEB.js} +27 -8
- package/dist/{chunk-QKIFBZKT.js → chunk-VW6DOEDG.js} +497 -81
- package/dist/{chunk-SCYB3HA4.js → chunk-W6RRQCPQ.js} +63 -19
- package/dist/{chunk-2NM363SV.js → chunk-WBKFA554.js} +10 -10
- package/dist/{chunk-R32CLGZ6.js → chunk-WCXUNS7U.js} +82 -21
- package/dist/{chunk-GPPB3JBE.js → chunk-WRBAGUNF.js} +3 -3
- package/dist/{chunk-IXJT6DCX.js → chunk-XIVNBFZS.js} +85 -30
- package/dist/{chunk-UEDMSP56.js → chunk-XPWWI35G.js} +417 -201
- package/dist/chunk-XRZT5WY5.js +47 -0
- package/dist/{chunk-3QSOM6PA.js → chunk-Y3CBHOR6.js} +2 -2
- package/dist/{chunk-VXMFAE2W.js → chunk-YPC6ZR5L.js} +19 -6
- package/dist/{chunk-AKB4GYDL.js → chunk-YQWYVTMC.js} +5 -5
- package/dist/{chunk-6I5ILFOF.js → chunk-ZA4VCIGV.js} +3 -3
- package/dist/{chunk-7OBGU7UB.js → chunk-ZDN3Y73Y.js} +12 -18
- package/dist/{chunk-3I5NY75V.js → chunk-ZWPRK62N.js} +8 -5
- package/dist/cli/index.js +41 -39
- package/dist/{clio-IT3G3VQH.js → clio-CMMK4KRR.js} +9 -9
- package/dist/{code-nav-RK6S7F6E.js → code-nav-MDZNQS33.js} +89 -21
- package/dist/{components-UBWCQSRW.js → components-UCUQ4QXW.js} +4 -4
- package/dist/{config-3QZRWZJF.js → config-SVM5P5YI.js} +131 -84
- package/dist/{configure-FL7Y3KJF.js → configure-LE3IK2TJ.js} +28 -26
- package/dist/{context-5HE7ODYK.js → context-2OHRKS42.js} +69 -64
- package/dist/{context-KYQFRVDC.js → context-E3VC7RX5.js} +15 -11
- package/dist/{context-XNHL75JV.js → context-VNCR7KAG.js} +93 -65
- package/dist/{context-clear-N545L53A.js → context-clear-BW4O37TG.js} +64 -60
- package/dist/context-map-COB37XXN.js +505 -0
- package/dist/{context-working-set-QHKXSV2F.js → context-working-set-VDS25HXZ.js} +19 -18
- package/dist/{dispatch-runner-RGIE5PCT.js → dispatch-runner-5AHT53RF.js} +93 -82
- package/dist/{docs-5NAF6AU7.js → docs-PD3EXDKU.js} +21 -20
- package/dist/{doctor-ZGPEGHIP.js → doctor-WNNVO6FY.js} +48 -47
- package/dist/{eval-GXLL44RD.js → eval-7G7SGAYO.js} +287 -115
- package/dist/{eval-inventory-HBWSWQOK.js → eval-inventory-Y6QRFOH5.js} +4 -4
- package/dist/{evidence-HWLBRH3Q.js → evidence-VD6736FQ.js} +67 -64
- package/dist/{evolve-FTZBMNVW.js → evolve-AL3NGVRL.js} +65 -62
- package/dist/{extensions-VHRBEID7.js → extensions-MOVJ32NM.js} +9 -7
- package/dist/{fleet-CKZHJWZJ.js → fleet-QZHUMAGI.js} +114 -111
- package/dist/{fleet-commands-EXDXBMV6.js → fleet-commands-BAYT5FJZ.js} +10 -10
- package/dist/{fleet-decisions-OTHB6KRL.js → fleet-decisions-IREVMRU4.js} +7 -6
- package/dist/{fleet-graph-YTEZUCUT.js → fleet-graph-YCTT3HTI.js} +22 -19
- package/dist/{fleet-inspect-SS6YMDCK.js → fleet-inspect-QVJTDAVB.js} +58 -55
- package/dist/{fleet-preflight-PBY4VYOM.js → fleet-preflight-25QAFPK4.js} +4 -4
- package/dist/{fleet-validate-KMEM5L3S.js → fleet-validate-5O57AAJ7.js} +26 -23
- package/dist/{fleet-verify-QD5M7E7Q.js → fleet-verify-CPH2W2T6.js} +59 -56
- package/dist/{fleet-view-WAMJYNDT.js → fleet-view-SWBR3VGQ.js} +58 -55
- package/dist/{init-5XQRBOFV.js → init-J477LKZH.js} +82 -79
- package/dist/{interop-34TVO25M.js → interop-3FCM6XLG.js} +11 -11
- package/dist/{library-3QY6KF57.js → library-QUQEIUG6.js} +30 -27
- package/dist/{memory-L4UTIIIW.js → memory-SGGSEP65.js} +67 -64
- package/dist/{models-ZVX3QOWE.js → models-HEKUAXXK.js} +53 -46
- package/dist/{monitor-CEKVSYTS.js → monitor-HKU57TYQ.js} +63 -60
- package/dist/{orchestrator-77BAP6BC.js → orchestrator-VDFAEFAI.js} +1831 -1057
- package/dist/{panes-7STHOAUJ.js → panes-DN2SSFOH.js} +5 -5
- package/dist/{panes-SHAUIRXY.js → panes-TALGNPZT.js} +29 -14
- package/dist/{paths-L7LGY6RN.js → paths-NBMFAIEZ.js} +5 -5
- package/dist/reset-EAJFFJVB.js +344 -0
- package/dist/{resources-74GKTLSF.js → resources-OVKSEFVE.js} +29 -20
- package/dist/{run-HBAUJNNZ.js → run-7DP7ZF2J.js} +120 -115
- package/dist/{share-G3APVLVP.js → share-WML67FT3.js} +32 -27
- package/dist/{skills-35HHUKCR.js → skills-SG662R2K.js} +41 -31
- package/dist/{skills-eval-QN4HSHDC.js → skills-eval-VVZEUU46.js} +78 -77
- package/dist/{skills-inventory-J357J34F.js → skills-inventory-I2E23GET.js} +23 -20
- package/dist/{slash-commands-JZZCQA32.js → slash-commands-S7MBJDQK.js} +40 -36
- package/dist/{steer-XAVHJM22.js → steer-2LQOMCPB.js} +3 -3
- package/dist/{support-U7QOWY26.js → support-CC2UJBJ6.js} +6 -6
- package/dist/{targets-DSM6CY3M.js → targets-4QC3HIEW.js} +54 -54
- package/dist/{terminal-lease-JOPFUVEM.js → terminal-lease-TUHIJ6Y2.js} +5 -5
- package/dist/{tools-MKNWVPBH.js → tools-TFGJICCU.js} +10 -10
- package/dist/{trace-ECQ7TIYZ.js → trace-FXMXUZUF.js} +55 -7
- package/dist/uninstall-5PEVOE5B.js +408 -0
- package/dist/upgrade-M4WXY6KN.js +303 -0
- package/dist/{usage-X52N3IDJ.js → usage-N7ZNVLEM.js} +151 -104
- package/dist/{verifiers-EJTVVSMA.js → verifiers-DJTP4XX6.js} +15 -15
- package/dist/{verify-YJL6XET2.js → verify-RWE4PPEK.js} +9 -9
- package/dist/{web-fetch-MPIFL3LL.js → web-fetch-MPARV2K7.js} +2 -2
- package/dist/{wiki-generate-4NDZTQ4B.js → wiki-generate-C7IQOXSP.js} +89 -86
- package/dist/{with-panes-OBOBFIIR.js → with-panes-4GCGSL7J.js} +53 -257
- package/dist/worker/entry.js +90 -74
- package/docs/README.md +176 -81
- package/docs/{acp.md → architecture/acp.md} +36 -20
- package/docs/{alcf-provider.md → architecture/alcf-provider.md} +8 -5
- package/docs/{architecture.md → architecture/architecture.md} +43 -22
- package/docs/{artifact-placement.md → architecture/artifact-placement.md} +27 -23
- package/docs/architecture/artifact-versions.md +90 -0
- package/docs/{capacity-and-scheduling.md → architecture/capacity-and-scheduling.md} +26 -13
- package/docs/{context-engine.md → architecture/context-engine.md} +29 -25
- package/docs/{context-working-set.md → architecture/context-working-set.md} +13 -10
- package/docs/{dispatch-architecture-rationale.md → architecture/dispatch-architecture-rationale.md} +12 -9
- package/docs/{dispatch-typed-intent.md → architecture/dispatch-typed-intent.md} +68 -46
- package/docs/{evidence-and-memory.md → architecture/evidence-and-memory.md} +23 -16
- package/docs/{middleware-and-components.md → architecture/middleware-and-components.md} +11 -5
- package/docs/{model-catalog.md → architecture/model-catalog.md} +61 -27
- package/docs/{observability.md → architecture/observability.md} +38 -14
- package/docs/{pi-boundary.md → architecture/pi-boundary.md} +24 -11
- package/docs/{prompt-envelope-and-tools.md → architecture/prompt-envelope-and-tools.md} +57 -20
- package/docs/{provider-adapter-cookbook.md → architecture/provider-adapter-cookbook.md} +99 -25
- package/docs/{safety-model.md → architecture/safety-model.md} +35 -20
- package/docs/{session-lifecycle.md → architecture/session-lifecycle.md} +8 -5
- package/docs/architecture/time-conventions.md +125 -0
- package/docs/{trace-store.md → architecture/trace-store.md} +13 -5
- package/docs/{tui-design.md → architecture/tui-design.md} +13 -13
- package/docs/{worker-dispatch-mechanics.md → architecture/worker-dispatch-mechanics.md} +27 -30
- package/docs/{built-in-agents.md → guide/built-in-agents.md} +65 -35
- package/docs/{commands-and-modes.md → guide/commands-and-modes.md} +66 -61
- package/docs/{configuration-and-targets.md → guide/configuration-and-targets.md} +323 -297
- package/docs/guide/configuration-reference.md +1163 -0
- package/docs/{environment-variables.md → guide/environment-variables.md} +33 -28
- package/docs/{exit-codes-and-output.md → guide/exit-codes-and-output.md} +6 -3
- package/docs/{extensions-and-sharing.md → guide/extensions-and-sharing.md} +41 -14
- package/docs/{fleet-dispatch.md → guide/fleet-dispatch.md} +39 -43
- package/docs/{glossary.md → guide/glossary.md} +14 -11
- package/docs/{installation-and-lifecycle.md → guide/installation-and-lifecycle.md} +81 -17
- package/docs/guide/panes-and-files.md +290 -0
- package/docs/{proactive-memory.md → guide/proactive-memory.md} +131 -107
- package/docs/{resource-library.md → guide/resource-library.md} +13 -4
- package/docs/{skills-marketplace.md → guide/skills-marketplace.md} +25 -3
- package/docs/{tool-usage.md → guide/tool-usage.md} +87 -23
- package/docs/{troubleshooting.md → guide/troubleshooting.md} +9 -4
- package/docs/{config-knobs-audit.md → history/config-knobs-audit.md} +11 -11
- package/docs/{release-cut-checklist.md → history/release-cut-checklist.md} +29 -2
- package/docs/process/development-pipeline.md +152 -0
- package/docs/process/documentation-coverage.md +100 -0
- package/docs/process/documentation-guide.md +187 -0
- package/docs/{eval-runner.md → process/eval-runner.md} +108 -53
- package/docs/{evals-internal.md → process/evals-internal.md} +10 -10
- package/docs/{evolution.md → process/evolution.md} +2 -2
- package/docs/{fleet-demo-runbook.md → process/fleet-demo-runbook.md} +11 -7
- package/docs/{git-commit-provenance.md → process/git-commit-provenance.md} +11 -4
- package/docs/{performance-methodology.md → process/performance-methodology.md} +87 -69
- package/docs/{scientific-validation.md → process/scientific-validation.md} +4 -4
- package/evals/README.md +2 -2
- package/evals/behavioral-model.yaml +3 -2
- package/package.json +10 -8
- package/skills/README.md +52 -41
- package/skills/coding/ast-grep/SKILL.md +102 -31
- package/skills/coding/ast-grep/evals.md +26 -0
- package/skills/coding/coding-standards/SKILL.md +41 -6
- package/skills/coding/coding-standards/evals.md +23 -0
- package/skills/coding/prototype/SKILL.md +88 -29
- package/skills/coding/prototype/evals.md +19 -0
- package/skills/coding/tdd/SKILL.md +81 -54
- package/skills/coding/tdd/evals.md +20 -0
- package/skills/context/context-handoff/SKILL.md +44 -3
- package/skills/context/context-handoff/evals.md +44 -0
- package/skills/context/context-prime/SKILL.md +46 -16
- 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 +78 -64
- 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 +88 -65
- 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 +101 -52
- 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/meta/clio-coder-dev/SKILL.md +9 -5
- package/skills/meta/clio-coder-dev/evals.md +3 -2
- package/skills/meta/clio-coder-test/SKILL.md +102 -95
- package/skills/meta/clio-coder-test/evals.md +9 -4
- package/skills/meta/clio-coder-test/references/harness.md +100 -124
- package/skills/meta/clio-coder-test/references/test-map.md +77 -50
- package/skills/meta/credentials/SKILL.md +2 -2
- package/skills/meta/find-skills/SKILL.md +2 -2
- package/skills/meta/herdr/SKILL.md +2 -2
- package/skills/meta/skill-craft/SKILL.md +22 -16
- package/skills/planning/archify/SKILL.md +196 -0
- package/skills/planning/archify/evals.md +65 -0
- package/skills/planning/architecture/SKILL.md +62 -13
- package/skills/planning/architecture/evals.md +65 -0
- package/skills/planning/backlog/SKILL.md +131 -15
- package/skills/planning/backlog/evals.md +142 -0
- package/skills/planning/prd/SKILL.md +47 -7
- package/skills/planning/prd/evals.md +54 -0
- package/skills/planning/product-intent/SKILL.md +58 -3
- package/skills/planning/product-intent/evals.md +70 -0
- package/skills/planning/tech-spec/SKILL.md +54 -3
- package/skills/planning/tech-spec/evals.md +73 -0
- package/skills/registry.yaml +70 -62
- package/skills/remote.yaml +13 -0
- package/skills/research/arxiv-literature/SKILL.md +77 -19
- package/skills/research/arxiv-literature/evals.md +50 -0
- package/skills/research/experiment-protocol/SKILL.md +21 -2
- package/skills/research/experiment-protocol/evals.md +23 -0
- package/skills/research/scientific-debugging/SKILL.md +24 -2
- package/skills/research/scientific-debugging/evals.md +18 -0
- package/skills/research/scientific-modernization/SKILL.md +27 -2
- package/skills/research/scientific-modernization/evals.md +27 -0
- package/skills/skill-marketplace.json +97 -62
- package/skills/workflow/cut-it/SKILL.md +66 -6
- package/skills/workflow/cut-it/evals.md +101 -0
- package/skills/workflow/design-council/SKILL.md +118 -28
- package/skills/workflow/design-council/evals.md +161 -0
- package/skills/workflow/grill-me/SKILL.md +87 -11
- package/skills/workflow/grill-me/evals.md +153 -0
- package/skills/workflow/workflow-distiller/SKILL.md +77 -18
- package/skills/workflow/workflow-distiller/evals.md +118 -0
- package/src/cli/args.ts +2 -2
- package/src/cli/bootstrap-generate.ts +1 -1
- package/src/cli/config-inspect.ts +65 -12
- 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 +1082 -532
- package/src/cli/context-map.ts +114 -0
- package/src/cli/context.ts +4 -0
- package/src/cli/docs.ts +22 -14
- package/src/cli/doctor-naming.ts +5 -5
- package/src/cli/doctor-toolchain.ts +3 -3
- package/src/cli/eval.ts +1 -2
- package/src/cli/extensions.ts +2 -1
- package/src/cli/fleet.ts +1 -1
- package/src/cli/index.ts +3 -1
- package/src/cli/internal-dispatch.ts +3 -4
- 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/panes.ts +19 -5
- package/src/cli/reset.ts +228 -106
- package/src/cli/run.ts +9 -4
- package/src/cli/select.ts +664 -0
- package/src/cli/share.ts +5 -1
- package/src/cli/skills-eval.ts +3 -3
- package/src/cli/skills.ts +9 -2
- package/src/cli/targets.ts +5 -6
- package/src/cli/trace.ts +55 -4
- package/src/cli/uninstall.ts +233 -165
- package/src/cli/upgrade.ts +204 -149
- package/src/cli/usage.ts +86 -27
- package/src/cli/validate-model.ts +3 -3
- package/src/cli/wiki-generate.ts +1 -1
- package/src/core/artifact-paths.ts +1 -1
- package/src/core/bash-exec.ts +131 -86
- package/src/core/bus-events.ts +51 -6
- package/src/core/config.ts +61 -1
- package/src/core/defaults.ts +7 -4
- package/src/core/dispatch-outcome.ts +16 -0
- package/src/core/external-diagnostic.ts +44 -0
- package/src/core/gateway-routing.ts +157 -0
- package/src/core/guardrails.ts +10 -49
- package/src/core/prompt-hint.ts +9 -0
- package/src/core/safe-exec.ts +17 -2
- package/src/core/skill-activation.ts +89 -2
- package/src/domains/agents/builtins/architect.md +2 -3
- package/src/domains/agents/builtins/coder.md +3 -2
- package/src/domains/agents/builtins/debugger.md +2 -2
- package/src/domains/agents/builtins/documenter.md +2 -2
- package/src/domains/agents/builtins/git-master.md +1 -1
- package/src/domains/agents/builtins/oracle.md +1 -1
- package/src/domains/agents/builtins/provenance.md +1 -1
- package/src/domains/agents/builtins/researcher.md +1 -1
- package/src/domains/agents/builtins/scout.md +1 -1
- package/src/domains/agents/builtins/tester.md +2 -2
- package/src/domains/agents/builtins/verifier.md +2 -2
- package/src/domains/agents/builtins/wiki-writer.md +1 -1
- package/src/domains/agents/builtins/world-knowledge.md +31 -0
- package/src/domains/agents/catalog.ts +13 -15
- package/src/domains/agents/contract.ts +2 -0
- package/src/domains/agents/extension.ts +23 -1
- package/src/domains/agents/result-contract.ts +70 -0
- package/src/domains/config/keybindings.ts +8 -0
- package/src/domains/context/extension.ts +0 -3
- package/src/domains/context/wiki/map-seed.ts +589 -0
- package/src/domains/context/wiki/plan.ts +2 -2
- package/src/domains/context/working-set/path-index.ts +1 -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 +11 -0
- package/src/domains/dispatch/capacity-lease.ts +17 -0
- package/src/domains/dispatch/contract.ts +11 -1
- package/src/domains/dispatch/extension.ts +237 -49
- package/src/domains/dispatch/host-verification.ts +435 -39
- package/src/domains/dispatch/intent-requirements.ts +10 -0
- package/src/domains/dispatch/intent.ts +18 -1
- package/src/domains/dispatch/path-scope.ts +235 -24
- package/src/domains/dispatch/run-event-journal.ts +4 -15
- package/src/domains/dispatch/state.ts +2 -3
- package/src/domains/dispatch/transport.ts +45 -21
- package/src/domains/dispatch/types.ts +58 -3
- package/src/domains/dispatch/worker-model-metadata.ts +38 -0
- package/src/domains/eval/artifacts/store.ts +5 -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 +5 -2
- package/src/domains/eval/schema/suite.ts +28 -0
- package/src/domains/eval/schema/verdict.ts +2 -2
- package/src/domains/eval/store.ts +8 -1
- package/src/domains/eval/suites/resolve.ts +13 -1
- package/src/domains/eval/suites/run.ts +24 -3
- package/src/domains/evidence/trust-status.ts +10 -1
- package/src/domains/extensions/contract.ts +15 -1
- package/src/domains/extensions/discovery.ts +238 -41
- package/src/domains/extensions/extension.ts +105 -6
- package/src/domains/extensions/index.ts +24 -0
- package/src/domains/extensions/integrity.ts +189 -0
- package/src/domains/extensions/manager.ts +17 -1
- package/src/domains/extensions/resource-path.ts +27 -0
- package/src/domains/extensions/resources.ts +18 -38
- package/src/domains/extensions/snapshot-store.ts +39 -0
- package/src/domains/extensions/snapshot.ts +180 -0
- package/src/domains/extensions/state.ts +385 -57
- package/src/domains/extensions/types.ts +118 -1
- package/src/domains/interop/registry.ts +6 -2
- package/src/domains/interop/types.ts +4 -0
- package/src/domains/lifecycle/migrations/2026-09-01-extension-install-digests.ts +27 -0
- package/src/domains/lifecycle/migrations/index.ts +6 -0
- package/src/domains/lifecycle/naming-resources.ts +19 -4
- package/src/domains/lifecycle/naming-yazi.ts +10 -5
- package/src/domains/memory/task-memory-policy.ts +70 -26
- package/src/domains/memory/task-memory-telemetry.ts +1 -0
- package/src/domains/middleware/contract.ts +26 -0
- package/src/domains/middleware/extension.ts +24 -24
- package/src/domains/middleware/hook-receipts.ts +27 -4
- package/src/domains/middleware/hooks-io.ts +65 -32
- package/src/domains/middleware/hooks.ts +64 -0
- package/src/domains/middleware/index.ts +28 -5
- package/src/domains/middleware/marketplace-offer.ts +3 -35
- package/src/domains/middleware/memory-intervention.ts +127 -32
- package/src/domains/middleware/memory-step-endpoint.ts +3 -2
- package/src/domains/middleware/registrations.ts +326 -0
- package/src/domains/middleware/runtime.ts +28 -0
- package/src/domains/middleware/skills-reminder.ts +31 -2
- package/src/domains/middleware/snapshot.ts +20 -7
- package/src/domains/mux/contract.ts +38 -0
- package/src/domains/mux/detect.ts +6 -13
- package/src/domains/mux/index.ts +1 -1
- package/src/domains/mux/operations.ts +44 -5
- package/src/domains/mux/yazi/assets/yazi.toml +2 -2
- package/src/domains/mux/yazi/session.ts +53 -4
- package/src/domains/mux/yazi/theme.ts +117 -17
- package/src/domains/observability/compaction-usage.ts +118 -0
- package/src/domains/observability/contract.ts +10 -11
- package/src/domains/observability/cost.ts +1 -1
- package/src/domains/observability/extension.ts +17 -4
- package/src/domains/observability/out-of-turn-usage.ts +52 -21
- package/src/domains/observability/projection.ts +14 -90
- package/src/domains/observability/trace-store.ts +43 -7
- package/src/domains/prompts/compiler.ts +73 -53
- package/src/domains/prompts/contract.ts +15 -3
- package/src/domains/prompts/extension.ts +97 -9
- package/src/domains/prompts/fragments/identity/clio-worker.md +1 -3
- package/src/domains/prompts/fragments/identity/clio.md +6 -12
- package/src/domains/prompts/fragments/identity/docs-routing.md +1 -2
- package/src/domains/prompts/fragments/identity/self-awareness.md +3 -11
- package/src/domains/prompts/fragments/operating/contract.md +7 -15
- package/src/domains/prompts/fragments/operating/delegation.md +32 -34
- package/src/domains/prompts/fragments/operating/skills.md +10 -24
- package/src/domains/prompts/fragments/operating/worker.md +1 -8
- package/src/domains/providers/contract.ts +4 -1
- package/src/domains/providers/extension.ts +40 -9
- package/src/domains/providers/index.ts +1 -1
- package/src/domains/providers/model-capabilities.ts +9 -0
- package/src/domains/providers/model-discovery.ts +2 -0
- package/src/domains/providers/model-runtime-capabilities.ts +99 -25
- package/src/domains/providers/models/local-models/clio-coder-local-coding-targets.yaml +699 -114
- package/src/domains/providers/runtime-resolution.ts +31 -0
- package/src/domains/providers/runtimes/antigravity/antigravity-code.ts +225 -45
- 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/common/probe-helpers.ts +7 -2
- package/src/domains/providers/runtimes/local-native/llamacpp.ts +9 -1
- 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/cost-provenance.ts +19 -0
- package/src/domains/providers/types/local-model-quirks.ts +85 -37
- 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 +23 -19
- package/src/domains/resources/skills/marketplace.ts +63 -11
- package/src/domains/safety/autonomy.ts +15 -0
- package/src/domains/safety/call-target.ts +1 -1
- package/src/domains/safety/index.ts +1 -0
- package/src/domains/safety/loop-detector.ts +7 -4
- package/src/domains/safety/path-policy.ts +1 -1
- package/src/domains/safety/policy-engine.ts +34 -11
- package/src/domains/safety/protected-artifacts.ts +191 -88
- package/src/domains/safety/run-effects.ts +2 -22
- package/src/domains/safety/skill-authority.ts +55 -0
- package/src/domains/session/compaction/compact.ts +72 -22
- package/src/domains/session/entries.ts +6 -0
- package/src/domains/session/task-board.ts +10 -9
- package/src/domains/session/usage.ts +3 -3
- package/src/domains/share/archive.ts +164 -7
- package/src/engine/acp/server.ts +62 -9
- 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/llamacpp-residency.ts +3 -4
- package/src/engine/apis/lmstudio.ts +3 -3
- package/src/engine/apis/ollama-native.ts +6 -6
- package/src/engine/apis/openai-completions.ts +145 -39
- package/src/engine/apis/output-budget.ts +8 -18
- package/src/engine/apis/residency.ts +8 -27
- package/src/engine/external-subprocess.ts +114 -6
- package/src/engine/gemma-channel-filter.ts +19 -0
- package/src/engine/loop-guard.ts +92 -12
- package/src/engine/worker-runtime.ts +40 -11
- package/src/engine/worker-tools.ts +3 -1
- package/src/entry/background-model-metadata.ts +18 -0
- package/src/entry/compaction-prompt.ts +57 -0
- package/src/entry/extension-hook-sources.ts +28 -0
- package/src/entry/extension-reload.ts +309 -0
- package/src/entry/orchestrator.ts +464 -251
- package/src/entry/task-memory-lifecycle.ts +35 -0
- package/src/interactive/application-controller.ts +2 -1
- package/src/interactive/bus-notices.ts +8 -1
- package/src/interactive/chat-loop-messages.ts +16 -17
- package/src/interactive/chat-loop.ts +75 -3
- package/src/interactive/chat-panel.ts +36 -13
- package/src/interactive/chat-renderer.ts +72 -7
- package/src/interactive/cost-overlay.ts +26 -2
- package/src/interactive/dispatch-board.ts +6 -11
- package/src/interactive/footer/widgets.ts +13 -0
- package/src/interactive/interactive-application.ts +39 -4
- package/src/interactive/interactive-input-runtime.ts +4 -0
- package/src/interactive/interactive-presentation.ts +2 -2
- package/src/interactive/interactive-slash-runtime.ts +4 -1
- package/src/interactive/overlays/extensions.ts +9 -1
- package/src/interactive/overlays/help-reference.ts +13 -0
- package/src/interactive/overlays/settings.ts +27 -16
- package/src/interactive/panes-runtime.ts +111 -35
- package/src/interactive/prompt-cache-identity.ts +88 -0
- package/src/interactive/renderers/worker-entry.ts +32 -0
- package/src/interactive/slash-commands.ts +153 -20
- package/src/interactive/stream-pacing-policy.ts +0 -23
- package/src/interactive/theme/labels.ts +19 -13
- package/src/interactive/turn-context.ts +39 -20
- 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/worker-receipts.ts +1 -0
- package/src/interactive/worker-stream.ts +6 -1
- package/src/interactive/yazi-bridge.ts +60 -6
- package/src/tools/agent-tools.ts +30 -1
- package/src/tools/artifact.ts +2 -2
- package/src/tools/ask-user.ts +3 -3
- package/src/tools/bash.ts +1 -1
- package/src/tools/bootstrap.ts +4 -0
- package/src/tools/builtin-tool-catalog.ts +52 -22
- package/src/tools/codewiki/code-nav-surface.ts +6 -0
- package/src/tools/codewiki/code-nav.ts +99 -13
- package/src/tools/context/docs-engine.ts +20 -7
- package/src/tools/context/index.ts +59 -21
- package/src/tools/core-bootstrap.ts +28 -6
- package/src/tools/credential-present.ts +1 -2
- package/src/tools/dispatch-arguments.ts +6 -1
- package/src/tools/dispatch-event-text.ts +10 -0
- package/src/tools/dispatch-plan.ts +49 -4
- package/src/tools/dispatch-run-events.ts +1 -1
- package/src/tools/dispatch-runner.ts +12 -0
- package/src/tools/dispatch-schema.ts +338 -0
- package/src/tools/dispatch-types.ts +3 -0
- package/src/tools/dispatch.ts +9 -254
- package/src/tools/ledger.ts +3 -5
- package/src/tools/monitor-surface.ts +5 -13
- package/src/tools/observation.ts +4 -5
- package/src/tools/panes-surface.ts +4 -11
- package/src/tools/panes.ts +4 -2
- package/src/tools/policy.ts +15 -2
- package/src/tools/read.ts +5 -6
- package/src/tools/registry.ts +41 -12
- package/src/tools/result-shaping.ts +18 -14
- package/src/tools/steer-surface.ts +1 -1
- package/src/tools/tasks.ts +1 -1
- package/src/tools/truncate.ts +6 -5
- package/src/tools/verify/surface.ts +6 -12
- package/src/tools/web-fetch-surface.ts +1 -3
- package/src/tools/worker-evidence.ts +3 -1
- package/src/worker/spec-contract.ts +4 -0
- package/dist/builtins-UJLMOVOV.js +0 -17
- package/dist/chunk-5QIAJV2D.js +0 -48
- package/dist/chunk-JZWT5J3Y.js +0 -814
- package/dist/chunk-K7VKOLQQ.js +0 -15
- package/dist/chunk-PMZCIOCJ.js +0 -25
- package/dist/chunk-SUW5DORT.js +0 -819
- package/dist/chunk-UOV2BYIW.js +0 -107
- package/dist/chunk-WR6U3OVP.js +0 -45
- package/dist/chunk-Y45G3AXC.js +0 -1558
- package/dist/reset-EOLM7GVE.js +0 -230
- package/dist/uninstall-N34PCTGJ.js +0 -331
- package/dist/upgrade-H7TOM7YL.js +0 -323
- package/docs/artifact-versions.md +0 -67
- package/docs/development-pipeline.md +0 -121
- package/docs/documentation-coverage.md +0 -46
- package/docs/documentation-guide.md +0 -167
- package/docs/time-conventions.md +0 -101
|
@@ -0,0 +1,589 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The architecture seed: an archify architecture specification derived from
|
|
3
|
+
* the codewiki index, with no model call.
|
|
4
|
+
*
|
|
5
|
+
* `clio-coder context map` writes it so a "map this repository" turn starts
|
|
6
|
+
* from real evidence instead of a blank page: components are the index's
|
|
7
|
+
* largest directory areas, connections are its import edges collapsed
|
|
8
|
+
* area-to-area, and every `sources` entry names a file and line the index
|
|
9
|
+
* actually recorded. Clio never renders the seed; the archify skill validates
|
|
10
|
+
* and delivers it, and `--repo-root` re-verifies every source path there.
|
|
11
|
+
*
|
|
12
|
+
* The output is deterministic for one index: keys are sorted, ids derive from
|
|
13
|
+
* area paths, and every ranking breaks ties on path order. Two runs over the
|
|
14
|
+
* same codewiki.json produce byte-identical JSON.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import type { Codewiki, CodewikiFile, CodewikiInternalEdge, CodewikiSymbol } from "../codewiki/schema.js";
|
|
18
|
+
import { areaForPath, classifyDepth, WIKI_DEPTH_STRATEGY } from "./plan.js";
|
|
19
|
+
|
|
20
|
+
export type SeedComponentType = "frontend" | "backend" | "database" | "external";
|
|
21
|
+
|
|
22
|
+
export interface SeedSource {
|
|
23
|
+
path: string;
|
|
24
|
+
line?: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type SeedSide = "top" | "bottom";
|
|
28
|
+
|
|
29
|
+
export interface SeedComponent {
|
|
30
|
+
id: string;
|
|
31
|
+
type: SeedComponentType;
|
|
32
|
+
label: string;
|
|
33
|
+
sublabel: string;
|
|
34
|
+
row: number;
|
|
35
|
+
col: number;
|
|
36
|
+
size: [number, number];
|
|
37
|
+
sources?: SeedSource[];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface SeedConnection {
|
|
41
|
+
id: string;
|
|
42
|
+
from: string;
|
|
43
|
+
to: string;
|
|
44
|
+
label: string;
|
|
45
|
+
fromSide: SeedSide;
|
|
46
|
+
toSide: SeedSide;
|
|
47
|
+
route?: "straight";
|
|
48
|
+
via?: [number, number][];
|
|
49
|
+
/** Label center; set on straight routes, whose midpoint would otherwise sit on a node. */
|
|
50
|
+
labelAt?: [number, number];
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface SeedLayout {
|
|
54
|
+
mode: "grid";
|
|
55
|
+
origin: [number, number];
|
|
56
|
+
cols: number;
|
|
57
|
+
cellW: number;
|
|
58
|
+
cellH: number;
|
|
59
|
+
gapX: number;
|
|
60
|
+
gapY: number;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface SeedRepository {
|
|
64
|
+
url: string;
|
|
65
|
+
revision: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface ArchitectureSeed {
|
|
69
|
+
schema_version: 1;
|
|
70
|
+
diagram_type: "architecture";
|
|
71
|
+
meta: {
|
|
72
|
+
title: string;
|
|
73
|
+
quality_profile: "standard";
|
|
74
|
+
repository?: SeedRepository;
|
|
75
|
+
};
|
|
76
|
+
layout: SeedLayout;
|
|
77
|
+
components: SeedComponent[];
|
|
78
|
+
connections: SeedConnection[];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export interface BuildArchitectureSeedOptions {
|
|
82
|
+
title: string;
|
|
83
|
+
/**
|
|
84
|
+
* Recorded as `meta.repository` only when it is a GitHub repository URL at
|
|
85
|
+
* a full 40-hex revision. Components carry `sources` only in that case,
|
|
86
|
+
* since archify accepts source citations only against a pinned revision.
|
|
87
|
+
*/
|
|
88
|
+
repository?: { url: string; revision: string } | undefined;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/** Most primary (internal area) components a seed carries. */
|
|
92
|
+
export const MAX_SEED_COMPONENTS = 12;
|
|
93
|
+
/** Most external-package components a seed carries. */
|
|
94
|
+
export const MAX_SEED_EXTERNALS = 3;
|
|
95
|
+
/** Most connections a seed carries, by descending import count. */
|
|
96
|
+
export const MAX_SEED_CONNECTIONS = 16;
|
|
97
|
+
/** Most `sources` entries per component; the schema caps at 3. */
|
|
98
|
+
const MAX_SEED_SOURCES = 3;
|
|
99
|
+
const GRID_COLS = 4;
|
|
100
|
+
const CELL_W = 220;
|
|
101
|
+
const CELL_H = 72;
|
|
102
|
+
const GAP_X = 70;
|
|
103
|
+
/** Vertical distance between route lanes inside one row gap or one margin. */
|
|
104
|
+
const LANE_STEP = 16;
|
|
105
|
+
/** Clearance between a node edge and the nearest lane, and beyond the last lane. */
|
|
106
|
+
const LANE_MARGIN = 24;
|
|
107
|
+
/** Horizontal offset of a straight route's label center from its line. */
|
|
108
|
+
const LABEL_BESIDE_OFFSET = 48;
|
|
109
|
+
|
|
110
|
+
const GITHUB_REPOSITORY_URL = /^https:\/\/github\.com\/[A-Za-z0-9_.-]+\/[A-Za-z0-9_.-]+(?:\.git)?\/?$/;
|
|
111
|
+
const FULL_REVISION = /^[a-fA-F0-9]{40}$/;
|
|
112
|
+
const DATABASE_DIR =
|
|
113
|
+
/^(?:store|stores|storage|persistence|persist|db|database|databases|repository|repositories|dao)$/i;
|
|
114
|
+
|
|
115
|
+
interface Area {
|
|
116
|
+
key: string;
|
|
117
|
+
files: CodewikiFile[];
|
|
118
|
+
loc: number;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/** A schema-legal id from an area path: letters, digits, `_`, `-`, starting with a letter. */
|
|
122
|
+
function areaId(key: string): string {
|
|
123
|
+
const slug = key
|
|
124
|
+
.replace(/[^A-Za-z0-9]+/g, "-")
|
|
125
|
+
.replace(/^-+|-+$/g, "")
|
|
126
|
+
.toLowerCase();
|
|
127
|
+
const body = slug.length > 0 ? slug : "root";
|
|
128
|
+
return /^[a-z]/.test(body) ? body : `a-${body}`;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** Keep readable ids, reserving every preferred spelling before adding collision suffixes. */
|
|
132
|
+
function uniqueIds(preferred: ReadonlyArray<string>): string[] {
|
|
133
|
+
const reserved = new Set(preferred);
|
|
134
|
+
const used = new Set<string>();
|
|
135
|
+
return preferred.map((base) => {
|
|
136
|
+
let id = base;
|
|
137
|
+
if (used.has(id)) {
|
|
138
|
+
let suffix = 2;
|
|
139
|
+
do {
|
|
140
|
+
id = `${base}-${suffix++}`;
|
|
141
|
+
} while (reserved.has(id) || used.has(id));
|
|
142
|
+
}
|
|
143
|
+
used.add(id);
|
|
144
|
+
return id;
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function componentTypeFor(area: Area): SeedComponentType {
|
|
149
|
+
const last = area.key.split("/").filter(Boolean).at(-1) ?? "";
|
|
150
|
+
if (DATABASE_DIR.test(last)) return "database";
|
|
151
|
+
if (area.files.some((file) => file.role === "entry")) return "frontend";
|
|
152
|
+
return "backend";
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function collectAreas(files: ReadonlyArray<CodewikiFile>, areaDepth: number): Area[] {
|
|
156
|
+
const byKey = new Map<string, Area>();
|
|
157
|
+
for (const file of files) {
|
|
158
|
+
const key = areaForPath(file.path, areaDepth);
|
|
159
|
+
const area = byKey.get(key) ?? { key, files: [], loc: 0 };
|
|
160
|
+
area.files.push(file);
|
|
161
|
+
area.loc += Math.max(0, file.loc);
|
|
162
|
+
byKey.set(key, area);
|
|
163
|
+
}
|
|
164
|
+
return [...byKey.values()].sort(
|
|
165
|
+
(a, b) => b.files.length - a.files.length || b.loc - a.loc || a.key.localeCompare(b.key),
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** The first declared symbol's line for each file id, when the index has one. */
|
|
170
|
+
function firstSymbolLines(symbols: ReadonlyArray<CodewikiSymbol>): Map<string, number> {
|
|
171
|
+
const lines = new Map<string, number>();
|
|
172
|
+
for (const symbol of symbols) {
|
|
173
|
+
if (!Number.isInteger(symbol.line) || symbol.line < 1) continue;
|
|
174
|
+
const current = lines.get(symbol.fileId);
|
|
175
|
+
if (current === undefined || symbol.line < current) lines.set(symbol.fileId, symbol.line);
|
|
176
|
+
}
|
|
177
|
+
return lines;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function sourcesFor(area: Area, lines: ReadonlyMap<string, number>): SeedSource[] {
|
|
181
|
+
return [...area.files]
|
|
182
|
+
.sort((a, b) => b.loc - a.loc || a.path.localeCompare(b.path))
|
|
183
|
+
.slice(0, MAX_SEED_SOURCES)
|
|
184
|
+
.map((file) => {
|
|
185
|
+
const line = lines.get(file.id);
|
|
186
|
+
return line === undefined ? { path: file.path } : { line, path: file.path };
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function isInternalEdge(edge: Codewiki["edges"][number]): edge is CodewikiInternalEdge {
|
|
191
|
+
return "toFileId" in edge;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* The package an external import specifier names: `@scope/pkg/deep` is
|
|
196
|
+
* `@scope/pkg`, `pkg/sub` is `pkg`. Runtime builtins (`node:fs`, `fs`) are
|
|
197
|
+
* not dependencies of the repository and return null.
|
|
198
|
+
*/
|
|
199
|
+
function externalPackage(specifier: string): string | null {
|
|
200
|
+
if (specifier.startsWith("node:") || NODE_BUILTINS.has(specifier)) return null;
|
|
201
|
+
const segments = specifier.split("/");
|
|
202
|
+
if (specifier.startsWith("@")) return segments.length >= 2 ? `${segments[0]}/${segments[1]}` : null;
|
|
203
|
+
return segments[0] && segments[0].length > 0 ? segments[0] : null;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const NODE_BUILTINS = new Set([
|
|
207
|
+
"assert",
|
|
208
|
+
"buffer",
|
|
209
|
+
"child_process",
|
|
210
|
+
"crypto",
|
|
211
|
+
"events",
|
|
212
|
+
"fs",
|
|
213
|
+
"http",
|
|
214
|
+
"https",
|
|
215
|
+
"module",
|
|
216
|
+
"net",
|
|
217
|
+
"os",
|
|
218
|
+
"path",
|
|
219
|
+
"process",
|
|
220
|
+
"readline",
|
|
221
|
+
"stream",
|
|
222
|
+
"url",
|
|
223
|
+
"util",
|
|
224
|
+
"zlib",
|
|
225
|
+
]);
|
|
226
|
+
|
|
227
|
+
/** JSON with every object's keys sorted, so equal seeds serialize identically. */
|
|
228
|
+
export function serializeArchitectureSeed(seed: ArchitectureSeed): string {
|
|
229
|
+
const sortKeys = (value: unknown): unknown => {
|
|
230
|
+
if (Array.isArray(value)) return value.map(sortKeys);
|
|
231
|
+
if (value && typeof value === "object") {
|
|
232
|
+
return Object.fromEntries(
|
|
233
|
+
Object.keys(value as Record<string, unknown>)
|
|
234
|
+
.sort()
|
|
235
|
+
.map((key) => [key, sortKeys((value as Record<string, unknown>)[key])]),
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
return value;
|
|
239
|
+
};
|
|
240
|
+
return `${JSON.stringify(sortKeys(seed), null, 2)}\n`;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
interface Unplaced {
|
|
244
|
+
id: string;
|
|
245
|
+
type: SeedComponentType;
|
|
246
|
+
label: string;
|
|
247
|
+
sublabel: string;
|
|
248
|
+
sources?: SeedSource[];
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
interface WeightedEdge {
|
|
252
|
+
from: string;
|
|
253
|
+
to: string;
|
|
254
|
+
weight: number;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Rows by import direction. Edges are admitted by descending weight into a
|
|
259
|
+
* DAG (an edge that would close a cycle is drawn anyway, but does not shape
|
|
260
|
+
* the rows), and each node's row is its longest path from a source. Rows
|
|
261
|
+
* wider than the grid wrap onto following rows; externals sit last since
|
|
262
|
+
* nothing imports back into them.
|
|
263
|
+
*/
|
|
264
|
+
function assignRows(nodes: ReadonlyArray<Unplaced>, edges: ReadonlyArray<WeightedEdge>): Map<string, number> {
|
|
265
|
+
const ids = nodes.filter((node) => node.type !== "external").map((node) => node.id);
|
|
266
|
+
const successors = new Map<string, Set<string>>(ids.map((id) => [id, new Set<string>()]));
|
|
267
|
+
const reaches = (from: string, to: string): boolean => {
|
|
268
|
+
const stack = [from];
|
|
269
|
+
const seen = new Set<string>();
|
|
270
|
+
while (stack.length > 0) {
|
|
271
|
+
const current = stack.pop() as string;
|
|
272
|
+
if (current === to) return true;
|
|
273
|
+
if (seen.has(current)) continue;
|
|
274
|
+
seen.add(current);
|
|
275
|
+
for (const next of successors.get(current) ?? []) stack.push(next);
|
|
276
|
+
}
|
|
277
|
+
return false;
|
|
278
|
+
};
|
|
279
|
+
for (const edge of edges) {
|
|
280
|
+
if (!successors.has(edge.from) || !successors.has(edge.to)) continue;
|
|
281
|
+
if (reaches(edge.to, edge.from)) continue;
|
|
282
|
+
successors.get(edge.from)?.add(edge.to);
|
|
283
|
+
}
|
|
284
|
+
const layer = new Map<string, number>();
|
|
285
|
+
const depth = (id: string): number => {
|
|
286
|
+
const known = layer.get(id);
|
|
287
|
+
if (known !== undefined) return known;
|
|
288
|
+
let best = 0;
|
|
289
|
+
for (const node of ids) {
|
|
290
|
+
if (successors.get(node)?.has(id)) best = Math.max(best, depth(node) + 1);
|
|
291
|
+
}
|
|
292
|
+
layer.set(id, best);
|
|
293
|
+
return best;
|
|
294
|
+
};
|
|
295
|
+
for (const id of ids) depth(id);
|
|
296
|
+
const rows = new Map<string, number>();
|
|
297
|
+
let row = 0;
|
|
298
|
+
const layers = [...new Set(ids.map((id) => layer.get(id) as number))].sort((a, b) => a - b);
|
|
299
|
+
for (const current of layers) {
|
|
300
|
+
// Node order within a layer follows the caller's ranking (file count).
|
|
301
|
+
const members = ids.filter((id) => layer.get(id) === current);
|
|
302
|
+
members.forEach((id, index) => {
|
|
303
|
+
rows.set(id, row + Math.floor(index / GRID_COLS));
|
|
304
|
+
});
|
|
305
|
+
row += Math.ceil(members.length / GRID_COLS);
|
|
306
|
+
}
|
|
307
|
+
const externals = nodes.filter((node) => node.type === "external");
|
|
308
|
+
externals.forEach((node, index) => {
|
|
309
|
+
rows.set(node.id, row + Math.floor(index / GRID_COLS));
|
|
310
|
+
});
|
|
311
|
+
return rows;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Place every node on the grid and give every connection an explicit
|
|
316
|
+
* orthogonal route that cannot cross a node: routes leave and enter on the
|
|
317
|
+
* top or bottom side, run horizontally only inside the gap between two rows,
|
|
318
|
+
* and when they must pass other rows they do so in a margin column outside
|
|
319
|
+
* the grid. Each gap and margin hands out distinct lanes so routes never
|
|
320
|
+
* share a segment. The geometry is fixed cell math, the same the renderer
|
|
321
|
+
* applies to `row`/`col`, so the via points land where the nodes are.
|
|
322
|
+
*/
|
|
323
|
+
function placeAndRoute(
|
|
324
|
+
nodes: ReadonlyArray<Unplaced>,
|
|
325
|
+
edges: ReadonlyArray<WeightedEdge>,
|
|
326
|
+
): { layout: SeedLayout; components: SeedComponent[]; connections: SeedConnection[] } {
|
|
327
|
+
const rowOf = assignRows(nodes, edges);
|
|
328
|
+
const colOf = new Map<string, number>();
|
|
329
|
+
const used = new Map<number, number>();
|
|
330
|
+
for (const node of nodes) {
|
|
331
|
+
const row = rowOf.get(node.id) as number;
|
|
332
|
+
const col = used.get(row) ?? 0;
|
|
333
|
+
colOf.set(node.id, col);
|
|
334
|
+
used.set(row, col + 1);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Lane bookkeeping: which gap (below row r) and which margin each route uses.
|
|
338
|
+
const gapLanes = new Map<number, number>();
|
|
339
|
+
const leftLanes = { count: 0 };
|
|
340
|
+
const rightLanes = { count: 0 };
|
|
341
|
+
const takeGap = (row: number): number => {
|
|
342
|
+
const lane = gapLanes.get(row) ?? 0;
|
|
343
|
+
gapLanes.set(row, lane + 1);
|
|
344
|
+
return lane;
|
|
345
|
+
};
|
|
346
|
+
interface Plan {
|
|
347
|
+
edge: WeightedEdge;
|
|
348
|
+
fromSide: SeedSide;
|
|
349
|
+
toSide: SeedSide;
|
|
350
|
+
straight: boolean;
|
|
351
|
+
/** [gap row, lane] pairs in route order, and an optional margin lane. */
|
|
352
|
+
gaps: Array<[number, number]>;
|
|
353
|
+
margin?: { side: "left" | "right"; lane: number };
|
|
354
|
+
}
|
|
355
|
+
const plans: Plan[] = edges.map((edge) => {
|
|
356
|
+
const fromRow = rowOf.get(edge.from) as number;
|
|
357
|
+
const toRow = rowOf.get(edge.to) as number;
|
|
358
|
+
const sameCol = colOf.get(edge.from) === colOf.get(edge.to);
|
|
359
|
+
if (fromRow === toRow) {
|
|
360
|
+
return { edge, fromSide: "bottom", toSide: "bottom", straight: false, gaps: [[fromRow, takeGap(fromRow)]] };
|
|
361
|
+
}
|
|
362
|
+
if (fromRow < toRow) {
|
|
363
|
+
if (toRow === fromRow + 1) {
|
|
364
|
+
return {
|
|
365
|
+
edge,
|
|
366
|
+
fromSide: "bottom",
|
|
367
|
+
toSide: "top",
|
|
368
|
+
straight: sameCol,
|
|
369
|
+
gaps: sameCol ? [] : [[fromRow, takeGap(fromRow)]],
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
return {
|
|
373
|
+
edge,
|
|
374
|
+
fromSide: "bottom",
|
|
375
|
+
toSide: "top",
|
|
376
|
+
straight: false,
|
|
377
|
+
gaps: [
|
|
378
|
+
[fromRow, takeGap(fromRow)],
|
|
379
|
+
[toRow - 1, takeGap(toRow - 1)],
|
|
380
|
+
],
|
|
381
|
+
margin: { side: "left", lane: leftLanes.count++ },
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
if (fromRow === toRow + 1) {
|
|
385
|
+
return {
|
|
386
|
+
edge,
|
|
387
|
+
fromSide: "top",
|
|
388
|
+
toSide: "bottom",
|
|
389
|
+
straight: sameCol,
|
|
390
|
+
gaps: sameCol ? [] : [[toRow, takeGap(toRow)]],
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
return {
|
|
394
|
+
edge,
|
|
395
|
+
fromSide: "top",
|
|
396
|
+
toSide: "bottom",
|
|
397
|
+
straight: false,
|
|
398
|
+
gaps: [
|
|
399
|
+
[fromRow - 1, takeGap(fromRow - 1)],
|
|
400
|
+
[toRow, takeGap(toRow)],
|
|
401
|
+
],
|
|
402
|
+
margin: { side: "right", lane: rightLanes.count++ },
|
|
403
|
+
};
|
|
404
|
+
});
|
|
405
|
+
|
|
406
|
+
const maxGapLanes = Math.max(0, ...gapLanes.values());
|
|
407
|
+
const gapY = Math.max(90, 2 * LANE_MARGIN + Math.max(1, maxGapLanes) * LANE_STEP);
|
|
408
|
+
const originX = LANE_MARGIN + Math.max(1, leftLanes.count) * LANE_STEP + LANE_MARGIN;
|
|
409
|
+
const layout: SeedLayout = {
|
|
410
|
+
mode: "grid",
|
|
411
|
+
origin: [originX, 80],
|
|
412
|
+
cols: GRID_COLS,
|
|
413
|
+
cellW: CELL_W,
|
|
414
|
+
cellH: CELL_H,
|
|
415
|
+
gapX: GAP_X,
|
|
416
|
+
gapY,
|
|
417
|
+
};
|
|
418
|
+
const centerX = (id: string): number => originX + (colOf.get(id) as number) * (CELL_W + GAP_X) + CELL_W / 2;
|
|
419
|
+
const topY = (row: number): number => layout.origin[1] + row * (CELL_H + gapY);
|
|
420
|
+
const laneY = (row: number, lane: number): number => topY(row) + CELL_H + LANE_MARGIN + lane * LANE_STEP;
|
|
421
|
+
const gridRight = originX + GRID_COLS * (CELL_W + GAP_X) - GAP_X;
|
|
422
|
+
const marginX = (margin: NonNullable<Plan["margin"]>): number =>
|
|
423
|
+
margin.side === "left"
|
|
424
|
+
? originX - LANE_MARGIN - margin.lane * LANE_STEP
|
|
425
|
+
: gridRight + LANE_MARGIN + margin.lane * LANE_STEP;
|
|
426
|
+
|
|
427
|
+
const components: SeedComponent[] = nodes.map((node) => ({
|
|
428
|
+
id: node.id,
|
|
429
|
+
type: node.type,
|
|
430
|
+
label: node.label,
|
|
431
|
+
sublabel: node.sublabel,
|
|
432
|
+
row: rowOf.get(node.id) as number,
|
|
433
|
+
col: colOf.get(node.id) as number,
|
|
434
|
+
size: [CELL_W, CELL_H],
|
|
435
|
+
...(node.sources ? { sources: node.sources } : {}),
|
|
436
|
+
}));
|
|
437
|
+
const connectionIds = uniqueIds(plans.map(({ edge }) => `${edge.from}-to-${edge.to}`));
|
|
438
|
+
const connections: SeedConnection[] = plans.map((plan, index) => {
|
|
439
|
+
const { edge } = plan;
|
|
440
|
+
const base: SeedConnection = {
|
|
441
|
+
id: connectionIds[index] as string,
|
|
442
|
+
from: edge.from,
|
|
443
|
+
to: edge.to,
|
|
444
|
+
label: `${edge.weight} import${edge.weight === 1 ? "" : "s"}`,
|
|
445
|
+
fromSide: plan.fromSide,
|
|
446
|
+
toSide: plan.toSide,
|
|
447
|
+
};
|
|
448
|
+
const xa = centerX(edge.from);
|
|
449
|
+
const xb = centerX(edge.to);
|
|
450
|
+
if (plan.straight) {
|
|
451
|
+
// A straight vertical between two adjacent rows in one column: put the
|
|
452
|
+
// label beside the line, centered on the gap, so it covers neither node.
|
|
453
|
+
const upperRow = Math.min(rowOf.get(edge.from) as number, rowOf.get(edge.to) as number);
|
|
454
|
+
const gapMid = topY(upperRow) + CELL_H + gapY / 2;
|
|
455
|
+
return { ...base, route: "straight", labelAt: [xa + LABEL_BESIDE_OFFSET, gapMid] };
|
|
456
|
+
}
|
|
457
|
+
const [first, second] = plan.gaps;
|
|
458
|
+
if (!first) return { ...base, route: "straight" };
|
|
459
|
+
const y1 = laneY(first[0], first[1]);
|
|
460
|
+
if (!plan.margin || !second)
|
|
461
|
+
return {
|
|
462
|
+
...base,
|
|
463
|
+
via: [
|
|
464
|
+
[xa, y1],
|
|
465
|
+
[xb, y1],
|
|
466
|
+
],
|
|
467
|
+
};
|
|
468
|
+
const y2 = laneY(second[0], second[1]);
|
|
469
|
+
const mx = marginX(plan.margin);
|
|
470
|
+
return {
|
|
471
|
+
...base,
|
|
472
|
+
via: [
|
|
473
|
+
[xa, y1],
|
|
474
|
+
[mx, y1],
|
|
475
|
+
[mx, y2],
|
|
476
|
+
[xb, y2],
|
|
477
|
+
],
|
|
478
|
+
};
|
|
479
|
+
});
|
|
480
|
+
return { layout, components, connections };
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
export function buildArchitectureSeed(codewiki: Codewiki, options: BuildArchitectureSeedOptions): ArchitectureSeed {
|
|
484
|
+
const source = codewiki.files.filter((file) => file.lang !== "config");
|
|
485
|
+
const sourceLines = source.reduce((total, file) => total + Math.max(0, file.loc), 0);
|
|
486
|
+
const { areaDepth } = WIKI_DEPTH_STRATEGY[classifyDepth(source.length, sourceLines)];
|
|
487
|
+
const areas = collectAreas(source, areaDepth).slice(0, MAX_SEED_COMPONENTS);
|
|
488
|
+
const lines = firstSymbolLines(codewiki.symbols);
|
|
489
|
+
const areaByFile = new Map<string, string>();
|
|
490
|
+
for (const area of areas) for (const file of area.files) areaByFile.set(file.id, area.key);
|
|
491
|
+
|
|
492
|
+
// Archify's repository-evidence contract: `sources` are only legal when
|
|
493
|
+
// `meta.repository` pins the revision they were read at. Without a GitHub
|
|
494
|
+
// origin at a full sha the seed cites nothing rather than citing what the
|
|
495
|
+
// validator would reject.
|
|
496
|
+
const repository = options.repository;
|
|
497
|
+
const pinned =
|
|
498
|
+
repository && GITHUB_REPOSITORY_URL.test(repository.url) && FULL_REVISION.test(repository.revision)
|
|
499
|
+
? { url: repository.url, revision: repository.revision.toLowerCase() }
|
|
500
|
+
: undefined;
|
|
501
|
+
|
|
502
|
+
// External packages: one component per top external module by import
|
|
503
|
+
// count, so the map shows what the repository leans on beyond itself.
|
|
504
|
+
const externalCounts = new Map<string, number>();
|
|
505
|
+
const externalWeights = new Map<string, number>();
|
|
506
|
+
for (const edge of codewiki.edges) {
|
|
507
|
+
if (isInternalEdge(edge)) continue;
|
|
508
|
+
const fromArea = areaByFile.get(edge.fileId);
|
|
509
|
+
const pkg = externalPackage(edge.externalModule);
|
|
510
|
+
if (fromArea === undefined || pkg === null) continue;
|
|
511
|
+
externalCounts.set(pkg, (externalCounts.get(pkg) ?? 0) + 1);
|
|
512
|
+
const key = `${fromArea}\0${pkg}`;
|
|
513
|
+
externalWeights.set(key, (externalWeights.get(key) ?? 0) + 1);
|
|
514
|
+
}
|
|
515
|
+
const externals = [...externalCounts.entries()]
|
|
516
|
+
.sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
|
|
517
|
+
.slice(0, MAX_SEED_EXTERNALS)
|
|
518
|
+
.map(([module]) => module);
|
|
519
|
+
// Both component kinds share one identity namespace. Reserve all readable
|
|
520
|
+
// spellings before allocating suffixes, including names already ending in -2.
|
|
521
|
+
const componentIds = uniqueIds([
|
|
522
|
+
...areas.map((area) => areaId(area.key)),
|
|
523
|
+
...externals.map((module) => `ext-${areaId(module)}`),
|
|
524
|
+
]);
|
|
525
|
+
const idByArea = new Map(areas.map((area, index) => [area.key, componentIds[index] as string]));
|
|
526
|
+
const idByExternal = new Map(externals.map((module, index) => [module, componentIds[areas.length + index] as string]));
|
|
527
|
+
const nodes: Unplaced[] = areas.map((area) => {
|
|
528
|
+
const sources = pinned ? sourcesFor(area, lines) : [];
|
|
529
|
+
return {
|
|
530
|
+
id: idByArea.get(area.key) as string,
|
|
531
|
+
type: componentTypeFor(area),
|
|
532
|
+
label: area.key,
|
|
533
|
+
sublabel: `${area.files.length} file${area.files.length === 1 ? "" : "s"}, ${area.loc} LOC`,
|
|
534
|
+
...(sources.length > 0 ? { sources } : {}),
|
|
535
|
+
};
|
|
536
|
+
});
|
|
537
|
+
for (const module of externals) {
|
|
538
|
+
const count = externalCounts.get(module) ?? 0;
|
|
539
|
+
nodes.push({
|
|
540
|
+
id: idByExternal.get(module) as string,
|
|
541
|
+
type: "external",
|
|
542
|
+
label: module,
|
|
543
|
+
sublabel: `${count} import${count === 1 ? "" : "s"}`,
|
|
544
|
+
});
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// Internal edges collapsed area to area; self edges are the area's own
|
|
548
|
+
// internal structure and say nothing about boundaries. Preserve destination
|
|
549
|
+
// kind in the weight key: a local area and a package may have the same name.
|
|
550
|
+
const weights = new Map<string, number>();
|
|
551
|
+
for (const edge of codewiki.edges) {
|
|
552
|
+
if (!isInternalEdge(edge)) continue;
|
|
553
|
+
const from = areaByFile.get(edge.fileId);
|
|
554
|
+
const to = areaByFile.get(edge.toFileId);
|
|
555
|
+
if (from === undefined || to === undefined || from === to) continue;
|
|
556
|
+
const key = `${from}\0${to}\0internal`;
|
|
557
|
+
weights.set(key, (weights.get(key) ?? 0) + 1);
|
|
558
|
+
}
|
|
559
|
+
for (const module of externals) {
|
|
560
|
+
for (const area of areas) {
|
|
561
|
+
const weight = externalWeights.get(`${area.key}\0${module}`);
|
|
562
|
+
if (weight) weights.set(`${area.key}\0${module}\0external`, weight);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
const edges: WeightedEdge[] = [...weights.entries()]
|
|
566
|
+
.sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))
|
|
567
|
+
.slice(0, MAX_SEED_CONNECTIONS)
|
|
568
|
+
.map(([key, weight]) => {
|
|
569
|
+
const [fromKey, toKey, kind] = key.split("\0") as [string, string, "internal" | "external"];
|
|
570
|
+
const from = idByArea.get(fromKey) as string;
|
|
571
|
+
const to = (kind === "internal" ? idByArea : idByExternal).get(toKey) as string;
|
|
572
|
+
return { from, to, weight };
|
|
573
|
+
});
|
|
574
|
+
const { layout, components, connections } = placeAndRoute(nodes, edges);
|
|
575
|
+
|
|
576
|
+
const meta: ArchitectureSeed["meta"] = {
|
|
577
|
+
title: options.title,
|
|
578
|
+
quality_profile: "standard",
|
|
579
|
+
...(pinned ? { repository: pinned } : {}),
|
|
580
|
+
};
|
|
581
|
+
return {
|
|
582
|
+
schema_version: 1,
|
|
583
|
+
diagram_type: "architecture",
|
|
584
|
+
meta,
|
|
585
|
+
layout,
|
|
586
|
+
components,
|
|
587
|
+
connections,
|
|
588
|
+
};
|
|
589
|
+
}
|
|
@@ -92,13 +92,13 @@ interface Area {
|
|
|
92
92
|
* filename is dropped first, so a file sitting directly in `src` joins the
|
|
93
93
|
* `src` area instead of becoming an area of its own named after itself.
|
|
94
94
|
*/
|
|
95
|
-
function areaForPath(path: string, maxDepth: number): string {
|
|
95
|
+
export function areaForPath(path: string, maxDepth: number): string {
|
|
96
96
|
const directories = path.split("/").filter(Boolean).slice(0, -1);
|
|
97
97
|
if (directories.length === 0) return ".";
|
|
98
98
|
return directories.slice(0, Math.max(1, maxDepth)).join("/");
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
-
function classifyDepth(sourceFiles: number, sourceLines: number): ResolvedWikiDepth {
|
|
101
|
+
export function classifyDepth(sourceFiles: number, sourceLines: number): ResolvedWikiDepth {
|
|
102
102
|
if (sourceFiles <= 150 && sourceLines <= 30_000) return "simple";
|
|
103
103
|
if (sourceFiles <= 800 && sourceLines <= 150_000) return "medium";
|
|
104
104
|
return "detailed";
|
|
@@ -241,6 +241,7 @@ function observedPath(op: PathOp, args: Record<string, unknown> | null, cwd: str
|
|
|
241
241
|
return explicit === null ? "" : canonicalize(explicit, cwd);
|
|
242
242
|
}
|
|
243
243
|
if (op === "code_nav") {
|
|
244
|
+
if (stringField(args, "source") === "clio") return "";
|
|
244
245
|
const mode = stringField(args, "mode");
|
|
245
246
|
if (mode === null || !CODE_NAV_PATH_MODES.has(mode)) return "";
|
|
246
247
|
const query = stringField(args, "query");
|
|
@@ -107,6 +107,27 @@ const PUMP_MAX_MS = 500;
|
|
|
107
107
|
* waiting or dispatching fewer runs is the way past it, so it retries the same
|
|
108
108
|
* shape and burns the deadline again.
|
|
109
109
|
*/
|
|
110
|
+
export function foregroundEndpointBlock(input: {
|
|
111
|
+
endpointKey?: string;
|
|
112
|
+
limits: CapacityLimits;
|
|
113
|
+
usage: {
|
|
114
|
+
endpoints: Readonly<Record<string, number>>;
|
|
115
|
+
endpointHolders?: Readonly<Record<string, EndpointCapacityHolders>>;
|
|
116
|
+
};
|
|
117
|
+
}): string | null {
|
|
118
|
+
if (input.endpointKey === undefined) return null;
|
|
119
|
+
const limit = input.limits.endpoints[input.endpointKey];
|
|
120
|
+
const active = input.usage.endpoints[input.endpointKey] ?? 0;
|
|
121
|
+
const holders = input.usage.endpointHolders?.[input.endpointKey];
|
|
122
|
+
if (limit === undefined || active < limit || !holders || holders.foregroundStreams < 1) return null;
|
|
123
|
+
return [
|
|
124
|
+
`dispatch: admission denied: endpoint '${endpointLabel(input.endpointKey)}' cannot open a worker slot`,
|
|
125
|
+
` while ${describeEndpointCapacityHolders(holders)} (${active}/${limit} slots).`,
|
|
126
|
+
" The foreground agent cannot release its slot until this tool call returns, so waiting here would deadlock.",
|
|
127
|
+
" Point workers at a second endpoint or raise this target's maxConcurrentRequests to the server's actual slot count.",
|
|
128
|
+
].join("");
|
|
129
|
+
}
|
|
130
|
+
|
|
110
131
|
function describeAdmissionFailure(input: {
|
|
111
132
|
state: "canceled" | "timed_out";
|
|
112
133
|
nodeId: string;
|
|
@@ -245,6 +266,14 @@ export function createCapacityAdmissionController(options: {
|
|
|
245
266
|
const controller: CapacityAdmissionController = {
|
|
246
267
|
async admit(input) {
|
|
247
268
|
if (draining) throw new Error("dispatch: admission denied: this process is shutting down");
|
|
269
|
+
const limits = options.limits();
|
|
270
|
+
const usage = options.usage?.() ?? capacityLeaseUsage({ nowMs: now() });
|
|
271
|
+
const foregroundBlock = foregroundEndpointBlock({
|
|
272
|
+
...(input.endpointKey !== undefined ? { endpointKey: input.endpointKey } : {}),
|
|
273
|
+
limits,
|
|
274
|
+
usage,
|
|
275
|
+
});
|
|
276
|
+
if (foregroundBlock !== null) throw new Error(foregroundBlock);
|
|
248
277
|
const queuedAt = now();
|
|
249
278
|
const requestId = `admit-${queuedAt.toString(36)}-${randomBytes(5).toString("hex")}`;
|
|
250
279
|
pending.set(input.assignmentId, requestId);
|
|
@@ -32,6 +32,7 @@ export type AgentTaskType =
|
|
|
32
32
|
| "docs"
|
|
33
33
|
| "config"
|
|
34
34
|
| "research"
|
|
35
|
+
| "world_knowledge"
|
|
35
36
|
| "unknown";
|
|
36
37
|
export type AgentTaskComplexity = "trivial" | "simple" | "moderate" | "complex";
|
|
37
38
|
export type AgentTaskDomain = "frontend" | "backend" | "infra" | "data" | "security" | "general";
|
|
@@ -53,6 +54,10 @@ const TASK_TYPE_RULES: ReadonlyArray<readonly [AgentTaskType, RegExp]> = [
|
|
|
53
54
|
["debug", /\b(debug|fix|bug|crash|failure|broken|regression)\b/i],
|
|
54
55
|
["refactor", /\b(refactor|clean ?up|restructure|rename|extract|simplify)\b/i],
|
|
55
56
|
["config", /\b(config|configuration|settings|setup|install|ci pipeline|workflow file)\b/i],
|
|
57
|
+
[
|
|
58
|
+
"world_knowledge",
|
|
59
|
+
/\b(?:open[- ]world|ecosystem landscape|industry landscape|state of (?:the )?art|current alternatives|latest alternatives|advisory second opinion)\b/i,
|
|
60
|
+
],
|
|
56
61
|
["research", /\b(research|investigate|explore|survey|compare|find out)\b/i],
|
|
57
62
|
["code_read", /\b(read|explain|understand|summarize|describe|walk through|map|locate|trace)\b/i],
|
|
58
63
|
["code_write", /\b(write|implement|add|create|build|develop|introduce)\b/i],
|
|
@@ -202,6 +207,11 @@ const TASK_SIGNALS: Readonly<
|
|
|
202
207
|
> = {
|
|
203
208
|
code_read: { ids: ["scout"], tags: ["reconnaissance", "symbols", "codewiki"], contracts: ["scout-report"] },
|
|
204
209
|
research: { ids: ["researcher"], tags: ["sources", "external-context", "papers"], contracts: ["research-report"] },
|
|
210
|
+
world_knowledge: {
|
|
211
|
+
ids: ["world-knowledge"],
|
|
212
|
+
tags: ["open-world", "ecosystem", "current-context", "second-opinion"],
|
|
213
|
+
contracts: ["world-knowledge-report"],
|
|
214
|
+
},
|
|
205
215
|
code_review: { ids: ["verifier"], tags: ["review", "verification"], contracts: ["verifier-report"] },
|
|
206
216
|
debug: { ids: ["debugger"], tags: ["debugging", "root-cause"], contracts: ["debugger-report"] },
|
|
207
217
|
test: { ids: ["verifier", "tester"], tags: ["tests", "validation", "regression"], contracts: ["verifier-report"] },
|