chainlesschain 0.166.106 → 0.166.107
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/README.md +179 -4
- package/package.json +2 -2
- package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
- package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-CKwEku2e.js → AIOps-DCx6L_HW.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BSUOuTpW.js → ActionButton-DYm1CN3Z.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-CGxvL_FI.js → Analytics-D5ItUS_y.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-bCPwz-5w.js → AppLayout-Cb7XeRdH.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-2_BOWo6e.js → Artifacts-DDDeqCDQ.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-CBOruzgW.js → Audit-BRt3x13w.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-lg0IU5HN.js → BackgroundAgents-C_oNALMd.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-OspCi452.js → Backup-PSU2p6CR.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-BMkliqlz.js → BaseInput-G3oL4hcX.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-BfoiUZwp.js → Chat-C2cLI10b.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-BjnfMwep.js → ChatBubbleRenderer-KX1OITf8.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-jTMlkNQZ.js → Checkbox-CHLnEgFD.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CycyJcnU.js → Codegen-DZm9g_Bc.js} +1 -1
- package/src/assets/web-panel/assets/{Col-BVWlReQj.js → Col-D5Z4zSay.js} +1 -1
- package/src/assets/web-panel/assets/{Community-CKRHl4xK.js → Community-DHw69NSk.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BtpfMdhT.js → Compact-B-vjYNWz.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-DtHB1Ct1.js → Compliance-DaIYVZQY.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-D_8X7-RK.js → Cowork-CoA9U-gF.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-DMCOyvEa.js → Cron-DXqmxlRC.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-CeHdsu7m.js → Crosschain-Cdkc3ue1.js} +1 -1
- package/src/assets/web-panel/assets/{DID-CL6mR6zX.js → DID-oKfYyNSR.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-oz9n6DC7.js → Dashboard-n_ycvgWu.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CbWm8mWu.js → Dropdown-D38rZ8WY.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DXlmbC45.js → EmailListRenderer-BjreeBQ1.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-DPwqgRYm.js → EvolutionSettings-CTxA_SIq.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DkV4YMFj.js → FamilyGuardDashboard-DmECNwV5.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CpUKHIOH.js → Federation-B2IaaDmQ.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-C6KXRgjR.js → FormItemContext-DgcgqUIk.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-C5Y4L5E3.js → GenericCardRenderer-B1-du6Qm.js} +1 -1
- package/src/assets/web-panel/assets/{Git-CBwKdF8s.js → Git-XceM21Il.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-Dt-OR7Aa.js → Governance-CV97iz3z.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-Czkl-Lhl.js → Inference-CI7fj305.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-C7NE4949.js → KnowledgeGraph-B5mekWRy.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CoAuZiMG.js → Logs-BlxFA0xY.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-DTkjTwGI.js → MarkdownRenderer-rDE-XyMY.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-IzrV-7zH.js → Marketplace-DL1BVCiX.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DYEea7aS.js → McpTools-BPtwrO3c.js} +2 -2
- package/src/assets/web-panel/assets/{Memory-Uqe7ZrV6.js → Memory-DuSNw4E-.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-D092EGyM.js → MobileBridge-DTgY9ywI.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-CwA1VoVJ.js → MobileProjects-CTpVHJMa.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-gg4jzfB-.js → Mtc-h4fCLjXw.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-BibGfs71.js → MtcAudit-fqMDY3-w.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-BmB5yRXP.js → Multisig-Do3FehBL.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-BBSlPDyY.js → NLProgramming-CQVY0kQF.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Bui3-KiC.js → Notes-4c3oNvWh.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-ovXtbHe5.js → NotificationSettings-BKr2JD4k.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-Bq-qD7eG.js → OrderTableRenderer-Bq4jgzRt.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-DacIY9oJ.js → Organization-Dy3XidyA.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-CX8osheZ.js → Overflow-DFF0qN5K.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-1lnikqVp.js → P2P-DAgYYykd.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-DCrU-V6A.js → PdhVaultBrowser-DgNHa8b1.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-Dfcb6kM2.js → Permissions-Cev6uSBc.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-dvgai4hf.js → PersonalDataHub-DJzbN06K.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-nymAEtnK.js → Pipeline-CoJWvbQ5.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-D0Vd91oM.js → Privacy-DZxV6etm.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BpUBcu7o.js → ProjectInit-BFW87JnM.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-DIzwTT-M.js → ProjectSettings-LBrRT27p.js} +2 -2
- package/src/assets/web-panel/assets/Projects-O3uz76R1.js +1 -0
- package/src/assets/web-panel/assets/{Providers-Cq8p-M0d.js → Providers-CnRbjOYk.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-DSmqOfYk.js → QrScannerModal-BVFnIS3r.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-BDHCeSnA.js → QuickAsk-DrcHx5f1.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-B_9M8oF4.js → Recommend-CbRgrSJm.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-5ot4leHy.js → RemoteSession-B2Uz_ElB.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-B3F013PY.js → Reputation-DS0ljTxL.js} +1 -1
- package/src/assets/web-panel/assets/{Row-BMyBJnZw.js → Row-ClLobFht.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-WmV0l52g.js → RssFeed-DxxcTD0x.js} +3 -3
- package/src/assets/web-panel/assets/{Search-Wl80yXnR.js → Search-BbHN0Fik.js} +1 -1
- package/src/assets/web-panel/assets/{Security-gbDMKb5m.js → Security-BAVU_EcY.js} +4 -4
- package/src/assets/web-panel/assets/{Services-Bx2Bjhah.js → Services-CtqRSVq_.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-BvJNybjV.js → Skeleton-IJ8ZKdSZ.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-Tz4rQcDp.js → Skills-DXxcznnO.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-BM9gyZwc.js → Sla-fRkhnA3i.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-Bu9FL9Tz.js → SpeechSettings-Bi8sYJ-I.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-D8ICJsMt.js → SyncSettings-CjeplUtS.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-B6MowBDo.js → Tasks-D4KB2Hbx.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BJzpTD0W.js → Templates-BwVugi8n.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-BN8eX4R2.js → Tenant-CsPuu5xK.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-CjtP9bpq.js → Terminal-DuaeOPjY.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-CpNRa4XW.js → TimelineRenderer-D-PMrFxO.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-2lNNvNAH.js → Tokens-BXZuiQPZ.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DxtxXyPg.js → Trigger-DgpTaHL3.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CakzGeF9.js → Trust-Bn7lEGRY.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CvJeRXwV.js → UkeySign-zz-8JAAQ.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-D80pMzcO.js → VideoEditing-DCzfQGTc.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BF-VOBmZ.js → Wallet-BiRHM_zB.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DXyoAzE_.js → WebAuthn-QmPo2JwU.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-X6CDxzrF.js → WorkflowEditor-gL7SsPnY.js} +1 -1
- package/src/assets/web-panel/assets/{chat-BcUhqjeA.js → chat-BysvK4hk.js} +1 -1
- package/src/assets/web-panel/assets/{colors-Dw4bKaCm.js → colors-CQq20vqN.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BWhu5Eri.js → compact-item-CAHlOf1X.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BLJ9JKoN.js → createContext-BeF3ESj_.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-D-Iugqxv.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DIkCiJbt.js → hasIn-CiqnRf-U.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgsVg5Up.js → index-4a0Lmz_y.js} +1 -1
- package/src/assets/web-panel/assets/index-B0Oz2_rQ.js +1 -0
- package/src/assets/web-panel/assets/{index-CFGOV-YT.js → index-B2AOvjgR.js} +1 -1
- package/src/assets/web-panel/assets/{index-BipG-tDs.js → index-B2xbtl_c.js} +1 -1
- package/src/assets/web-panel/assets/{index-0mHbawfQ.js → index-B5941vyo.js} +1 -1
- package/src/assets/web-panel/assets/{index-BaStonJm.js → index-BHpHGGmB.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cmc7qH2C.js → index-BOiyW31p.js} +1 -1
- package/src/assets/web-panel/assets/{index-BotMuGS2.js → index-BcVmt6u_.js} +1 -1
- package/src/assets/web-panel/assets/{index-BcTch6Fp.js → index-BfJabF_8.js} +1 -1
- package/src/assets/web-panel/assets/{index-CXJ8t1hK.js → index-Br5tGVbC.js} +1 -1
- package/src/assets/web-panel/assets/{index-u0tqS0iq.js → index-BsnLkZjz.js} +1 -1
- package/src/assets/web-panel/assets/{index-D1r2R4a-.js → index-BtWchYfW.js} +1 -1
- package/src/assets/web-panel/assets/{index-DOjQi7oU.js → index-Bvkbj3x-.js} +1 -1
- package/src/assets/web-panel/assets/{index-BAwcMKaD.js → index-CCX0daFQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-D-Erv8A9.js → index-CImCEo8S.js} +1 -1
- package/src/assets/web-panel/assets/{index-CTPoBbIR.js → index-CTp89vmg.js} +1 -1
- package/src/assets/web-panel/assets/{index-CqGqoID5.js → index-CcccefJc.js} +1 -1
- package/src/assets/web-panel/assets/{index-DQbWGvE4.js → index-CeIL3-nY.js} +1 -1
- package/src/assets/web-panel/assets/{index-uMtx6e3D.js → index-CgkUkmEJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-5vzPcr1g.js → index-CowbNBJs.js} +1 -1
- package/src/assets/web-panel/assets/{index-CDfB6hWf.js → index-Cp3IRTDK.js} +1 -1
- package/src/assets/web-panel/assets/{index-B1fufz1A.js → index-D7q5VH2n.js} +1 -1
- package/src/assets/web-panel/assets/{index-DV4FSjmI.js → index-DBmGQHEz.js} +3 -3
- package/src/assets/web-panel/assets/{index-04SKBH8l.js → index-DHGtFwwR.js} +1 -1
- package/src/assets/web-panel/assets/{index-BxLDNxEQ.js → index-DKYbru3i.js} +1 -1
- package/src/assets/web-panel/assets/{index-DKzG3kBM.js → index-DTPUVm71.js} +1 -1
- package/src/assets/web-panel/assets/{index-DHLW27Je.js → index-DXT7MKkD.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGFqk1-E.js → index-DXsXhR7p.js} +1 -1
- package/src/assets/web-panel/assets/{index-BUC4TZWg.js → index-Dqkls2_6.js} +1 -1
- package/src/assets/web-panel/assets/index-DwoycEQa.js +1 -0
- package/src/assets/web-panel/assets/{index-BxfimJOH.js → index-QALafVsT.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cr05twNa.js → index-TdVEaJfk.js} +1 -1
- package/src/assets/web-panel/assets/{index-LOsZYbic.js → index-ZBuJ6O6g.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5qms36i.js → index-i9aJV9qk.js} +1 -1
- package/src/assets/web-panel/assets/{index-D3wp_jgy.js → index-jJhemX1R.js} +1 -1
- package/src/assets/web-panel/assets/{index-DjEP26Te.js → index-qjaCk1Mj.js} +1 -1
- package/src/assets/web-panel/assets/{index-PRYboDFm.js → index-xwtRrgVY.js} +1 -1
- package/src/assets/web-panel/assets/{index-D5vFJmmX.js → index-yFQWSRoW.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGMzh2oj.js → index-zNkw0IY7.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-Bx6Hj_FG.js → initDefaultProps-BQR2HnKb.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BSWivB70.js → motion-gAz6l-nZ.js} +1 -1
- package/src/assets/web-panel/assets/{move-Dv1Pg9R7.js → move-Cy5TN856.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-Bqtl8fsk.js → mtc-parser-BeT7VrGi.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DpOBjOSQ.js → omit-BLN3mlgK.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-D-M-dz48.js → pickAttrs-DtwZ8u2d.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DsTLAifk.js → placementArrow-ViMwQSa-.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BVTetMpc.js → responsiveObserve-dEL3u4E7.js} +1 -1
- package/src/assets/web-panel/assets/{slide-abEcz-Cv.js → slide-l05us-Gz.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-CBhrdU2G.js → statusUtils-Bk-Qn2Og.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-CFq8ZCKa.js → styleChecker-Bn186qeY.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-o4eE7fDV.js → useFlexGapSupport-WP-ugR3H.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-Hs9W8ihi.js → useFs-1SvoeSCL.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-Bnet5Jho.js → usePersonalDataHub-CfNU8N3z.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-DJfN4kWs.js → vnode-Bd2Ya101.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-BzV-2e7X.js → zoom-Def_MeZv.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +2 -2
- package/src/commands/agent.js +20 -20
- package/src/commands/goal.js +299 -1
- package/src/commands/plugin.js +129 -68
- package/src/constants.js +2 -2
- package/src/data/changelog.json +13 -0
- package/src/lib/cli-goal-catalog.js +129 -0
- package/src/lib/cli-goal-source.js +119 -0
- package/src/lib/config-schema.js +1 -1
- package/src/lib/eval/stream-terminal.js +27 -2
- package/src/lib/evolution/evolution-artifact-ports.js +22 -11
- package/src/lib/evolution/evolution-file-witness.js +86 -63
- package/src/lib/evolution/evolution-ledger-file-backend.js +22 -0
- package/src/lib/evolution/evolution-ledger-file-manifest-catalog.js +34 -35
- package/src/lib/evolution/evolution-ledger-file-manifest-head-store.js +32 -39
- package/src/lib/evolution/evolution-ledger.js +367 -169
- package/src/lib/evolution/evolution-manifest-state-reader.js +58 -0
- package/src/lib/evolution/evolution-physical-state-reader.js +308 -0
- package/src/lib/evolution/evolution-witness-segments.js +12 -13
- package/src/lib/evolution/governed-wiki-pruning-ledger-adapter.js +82 -56
- package/src/lib/evolution/rrsi-observed-text-index.js +17 -1
- package/src/lib/evolution/rrsi-tenant-index-anchor-history.js +5 -0
- package/src/lib/execution-location-failure-site.js +20 -3
- package/src/lib/goal-store.js +8 -1
- package/src/lib/image-input.js +43 -14
- package/src/lib/llm-providers.js +1 -0
- package/src/lib/plugin-runtime/capabilities.js +10 -0
- package/src/lib/plugin-runtime/cli-goal-draft-request.js +138 -0
- package/src/lib/plugin-runtime/cli-goal-drafts.js +413 -0
- package/src/lib/plugin-runtime/cli-goal-extension-host.js +234 -0
- package/src/lib/plugin-runtime/examples/goal-description-drafter/plugin.json +17 -0
- package/src/lib/plugin-runtime/examples/goal-evidence-viewer/plugin.json +25 -0
- package/src/lib/plugin-runtime/examples/goal-progress-viewer/plugin.json +21 -0
- package/src/lib/plugin-runtime/examples/project-delivery-assistant/plugin.json +38 -0
- package/src/lib/plugin-runtime/goal-extension-contract.js +190 -0
- package/src/lib/plugin-runtime/goal-extensions.js +277 -0
- package/src/lib/plugin-runtime/install.js +40 -40
- package/src/lib/plugin-runtime/manifest.js +12 -0
- package/src/lib/plugin-runtime/policy.js +1 -0
- package/src/lib/project-goal-connection.js +225 -0
- package/src/lib/project-goal-draft-connection.js +217 -0
- package/src/lib/task-model-selector.js +1 -1
- package/src/repl/agent-repl.js +14 -7
- package/src/repl/config-summary.js +1 -1
- package/src/runtime/agent-core.js +1 -1
- package/src/runtime/headless-stream.js +4 -6
- package/src/runtime/policies/agent-policy.js +1 -0
- package/src/assets/web-panel/assets/Projects-Den4RUw6.js +0 -1
- package/src/assets/web-panel/assets/devWarning-D_MJgDGJ.js +0 -1
- package/src/assets/web-panel/assets/index-BP8log78.js +0 -1
- package/src/assets/web-panel/assets/index-PexF9zYf.js +0 -1
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { VERSION } from "../../constants.js";
|
|
4
|
+
import { managedSettingsPath } from "../settings-loader.cjs";
|
|
5
|
+
import { createProjectGoalConnection } from "../project-goal-connection.js";
|
|
6
|
+
import {
|
|
7
|
+
collectGoalExtensions,
|
|
8
|
+
proposeGoalExtensionAction,
|
|
9
|
+
} from "./goal-extensions.js";
|
|
10
|
+
import { readGoalDraftDescription } from "./cli-goal-draft-request.js";
|
|
11
|
+
import { digestBusinessObjectContent as digest } from "@chainlesschain/session-core/business-object-contract";
|
|
12
|
+
import {
|
|
13
|
+
ACCESS_SCHEMA,
|
|
14
|
+
MAX_SUBMISSION_REFERENCE_BYTES,
|
|
15
|
+
validateGoalDraftAccess,
|
|
16
|
+
validateGoalDraftProposal,
|
|
17
|
+
validateGoalDraftReceipt,
|
|
18
|
+
validateGoalDraftSources,
|
|
19
|
+
createGoalDraftSubmissionReference,
|
|
20
|
+
validateGoalDraftSubmissionReference,
|
|
21
|
+
} from "@chainlesschain/session-core/goal-draft-connection-contract";
|
|
22
|
+
|
|
23
|
+
const HOST = Object.freeze({
|
|
24
|
+
id: "cli",
|
|
25
|
+
version: VERSION,
|
|
26
|
+
capabilities: Object.freeze(["proposal:task.description.update"]),
|
|
27
|
+
});
|
|
28
|
+
export const CLI_GOAL_DRAFT_SUBMISSION_SCHEMA =
|
|
29
|
+
"chainlesschain.goal-draft-submission/v1";
|
|
30
|
+
export const CLI_GOAL_DRAFT_SOURCES_SCHEMA =
|
|
31
|
+
"chainlesschain.goal-draft-source-page/v1";
|
|
32
|
+
export const _deps = {
|
|
33
|
+
createProjectGoalConnection,
|
|
34
|
+
collectGoalExtensions,
|
|
35
|
+
proposeGoalExtensionAction,
|
|
36
|
+
};
|
|
37
|
+
const same = (a, b) => digest(a) === digest(b);
|
|
38
|
+
function fail(code) {
|
|
39
|
+
throw Object.assign(new Error(code), { code });
|
|
40
|
+
}
|
|
41
|
+
function required(value) {
|
|
42
|
+
if (
|
|
43
|
+
typeof value !== "string" ||
|
|
44
|
+
!value.trim() ||
|
|
45
|
+
value.length > 4096 ||
|
|
46
|
+
/[\u0000-\u001f\u007f]/u.test(value)
|
|
47
|
+
)
|
|
48
|
+
fail("CLI_GOAL_DRAFT_ARGUMENTS_REQUIRED");
|
|
49
|
+
return value;
|
|
50
|
+
}
|
|
51
|
+
function fixedOptions(raw) {
|
|
52
|
+
const options = { ...raw },
|
|
53
|
+
env = Object.freeze({ ...(options.env || process.env) });
|
|
54
|
+
const cwd = path.resolve(options.cwd || process.cwd());
|
|
55
|
+
required(options.plugin);
|
|
56
|
+
if (!["user", "project", "local"].includes(options.scope))
|
|
57
|
+
fail("CLI_GOAL_DRAFT_ARGUMENTS_REQUIRED");
|
|
58
|
+
for (const key of [
|
|
59
|
+
"connection",
|
|
60
|
+
"record",
|
|
61
|
+
"out",
|
|
62
|
+
"descriptionFile",
|
|
63
|
+
"managedSettingsFile",
|
|
64
|
+
])
|
|
65
|
+
if (options[key] !== undefined)
|
|
66
|
+
options[key] = path.resolve(cwd, required(options[key]));
|
|
67
|
+
const policyEnv = { ...env };
|
|
68
|
+
if (policyEnv.CC_MANAGED_SETTINGS)
|
|
69
|
+
policyEnv.CC_MANAGED_SETTINGS = path.resolve(
|
|
70
|
+
cwd,
|
|
71
|
+
policyEnv.CC_MANAGED_SETTINGS,
|
|
72
|
+
);
|
|
73
|
+
return Object.freeze({
|
|
74
|
+
...options,
|
|
75
|
+
cwd,
|
|
76
|
+
env,
|
|
77
|
+
managedSettingsFile: managedSettingsPath({
|
|
78
|
+
env: policyEnv,
|
|
79
|
+
managedSettingsFile: options.managedSettingsFile,
|
|
80
|
+
}),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function hostOptions(options) {
|
|
84
|
+
return Object.freeze({
|
|
85
|
+
cwd: options.cwd,
|
|
86
|
+
env: options.env,
|
|
87
|
+
managedSettingsFile: options.managedSettingsFile,
|
|
88
|
+
host: HOST,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
function admitted(options, expected) {
|
|
92
|
+
const entry = _deps
|
|
93
|
+
.collectGoalExtensions(hostOptions(options))
|
|
94
|
+
.extensions.find(
|
|
95
|
+
(item) => item.name === options.plugin && item.scope === options.scope,
|
|
96
|
+
);
|
|
97
|
+
if (
|
|
98
|
+
!entry ||
|
|
99
|
+
!entry.declaration.proposals.includes("task.description.update")
|
|
100
|
+
)
|
|
101
|
+
fail("CLI_GOAL_DRAFT_NOT_ADMITTED");
|
|
102
|
+
const access = validateGoalDraftAccess({
|
|
103
|
+
schema: ACCESS_SCHEMA,
|
|
104
|
+
plugin: { name: entry.name, scope: entry.scope, version: entry.version },
|
|
105
|
+
declarationDigest: digest(entry.declaration),
|
|
106
|
+
});
|
|
107
|
+
if (expected && !same(access, expected))
|
|
108
|
+
fail("CLI_GOAL_DRAFT_ADMISSION_CHANGED");
|
|
109
|
+
return access;
|
|
110
|
+
}
|
|
111
|
+
function connected(id, options) {
|
|
112
|
+
required(id);
|
|
113
|
+
required(options.connection);
|
|
114
|
+
const connection = _deps.createProjectGoalConnection(options.connection);
|
|
115
|
+
if (
|
|
116
|
+
connection.drafts !== true ||
|
|
117
|
+
!["read", "sources", "receipt", "enqueue"].every(
|
|
118
|
+
(key) => typeof connection[key] === "function",
|
|
119
|
+
)
|
|
120
|
+
)
|
|
121
|
+
fail("CLI_GOAL_DRAFT_CONNECTION_REQUIRED");
|
|
122
|
+
if (
|
|
123
|
+
connection.goalRef.id !== id ||
|
|
124
|
+
(options.expectedStore !== undefined &&
|
|
125
|
+
options.expectedStore !== connection.goalRef.storeId)
|
|
126
|
+
)
|
|
127
|
+
fail("CLI_GOAL_STORE_MISMATCH");
|
|
128
|
+
const access = admitted(options);
|
|
129
|
+
if (
|
|
130
|
+
!same(access.plugin, connection.plugin) ||
|
|
131
|
+
access.declarationDigest !== connection.declarationDigest
|
|
132
|
+
)
|
|
133
|
+
fail("CLI_GOAL_DRAFT_CONNECTION_MISMATCH");
|
|
134
|
+
return { connection, access };
|
|
135
|
+
}
|
|
136
|
+
function sameFile(a, b) {
|
|
137
|
+
return (
|
|
138
|
+
a.isFile() &&
|
|
139
|
+
b.isFile() &&
|
|
140
|
+
!b.isSymbolicLink() &&
|
|
141
|
+
b.nlink === 1 &&
|
|
142
|
+
a.dev === b.dev &&
|
|
143
|
+
a.ino === b.ino &&
|
|
144
|
+
a.size === b.size &&
|
|
145
|
+
a.mtimeMs === b.mtimeMs &&
|
|
146
|
+
a.ctimeMs === b.ctimeMs
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
function readReference(file) {
|
|
150
|
+
const before = fs.lstatSync(file);
|
|
151
|
+
if (
|
|
152
|
+
!before.isFile() ||
|
|
153
|
+
before.isSymbolicLink() ||
|
|
154
|
+
before.nlink !== 1 ||
|
|
155
|
+
before.size > MAX_SUBMISSION_REFERENCE_BYTES
|
|
156
|
+
)
|
|
157
|
+
fail("CLI_GOAL_DRAFT_RECORD_INVALID");
|
|
158
|
+
const fd = fs.openSync(
|
|
159
|
+
file,
|
|
160
|
+
fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW || 0),
|
|
161
|
+
);
|
|
162
|
+
try {
|
|
163
|
+
if (!sameFile(before, fs.fstatSync(fd)))
|
|
164
|
+
fail("CLI_GOAL_DRAFT_RECORD_CHANGED");
|
|
165
|
+
const bytes = Buffer.alloc(MAX_SUBMISSION_REFERENCE_BYTES + 1);
|
|
166
|
+
const length = fs.readSync(fd, bytes, 0, bytes.length, 0);
|
|
167
|
+
if (
|
|
168
|
+
length !== before.size ||
|
|
169
|
+
!sameFile(before, fs.fstatSync(fd)) ||
|
|
170
|
+
!sameFile(before, fs.lstatSync(file))
|
|
171
|
+
)
|
|
172
|
+
fail("CLI_GOAL_DRAFT_RECORD_CHANGED");
|
|
173
|
+
const reference = validateGoalDraftSubmissionReference(
|
|
174
|
+
JSON.parse(
|
|
175
|
+
new TextDecoder("utf-8", { fatal: true }).decode(
|
|
176
|
+
bytes.subarray(0, length),
|
|
177
|
+
),
|
|
178
|
+
),
|
|
179
|
+
);
|
|
180
|
+
return {
|
|
181
|
+
reference,
|
|
182
|
+
verify() {
|
|
183
|
+
if (!sameFile(before, fs.lstatSync(file)))
|
|
184
|
+
fail("CLI_GOAL_DRAFT_RECORD_CHANGED");
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
} finally {
|
|
188
|
+
fs.closeSync(fd);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
function writeNew(file, value) {
|
|
192
|
+
const fd = fs.openSync(file, "wx", 0o600);
|
|
193
|
+
try {
|
|
194
|
+
fs.writeFileSync(fd, JSON.stringify(value));
|
|
195
|
+
fs.fsyncSync(fd);
|
|
196
|
+
} finally {
|
|
197
|
+
fs.closeSync(fd);
|
|
198
|
+
}
|
|
199
|
+
// Persist the new directory entry as well on systems that support it.
|
|
200
|
+
if (process.platform !== "win32") {
|
|
201
|
+
const directory = fs.openSync(path.dirname(file), fs.constants.O_RDONLY);
|
|
202
|
+
try {
|
|
203
|
+
fs.fsyncSync(directory);
|
|
204
|
+
} finally {
|
|
205
|
+
fs.closeSync(directory);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
function persistReference(file, expected) {
|
|
210
|
+
let created = false;
|
|
211
|
+
try {
|
|
212
|
+
writeNew(file, expected);
|
|
213
|
+
created = true;
|
|
214
|
+
} catch (error) {
|
|
215
|
+
if (error.code !== "EEXIST") throw error;
|
|
216
|
+
}
|
|
217
|
+
const saved = readReference(file);
|
|
218
|
+
if (!same(saved.reference, expected)) fail("CLI_GOAL_DRAFT_RECORD_CONFLICT");
|
|
219
|
+
return { ...saved, created };
|
|
220
|
+
}
|
|
221
|
+
function referenceFor(connection, access, requestId, inputDigest) {
|
|
222
|
+
return createGoalDraftSubmissionReference({
|
|
223
|
+
goalRef: connection.goalRef,
|
|
224
|
+
...Object.fromEntries(
|
|
225
|
+
["plugin", "declarationDigest"].map((key) => [key, access[key]]),
|
|
226
|
+
),
|
|
227
|
+
grantRef: connection.grantRef,
|
|
228
|
+
requestId,
|
|
229
|
+
inputDigest,
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
function outcome(reference, file, receipt) {
|
|
233
|
+
return {
|
|
234
|
+
schema: CLI_GOAL_DRAFT_SUBMISSION_SCHEMA,
|
|
235
|
+
state: receipt?.state ?? "unknown",
|
|
236
|
+
goalRef: reference.goalRef,
|
|
237
|
+
plugin: reference.plugin,
|
|
238
|
+
declarationDigest: reference.declarationDigest,
|
|
239
|
+
grantRef: reference.grantRef,
|
|
240
|
+
requestId: reference.requestId,
|
|
241
|
+
inputDigest: reference.inputDigest,
|
|
242
|
+
proposalId: receipt?.proposalId ?? null,
|
|
243
|
+
record: file,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
async function queryReceipt(connection, saved, file) {
|
|
247
|
+
saved.verify();
|
|
248
|
+
try {
|
|
249
|
+
const receipt = validateGoalDraftReceipt(
|
|
250
|
+
await connection.receipt({
|
|
251
|
+
requestId: saved.reference.requestId,
|
|
252
|
+
inputDigest: saved.reference.inputDigest,
|
|
253
|
+
}),
|
|
254
|
+
);
|
|
255
|
+
if (
|
|
256
|
+
receipt.requestId !== saved.reference.requestId ||
|
|
257
|
+
receipt.inputDigest !== saved.reference.inputDigest
|
|
258
|
+
)
|
|
259
|
+
fail("CLI_GOAL_DRAFT_RECEIPT_MISMATCH");
|
|
260
|
+
return outcome(saved.reference, file, receipt);
|
|
261
|
+
} catch {
|
|
262
|
+
return outcome(saved.reference, file);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/** Exports an identity label and declaration digest, never native authority. */
|
|
267
|
+
export async function exportCliGoalDraftAccess(raw = {}) {
|
|
268
|
+
const options = fixedOptions(raw);
|
|
269
|
+
required(options.out);
|
|
270
|
+
const access = admitted(options);
|
|
271
|
+
writeNew(options.out, access);
|
|
272
|
+
return {
|
|
273
|
+
schema: "chainlesschain.goal-draft-access-export/v1",
|
|
274
|
+
state: "access-exported",
|
|
275
|
+
plugin: access.plugin,
|
|
276
|
+
declarationDigest: access.declarationDigest,
|
|
277
|
+
file: options.out,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
export async function readCliGoalDraftSources(id, raw = {}) {
|
|
281
|
+
const options = fixedOptions(raw),
|
|
282
|
+
{ connection, access } = connected(id, options);
|
|
283
|
+
if (
|
|
284
|
+
options.after !== undefined &&
|
|
285
|
+
(typeof options.after !== "string" ||
|
|
286
|
+
!/^goal-proposal-[a-f0-9]{64}$/u.test(options.after))
|
|
287
|
+
)
|
|
288
|
+
fail("CLI_GOAL_DRAFT_INVALID_CURSOR");
|
|
289
|
+
const sources = validateGoalDraftSources(
|
|
290
|
+
await connection.sources(options.after),
|
|
291
|
+
);
|
|
292
|
+
admitted(options, access);
|
|
293
|
+
return {
|
|
294
|
+
schema: CLI_GOAL_DRAFT_SOURCES_SCHEMA,
|
|
295
|
+
goalRef: connection.goalRef,
|
|
296
|
+
plugin: access.plugin,
|
|
297
|
+
declarationDigest: access.declarationDigest,
|
|
298
|
+
grantRef: connection.grantRef,
|
|
299
|
+
sources,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
export async function sendCliGoalDraft(id, raw = {}) {
|
|
303
|
+
const options = fixedOptions(raw);
|
|
304
|
+
required(options.record);
|
|
305
|
+
required(options.descriptionFile);
|
|
306
|
+
const { connection, access } = connected(id, options);
|
|
307
|
+
const proposal = validateGoalDraftProposal({
|
|
308
|
+
type: "task.description.update",
|
|
309
|
+
goalRef: connection.goalRef,
|
|
310
|
+
sourceRef: options.source,
|
|
311
|
+
requestId: options.requestId,
|
|
312
|
+
title: options.title,
|
|
313
|
+
description: readGoalDraftDescription(options.descriptionFile),
|
|
314
|
+
});
|
|
315
|
+
const reference = referenceFor(
|
|
316
|
+
connection,
|
|
317
|
+
access,
|
|
318
|
+
proposal.requestId,
|
|
319
|
+
digest(proposal),
|
|
320
|
+
);
|
|
321
|
+
const saved = persistReference(options.record, reference);
|
|
322
|
+
// Existing durable identity is always reconciled. Even a not-found response
|
|
323
|
+
// does not authorize this retry path to send another mutation automatically.
|
|
324
|
+
if (!saved.created) return queryReceipt(connection, saved, options.record);
|
|
325
|
+
let nativeReceipt;
|
|
326
|
+
let dispatched = false;
|
|
327
|
+
try {
|
|
328
|
+
await _deps.proposeGoalExtensionAction(access.plugin, proposal, {
|
|
329
|
+
...hostOptions(options),
|
|
330
|
+
async authorize(context) {
|
|
331
|
+
if (
|
|
332
|
+
context.operation !== "propose-action" ||
|
|
333
|
+
!same(context.plugin, access.plugin) ||
|
|
334
|
+
!same(context.goalRef, proposal.goalRef) ||
|
|
335
|
+
context.requestId !== proposal.requestId ||
|
|
336
|
+
context.sourceRef !== proposal.sourceRef ||
|
|
337
|
+
context.type !== proposal.type
|
|
338
|
+
)
|
|
339
|
+
return false;
|
|
340
|
+
saved.verify();
|
|
341
|
+
const current = await connection.read(id);
|
|
342
|
+
if (
|
|
343
|
+
!same(current.goalRef, proposal.goalRef) ||
|
|
344
|
+
current.status !== "active"
|
|
345
|
+
)
|
|
346
|
+
return false;
|
|
347
|
+
admitted(options, access);
|
|
348
|
+
saved.verify();
|
|
349
|
+
return true;
|
|
350
|
+
},
|
|
351
|
+
async enqueueProposal(context) {
|
|
352
|
+
const projected = validateGoalDraftProposal(
|
|
353
|
+
Object.fromEntries(
|
|
354
|
+
[
|
|
355
|
+
"type",
|
|
356
|
+
"goalRef",
|
|
357
|
+
"sourceRef",
|
|
358
|
+
"requestId",
|
|
359
|
+
"title",
|
|
360
|
+
"description",
|
|
361
|
+
].map((key) => [key, context[key]]),
|
|
362
|
+
),
|
|
363
|
+
);
|
|
364
|
+
if (
|
|
365
|
+
!same(context.plugin, access.plugin) ||
|
|
366
|
+
context.operation !== "propose-action" ||
|
|
367
|
+
context.state !== "pending-confirmation" ||
|
|
368
|
+
!same(projected, proposal)
|
|
369
|
+
)
|
|
370
|
+
fail("CLI_GOAL_DRAFT_CONTEXT_CHANGED");
|
|
371
|
+
admitted(options, access);
|
|
372
|
+
saved.verify();
|
|
373
|
+
dispatched = true;
|
|
374
|
+
const receipt = validateGoalDraftReceipt(
|
|
375
|
+
await connection.enqueue(projected),
|
|
376
|
+
);
|
|
377
|
+
if (
|
|
378
|
+
receipt.state !== "saved" ||
|
|
379
|
+
receipt.requestId !== reference.requestId ||
|
|
380
|
+
receipt.inputDigest !== reference.inputDigest
|
|
381
|
+
)
|
|
382
|
+
fail("CLI_GOAL_DRAFT_RECEIPT_MISMATCH");
|
|
383
|
+
nativeReceipt = receipt;
|
|
384
|
+
return {
|
|
385
|
+
proposalId: receipt.proposalId,
|
|
386
|
+
state: "pending-confirmation",
|
|
387
|
+
};
|
|
388
|
+
},
|
|
389
|
+
});
|
|
390
|
+
if (!nativeReceipt) fail("CLI_GOAL_DRAFT_RECEIPT_MISMATCH");
|
|
391
|
+
// A verified saved receipt is not undone by a later local admission change.
|
|
392
|
+
return outcome(reference, options.record, nativeReceipt);
|
|
393
|
+
} catch (error) {
|
|
394
|
+
if (nativeReceipt) return outcome(reference, options.record, nativeReceipt);
|
|
395
|
+
if (dispatched || error.outcomeUnknown)
|
|
396
|
+
return outcome(reference, options.record);
|
|
397
|
+
throw error;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
export async function readCliGoalDraftReceipt(id, raw = {}) {
|
|
401
|
+
const options = fixedOptions(raw);
|
|
402
|
+
required(options.record);
|
|
403
|
+
const { connection, access } = connected(id, options),
|
|
404
|
+
saved = readReference(options.record);
|
|
405
|
+
const expected = referenceFor(
|
|
406
|
+
connection,
|
|
407
|
+
access,
|
|
408
|
+
saved.reference.requestId,
|
|
409
|
+
saved.reference.inputDigest,
|
|
410
|
+
);
|
|
411
|
+
if (!same(expected, saved.reference)) fail("CLI_GOAL_DRAFT_RECORD_CONFLICT");
|
|
412
|
+
return queryReceipt(connection, saved, options.record);
|
|
413
|
+
}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
/** Explicit goal panels from standalone files or a short-lived desktop read lease. */
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import { VERSION } from "../../constants.js";
|
|
5
|
+
import { resolveConfigDataRoot } from "../paths.js";
|
|
6
|
+
import { managedSettingsPath } from "../settings-loader.cjs";
|
|
7
|
+
import { createCliGoalSnapshotReader } from "../cli-goal-source.js";
|
|
8
|
+
import { createProjectGoalConnection } from "../project-goal-connection.js";
|
|
9
|
+
import { formatGoalEvidenceProjection } from "@chainlesschain/session-core/goal-evidence-contract";
|
|
10
|
+
import {
|
|
11
|
+
collectGoalExtensions,
|
|
12
|
+
projectGoalExtensionPanel,
|
|
13
|
+
} from "./goal-extensions.js";
|
|
14
|
+
|
|
15
|
+
export const CLI_GOAL_PANEL_SCHEMA = "chainlesschain.goal-extension-panels.v1";
|
|
16
|
+
export const CLI_GOAL_EXTENSION_HOST = Object.freeze({
|
|
17
|
+
id: "cli",
|
|
18
|
+
version: VERSION,
|
|
19
|
+
capabilities: Object.freeze(["panel:goal.summary"]),
|
|
20
|
+
});
|
|
21
|
+
export const _deps = { collectGoalExtensions, projectGoalExtensionPanel };
|
|
22
|
+
|
|
23
|
+
function fail(code) {
|
|
24
|
+
throw new Error(code);
|
|
25
|
+
}
|
|
26
|
+
function digest(record) {
|
|
27
|
+
return createHash("sha256").update(JSON.stringify(record)).digest("hex");
|
|
28
|
+
}
|
|
29
|
+
/** Explicit user read; all source/plugin revalidation completes before return. */
|
|
30
|
+
export async function readCliGoalExtensionPanels(id, options = {}) {
|
|
31
|
+
const cwd = path.resolve(options.cwd || process.cwd());
|
|
32
|
+
const env = Object.freeze({ ...(options.env || process.env) });
|
|
33
|
+
const root = path.resolve(
|
|
34
|
+
options.root ||
|
|
35
|
+
path.join(resolveConfigDataRoot({ cwd, env }).path, "goals"),
|
|
36
|
+
);
|
|
37
|
+
const managedSettingsFile = managedSettingsPath({
|
|
38
|
+
env,
|
|
39
|
+
managedSettingsFile: options.managedSettingsFile,
|
|
40
|
+
});
|
|
41
|
+
const pluginName = options.plugin;
|
|
42
|
+
const scope = options.scope;
|
|
43
|
+
if (scope !== undefined && !["user", "project", "local"].includes(scope))
|
|
44
|
+
fail("CLI_GOAL_INVALID_PLUGIN_SCOPE");
|
|
45
|
+
if (
|
|
46
|
+
pluginName !== undefined &&
|
|
47
|
+
(typeof pluginName !== "string" || !pluginName || pluginName.length > 256)
|
|
48
|
+
)
|
|
49
|
+
fail("CLI_GOAL_INVALID_PLUGIN_NAME");
|
|
50
|
+
const connection =
|
|
51
|
+
options.connection !== undefined
|
|
52
|
+
? createProjectGoalConnection(options.connection)
|
|
53
|
+
: null;
|
|
54
|
+
const source = connection
|
|
55
|
+
? { storeId: connection.goalRef.storeId }
|
|
56
|
+
: createCliGoalSnapshotReader(root);
|
|
57
|
+
if (
|
|
58
|
+
options.expectedStore !== undefined &&
|
|
59
|
+
options.expectedStore !== source.storeId
|
|
60
|
+
)
|
|
61
|
+
fail("CLI_GOAL_STORE_MISMATCH");
|
|
62
|
+
const remote = connection ? await connection.read(id) : null;
|
|
63
|
+
const snapshot = connection ? null : source.read(id);
|
|
64
|
+
const goal = remote
|
|
65
|
+
? { ...remote.goalRef, objective: remote.objective, status: remote.status }
|
|
66
|
+
: snapshot.goal;
|
|
67
|
+
const goalRef = Object.freeze({
|
|
68
|
+
id: goal.id,
|
|
69
|
+
storeId: goal.storeId,
|
|
70
|
+
revision: goal.revision,
|
|
71
|
+
controlGeneration: goal.controlGeneration,
|
|
72
|
+
});
|
|
73
|
+
const currentGoal = async () => {
|
|
74
|
+
if (!connection) return source.revalidate(snapshot);
|
|
75
|
+
const latest = await connection.read(id);
|
|
76
|
+
if (
|
|
77
|
+
latest.objective !== goal.objective ||
|
|
78
|
+
latest.status !== goal.status ||
|
|
79
|
+
(connection.evidence &&
|
|
80
|
+
digest({ risk: latest.risk, receipts: latest.receipts }) !==
|
|
81
|
+
digest({ risk: remote.risk, receipts: remote.receipts }))
|
|
82
|
+
)
|
|
83
|
+
fail("CLI_GOAL_CONNECTION_CHANGED");
|
|
84
|
+
return {
|
|
85
|
+
...latest.goalRef,
|
|
86
|
+
objective: latest.objective,
|
|
87
|
+
status: latest.status,
|
|
88
|
+
...(connection.evidence
|
|
89
|
+
? { risk: latest.risk, receipts: latest.receipts }
|
|
90
|
+
: {}),
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
const hostOptions = Object.freeze({
|
|
94
|
+
cwd,
|
|
95
|
+
env,
|
|
96
|
+
managedSettingsFile,
|
|
97
|
+
host: connection?.evidence
|
|
98
|
+
? Object.freeze({
|
|
99
|
+
...CLI_GOAL_EXTENSION_HOST,
|
|
100
|
+
capabilities: Object.freeze([
|
|
101
|
+
"panel:goal.summary",
|
|
102
|
+
"panel:goal.evidence",
|
|
103
|
+
]),
|
|
104
|
+
})
|
|
105
|
+
: CLI_GOAL_EXTENSION_HOST,
|
|
106
|
+
async authorize(context) {
|
|
107
|
+
if (
|
|
108
|
+
context.operation !== "read-panel" ||
|
|
109
|
+
context.goalRef.id !== id ||
|
|
110
|
+
context.goalRef.storeId !== source.storeId ||
|
|
111
|
+
context.goalRef.revision !== goalRef.revision ||
|
|
112
|
+
context.goalRef.controlGeneration !== goalRef.controlGeneration
|
|
113
|
+
)
|
|
114
|
+
return false;
|
|
115
|
+
await currentGoal();
|
|
116
|
+
return true;
|
|
117
|
+
},
|
|
118
|
+
async readPanel(context) {
|
|
119
|
+
if (
|
|
120
|
+
![
|
|
121
|
+
"goal.summary",
|
|
122
|
+
...(connection?.evidence ? ["goal.evidence"] : []),
|
|
123
|
+
].includes(context.panel.slot) ||
|
|
124
|
+
context.panel.fields.some(
|
|
125
|
+
(field) =>
|
|
126
|
+
![
|
|
127
|
+
"objective",
|
|
128
|
+
"status",
|
|
129
|
+
...(connection?.evidence && context.panel.slot === "goal.evidence"
|
|
130
|
+
? ["riskSummary", "receiptSummary"]
|
|
131
|
+
: []),
|
|
132
|
+
].includes(field),
|
|
133
|
+
)
|
|
134
|
+
)
|
|
135
|
+
fail("CLI_GOAL_PANEL_FIELDS_UNSUPPORTED");
|
|
136
|
+
const current = await currentGoal();
|
|
137
|
+
const objective =
|
|
138
|
+
current.objective.length > 4096
|
|
139
|
+
? `${current.objective.slice(0, 4075)}… [truncated]`
|
|
140
|
+
: current.objective;
|
|
141
|
+
return {
|
|
142
|
+
objective,
|
|
143
|
+
status: current.status,
|
|
144
|
+
...(connection?.evidence && context.panel.slot === "goal.evidence"
|
|
145
|
+
? formatGoalEvidenceProjection({
|
|
146
|
+
risk: current.risk,
|
|
147
|
+
receipts: current.receipts,
|
|
148
|
+
})
|
|
149
|
+
: {}),
|
|
150
|
+
};
|
|
151
|
+
},
|
|
152
|
+
});
|
|
153
|
+
const selected = (entry) =>
|
|
154
|
+
(!pluginName || entry.name === pluginName) &&
|
|
155
|
+
(!scope || entry.scope === scope);
|
|
156
|
+
const initial = _deps.collectGoalExtensions(hostOptions);
|
|
157
|
+
const plugins = initial.extensions.filter(selected);
|
|
158
|
+
const dropped = initial.dropped.filter(
|
|
159
|
+
(entry) => !entry.name || selected(entry),
|
|
160
|
+
);
|
|
161
|
+
if (plugins.length > 32) fail("CLI_GOAL_PANEL_LIMIT_EXCEEDED");
|
|
162
|
+
let panels = [];
|
|
163
|
+
for (const plugin of plugins) {
|
|
164
|
+
const ref = {
|
|
165
|
+
name: plugin.name,
|
|
166
|
+
scope: plugin.scope,
|
|
167
|
+
version: plugin.version,
|
|
168
|
+
};
|
|
169
|
+
const projected = [];
|
|
170
|
+
try {
|
|
171
|
+
for (const panel of plugin.declaration.panels) {
|
|
172
|
+
projected.push({
|
|
173
|
+
plugin: ref,
|
|
174
|
+
...(await _deps.projectGoalExtensionPanel(
|
|
175
|
+
ref,
|
|
176
|
+
{ panelId: panel.id, goalRef },
|
|
177
|
+
hostOptions,
|
|
178
|
+
)),
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
panels.push(...projected);
|
|
182
|
+
} catch {
|
|
183
|
+
dropped.push({
|
|
184
|
+
name: plugin.name,
|
|
185
|
+
scope: plugin.scope,
|
|
186
|
+
reason: "panel_unavailable",
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
if (panels.length > 16) fail("CLI_GOAL_PANEL_LIMIT_EXCEEDED");
|
|
190
|
+
}
|
|
191
|
+
await currentGoal();
|
|
192
|
+
const latest = _deps.collectGoalExtensions(hostOptions);
|
|
193
|
+
panels = panels.filter((panel) => {
|
|
194
|
+
const before = plugins.find(
|
|
195
|
+
(plugin) =>
|
|
196
|
+
plugin.name === panel.plugin.name &&
|
|
197
|
+
plugin.scope === panel.plugin.scope,
|
|
198
|
+
);
|
|
199
|
+
const after = latest.extensions.find(
|
|
200
|
+
(plugin) =>
|
|
201
|
+
plugin.name === panel.plugin.name &&
|
|
202
|
+
plugin.scope === panel.plugin.scope &&
|
|
203
|
+
plugin.version === panel.plugin.version,
|
|
204
|
+
);
|
|
205
|
+
const allowed =
|
|
206
|
+
after && digest(after.declaration) === digest(before.declaration);
|
|
207
|
+
if (
|
|
208
|
+
!allowed &&
|
|
209
|
+
!dropped.some(
|
|
210
|
+
(entry) =>
|
|
211
|
+
entry.name === panel.plugin.name &&
|
|
212
|
+
entry.scope === panel.plugin.scope,
|
|
213
|
+
)
|
|
214
|
+
)
|
|
215
|
+
dropped.push({
|
|
216
|
+
name: panel.plugin.name,
|
|
217
|
+
scope: panel.plugin.scope,
|
|
218
|
+
reason: "admission_changed",
|
|
219
|
+
});
|
|
220
|
+
return allowed;
|
|
221
|
+
});
|
|
222
|
+
const result = {
|
|
223
|
+
schema: CLI_GOAL_PANEL_SCHEMA,
|
|
224
|
+
...(connection ? { source: "desktop-project" } : {}),
|
|
225
|
+
goalRef,
|
|
226
|
+
snapshot: true,
|
|
227
|
+
observedAt: new Date().toISOString(),
|
|
228
|
+
panels,
|
|
229
|
+
dropped,
|
|
230
|
+
};
|
|
231
|
+
if (Buffer.byteLength(JSON.stringify(result), "utf8") > 128 * 1024)
|
|
232
|
+
fail("CLI_GOAL_PANEL_LIMIT_EXCEEDED");
|
|
233
|
+
return result;
|
|
234
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "goal-description-drafter",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Export user-selected description requests for explicit native adoption",
|
|
5
|
+
"permissions": { "goalExtension": ["proposal:task.description.update"] },
|
|
6
|
+
"goalExtension": {
|
|
7
|
+
"apiVersion": "1.0.0",
|
|
8
|
+
"hosts": {
|
|
9
|
+
"cli": ">=0.166.104",
|
|
10
|
+
"vscode": ">=0.37.149",
|
|
11
|
+
"jetbrains": ">=0.4.166"
|
|
12
|
+
},
|
|
13
|
+
"events": [],
|
|
14
|
+
"panels": [],
|
|
15
|
+
"proposals": ["task.description.update"]
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "goal-evidence-viewer",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Read historical risk checks and action-receipt summaries through an explicitly authorized desktop evidence connection",
|
|
5
|
+
"permissions": { "goalExtension": ["panel:goal.evidence"] },
|
|
6
|
+
"goalExtension": {
|
|
7
|
+
"apiVersion": "1.0.0",
|
|
8
|
+
"hosts": {
|
|
9
|
+
"cli": ">=0.166.104",
|
|
10
|
+
"vscode": ">=0.37.149",
|
|
11
|
+
"jetbrains": ">=0.4.166"
|
|
12
|
+
},
|
|
13
|
+
"events": [],
|
|
14
|
+
"panels": [
|
|
15
|
+
{
|
|
16
|
+
"id": "delivery-evidence",
|
|
17
|
+
"title": "Historical project goal evidence",
|
|
18
|
+
"slot": "goal.evidence",
|
|
19
|
+
"fields": ["objective", "status", "riskSummary", "receiptSummary"],
|
|
20
|
+
"fallback": "text"
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
"proposals": []
|
|
24
|
+
}
|
|
25
|
+
}
|