@iowarp/clio-coder 0.3.1 → 0.3.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 +233 -373
- package/CONTRIBUTING.md +23 -23
- package/README.md +284 -613
- package/dist/{acp-FPR54DGL.js → acp-P2AQILE2.js} +43 -53
- package/dist/{agents-OGPIHPJH.js → agents-72W3BI7I.js} +43 -26
- package/dist/assets/codewiki.json +1 -1
- package/dist/{auth-IC3K6NIZ.js → auth-5TWEIYDN.js} +20 -12
- package/dist/chunk-2DJ2KNFG.js +2095 -0
- package/dist/{chunk-IS3ONKU3.js → chunk-2IR2NMPA.js} +6 -4
- package/dist/chunk-2SFS6XQE.js +122 -0
- package/dist/{chunk-PV4JUBVJ.js → chunk-2TLUCQVG.js} +40 -21
- package/dist/chunk-2VTFPG5O.js +48 -0
- package/dist/chunk-4BJ5BYCE.js +61 -0
- package/dist/{chunk-474KN5II.js → chunk-4BPJXDWC.js} +111 -181
- package/dist/chunk-4VP4KH3K.js +962 -0
- package/dist/chunk-4XUGQOHA.js +797 -0
- package/dist/chunk-4ZG3XFUR.js +77 -0
- package/dist/chunk-5B2AEOW5.js +5407 -0
- package/dist/{chunk-K2ITRMHZ.js → chunk-5TSRNF4G.js} +6 -138
- package/dist/{chunk-4QKXUHSR.js → chunk-5UFT4SUX.js} +70 -20
- package/dist/{chunk-OLBBMFRD.js → chunk-5UUP6MWO.js} +24 -62
- package/dist/chunk-65DEGPJ6.js +52 -0
- package/dist/chunk-6EJMN2Y3.js +17 -0
- package/dist/chunk-6N5PTWMY.js +136 -0
- package/dist/chunk-6SGHMWE3.js +277 -0
- package/dist/chunk-6XLNIQDB.js +27 -0
- package/dist/chunk-7CR24IG7.js +242 -0
- package/dist/chunk-7MNJORFF.js +22 -0
- package/dist/{chunk-KY56HMHH.js → chunk-A3CYT5EX.js} +125 -31
- package/dist/chunk-AGYYIBLL.js +1069 -0
- package/dist/{chunk-GB6QRBXN.js → chunk-APJ265NV.js} +54 -1187
- package/dist/{chunk-673JJUWJ.js → chunk-BMEMKKIT.js} +2 -2
- package/dist/chunk-CBCAPZAA.js +229 -0
- package/dist/chunk-CMZWFGD2.js +352 -0
- package/dist/chunk-COU2UHX6.js +400 -0
- package/dist/chunk-DSELYM6W.js +1077 -0
- package/dist/chunk-DUYJ5IO6.js +644 -0
- package/dist/chunk-ECH6PKUQ.js +39 -0
- package/dist/chunk-ED4KHGC3.js +143 -0
- package/dist/chunk-EKMEHE4H.js +340 -0
- package/dist/chunk-FCSXB6T2.js +338 -0
- package/dist/chunk-FJ3H4MN5.js +48 -0
- package/dist/{chunk-RPTR2H26.js → chunk-FNTMWMX5.js} +21 -15
- package/dist/chunk-FQ4SKYE4.js +29 -0
- package/dist/chunk-G4BMMOKF.js +182 -0
- package/dist/{chunk-ZPY3JZ5E.js → chunk-GGXXDWE4.js} +183 -1233
- package/dist/chunk-HC4CLZ2Y.js +68 -0
- package/dist/{chunk-LU4TK2PR.js → chunk-HFSBBKSQ.js} +5 -56
- package/dist/{chunk-PIUMUEMV.js → chunk-HKIYEGME.js} +10 -6
- package/dist/chunk-I4HZDVNP.js +73 -0
- package/dist/chunk-IKCO5N3L.js +162 -0
- package/dist/chunk-IR4CFBFN.js +56 -0
- package/dist/{chunk-R5KLMSBV.js → chunk-J5Q24KAG.js} +2 -2
- package/dist/chunk-J7CWMCQD.js +255 -0
- package/dist/{chunk-K5XEMXTI.js → chunk-JVCV3ICN.js} +1 -1
- package/dist/chunk-KZWTDYJF.js +217 -0
- package/dist/chunk-LBMZMYH2.js +285 -0
- package/dist/{chunk-G34LV2PF.js → chunk-LM5TQCJZ.js} +84 -170
- package/dist/chunk-LW6DSM3M.js +5135 -0
- package/dist/chunk-LWLEKMDQ.js +3482 -0
- package/dist/{chunk-H6F6BYOH.js → chunk-LZSJBIVT.js} +7003 -7434
- package/dist/{chunk-HQQID6OA.js → chunk-M6SHUN7Q.js} +5 -5
- package/dist/{chunk-FST4FYJB.js → chunk-MFFY33HR.js} +99 -140
- package/dist/{chunk-BSU2YIWB.js → chunk-MVVUPGPW.js} +131 -136
- package/dist/chunk-OAO4GE4M.js +619 -0
- package/dist/{chunk-Q3RUPKEJ.js → chunk-OC7FIQPC.js} +58 -189
- package/dist/chunk-OKGUZO2U.js +34 -0
- package/dist/{chunk-GAEBEQVI.js → chunk-OOJYHWRB.js} +32 -346
- package/dist/{chunk-Q5WJOSJ7.js → chunk-OQ33BKR3.js} +2 -1
- package/dist/chunk-OQE5J4C6.js +73 -0
- package/dist/{chunk-KKNLWXI6.js → chunk-ORBHGJC5.js} +8 -8
- package/dist/{chunk-MAR7Y6HW.js → chunk-PAJK6MAQ.js} +23 -16
- package/dist/{chunk-M5T5VO65.js → chunk-PIWWS5BL.js} +837 -635
- package/dist/chunk-POHLU5DW.js +1186 -0
- package/dist/chunk-QKMUKYO7.js +4961 -0
- package/dist/chunk-SRDMMSEP.js +16405 -0
- package/dist/chunk-SST6Z5JA.js +80 -0
- package/dist/chunk-STBPMHSX.js +2456 -0
- package/dist/chunk-T6YILFSB.js +80 -0
- package/dist/chunk-TZK7PACC.js +174 -0
- package/dist/chunk-TZTZS7QK.js +227 -0
- package/dist/{chunk-ASND7OZK.js → chunk-UFIIWP2H.js} +13 -13
- package/dist/chunk-UOV2BYIW.js +107 -0
- package/dist/{chunk-PFEFKVGL.js → chunk-V6RTAOC2.js} +13 -11
- package/dist/chunk-VAKQQHWR.js +434 -0
- package/dist/chunk-VG7TBQIY.js +128 -0
- package/dist/chunk-VJWL6YS5.js +244 -0
- package/dist/{chunk-EYOKLTMF.js → chunk-VPAYEGVX.js} +17 -3
- package/dist/chunk-WEH5XRJQ.js +32 -0
- package/dist/chunk-X4RCMKVQ.js +641 -0
- package/dist/{chunk-TEKV33Q5.js → chunk-X6IAEBZR.js} +65 -33
- package/dist/chunk-XBXAASKX.js +18 -0
- package/dist/chunk-XN3L4EYL.js +46 -0
- package/dist/{chunk-RDLVBZEO.js → chunk-YCWGATWI.js} +6 -4
- package/dist/chunk-YHZX5GEU.js +193 -0
- package/dist/chunk-YXLYO42X.js +91 -0
- package/dist/{chunk-NMOX6HFD.js → chunk-ZDOOVTXZ.js} +29 -77
- package/dist/chunk-ZI647VB5.js +37 -0
- package/dist/{chunk-C4PTHK7P.js → chunk-ZWLZP4ZT.js} +5 -5
- package/dist/chunk-ZWMF7253.js +1882 -0
- package/dist/cli/index.js +62 -54
- package/dist/clio-JOU4FXVA.js +25 -0
- package/dist/code-nav-7AX6FYE6.js +600 -0
- package/dist/codewiki/build-worker.js +66 -0
- package/dist/compile-cache-CVJMMODC.js +18 -0
- package/dist/{components-DMAOEKFB.js → components-KELWS457.js} +11 -6
- package/dist/{config-IRUQ7SE4.js → config-XCDVKR23.js} +92 -55
- package/dist/configure-4GAP54ZW.js +42 -0
- package/dist/{context-5RADCKTR.js → context-4UOGGLQ5.js} +71 -35
- package/dist/context-5VKGUVJJ.js +866 -0
- package/dist/{context-3KWFLHJG.js → context-77FM5DV5.js} +15 -13
- package/dist/{context-clear-7TSNPAAI.js → context-clear-XXJRLCJJ.js} +54 -28
- package/dist/{context-index-W4RLWOQH.js → context-index-BZ4UYMTC.js} +30 -24
- package/dist/dispatch-runner-QPRDDBDX.js +1997 -0
- package/dist/{docs-5AWSPS37.js → docs-2C2LTVT2.js} +23 -10
- package/dist/{doctor-UC5NAJYQ.js → doctor-HR46URBJ.js} +27 -17
- package/dist/{eval-U6TJHRLX.js → eval-XSSNATB4.js} +29 -16
- package/dist/{evidence-YEGUW4L3.js → evidence-6HG2PY2B.js} +46 -26
- package/dist/{evolve-TXARCTPG.js → evolve-K7YU3NCY.js} +45 -25
- package/dist/{extensions-OZFJ3A3G.js → extensions-QVDOHDGJ.js} +16 -7
- package/dist/{fleet-6G3DHNYE.js → fleet-VY3HHKN6.js} +163 -54
- package/dist/{fleet-preflight-DSNT37JK.js → fleet-preflight-DDN536IT.js} +7 -4
- package/dist/{init-KZ5QTF6M.js → init-JYGXI3FK.js} +69 -32
- package/dist/{memory-73ESV5YC.js → memory-WFZMGYHX.js} +48 -27
- package/dist/{models-A4PVNWJK.js → models-I5QWSEOM.js} +39 -25
- package/dist/monitor-GE4ID3IA.js +661 -0
- package/dist/{chunk-FCIH3BIZ.js → orchestrator-EM5MC3HM.js} +15979 -12407
- package/dist/{paths-C4H6IV77.js → paths-UXLN5YYZ.js} +10 -5
- package/dist/{preload-6WVMHX3A.js → preload-P6DGH2PZ.js} +2 -2
- package/dist/{reset-BGW6OGMV.js → reset-L2FQEE3E.js} +16 -10
- package/dist/{run-YTPEYQOH.js → run-ZU3QMZPZ.js} +101 -61
- package/dist/{share-YIFFV4NQ.js → share-S5BZQC5I.js} +15 -8
- package/dist/{skills-2V6RA3OQ.js → skills-X5VXCRNQ.js} +34 -14
- package/dist/{skills-eval-S2TVJO4F.js → skills-eval-WKIHWTHR.js} +70 -34
- package/dist/steer-GGWFUJUD.js +77 -0
- package/dist/{targets-TYXLPB23.js → targets-SNCPI2NR.js} +43 -27
- package/dist/terminal-lease-BNAHVHBS.js +395 -0
- package/dist/{trace-GGOJ6Q6Z.js → trace-PNCASAXC.js} +41 -16
- package/dist/{chunk-N6F52NLF.js → tree-sitter-HGKH6LG4.js} +28 -2306
- package/dist/{uninstall-LLLT4F4W.js → uninstall-FZCQCDKC.js} +10 -5
- package/dist/{upgrade-33G2LMM5.js → upgrade-JQHHPQ4K.js} +45 -25
- package/dist/{usage-ZAFSXKKG.js → usage-OR4O5SMZ.js} +62 -31
- package/dist/verify-375KUB3Y.js +716 -0
- package/dist/web-fetch-2YHJ3KTG.js +638 -0
- package/dist/{wiki-generate-NUQCVOQ3.js → wiki-generate-UEXP2ARI.js} +74 -34
- package/dist/worker/entry.js +221 -36
- package/dist/workspace-G4ZWUIPR.js +22 -0
- package/docs/README.md +22 -17
- package/docs/acp.md +168 -16
- package/docs/alcf-provider.md +1 -1
- package/docs/architecture.md +136 -7
- package/docs/artifact-versions.md +1 -1
- package/docs/built-in-agents.md +1 -1
- package/docs/capacity-and-scheduling.md +1 -1
- package/docs/commands-and-modes.md +114 -71
- package/docs/config-knobs-audit.md +1 -3
- package/docs/configuration-and-targets.md +174 -46
- package/docs/context-engine.md +29 -6
- package/docs/development-pipeline.md +26 -1
- package/docs/dispatch-architecture-rationale.md +1 -1
- package/docs/documentation-coverage.md +2 -2
- package/docs/documentation-guide.md +1 -1
- package/docs/environment-variables.md +13 -5
- package/docs/eval-runner.md +1 -1
- package/docs/evals-internal.md +1 -1
- package/docs/evidence-and-memory.md +6 -2
- package/docs/evolution.md +2 -2
- package/docs/exit-codes-and-output.md +15 -9
- package/docs/extensions-and-sharing.md +9 -9
- package/docs/fleet-dispatch.md +7 -5
- package/docs/git-commit-provenance.md +120 -0
- package/docs/glossary.md +1 -1
- package/docs/installation-and-lifecycle.md +34 -27
- package/docs/middleware-and-components.md +1 -1
- package/docs/model-catalog.md +45 -14
- package/docs/observability.md +8 -5
- package/docs/performance-methodology.md +491 -0
- package/docs/pi-boundary.md +72 -0
- package/docs/proactive-memory.md +3 -3
- package/docs/prompt-envelope-and-tools.md +24 -3
- package/docs/provider-adapter-cookbook.md +57 -4
- package/docs/release-cut-checklist.md +129 -115
- package/docs/safety-model.md +9 -5
- package/docs/scientific-validation.md +3 -3
- package/docs/session-lifecycle.md +55 -12
- package/docs/skills-marketplace.md +12 -8
- package/docs/time-conventions.md +1 -1
- package/docs/tool-usage.md +3 -3
- package/docs/trace-store.md +1 -1
- package/docs/troubleshooting.md +10 -7
- package/docs/tui-design.md +47 -10
- package/docs/worker-dispatch-mechanics.md +1 -1
- package/package.json +19 -22
- package/skills/coding/ast-grep/SKILL.md +136 -0
- package/skills/coding/ast-grep/evals.md +56 -0
- package/skills/coding/ast-grep/references/rule_reference.md +297 -0
- package/skills/coding/coding-standards/SKILL.md +113 -0
- package/skills/coding/coding-standards/evals.md +34 -0
- package/skills/coding/prototype/SKILL.md +86 -0
- package/skills/coding/prototype/evals.md +42 -0
- package/skills/coding/prototype/references/LOGIC.md +67 -0
- package/skills/coding/prototype/references/UI.md +112 -0
- package/skills/coding/tdd/SKILL.md +101 -0
- package/skills/coding/tdd/evals.md +41 -0
- package/skills/coding/tdd/references/mocking.md +59 -0
- package/skills/coding/tdd/references/tests.md +77 -0
- package/skills/context/context-handoff/SKILL.md +126 -0
- package/skills/context/context-handoff/evals.md +57 -0
- package/skills/context/context-handoff/scripts/new-handoff.sh +26 -0
- package/skills/context/context-prime/SKILL.md +95 -0
- package/skills/context/context-prime/evals.md +54 -0
- package/skills/meta/clio-dev/SKILL.md +91 -0
- package/skills/meta/clio-dev/evals.md +45 -0
- package/skills/meta/clio-test/SKILL.md +130 -0
- package/skills/meta/clio-test/evals.md +43 -0
- package/skills/meta/clio-test/references/harness.md +97 -0
- package/skills/meta/clio-test/references/test-map.md +59 -0
- package/skills/meta/credentials/SKILL.md +125 -0
- package/skills/meta/credentials/evals.md +104 -0
- package/skills/meta/find-skills/SKILL.md +72 -0
- package/skills/meta/find-skills/evals.md +47 -0
- package/skills/meta/herdr/SKILL.md +127 -0
- package/skills/meta/herdr/evals.md +38 -0
- package/skills/meta/skill-craft/SKILL.md +102 -0
- package/skills/meta/skill-craft/evals.md +41 -0
- package/skills/planning/architecture/SKILL.md +129 -0
- package/skills/planning/architecture/evals.md +36 -0
- package/skills/planning/backlog/SKILL.md +90 -0
- package/skills/planning/backlog/evals.md +43 -0
- package/skills/planning/prd/SKILL.md +82 -0
- package/skills/planning/prd/evals.md +49 -0
- package/skills/planning/product-intent/SKILL.md +112 -0
- package/skills/planning/product-intent/evals.md +36 -0
- package/skills/planning/tech-spec/SKILL.md +115 -0
- package/skills/planning/tech-spec/evals.md +47 -0
- package/skills/registry.yaml +136 -0
- package/skills/research/arxiv-literature/SKILL.md +104 -0
- package/skills/research/arxiv-literature/evals.md +58 -0
- package/skills/research/experiment-protocol/SKILL.md +122 -0
- package/skills/research/experiment-protocol/evals.md +91 -0
- package/skills/research/scientific-debugging/SKILL.md +119 -0
- package/skills/research/scientific-debugging/evals.md +138 -0
- package/skills/research/scientific-modernization/SKILL.md +138 -0
- package/skills/research/scientific-modernization/evals.md +84 -0
- package/skills/workflow/design-council/SKILL.md +139 -0
- package/skills/workflow/design-council/evals.md +97 -0
- package/skills/workflow/grill-me/SKILL.md +186 -0
- package/skills/workflow/grill-me/evals.md +78 -0
- package/skills/workflow/workflow-distiller/SKILL.md +136 -0
- package/skills/workflow/workflow-distiller/evals.md +107 -0
- package/src/cli/acp.ts +31 -4
- package/src/cli/clio.ts +68 -6
- package/src/cli/config-inspect.ts +28 -22
- package/src/cli/configure.ts +47 -9
- package/src/cli/context-clear.ts +2 -2
- package/src/cli/context-index.ts +21 -23
- package/src/cli/context.ts +13 -8
- package/src/cli/default-target.ts +9 -17
- package/src/cli/docs.ts +11 -5
- package/src/cli/evidence.ts +4 -1
- package/src/cli/extensions.ts +10 -1
- package/src/cli/fleet.ts +47 -6
- package/src/cli/index.ts +55 -26
- package/src/cli/memory.ts +3 -1
- package/src/cli/models.ts +1 -1
- package/src/cli/modes/json-stream.ts +37 -1
- package/src/cli/modes/print.ts +24 -9
- package/src/cli/run.ts +2 -2
- package/src/cli/skills-eval.ts +23 -8
- package/src/cli/skills.ts +19 -4
- package/src/cli/targets.ts +4 -0
- package/src/cli/text-layout.ts +15 -5
- package/src/cli/trace.ts +62 -14
- package/src/cli/upgrade.ts +18 -2
- package/src/cli/usage.ts +10 -3
- package/src/cli/wiki-generate.ts +2 -1
- package/src/core/agent-environment.ts +7 -0
- package/src/core/bash-exec.ts +72 -1
- package/src/core/boot-trace.ts +9 -4
- package/src/core/bus-events.ts +20 -4
- package/src/core/commit-attribution.ts +157 -0
- package/src/core/compile-cache.ts +159 -0
- package/src/core/config.ts +131 -2
- package/src/core/defaults.ts +39 -5
- package/src/core/domain-loader.ts +12 -5
- package/src/core/git-commit-attribution.ts +387 -0
- package/src/core/incomplete-installation.ts +45 -0
- package/src/core/response-schema.ts +1 -1
- package/src/core/safe-exec.ts +13 -1
- package/src/core/settings-layers.ts +155 -21
- package/src/core/skill-activation.ts +1 -1
- package/src/core/startup-timer.ts +3 -3
- package/src/core/state-file-lock.ts +13 -1
- package/src/core/termination.ts +78 -5
- package/src/domains/config/classify.ts +15 -3
- package/src/domains/config/extension.ts +19 -13
- package/src/domains/config/index.ts +10 -0
- package/src/domains/config/keybindings.ts +45 -9
- package/src/domains/context/bootstrap-prompt.ts +1 -1
- package/src/domains/context/bootstrap.ts +111 -18
- package/src/domains/context/clear.ts +16 -11
- package/src/domains/context/clio-md.ts +111 -9
- package/src/domains/context/codewiki/artifact.ts +400 -0
- package/src/domains/context/codewiki/build-worker-protocol.ts +24 -0
- package/src/domains/context/codewiki/build-worker.ts +54 -0
- package/src/domains/context/codewiki/coordinator.ts +182 -0
- package/src/domains/context/codewiki/indexer.ts +59 -144
- package/src/domains/context/codewiki/paths.ts +67 -0
- package/src/domains/context/codewiki/schema.ts +80 -0
- package/src/domains/context/codewiki/tree-sitter.ts +1 -1
- package/src/domains/context/contract.ts +11 -5
- package/src/domains/context/extension.ts +94 -143
- package/src/domains/context/fingerprint.ts +3 -1
- package/src/domains/context/index.ts +12 -22
- package/src/domains/context/project-metadata.ts +19 -0
- package/src/domains/context/prompt-context.ts +9 -10
- package/src/domains/context/refresh.ts +29 -21
- package/src/domains/context/runtime.ts +17 -0
- package/src/domains/context/wiki/generate.ts +39 -34
- package/src/domains/context/wiki/plan.ts +1 -1
- package/src/domains/context/wiki/prompts.ts +21 -8
- package/src/domains/dispatch/code-step.ts +20 -1
- package/src/domains/dispatch/extension.ts +158 -21
- package/src/domains/dispatch/failure-classification.ts +6 -0
- package/src/domains/dispatch/fleet-commit-attribution.ts +56 -0
- package/src/domains/dispatch/orphan-recovery.ts +50 -8
- package/src/domains/dispatch/receipt-integrity.ts +5 -0
- package/src/domains/dispatch/state.ts +31 -6
- package/src/domains/dispatch/transport.ts +2 -1
- package/src/domains/dispatch/types.ts +14 -0
- package/src/domains/dispatch/worker-spawn.ts +21 -2
- package/src/domains/eval/metrics/context.ts +1 -1
- package/src/domains/eval/types.ts +0 -1
- package/src/domains/evidence/build.ts +41 -1
- package/src/domains/lifecycle/migrations/2026-08-18-lmstudio-runtime-id.ts +52 -0
- package/src/domains/lifecycle/migrations/index.ts +24 -4
- package/src/domains/middleware/hooks-io.ts +12 -0
- package/src/domains/middleware/skills-reminder.ts +30 -15
- package/src/domains/prompts/compiler.ts +142 -84
- package/src/domains/prompts/contract.ts +18 -2
- package/src/domains/prompts/extension.ts +39 -7
- package/src/domains/prompts/fragment-loader.ts +0 -1
- package/src/domains/prompts/fragments/identity/clio.md +2 -4
- package/src/domains/prompts/fragments/identity/docs-routing.md +10 -0
- package/src/domains/prompts/fragments/identity/self-awareness.md +1 -45
- package/src/domains/prompts/fragments/operating/contract.md +4 -50
- package/src/domains/prompts/fragments/operating/delegation.md +42 -0
- package/src/domains/prompts/fragments/operating/skills.md +26 -0
- package/src/domains/prompts/fragments/operating/worker.md +16 -0
- package/src/domains/prompts/fragments/safety/auto-edit.md +5 -5
- package/src/domains/prompts/fragments/safety/full-auto.md +3 -3
- package/src/domains/prompts/fragments/safety/read-only.md +4 -4
- package/src/domains/prompts/fragments/safety/suggest.md +2 -2
- package/src/domains/prompts/fragments/wiki/page.md +10 -0
- package/src/domains/prompts/fragments/wiki/plan.md +10 -0
- package/src/domains/prompts/preload.ts +3 -3
- package/src/domains/providers/auth/api-key.ts +1 -1
- package/src/domains/providers/auth/backend-file.ts +20 -10
- package/src/domains/providers/auth/backend-memory.ts +59 -4
- package/src/domains/providers/auth/boot-status.ts +65 -0
- package/src/domains/providers/auth/oauth.ts +2 -1
- package/src/domains/providers/auth/storage.ts +97 -38
- package/src/domains/providers/capabilities.ts +12 -4
- package/src/domains/providers/contract.ts +15 -4
- package/src/domains/providers/extension.ts +18 -6
- package/src/domains/providers/model-runtime-capabilities.ts +15 -4
- package/src/domains/providers/models/local-models/clio-local-coding-targets.yaml +118 -35
- package/src/domains/providers/plugins.ts +5 -3
- package/src/domains/providers/probe/fingerprint.ts +25 -5
- package/src/domains/providers/registry.ts +31 -10
- package/src/domains/providers/runtimes/boot-manifest.ts +55 -0
- package/src/domains/providers/runtimes/builtins.ts +2 -2
- package/src/domains/providers/runtimes/common/lmstudio-http.ts +423 -0
- package/src/domains/providers/runtimes/common/local-synth.ts +6 -7
- package/src/domains/providers/runtimes/local-native/lmstudio.ts +241 -0
- package/src/domains/providers/support.ts +6 -3
- package/src/domains/providers/types/local-model-quirks.ts +7 -9
- package/src/domains/providers/types/runtime-descriptor.ts +12 -1
- package/src/domains/providers/types/target-descriptor.ts +22 -0
- package/src/domains/resources/contract.ts +0 -1
- package/src/domains/resources/extension.ts +1 -3
- package/src/domains/resources/loader.ts +3 -4
- package/src/domains/resources/prompts/loader.ts +16 -2
- package/src/domains/resources/prompts/substitute.ts +1 -65
- package/src/domains/resources/skills/content-hash.ts +2 -0
- package/src/domains/resources/skills/install.ts +17 -0
- package/src/domains/resources/skills/loader.ts +17 -10
- package/src/domains/resources/skills/marketplace.ts +55 -9
- package/src/domains/safety/action-classifier.ts +4 -2
- package/src/domains/safety/audit.ts +8 -2
- package/src/domains/safety/extension.ts +1 -1
- package/src/domains/session/compaction/branch-summary.ts +3 -2
- package/src/domains/session/compaction/cut-point.ts +2 -1
- package/src/domains/session/compaction/tokens.ts +2 -1
- package/src/domains/session/context-ledger.ts +14 -0
- package/src/domains/session/contract.ts +15 -0
- package/src/domains/session/decision-board.ts +190 -0
- package/src/domains/session/entries.ts +66 -3
- package/src/domains/session/extension.ts +93 -12
- package/src/domains/session/retry.ts +10 -18
- package/src/domains/session/session-artifacts.ts +107 -0
- package/src/domains/session/task-board.ts +207 -13
- package/src/domains/session/tree/active-path.ts +44 -5
- package/src/domains/session/tree/fork.ts +26 -27
- package/src/domains/session/tree/preview.ts +2 -2
- package/src/domains/session/workspace/git-probe.ts +17 -11
- package/src/domains/user-tasks/store.ts +297 -0
- package/src/engine/acp/errors.ts +96 -0
- package/src/engine/acp/server.ts +1728 -146
- package/src/engine/acp/transport.ts +135 -14
- package/src/engine/acp/types.ts +26 -0
- package/src/engine/agent.ts +3 -3
- package/src/engine/ai.ts +32 -27
- package/src/engine/alcf-oauth.ts +26 -19
- package/src/engine/api-registry.ts +223 -0
- package/src/engine/apis/index.ts +3 -7
- package/src/engine/apis/llamacpp-residency.ts +49 -9
- package/src/engine/apis/lmstudio-residency.ts +5 -21
- package/src/engine/apis/lmstudio.ts +243 -0
- package/src/engine/apis/ollama-native.ts +24 -3
- package/src/engine/apis/openai-completions.ts +170 -91
- package/src/engine/apis/residency.ts +139 -3
- package/src/engine/apis/types.ts +16 -0
- package/src/engine/env-api-keys.ts +98 -0
- package/src/engine/gemma-channel-filter.ts +223 -0
- package/src/engine/instrumented-tui.ts +192 -0
- package/src/engine/messages.ts +14 -0
- package/src/engine/models.ts +42 -0
- package/src/engine/oauth.ts +16 -12
- package/src/engine/prompt-templates.ts +1 -0
- package/src/engine/provider-payload.ts +16 -59
- package/src/engine/strip-tokenizer-sentinels.ts +1 -1
- package/src/engine/truncate.ts +9 -0
- package/src/engine/tui.ts +17 -9
- package/src/engine/types.ts +3 -6
- package/src/engine/worker-runtime-capabilities.ts +5 -0
- package/src/engine/worker-runtime.ts +1 -1
- package/src/engine/worker-tools.ts +9 -4
- package/src/entry/boot-options.ts +50 -0
- package/src/entry/orchestrator.ts +288 -150
- package/src/interactive/application-controller.ts +89 -2
- package/src/interactive/chat-loop.ts +266 -41
- package/src/interactive/chat-panel.ts +715 -278
- package/src/interactive/chat-renderer.ts +306 -85
- package/src/interactive/clio-editor.ts +3 -8
- package/src/interactive/command-fallbacks.ts +2 -2
- package/src/interactive/context-overlay.ts +27 -1
- package/src/interactive/editor-submit.ts +253 -24
- package/src/interactive/export-html/ansi-to-html.ts +161 -0
- package/src/interactive/export-html/index.ts +51 -0
- package/src/interactive/export-html/template.ts +45 -0
- package/src/interactive/export-html/tool-renderer.ts +54 -0
- package/src/interactive/footer/dashboard.ts +4 -0
- package/src/interactive/footer/notifications.ts +1 -1
- package/src/interactive/footer/widgets.ts +42 -22
- package/src/interactive/footer-panel.ts +8 -3
- package/src/interactive/format-time.ts +14 -2
- package/src/interactive/interactive-application.ts +203 -17
- package/src/interactive/interactive-event-projection.ts +18 -1
- package/src/interactive/interactive-input-runtime.ts +50 -4
- package/src/interactive/interactive-presentation.ts +151 -19
- package/src/interactive/interactive-shell.ts +268 -14
- package/src/interactive/interactive-slash-runtime.ts +184 -117
- package/src/interactive/interactive-tickers.ts +38 -7
- package/src/interactive/keybinding-manager.ts +1 -1
- package/src/interactive/layout.ts +40 -3
- package/src/interactive/overlay-frame.ts +1 -1
- package/src/interactive/overlay-general-openers.ts +58 -1
- package/src/interactive/overlay-key-routing.ts +3 -0
- package/src/interactive/overlay-lifecycle.ts +13 -0
- package/src/interactive/overlay-permission-lifecycle.ts +2 -1
- package/src/interactive/overlay-session-lifecycle.ts +69 -12
- package/src/interactive/overlays/ask-user.ts +146 -24
- package/src/interactive/overlays/decisions.ts +300 -0
- package/src/interactive/overlays/help-reference.ts +15 -10
- package/src/interactive/overlays/model-selector.ts +34 -16
- package/src/interactive/overlays/session-selector.ts +18 -0
- package/src/interactive/overlays/settings.ts +105 -17
- package/src/interactive/overlays/skills-hub.ts +4 -4
- package/src/interactive/overlays/tree-selector.ts +41 -6
- package/src/interactive/render-trace.ts +499 -90
- package/src/interactive/renderers/compaction-summary.ts +2 -2
- package/src/interactive/renderers/diff.ts +115 -104
- package/src/interactive/renderers/mermaid.ts +53 -0
- package/src/interactive/renderers/tool-execution.ts +516 -168
- package/src/interactive/renderers/worker-entry.ts +20 -4
- package/src/interactive/session-switch-settlement.ts +10 -0
- package/src/interactive/slash-autocomplete.ts +6 -114
- package/src/interactive/slash-commands.ts +135 -47
- package/src/interactive/slash-spec.ts +9 -38
- package/src/interactive/status/controller.ts +5 -1
- package/src/interactive/status/index.ts +12 -1
- package/src/interactive/status/reasoning.ts +87 -0
- package/src/interactive/status/summary.ts +13 -2
- package/src/interactive/stdout-backpressure.ts +99 -0
- package/src/interactive/stream-pacer.ts +530 -0
- package/src/interactive/stream-pacing-policy.ts +66 -0
- package/src/interactive/tasks-overlay.ts +368 -14
- package/src/interactive/terminal-lease.ts +485 -0
- package/src/interactive/theme/tokens.ts +1 -1
- package/src/interactive/transcript-detail.ts +120 -0
- package/src/interactive/turn-context.ts +4 -3
- package/src/interactive/turn-persistence.ts +30 -13
- package/src/interactive/turn-queues.ts +12 -0
- package/src/interactive/turn-recovery.ts +25 -8
- package/src/interactive/turn-runtime.ts +79 -12
- package/src/interactive/turn-state.ts +10 -0
- package/src/interactive/view/artifacts.ts +114 -4
- package/src/interactive/view/view-overlay.ts +3 -0
- package/src/interactive/welcome-dashboard.ts +17 -16
- package/src/interactive/worker-receipts.ts +52 -3
- package/src/interactive/worker-stream.ts +5 -1
- package/src/tools/agent-tools.ts +23 -3
- package/src/tools/artifact.ts +2 -2
- package/src/tools/ask-user.ts +23 -13
- package/src/tools/bash.ts +30 -2
- package/src/tools/bootstrap.ts +34 -431
- package/src/tools/builtin-tool-catalog.ts +271 -0
- package/src/tools/codewiki/code-nav-surface.ts +29 -0
- package/src/tools/codewiki/code-nav.ts +8 -22
- package/src/tools/codewiki/shared.ts +41 -38
- package/src/tools/context/docs-engine.ts +14 -3
- package/src/tools/context/index.ts +107 -28
- package/src/tools/context/surface.ts +19 -0
- package/src/tools/core-bootstrap.ts +168 -0
- package/src/tools/credential-present.ts +5 -5
- package/src/tools/dispatch-admission.ts +533 -0
- package/src/tools/dispatch-background.ts +54 -0
- package/src/tools/dispatch-event-text.ts +6 -0
- package/src/tools/dispatch-plan.ts +9 -4
- package/src/tools/dispatch-run-events.ts +238 -0
- package/src/tools/dispatch-runner.ts +2370 -0
- package/src/tools/dispatch-scout-admission.ts +295 -0
- package/src/tools/dispatch-types.ts +77 -0
- package/src/tools/dispatch.ts +67 -3161
- package/src/tools/find.ts +4 -2
- package/src/tools/grep.ts +2 -2
- package/src/tools/lazy-tool.ts +60 -0
- package/src/tools/ledger.ts +3 -3
- package/src/tools/monitor-surface.ts +36 -0
- package/src/tools/monitor.ts +2 -32
- package/src/tools/observers.ts +2 -2
- package/src/tools/presentation.ts +107 -0
- package/src/tools/registry.ts +45 -27
- package/src/tools/safe-exec.ts +2 -2
- package/src/tools/steer-surface.ts +17 -0
- package/src/tools/steer.ts +2 -13
- package/src/tools/tasks.ts +108 -11
- package/src/tools/truncate.ts +25 -184
- package/src/tools/verify/frontend.ts +3 -1
- package/src/tools/verify/index.ts +3 -38
- package/src/tools/verify/surface.ts +46 -0
- package/src/tools/web-fetch-surface.ts +23 -0
- package/src/tools/web-fetch.ts +2 -20
- package/src/tools/write.ts +7 -2
- package/src/worker/entry.ts +39 -2
- package/src/worker/spec-contract.ts +26 -5
- package/dist/chunk-7SS2CTV2.js +0 -61361
- package/dist/chunk-DKGKUHFA.js +0 -924
- package/dist/chunk-GEP36Y4X.js +0 -12796
- package/dist/chunk-XYWBQRDM.js +0 -137
- package/dist/clio-BZVGEUFJ.js +0 -58
- package/dist/configure-S7S6F6CL.js +0 -32
- package/docs/html/agents_blueprint.html +0 -936
- package/docs/html/alcf_blueprint.html +0 -324
- package/docs/html/architecture_blueprint.html +0 -850
- package/docs/html/commands_blueprint.html +0 -939
- package/docs/html/config_knobs_audit_blueprint.html +0 -178
- package/docs/html/configuration_blueprint.html +0 -1080
- package/docs/html/context_blueprint.html +0 -603
- package/docs/html/documentation_blueprint.html +0 -832
- package/docs/html/environment_blueprint.html +0 -404
- package/docs/html/eval_blueprint.html +0 -743
- package/docs/html/evals_internal_blueprint.html +0 -190
- package/docs/html/evolution_blueprint.html +0 -674
- package/docs/html/extensions_blueprint.html +0 -2065
- package/docs/html/fleet_dispatch_blueprint.html +0 -286
- package/docs/html/index.html +0 -919
- package/docs/html/lifecycle_blueprint.html +0 -723
- package/docs/html/memory_blueprint.html +0 -699
- package/docs/html/middleware_blueprint.html +0 -664
- package/docs/html/models_blueprint.html +0 -2366
- package/docs/html/observability_blueprint.html +0 -683
- package/docs/html/provider_adapter_blueprint.html +0 -245
- package/docs/html/safety_blueprint.html +0 -1386
- package/docs/html/shared.css +0 -571
- package/docs/html/shared.js +0 -143
- package/docs/html/skills_blueprint.html +0 -671
- package/docs/html/soak_blueprint.html +0 -182
- package/docs/html/tool_usage_blueprint.html +0 -350
- package/docs/html/tools_blueprint.html +0 -2249
- package/docs/html/trace_blueprint.html +0 -235
- package/docs/html/tui_design_blueprint.html +0 -374
- package/docs/html/validation_blueprint.html +0 -961
- package/docs/html/worker_dispatch_blueprint.html +0 -231
- package/src/core/release.ts +0 -2
- package/src/domains/providers/runtimes/common/lmstudio-logger.ts +0 -32
- package/src/domains/providers/runtimes/local-native/lmstudio-native.ts +0 -491
- package/src/engine/apis/lmstudio-native.ts +0 -1438
- package/src/engine/apis/thinking-replay.ts +0 -11
- package/src/tools/string-enum.ts +0 -15
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
+
import { resolvePackageRoot } from "../../../core/package-root.js";
|
|
3
4
|
import { clioConfigDir } from "../../../core/xdg.js";
|
|
4
5
|
import {
|
|
5
6
|
type InstallSkillInput,
|
|
@@ -13,12 +14,21 @@ import { loadSkills, type Skill } from "./loader.js";
|
|
|
13
14
|
/**
|
|
14
15
|
* Local skill marketplace. Entries come from two real sources only:
|
|
15
16
|
*
|
|
16
|
-
* 1. A catalog directory of actual SKILL.md packages
|
|
17
|
-
* repo-level skills/ folder
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
17
|
+
* 1. A catalog directory of actual SKILL.md packages: CLIO_CODER_SKILL_CATALOG_DIR,
|
|
18
|
+
* else a repo-level skills/ folder in the working tree, else the skills/
|
|
19
|
+
* catalog the installed clio-coder package carries. Metadata is read from
|
|
20
|
+
* the packages themselves via the normal skill loader.
|
|
21
|
+
* 2. A JSON index file: CLIO_CODER_SKILL_MARKETPLACE_INDEX, else
|
|
22
|
+
* <config>/skill-marketplace.json, else the skill-marketplace.json the
|
|
23
|
+
* package carries. Entries point at installable sources.
|
|
24
|
+
*
|
|
25
|
+
* The package fallbacks are what make a fresh npm install a marketplace at
|
|
26
|
+
* all: before them, an operator outside this repository with no env var set
|
|
27
|
+
* had no catalog and no index, so every bare-name install and every
|
|
28
|
+
* `/skill <name>` for a catalog skill failed. The package catalog is a
|
|
29
|
+
* marketplace source only, never a discovery root; catalog skills stay
|
|
30
|
+
* uninstalled until the operator asks, and install copies them out of the
|
|
31
|
+
* package into a Clio root without touching the network.
|
|
22
32
|
*
|
|
23
33
|
* There is no synthetic or hardcoded marketplace data; an empty result means
|
|
24
34
|
* no marketplace is configured.
|
|
@@ -62,14 +72,45 @@ export interface DiscoverMarketplaceOptions {
|
|
|
62
72
|
catalogDir?: string | null;
|
|
63
73
|
}
|
|
64
74
|
|
|
65
|
-
|
|
75
|
+
/**
|
|
76
|
+
* The catalog directory and index the installed package carries. Resolved
|
|
77
|
+
* lazily and defensively: a source checkout that has not built, or a package
|
|
78
|
+
* root the harness cannot locate, must degrade to "no package catalog" rather
|
|
79
|
+
* than throw out of a listing.
|
|
80
|
+
*/
|
|
81
|
+
function packageCatalogDir(): string | null {
|
|
82
|
+
try {
|
|
83
|
+
return path.join(resolvePackageRoot(), "skills");
|
|
84
|
+
} catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function packageIndexPath(): string | null {
|
|
66
90
|
try {
|
|
67
|
-
return path.join(
|
|
91
|
+
return path.join(resolvePackageRoot(), "skills", "skill-marketplace.json");
|
|
68
92
|
} catch {
|
|
69
93
|
return null;
|
|
70
94
|
}
|
|
71
95
|
}
|
|
72
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Index precedence when no explicit path is given: the operator's config-dir
|
|
99
|
+
* copy beats the package's, so a hand-curated index still wins, and the
|
|
100
|
+
* package's own index is what a fresh install falls back to.
|
|
101
|
+
*/
|
|
102
|
+
function defaultIndexPath(): string | null {
|
|
103
|
+
try {
|
|
104
|
+
const configured = path.join(clioConfigDir(), "skill-marketplace.json");
|
|
105
|
+
if (existsSync(configured)) return configured;
|
|
106
|
+
} catch {
|
|
107
|
+
// Fall through: no config dir is not "no marketplace" once the package
|
|
108
|
+
// carries an index of its own.
|
|
109
|
+
}
|
|
110
|
+
const bundled = packageIndexPath();
|
|
111
|
+
return bundled && existsSync(bundled) ? bundled : null;
|
|
112
|
+
}
|
|
113
|
+
|
|
73
114
|
function isIndexSkill(value: unknown): value is { name: string; description: string; sourceUrl: string } {
|
|
74
115
|
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
75
116
|
const record = value as Record<string, unknown>;
|
|
@@ -154,7 +195,12 @@ function resolveCatalogDir(options: DiscoverMarketplaceOptions): string | null {
|
|
|
154
195
|
const fromEnv = process.env.CLIO_CODER_SKILL_CATALOG_DIR;
|
|
155
196
|
if (fromEnv && fromEnv.trim().length > 0) return path.resolve(fromEnv.trim());
|
|
156
197
|
const repoCatalog = path.join(options.cwd ?? process.cwd(), "skills");
|
|
157
|
-
|
|
198
|
+
if (looksLikeSkillCatalog(repoCatalog)) return repoCatalog;
|
|
199
|
+
// The package's own catalog: rows resolve to local files, so a bare-name
|
|
200
|
+
// install copies out of the package and needs no network. From a checkout
|
|
201
|
+
// of this repository the two paths coincide.
|
|
202
|
+
const bundled = packageCatalogDir();
|
|
203
|
+
return bundled && looksLikeSkillCatalog(bundled) ? bundled : null;
|
|
158
204
|
}
|
|
159
205
|
|
|
160
206
|
/**
|
|
@@ -95,8 +95,10 @@ function baseClassify(tool: string): ActionClass | null {
|
|
|
95
95
|
case ToolNames.Monitor:
|
|
96
96
|
case ToolNames.AskUser:
|
|
97
97
|
case ToolNames.CredentialPresent:
|
|
98
|
-
// tasks mutates only
|
|
99
|
-
//
|
|
98
|
+
// tasks pick mutates only Clio-owned session-ledger and project-local
|
|
99
|
+
// .clio-coder runtime state, never source-workspace files. By intentional
|
|
100
|
+
// policy it stays read class and ungated; the tool itself still requires
|
|
101
|
+
// a durable operator task id before it can mutate either store.
|
|
100
102
|
case ToolNames.Tasks:
|
|
101
103
|
// ledger posts a typed contribution to a coordination board and reads a
|
|
102
104
|
// local mirror. Neither touches the workspace, so it is never gated
|
|
@@ -85,7 +85,7 @@ export interface PermissionAuditRecord {
|
|
|
85
85
|
kind: "permission";
|
|
86
86
|
ts: string;
|
|
87
87
|
correlationId: string;
|
|
88
|
-
status: "requested" | "granted" | "denied";
|
|
88
|
+
status: "requested" | "granted" | "denied" | "expired";
|
|
89
89
|
requestId?: string;
|
|
90
90
|
origin?: string;
|
|
91
91
|
decidedBy?: string;
|
|
@@ -204,7 +204,13 @@ let dateFormatter = new Intl.DateTimeFormat("en-CA", DATE_OPTIONS);
|
|
|
204
204
|
function localDateString(d: Date): string {
|
|
205
205
|
if (process.env.TZ !== dateFormatterZone) {
|
|
206
206
|
dateFormatterZone = process.env.TZ;
|
|
207
|
-
|
|
207
|
+
// The zone is passed explicitly, not left for Intl to pick up from
|
|
208
|
+
// process.env.TZ implicitly: see src/interactive/format-time.ts's
|
|
209
|
+
// syncZone() for the traced repro (issue #84) of a rebuilt formatter
|
|
210
|
+
// resolving to the wrong zone while process.env.TZ read correctly at
|
|
211
|
+
// both construction and format time. Same idiom, same fix.
|
|
212
|
+
const zone = dateFormatterZone === undefined ? undefined : { timeZone: dateFormatterZone };
|
|
213
|
+
dateFormatter = new Intl.DateTimeFormat("en-CA", { ...DATE_OPTIONS, ...zone });
|
|
208
214
|
}
|
|
209
215
|
return dateFormatter.format(d);
|
|
210
216
|
}
|
|
@@ -31,7 +31,7 @@ import { CONFIRMED_SCOPE, isSubset, READONLY_SCOPE, WORKSPACE_SCOPE } from "./sc
|
|
|
31
31
|
function isPermissionResolvedPayload(value: unknown): value is PermissionResolvedPayload {
|
|
32
32
|
if (!value || typeof value !== "object") return false;
|
|
33
33
|
const p = value as Record<string, unknown>;
|
|
34
|
-
if (p.status !== "granted" && p.status !== "denied") return false;
|
|
34
|
+
if (p.status !== "granted" && p.status !== "denied" && p.status !== "expired") return false;
|
|
35
35
|
if (p.tool !== undefined && typeof p.tool !== "string") return false;
|
|
36
36
|
if (p.actionClass !== undefined && typeof p.actionClass !== "string") return false;
|
|
37
37
|
if (p.reason !== undefined && typeof p.reason !== "string") return false;
|
|
@@ -123,7 +123,7 @@ function toolResultText(entry: MessageEntry): string {
|
|
|
123
123
|
* stable for a given input. Tests rely on this determinism.
|
|
124
124
|
*
|
|
125
125
|
* Non-context-bearing kinds (modelChange, thinkingLevelChange, fileEntry,
|
|
126
|
-
* sessionInfo, protectedArtifact, custom) are skipped: they never contribute
|
|
126
|
+
* sessionInfo, protectedArtifact, taskLedger, decisionLedger, custom) are skipped: they never contribute
|
|
127
127
|
* to the replayed LLM context, so summarizing them would waste tokens on
|
|
128
128
|
* bookkeeping.
|
|
129
129
|
*/
|
|
@@ -180,7 +180,8 @@ export function serializeConversation(entries: ReadonlyArray<SessionEntry>): str
|
|
|
180
180
|
);
|
|
181
181
|
}
|
|
182
182
|
// custom, modelChange, thinkingLevelChange, fileEntry, sessionInfo,
|
|
183
|
-
// protectedArtifact
|
|
183
|
+
// protectedArtifact, taskLedger, decisionLedger, and workerRun do not
|
|
184
|
+
// project into the serialized conversation.
|
|
184
185
|
}
|
|
185
186
|
return parts.join("\n\n");
|
|
186
187
|
}
|
|
@@ -70,6 +70,7 @@ function isValidCutPoint(entry: SessionEntry): boolean {
|
|
|
70
70
|
case "label":
|
|
71
71
|
case "protectedArtifact":
|
|
72
72
|
case "taskLedger":
|
|
73
|
+
case "decisionLedger":
|
|
73
74
|
case "workerRun":
|
|
74
75
|
return false;
|
|
75
76
|
}
|
|
@@ -96,7 +97,7 @@ function findValidCutPoints(entries: ReadonlyArray<SessionEntry>, startIndex: nu
|
|
|
96
97
|
* accumulating `keepRecentTokens`, the pi-coding-agent reference left
|
|
97
98
|
* `cutIndex` at the oldest valid cut, which made `compact()` produce an
|
|
98
99
|
* empty `pre` slice and the chat-loop report "nothing to compact" on
|
|
99
|
-
* populated sessions below the keep-recent window. Clio's manual `/compact`
|
|
100
|
+
* populated sessions below the keep-recent window. Clio's manual `/context compact`
|
|
100
101
|
* expects to summarize whatever older history exists, so when no suffix
|
|
101
102
|
* crosses the threshold the cut falls back to the newest turn start (user
|
|
102
103
|
* message, bashExecution, or branchSummary). Sessions with only a single
|
|
@@ -53,7 +53,7 @@ function estimateSummary(entry: BranchSummaryEntry | CompactionSummaryEntry): nu
|
|
|
53
53
|
/**
|
|
54
54
|
* Estimate the token load of a single session entry. Non-context-bearing
|
|
55
55
|
* kinds (modelChange, thinkingLevelChange, fileEntry, sessionInfo,
|
|
56
|
-
* label, protectedArtifact, taskLedger, workerRun) return 0 so they never
|
|
56
|
+
* label, protectedArtifact, taskLedger, decisionLedger, workerRun) return 0 so they never
|
|
57
57
|
* distort the context budget.
|
|
58
58
|
*/
|
|
59
59
|
export function estimateTokens(entry: SessionEntry): number {
|
|
@@ -76,6 +76,7 @@ export function estimateTokens(entry: SessionEntry): number {
|
|
|
76
76
|
case "label":
|
|
77
77
|
case "protectedArtifact":
|
|
78
78
|
case "taskLedger":
|
|
79
|
+
case "decisionLedger":
|
|
79
80
|
case "workerRun":
|
|
80
81
|
return 0;
|
|
81
82
|
}
|
|
@@ -84,6 +84,12 @@ export interface BuildContextLedgerInput {
|
|
|
84
84
|
* a prompt has compiled.
|
|
85
85
|
*/
|
|
86
86
|
projectPreload?: string | null;
|
|
87
|
+
/**
|
|
88
|
+
* Absolute paths of the effective project handbooks the compiled prompt
|
|
89
|
+
* selected, ancestor to nearest. Null before a prompt has compiled; empty
|
|
90
|
+
* when the workspace has no parseable handbook.
|
|
91
|
+
*/
|
|
92
|
+
projectHandbookFiles?: ReadonlyArray<string> | null;
|
|
87
93
|
lastCompaction?: {
|
|
88
94
|
stage: string;
|
|
89
95
|
tokensBefore: number;
|
|
@@ -152,6 +158,11 @@ export interface ContextLedger {
|
|
|
152
158
|
compactionAuto: boolean;
|
|
153
159
|
/** Preload class label for the project category detail line; null when unknown. */
|
|
154
160
|
projectPreload: string | null;
|
|
161
|
+
/**
|
|
162
|
+
* Which handbook files won for this session, ancestor to nearest (an
|
|
163
|
+
* override resets the inherited chain). Null before a prompt has compiled.
|
|
164
|
+
*/
|
|
165
|
+
projectHandbookFiles: ReadonlyArray<string> | null;
|
|
155
166
|
toolCount: number;
|
|
156
167
|
/** Non-empty content categories in display order (excludes reserve/free). */
|
|
157
168
|
groups: ReadonlyArray<ContextLedgerGroup>;
|
|
@@ -170,6 +181,8 @@ export interface ContextLedger {
|
|
|
170
181
|
const SEGMENT_CATEGORY: Readonly<Record<string, ContextLedgerCategory>> = {
|
|
171
182
|
identity: "system",
|
|
172
183
|
"operating-contract": "system",
|
|
184
|
+
delegation: "agents",
|
|
185
|
+
skills: "skills",
|
|
173
186
|
safety: "system",
|
|
174
187
|
runtime: "system",
|
|
175
188
|
"tool-contract": "system",
|
|
@@ -339,6 +352,7 @@ export function buildContextLedger(input: BuildContextLedgerInput): ContextLedge
|
|
|
339
352
|
compactionThreshold: effectiveThreshold,
|
|
340
353
|
compactionAuto: input.compactionAuto === true,
|
|
341
354
|
projectPreload: input.projectPreload ?? null,
|
|
355
|
+
projectHandbookFiles: input.projectHandbookFiles ?? null,
|
|
342
356
|
toolCount: Math.max(0, Math.floor(input.toolCount ?? 0)),
|
|
343
357
|
groups,
|
|
344
358
|
meter,
|
|
@@ -47,6 +47,14 @@ export type ClioSessionMetaExtension = {
|
|
|
47
47
|
workspace?: WorkspaceSnapshot;
|
|
48
48
|
/** Ordered record of skills activated in this session. */
|
|
49
49
|
skillActivations?: SkillActivation[];
|
|
50
|
+
/**
|
|
51
|
+
* The turn `/tree` last switched the append point to, persisted so it
|
|
52
|
+
* survives quit + resume. `resume()`/`switchBranch()` prefer this over
|
|
53
|
+
* inferring the leaf from timestamps (`computeLeafId`) when it still
|
|
54
|
+
* names a real turn; a plain append clears it, since once the tree grows
|
|
55
|
+
* past it the inferred newest-node leaf is correct again.
|
|
56
|
+
*/
|
|
57
|
+
pinnedLeafTurnId?: string | null;
|
|
50
58
|
};
|
|
51
59
|
|
|
52
60
|
export type SessionMeta = ClioSessionMeta & ClioSessionMetaExtension;
|
|
@@ -130,6 +138,13 @@ export interface SessionContract {
|
|
|
130
138
|
* otherwise the helper appends directly to that session's transcript.
|
|
131
139
|
*/
|
|
132
140
|
editLabel(turnId: string, label: string, sessionId?: string): void;
|
|
141
|
+
/**
|
|
142
|
+
* Persist the session's display name as a session-wide SessionInfoEntry.
|
|
143
|
+
* Empty or whitespace-only names clear the name when history is rebuilt.
|
|
144
|
+
* If the target session is current, writes flow through the live writer;
|
|
145
|
+
* otherwise the entry is durably appended directly to its transcript.
|
|
146
|
+
*/
|
|
147
|
+
setName(name: string, sessionId?: string): void;
|
|
133
148
|
/**
|
|
134
149
|
* Remove the given session. By default, wipes the session directory.
|
|
135
150
|
* `opts.keepFiles` preserves the transcript and only tombstones meta.json.
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import type { AskUserToolPolicy } from "../../tools/registry.js";
|
|
2
|
+
import type { DecisionLedgerEntry, DecisionRecord } from "./entries.js";
|
|
3
|
+
|
|
4
|
+
export interface DecisionLedgerEntryFields {
|
|
5
|
+
kind: "decisionLedger";
|
|
6
|
+
parentTurnId: string;
|
|
7
|
+
interviewId: string;
|
|
8
|
+
interviewStatus: "complete" | "cancelled";
|
|
9
|
+
startedAt: string;
|
|
10
|
+
endedAt: string;
|
|
11
|
+
roundCount: number;
|
|
12
|
+
summary?: string;
|
|
13
|
+
transcriptPath?: string;
|
|
14
|
+
decisions: DecisionRecord[];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface DecisionBoardStoreDeps {
|
|
18
|
+
/** Current session id, used to keep the in-memory fold scoped to one ledger. */
|
|
19
|
+
getSessionId?: () => string | null;
|
|
20
|
+
/** Active-path entries for the current session. */
|
|
21
|
+
readEntries?: () => ReadonlyArray<unknown>;
|
|
22
|
+
/** The current branch leaf used to anchor operator-authored revisions. */
|
|
23
|
+
getActiveLeafTurnId?: () => string | null;
|
|
24
|
+
/** Acknowledged session append. A throw means the board did not change. */
|
|
25
|
+
appendEntry?: (entry: DecisionLedgerEntryFields) => void;
|
|
26
|
+
now?: () => Date;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface DecisionBoardStore {
|
|
30
|
+
/** Latest snapshot per interview, newest interview first. */
|
|
31
|
+
snapshot(): ReadonlyArray<DecisionLedgerEntry>;
|
|
32
|
+
/** Persist the one host-finalized snapshot for a settled interview. */
|
|
33
|
+
recordFinalizedInterview(policy: AskUserToolPolicy): boolean;
|
|
34
|
+
/** Append an operator revision snapshot anchored to the active branch leaf. */
|
|
35
|
+
supersede(interviewId: string, key: string, correction?: string): DecisionLedgerEntryFields;
|
|
36
|
+
/** Force the next read to refold, including after a same-session tree switch. */
|
|
37
|
+
invalidate(): void;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function answeredAtForDecision(policy: AskUserToolPolicy, sourceQuestion: string): string | undefined {
|
|
41
|
+
for (let index = policy.rounds.length - 1; index >= 0; index -= 1) {
|
|
42
|
+
const round = policy.rounds[index];
|
|
43
|
+
if (!round?.answeredAt) continue;
|
|
44
|
+
if (round.answers.some((answer) => answer.question === sourceQuestion)) return round.answeredAt;
|
|
45
|
+
if (round.questions.some((question) => question.question === sourceQuestion)) return round.answeredAt;
|
|
46
|
+
}
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Convert the settled, host-owned policy into the complete durable snapshot.
|
|
52
|
+
* The policy already keeps last-value-wins decisions; the defensive map also
|
|
53
|
+
* makes conversion deterministic for hand-built policies and older callers.
|
|
54
|
+
*/
|
|
55
|
+
export function finalizedInterviewEntryFields(policy: AskUserToolPolicy): DecisionLedgerEntryFields | null {
|
|
56
|
+
if (policy.rounds.length === 0 && policy.decisions.length === 0) return null;
|
|
57
|
+
if (!policy.turnId) throw new Error(`decision board: interview ${policy.id} has no originating user turn`);
|
|
58
|
+
if (policy.status !== "complete" && policy.status !== "cancelled") {
|
|
59
|
+
throw new Error(`decision board: interview ${policy.id} finalized with status ${policy.status}`);
|
|
60
|
+
}
|
|
61
|
+
const endedAt = policy.endedAt ?? policy.updatedAt;
|
|
62
|
+
const decisionsByKey = new Map<string, DecisionRecord>();
|
|
63
|
+
for (const decision of policy.decisions) {
|
|
64
|
+
const decidedAt = decision.source_question
|
|
65
|
+
? (answeredAtForDecision(policy, decision.source_question) ?? endedAt)
|
|
66
|
+
: endedAt;
|
|
67
|
+
decisionsByKey.set(decision.key, {
|
|
68
|
+
key: decision.key,
|
|
69
|
+
value: decision.value,
|
|
70
|
+
...(decision.label ? { label: decision.label } : {}),
|
|
71
|
+
...(decision.source_question ? { source_question: decision.source_question } : {}),
|
|
72
|
+
status: "active",
|
|
73
|
+
decidedAt,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
kind: "decisionLedger",
|
|
78
|
+
parentTurnId: policy.turnId,
|
|
79
|
+
interviewId: policy.id,
|
|
80
|
+
interviewStatus: policy.status,
|
|
81
|
+
startedAt: policy.startedAt,
|
|
82
|
+
endedAt,
|
|
83
|
+
roundCount: policy.rounds.length,
|
|
84
|
+
...(policy.summary ? { summary: policy.summary } : {}),
|
|
85
|
+
...(policy.transcriptPath ? { transcriptPath: policy.transcriptPath } : {}),
|
|
86
|
+
decisions: [...decisionsByKey.values()],
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function isDecisionLedgerEntry(value: unknown): value is DecisionLedgerEntry {
|
|
91
|
+
return !!value && typeof value === "object" && (value as { kind?: unknown }).kind === "decisionLedger";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/** Last full snapshot wins independently for each interview. */
|
|
95
|
+
export function foldDecisionBoard(entries: ReadonlyArray<unknown>): DecisionLedgerEntry[] {
|
|
96
|
+
const lastByInterview = new Map<string, { entry: DecisionLedgerEntry; index: number }>();
|
|
97
|
+
for (let index = 0; index < entries.length; index += 1) {
|
|
98
|
+
const raw = entries[index];
|
|
99
|
+
if (!isDecisionLedgerEntry(raw)) continue;
|
|
100
|
+
lastByInterview.set(raw.interviewId, { entry: raw, index });
|
|
101
|
+
}
|
|
102
|
+
return [...lastByInterview.values()]
|
|
103
|
+
.sort((left, right) => {
|
|
104
|
+
const byEndedAt = right.entry.endedAt.localeCompare(left.entry.endedAt);
|
|
105
|
+
return byEndedAt !== 0 ? byEndedAt : right.index - left.index;
|
|
106
|
+
})
|
|
107
|
+
.map(({ entry }) => entry);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function activeLeafFromEntries(entries: ReadonlyArray<unknown>): string | null {
|
|
111
|
+
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
|
112
|
+
const entry = entries[index];
|
|
113
|
+
if (entry && typeof entry === "object" && (entry as { kind?: unknown }).kind === "message") {
|
|
114
|
+
const turnId = (entry as { turnId?: unknown }).turnId;
|
|
115
|
+
if (typeof turnId === "string" && turnId.length > 0) return turnId;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function createDecisionBoardStore(deps: DecisionBoardStoreDeps = {}): DecisionBoardStore {
|
|
122
|
+
let cachedSessionId: string | null | undefined;
|
|
123
|
+
let dirty = true;
|
|
124
|
+
let interviews: DecisionLedgerEntry[] = [];
|
|
125
|
+
|
|
126
|
+
const syncToSession = (): void => {
|
|
127
|
+
const sessionId = deps.getSessionId?.() ?? null;
|
|
128
|
+
if (!dirty && sessionId === cachedSessionId) return;
|
|
129
|
+
const entries = deps.readEntries?.() ?? [];
|
|
130
|
+
interviews = foldDecisionBoard(entries);
|
|
131
|
+
cachedSessionId = sessionId;
|
|
132
|
+
dirty = false;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const append = (entry: DecisionLedgerEntryFields): void => {
|
|
136
|
+
if (!deps.appendEntry) throw new Error("decision board: no session ledger is available");
|
|
137
|
+
deps.appendEntry(entry);
|
|
138
|
+
// Read the acknowledged append back through the active-path source. This
|
|
139
|
+
// never publishes a snapshot the ledger did not accept.
|
|
140
|
+
dirty = true;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
snapshot(): ReadonlyArray<DecisionLedgerEntry> {
|
|
145
|
+
syncToSession();
|
|
146
|
+
return interviews;
|
|
147
|
+
},
|
|
148
|
+
recordFinalizedInterview(policy: AskUserToolPolicy): boolean {
|
|
149
|
+
const entry = finalizedInterviewEntryFields(policy);
|
|
150
|
+
if (entry === null) return false;
|
|
151
|
+
append(entry);
|
|
152
|
+
return true;
|
|
153
|
+
},
|
|
154
|
+
supersede(interviewId: string, key: string, correction?: string): DecisionLedgerEntryFields {
|
|
155
|
+
syncToSession();
|
|
156
|
+
const interview = interviews.find((candidate) => candidate.interviewId === interviewId);
|
|
157
|
+
if (!interview) throw new Error(`decision board: interview ${interviewId} was not found on the active branch`);
|
|
158
|
+
const selected = interview.decisions.find((decision) => decision.key === key);
|
|
159
|
+
if (!selected) throw new Error(`decision board: decision ${key} was not found in interview ${interviewId}`);
|
|
160
|
+
const revisedAt = (deps.now?.() ?? new Date()).toISOString();
|
|
161
|
+
const normalizedCorrection = correction?.trim();
|
|
162
|
+
const entries = deps.readEntries?.() ?? [];
|
|
163
|
+
const parentTurnId = deps.getActiveLeafTurnId?.() ?? activeLeafFromEntries(entries);
|
|
164
|
+
if (!parentTurnId) throw new Error("decision board: no active branch leaf is available for the revision");
|
|
165
|
+
const revision: DecisionLedgerEntryFields = {
|
|
166
|
+
kind: "decisionLedger",
|
|
167
|
+
parentTurnId,
|
|
168
|
+
interviewId: interview.interviewId,
|
|
169
|
+
interviewStatus: interview.interviewStatus,
|
|
170
|
+
startedAt: interview.startedAt,
|
|
171
|
+
endedAt: interview.endedAt,
|
|
172
|
+
roundCount: interview.roundCount,
|
|
173
|
+
...(interview.summary ? { summary: interview.summary } : {}),
|
|
174
|
+
...(interview.transcriptPath ? { transcriptPath: interview.transcriptPath } : {}),
|
|
175
|
+
decisions: interview.decisions.map((decision) => {
|
|
176
|
+
if (decision.key !== selected.key) return { ...decision };
|
|
177
|
+
const next: DecisionRecord = { ...decision, status: "superseded", revisedAt };
|
|
178
|
+
if (normalizedCorrection) next.correction = normalizedCorrection;
|
|
179
|
+
else delete next.correction;
|
|
180
|
+
return next;
|
|
181
|
+
}),
|
|
182
|
+
};
|
|
183
|
+
append(revision);
|
|
184
|
+
return revision;
|
|
185
|
+
},
|
|
186
|
+
invalidate(): void {
|
|
187
|
+
dirty = true;
|
|
188
|
+
},
|
|
189
|
+
};
|
|
190
|
+
}
|
|
@@ -85,10 +85,10 @@ export interface BranchSummaryEntry extends BaseSessionEntry {
|
|
|
85
85
|
|
|
86
86
|
/**
|
|
87
87
|
* Why a compaction run fired. Persisted on CompactionSummaryEntry so post-mortem
|
|
88
|
-
* tools can distinguish a threshold-driven shrink from a user-issued
|
|
88
|
+
* tools can distinguish a threshold-driven shrink from a user-issued `/context compact`
|
|
89
89
|
* and from a context-overflow retry.
|
|
90
90
|
* - "auto" : pre-submit context-pressure trigger via shouldCompact().
|
|
91
|
-
* - "force" : explicit
|
|
91
|
+
* - "force" : explicit `/context compact` command or CLIO_CODER_FORCE_COMPACT=1.
|
|
92
92
|
* - "overflow" : compact-and-retry path after a context overflow error.
|
|
93
93
|
*/
|
|
94
94
|
export type CompactionTrigger = "auto" | "force" | "overflow";
|
|
@@ -183,6 +183,8 @@ export interface TaskLedgerGoal {
|
|
|
183
183
|
status: TaskLedgerStatus;
|
|
184
184
|
parentGoalId?: string | null;
|
|
185
185
|
description?: string;
|
|
186
|
+
origin?: "agent" | "user";
|
|
187
|
+
userTaskId?: string;
|
|
186
188
|
}
|
|
187
189
|
|
|
188
190
|
export interface TaskLedgerValidationEvidence {
|
|
@@ -197,12 +199,39 @@ export interface TaskLedgerValidationEvidence {
|
|
|
197
199
|
|
|
198
200
|
export interface TaskLedgerEntry extends BaseSessionEntry {
|
|
199
201
|
kind: "taskLedger";
|
|
202
|
+
boardId?: string;
|
|
200
203
|
goals: TaskLedgerGoal[];
|
|
201
204
|
subgoals: TaskLedgerGoal[];
|
|
202
205
|
activeRunIds: string[];
|
|
203
206
|
requiredValidationEvidence: TaskLedgerValidationEvidence[];
|
|
204
207
|
}
|
|
205
208
|
|
|
209
|
+
export type DecisionStatus = "active" | "superseded";
|
|
210
|
+
|
|
211
|
+
export interface DecisionRecord {
|
|
212
|
+
key: string;
|
|
213
|
+
value: string;
|
|
214
|
+
label?: string;
|
|
215
|
+
source_question?: string;
|
|
216
|
+
status: DecisionStatus;
|
|
217
|
+
decidedAt: string;
|
|
218
|
+
revisedAt?: string;
|
|
219
|
+
correction?: string;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** One complete, branch-anchored snapshot of a settled operator interview. */
|
|
223
|
+
export interface DecisionLedgerEntry extends BaseSessionEntry {
|
|
224
|
+
kind: "decisionLedger";
|
|
225
|
+
interviewId: string;
|
|
226
|
+
interviewStatus: "complete" | "cancelled";
|
|
227
|
+
startedAt: string;
|
|
228
|
+
endedAt: string;
|
|
229
|
+
roundCount: number;
|
|
230
|
+
summary?: string;
|
|
231
|
+
transcriptPath?: string;
|
|
232
|
+
decisions: DecisionRecord[];
|
|
233
|
+
}
|
|
234
|
+
|
|
206
235
|
/** Who asked for a dispatched run. Internal runs never reach the transcript, so they never reach this entry. */
|
|
207
236
|
export type WorkerRunOrigin = "user" | "agent";
|
|
208
237
|
|
|
@@ -261,6 +290,7 @@ export type SessionEntry =
|
|
|
261
290
|
| ProtectedArtifactEntry
|
|
262
291
|
| SkillActivationEntry
|
|
263
292
|
| TaskLedgerEntry
|
|
293
|
+
| DecisionLedgerEntry
|
|
264
294
|
| WorkerRunEntry;
|
|
265
295
|
|
|
266
296
|
export type SessionFileEntry = SessionHeader | SessionEntry;
|
|
@@ -285,6 +315,7 @@ export const SESSION_ENTRY_KINDS = [
|
|
|
285
315
|
"protectedArtifact",
|
|
286
316
|
"skillActivation",
|
|
287
317
|
"taskLedger",
|
|
318
|
+
"decisionLedger",
|
|
288
319
|
"workerRun",
|
|
289
320
|
] as const;
|
|
290
321
|
|
|
@@ -354,6 +385,8 @@ const TASK_LEDGER_EVIDENCE_STATUSES: readonly TaskLedgerEvidenceStatus[] = [
|
|
|
354
385
|
"failed",
|
|
355
386
|
"missing",
|
|
356
387
|
];
|
|
388
|
+
const DECISION_STATUSES: readonly DecisionStatus[] = ["active", "superseded"];
|
|
389
|
+
const DECISION_INTERVIEW_STATUSES = ["complete", "cancelled"] as const;
|
|
357
390
|
const WORKER_RUN_ORIGINS: readonly WorkerRunOrigin[] = ["user", "agent"];
|
|
358
391
|
const WORKER_RUN_RUNTIME_KINDS: readonly WorkerRunRuntimeKind[] = ["clio", "acp", "claude-sdk", "claude-code"];
|
|
359
392
|
|
|
@@ -372,7 +405,11 @@ function isTaskLedgerGoal(value: unknown): value is TaskLedgerGoal {
|
|
|
372
405
|
if (!isString(value.id) || !isString(value.title)) return false;
|
|
373
406
|
if (!isOneOf(value.status, TASK_LEDGER_STATUSES)) return false;
|
|
374
407
|
if (value.parentGoalId !== undefined && !isNullableString(value.parentGoalId)) return false;
|
|
375
|
-
|
|
408
|
+
const hasPairedProvenance =
|
|
409
|
+
value.origin === "user"
|
|
410
|
+
? isString(value.userTaskId) && /^u[1-9]\d*$/.test(value.userTaskId)
|
|
411
|
+
: (value.origin === undefined || value.origin === "agent") && value.userTaskId === undefined;
|
|
412
|
+
return isOptionalString(value.description) && hasPairedProvenance;
|
|
376
413
|
}
|
|
377
414
|
|
|
378
415
|
function isTaskLedgerEvidence(value: unknown): value is TaskLedgerValidationEvidence {
|
|
@@ -387,6 +424,17 @@ function isTaskLedgerEvidence(value: unknown): value is TaskLedgerValidationEvid
|
|
|
387
424
|
);
|
|
388
425
|
}
|
|
389
426
|
|
|
427
|
+
function isDecisionRecord(value: unknown): value is DecisionRecord {
|
|
428
|
+
if (!isRecord(value)) return false;
|
|
429
|
+
if (!isString(value.key) || !/^[a-z0-9]+(?:_[a-z0-9]+)*$/.test(value.key)) return false;
|
|
430
|
+
if (!isString(value.value) || !isOneOf(value.status, DECISION_STATUSES) || !isString(value.decidedAt)) return false;
|
|
431
|
+
if (!isOptionalString(value.label) || !isOptionalString(value.source_question)) return false;
|
|
432
|
+
if (!isOptionalString(value.revisedAt) || !isOptionalString(value.correction)) return false;
|
|
433
|
+
return value.status === "superseded"
|
|
434
|
+
? isString(value.revisedAt)
|
|
435
|
+
: value.revisedAt === undefined && value.correction === undefined;
|
|
436
|
+
}
|
|
437
|
+
|
|
390
438
|
function isOptionalCompactionUsage(value: unknown): boolean {
|
|
391
439
|
if (value === undefined) return true;
|
|
392
440
|
if (!isRecord(value)) return false;
|
|
@@ -487,6 +535,7 @@ export function isSessionEntry(value: unknown): value is SessionEntry {
|
|
|
487
535
|
return isSkillActivation(v.activation);
|
|
488
536
|
case "taskLedger":
|
|
489
537
|
return (
|
|
538
|
+
isOptionalString(v.boardId) &&
|
|
490
539
|
Array.isArray(v.goals) &&
|
|
491
540
|
v.goals.every(isTaskLedgerGoal) &&
|
|
492
541
|
Array.isArray(v.subgoals) &&
|
|
@@ -495,6 +544,20 @@ export function isSessionEntry(value: unknown): value is SessionEntry {
|
|
|
495
544
|
Array.isArray(v.requiredValidationEvidence) &&
|
|
496
545
|
v.requiredValidationEvidence.every(isTaskLedgerEvidence)
|
|
497
546
|
);
|
|
547
|
+
case "decisionLedger":
|
|
548
|
+
return (
|
|
549
|
+
isString(v.interviewId) &&
|
|
550
|
+
isOneOf(v.interviewStatus, DECISION_INTERVIEW_STATUSES) &&
|
|
551
|
+
isString(v.startedAt) &&
|
|
552
|
+
isString(v.endedAt) &&
|
|
553
|
+
isNumber(v.roundCount) &&
|
|
554
|
+
Number.isInteger(v.roundCount) &&
|
|
555
|
+
v.roundCount >= 0 &&
|
|
556
|
+
isOptionalString(v.summary) &&
|
|
557
|
+
isOptionalString(v.transcriptPath) &&
|
|
558
|
+
Array.isArray(v.decisions) &&
|
|
559
|
+
v.decisions.every(isDecisionRecord)
|
|
560
|
+
);
|
|
498
561
|
case "workerRun":
|
|
499
562
|
return (
|
|
500
563
|
isString(v.assignmentId) &&
|