chainlesschain 0.166.15 → 0.166.17
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 +3 -3
- package/completions/_cc +1 -1
- package/completions/cc.bash +1 -1
- package/completions/cc.fish +1 -1
- package/completions/cc.ps1 +1 -1
- package/package.json +2 -2
- package/src/assets/web-panel/assets/{AIOps-To-6rimH.js → AIOps-CVW2n2rh.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CpdCnTv3.js → ActionButton-DtuM163O.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DK7VNES_.js → Analytics-BXvl_qHu.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-NZ5FvhCx.js → AppLayout-VDBTFKOp.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-NXceQPmN.js → Artifacts-BNz2xCiG.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-B2d64DH2.js → Audit-DTu9Hn9P.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-ByYgvEVY.js → BackgroundAgents-D2OCPzLe.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BXvQLDvN.js → Backup-C9M-vG7G.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-C4GZk-As.js → BaseInput-BUkCNiUQ.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CvPuohL8.js → Chat-OJ2ajF7l.js} +5 -5
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-DTftcclX.js → ChatBubbleRenderer-BdZt76Ab.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-C8dQGIqD.js → Checkbox-C1gXKDsc.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-DRM6S1W4.js → Codegen-BXbznLg7.js} +1 -1
- package/src/assets/web-panel/assets/{Col-BDM8l-r5.js → Col-CbCq5N0i.js} +1 -1
- package/src/assets/web-panel/assets/{Community-Bvmfi1fX.js → Community-V8Ks6Yun.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DGQTCima.js → Compact-DkeHQTpQ.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-D_0C-2P6.js → Compliance-JeLKwn4Q.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-3C_q99ok.js → Cowork-azfetcBz.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-CIiMQ1Hl.js → Cron-Q691i_Gp.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-peebGnES.js → Crosschain-BLjDRbr_.js} +1 -1
- package/src/assets/web-panel/assets/{DID-OkX4KB9T.js → DID-D8ptXplK.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-D9lm0Wxa.js → Dashboard-Ctj2VVZL.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CitActXx.js → Dropdown-D8VgkMJ8.js} +1 -1
- package/src/assets/web-panel/assets/EmailListRenderer-CQPe5S6q.js +1 -0
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-CBWAi8XL.js → FamilyGuardDashboard-ySA-7SiN.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-afj8jDcp.js → Federation-1PMD-fBf.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Dabt59KY.js → FormItemContext-C_jr6U4Q.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-BQpXA9kj.js → GenericCardRenderer-Bu3bKf2B.js} +1 -1
- package/src/assets/web-panel/assets/{Git-D2p2Moo1.js → Git-Dv4Fa_T5.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DkFfPykv.js → Governance-DOEy1n1k.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-C1DKpeN2.js → Inference-DkvqzWcJ.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-CjfVg4oQ.js → KnowledgeGraph-DdUJK949.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-D-zMvdSf.js → Logs-CRelcdUZ.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-jzEpGkbc.js → MarkdownRenderer-0AHbbTA4.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-DfAjJLyS.js → Marketplace-BuuBKsev.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BGDHQES1.js → McpTools-DlgpEmA1.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-BYqrGAPS.js → Memory-DTfdqUGy.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CQ6FEtty.js → MobileBridge-CXLE5ZFO.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BpMvh5JW.js → MobileProjects-Dz25OB0n.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-CWH25SrU.js → Mtc-kEL0fhgD.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-D6DiLmei.js → MtcAudit-BE4UvFJU.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-BSxRN4jD.js → Multisig-CSApSn8c.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-C0FDPKT4.js → NLProgramming-D11FpKWx.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-VKR78bH-.js → Notes-CDL-D2CS.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-DLSklSZB.js → NotificationSettings-C0Q6lO-c.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-ZRE0OKbj.js +1 -0
- package/src/assets/web-panel/assets/{Organization-BB3pB27e.js → Organization-Dc-maVAq.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Cr7bzwcs.js → Overflow-B5mUpSvi.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-D1fkMMzI.js → P2P-TjXV53wq.js} +2 -2
- package/src/assets/web-panel/assets/PdhVaultBrowser-DvV2btIr.js +7 -0
- package/src/assets/web-panel/assets/{Permissions-c3Ijv0v4.js → Permissions-DKRzQ2O6.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BJwbh3P2.js → PersonalDataHub-Dx2eqft8.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-C4fhXafB.js → Pipeline-CnYZMB5p.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DzSx3CD-.js → Privacy-BonKpPnp.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-D9fL5fED.js → ProjectInit-DWO0Du3J.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CB5FVrOR.js → ProjectSettings-C9jqyYRv.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-DWhwdgfY.js → Projects-CYpKwXbz.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-B9ZH4faS.js → Providers-CW-fkwJq.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-BLKDHT8_.js → QrScannerModal-Cw0J3Zud.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-D1oYUcSY.js → QuickAsk-BH4A4IpR.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CC2nmrOD.js → Recommend-CDwMwJus.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-qW9QF4-r.js → RemoteSession-DKIPwzTf.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-BDWqfzcr.js → Reputation-CklDj7qS.js} +1 -1
- package/src/assets/web-panel/assets/{Row-BBV2iCjT.js → Row-DJWZKsH0.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CcwrNwZB.js → RssFeed-BfSLCewo.js} +3 -3
- package/src/assets/web-panel/assets/{Search-Dr6fZ0D_.js → Search-B0IST--x.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BPzaoCU6.js → Security-h1sYNWtt.js} +4 -4
- package/src/assets/web-panel/assets/{Services-BoKUU1I_.js → Services-Gh0-oxI_.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-C8lT8GUg.js → Skeleton-CNDV_jOs.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DPpWeicz.js → Skills-ByCLTh1n.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-UiijzpMU.js → Sla-BfyrJTJz.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DoofrLwS.js → SpeechSettings-BQzo9kNX.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DXnyfTDw.js → SyncSettings-B6fS6z_1.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-g_WHjKeg.js → Tasks-C-uKCP-l.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-DRuCh9g2.js → Templates-D6oDy7wL.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-QHIq1pH1.js → Tenant-D3LT2wNQ.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-G0fuI216.js → Terminal-BteLcv_O.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-4MT7SpGk.js → TimelineRenderer-DHHuxfqH.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-B5xT5umA.js → Tokens-BRQeykXw.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-D7HPbNgc.js → Trigger-p2XaFWEu.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CxH69dU5.js → Trust-BxadBMft.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CPPosveH.js → UkeySign-DRBP7LDk.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-Du5lGwAt.js → VideoEditing-CZ3NZkh7.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BBIGNESK.js → Wallet-C3NTBN7G.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-Cc3HSGmv.js → WebAuthn-C7LVgMlb.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-DBoVPNCh.js → WorkflowEditor-0_Iveog7.js} +1 -1
- package/src/assets/web-panel/assets/{chat-DHcjgiem.js → chat-DzzluYo3.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DrRrvJIV.js → colors-DSMYXpaj.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BuY_sAoN.js → compact-item-W76u1VSV.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-CepH1Fha.js → createContext-otsESjb5.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BztaXF84.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-Dh80Ot6o.js → hasIn-3sNLrvug.js} +1 -1
- package/src/assets/web-panel/assets/index-4jP_hG_4.js +1 -0
- package/src/assets/web-panel/assets/{index-LBkSOwky.js → index-B1I1AYJs.js} +1 -1
- package/src/assets/web-panel/assets/{index-B0rvJjId.js → index-B5LOYdYm.js} +1 -1
- package/src/assets/web-panel/assets/{index-D6tOVlq-.js → index-B9X_jqXe.js} +1 -1
- package/src/assets/web-panel/assets/{index-D7lstbTh.js → index-BA8mZxd-.js} +1 -1
- package/src/assets/web-panel/assets/{index-BPDEOOlA.js → index-BDlDO2px.js} +1 -1
- package/src/assets/web-panel/assets/{index-DuSUCH7h.js → index-BJsQio5O.js} +1 -1
- package/src/assets/web-panel/assets/{index-CEfVkKIY.js → index-BRsD1PT2.js} +1 -1
- package/src/assets/web-panel/assets/{index-CYydOga6.js → index-BXLx9HfA.js} +1 -1
- package/src/assets/web-panel/assets/{index-DkZP_QaB.js → index-BcGJtmHM.js} +1 -1
- package/src/assets/web-panel/assets/{index-BnVIvc15.js → index-BdtmEKat.js} +1 -1
- package/src/assets/web-panel/assets/{index-DuRYBWrj.js → index-BpcQYzP7.js} +1 -1
- package/src/assets/web-panel/assets/{index-By0qqC3S.js → index-C2aht9-M.js} +1 -1
- package/src/assets/web-panel/assets/{index-C10033eO.js → index-CE7tSow-.js} +1 -1
- package/src/assets/web-panel/assets/{index-9crgJ3Id.js → index-CENWwjef.js} +1 -1
- package/src/assets/web-panel/assets/{index-CNQK9DIr.js → index-CKoFyHYQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUNyTmkS.js → index-Cg86EzNp.js} +1 -1
- package/src/assets/web-panel/assets/{index-CnRK8_Dd.js → index-ClOFeZ-t.js} +1 -1
- package/src/assets/web-panel/assets/{index-BW9Pycxh.js → index-CtFOt5x1.js} +1 -1
- package/src/assets/web-panel/assets/{index-D5_K3GKu.js → index-D7A5U2IH.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRy3_beb.js → index-DH4cl52p.js} +1 -1
- package/src/assets/web-panel/assets/{index-DWANFMlq.js → index-DLDh1OW3.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5vhNRqS.js → index-DMmdIpLA.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ca5d64IH.js → index-DS9WYDMf.js} +1 -1
- package/src/assets/web-panel/assets/{index-zGH9zH3w.js → index-DTA8Iavv.js} +3 -3
- package/src/assets/web-panel/assets/{index-BoRy2yup.js → index-DZKAzEge.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cx21_p3m.js → index-DdU7IkKX.js} +1 -1
- package/src/assets/web-panel/assets/{index-B9Gh-SOn.js → index-Ddd4mird.js} +1 -1
- package/src/assets/web-panel/assets/{index-CiUx-tkV.js → index-DmpaC2yk.js} +1 -1
- package/src/assets/web-panel/assets/{index-DYN49m7k.js → index-GlIOE4ja.js} +1 -1
- package/src/assets/web-panel/assets/{index-CUnd5hyp.js → index-MhQQ3h8q.js} +1 -1
- package/src/assets/web-panel/assets/{index-CW_23-gU.js → index-NaO9AE-F.js} +1 -1
- package/src/assets/web-panel/assets/{index-0TYLnd11.js → index-UUHCwfNq.js} +1 -1
- package/src/assets/web-panel/assets/{index-NS9dW1F1.js → index-pVm_iUre.js} +1 -1
- package/src/assets/web-panel/assets/{index-hYaigdGm.js → index-q7ftLqNt.js} +1 -1
- package/src/assets/web-panel/assets/{index-A5lVwYVq.js → index-uSCkbpZH.js} +1 -1
- package/src/assets/web-panel/assets/{index-BtqigRzf.js → index-vBKPcmAP.js} +1 -1
- package/src/assets/web-panel/assets/{index-BiZQooWK.js → index-vUmYkqmu.js} +1 -1
- package/src/assets/web-panel/assets/index-zxwuAXL5.js +1 -0
- package/src/assets/web-panel/assets/{initDefaultProps-nI_X3wKl.js → initDefaultProps-DF6llUXV.js} +1 -1
- package/src/assets/web-panel/assets/{motion-LUHbQu_R.js → motion-vtDV8_5K.js} +1 -1
- package/src/assets/web-panel/assets/{move-DHI_KvJt.js → move-B6c0bdy2.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-AYdL_7Mo.js → mtc-parser-DlLYWuBK.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CtV3HRKa.js → omit-BH0zOxLN.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-CcJLTOu4.js → pickAttrs-D9di8_In.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DHbiLUps.js → placementArrow-BDSngufM.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BC2DGkWP.js → responsiveObserve-C_EawMvP.js} +1 -1
- package/src/assets/web-panel/assets/{slide-B4ga4pPY.js → slide-B_4wShxA.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-hzphgKfH.js → statusUtils-CbQu6qJ-.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-IfN9Bxoi.js → styleChecker-CvXJWYXb.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-pcGKJ4pT.js → useFlexGapSupport-jjY1XknO.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-COXhQpTG.js → useFs-CMXBdsK_.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-xp9F9szv.js → usePersonalDataHub-YbAhhPXx.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BdSQy1Ve.js → vnode-BFCTKc0H.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-CHCt5P55.js → zoom-CY9aBl5O.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +2 -2
- package/src/command-manifest.json +2 -2
- package/src/commands/evolution.js +30 -17
- package/src/commands/learning.js +95 -9
- package/src/commands/team.js +5 -0
- package/src/data/changelog.json +28 -2
- package/src/lib/agent-team/task-lease.js +12 -1
- package/src/lib/capability-manifest.js +212 -1
- package/src/lib/evolution/bounded-skill-improvement-pilot.js +498 -0
- package/src/lib/evolution/evolution-artifact-ports.js +3277 -0
- package/src/lib/evolution/evolution-eval-gate.js +6442 -0
- package/src/lib/evolution/evolution-evidence-projector.js +3786 -0
- package/src/lib/evolution/evolution-ledger-ports.js +2689 -0
- package/src/lib/evolution/evolution-ledger.js +4280 -0
- package/src/lib/evolution/evolution-run-runtime-adapter.js +5 -0
- package/src/lib/evolution/skill-candidate-registry.js +2258 -0
- package/src/lib/evolution/skill-evaluated-promotion-durability.js +899 -0
- package/src/lib/evolution/skill-evaluated-promotion.js +481 -0
- package/src/lib/evolution/skill-execution-manifest.js +942 -0
- package/src/lib/evolution/skill-mutation-authority.js +1677 -0
- package/src/lib/evolution/skill-promotion-controller.js +618 -0
- package/src/lib/evolution/skill-release-registry.js +3277 -0
- package/src/lib/evolution/skill-target-matrix-eval.js +3233 -0
- package/src/lib/evolution/skill-writer-inventory-manifest.js +998 -0
- package/src/lib/evolution/skill-writer-inventory-validator.js +816 -0
- package/src/lib/evolution/wiki-informed-skill-proposer.js +343 -0
- package/src/lib/formal-quality-eval-runtime.js +100 -0
- package/src/lib/graph-kernel/cutover-contract.js +7 -0
- package/src/lib/graph-kernel/cutover-ledger.js +8 -7
- package/src/lib/graph-kernel/evidence-digest.js +47 -0
- package/src/lib/graph-kernel/evolution-run-runtime-adapter.js +5 -0
- package/src/lib/graph-kernel/graph-runtime-surfaces.json +8 -1
- package/src/lib/graph-kernel/production-cutover-evidence.js +342 -15
- package/src/lib/graph-kernel/production-source-evidence.js +1599 -0
- package/src/lib/graph-kernel/retirement-evidence.js +15 -5
- package/src/lib/graph-kernel/runtime-surface-manifest.js +67 -2
- package/src/lib/headless-manifest.js +3 -1
- package/src/lib/hooks-v2-runtime.js +20 -0
- package/src/lib/learning/skill-improver.js +311 -43
- package/src/lib/learning/skill-synthesizer.js +236 -16
- package/src/lib/secure-fs.js +20 -0
- package/src/runtime/agent-core.js +68 -0
- package/src/assets/web-panel/assets/EmailListRenderer-DSmFkNKV.js +0 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-Dpj7D6tC.js +0 -1
- package/src/assets/web-panel/assets/PdhVaultBrowser-BiDEbLNA.js +0 -7
- package/src/assets/web-panel/assets/devWarning-DIb8j04q.js +0 -1
- package/src/assets/web-panel/assets/index-BJc3t4PC.js +0 -1
- package/src/assets/web-panel/assets/index-CkksSUnI.js +0 -1
|
@@ -0,0 +1,343 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
export const WIKI_SKILL_PROPOSAL_SCHEMA =
|
|
4
|
+
"chainlesschain.wiki-informed-skill-proposal/v1";
|
|
5
|
+
export const WIKI_PROPOSAL_STATUS = Object.freeze({
|
|
6
|
+
PROPOSAL: "proposal",
|
|
7
|
+
NO_PROPOSAL: "no-proposal",
|
|
8
|
+
NEEDS_EVIDENCE: "needs-evidence",
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
12
|
+
const SKILL_NAME = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u;
|
|
13
|
+
const INITIAL_SOURCES = Object.freeze([
|
|
14
|
+
"wiki-index",
|
|
15
|
+
"skill-impact",
|
|
16
|
+
"active-skill",
|
|
17
|
+
"training-summary",
|
|
18
|
+
]);
|
|
19
|
+
const SELECTIVE_SOURCES = new Set(["pattern", "raw"]);
|
|
20
|
+
const SAFE_DIFF_ROOTS = new Set([
|
|
21
|
+
"SKILL.md",
|
|
22
|
+
"PURPOSE.md",
|
|
23
|
+
"assets",
|
|
24
|
+
"references",
|
|
25
|
+
"scripts",
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
function canonical(value) {
|
|
29
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
30
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
31
|
+
return `{${Object.keys(value)
|
|
32
|
+
.sort()
|
|
33
|
+
.map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)
|
|
34
|
+
.join(",")}}`;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function hash(value) {
|
|
38
|
+
return `sha256:${createHash("sha256").update(canonical(value)).digest("hex")}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function deepFreeze(value) {
|
|
42
|
+
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
43
|
+
Object.freeze(value);
|
|
44
|
+
for (const child of Object.values(value)) deepFreeze(child);
|
|
45
|
+
}
|
|
46
|
+
return value;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function requiredString(value, name) {
|
|
50
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
51
|
+
throw new TypeError(`${name} is required`);
|
|
52
|
+
}
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function stringList(value, name, { allowEmpty = false, max = 64 } = {}) {
|
|
57
|
+
if (
|
|
58
|
+
!Array.isArray(value) ||
|
|
59
|
+
(!allowEmpty && value.length === 0) ||
|
|
60
|
+
value.length > max ||
|
|
61
|
+
value.some((item) => typeof item !== "string" || item.trim() === "") ||
|
|
62
|
+
new Set(value).size !== value.length
|
|
63
|
+
) {
|
|
64
|
+
throw new TypeError(`${name} must be a bounded unique string list`);
|
|
65
|
+
}
|
|
66
|
+
return [...value];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function verifyEnvelope(value, expectedKind) {
|
|
70
|
+
if (
|
|
71
|
+
!value ||
|
|
72
|
+
typeof value !== "object" ||
|
|
73
|
+
value.kind !== expectedKind ||
|
|
74
|
+
value.trusted !== true ||
|
|
75
|
+
typeof value.ref !== "string" ||
|
|
76
|
+
!DIGEST.test(value.digest ?? "") ||
|
|
77
|
+
value.digest !== hash(value.data)
|
|
78
|
+
) {
|
|
79
|
+
const error = new Error(`${expectedKind} evidence is not digest-bound and trusted`);
|
|
80
|
+
error.code = "WIKI_PROPOSAL_UNTRUSTED_EVIDENCE";
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
return deepFreeze({
|
|
84
|
+
kind: value.kind,
|
|
85
|
+
ref: value.ref,
|
|
86
|
+
digest: value.digest,
|
|
87
|
+
data: structuredClone(value.data),
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function normalizeDescriptor(input) {
|
|
92
|
+
const descriptor = {
|
|
93
|
+
tenantId: requiredString(input?.tenantId, "tenantId"),
|
|
94
|
+
evolutionRunId: requiredString(input?.evolutionRunId, "evolutionRunId"),
|
|
95
|
+
targetSkillName: requiredString(input?.targetSkillName, "targetSkillName"),
|
|
96
|
+
wikiRevision: requiredString(input?.wikiRevision, "wikiRevision"),
|
|
97
|
+
proposerModel: requiredString(input?.proposerModel, "proposerModel"),
|
|
98
|
+
minEvidenceSamples: Math.max(1, Number(input?.minEvidenceSamples) || 1),
|
|
99
|
+
maxSelectiveEvidence: Math.min(
|
|
100
|
+
16,
|
|
101
|
+
Math.max(0, Number(input?.maxSelectiveEvidence) || 4),
|
|
102
|
+
),
|
|
103
|
+
};
|
|
104
|
+
if (!SKILL_NAME.test(descriptor.targetSkillName)) {
|
|
105
|
+
throw new TypeError("targetSkillName must be canonical kebab-case");
|
|
106
|
+
}
|
|
107
|
+
return deepFreeze(descriptor);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function validateDiff(diff) {
|
|
111
|
+
if (!Array.isArray(diff) || diff.length === 0 || diff.length > 128) {
|
|
112
|
+
throw new TypeError("machineDiff must contain 1..128 operations");
|
|
113
|
+
}
|
|
114
|
+
return diff.map((entry) => {
|
|
115
|
+
if (!entry || !["add", "replace", "remove"].includes(entry.op)) {
|
|
116
|
+
throw new TypeError("machineDiff operation is invalid");
|
|
117
|
+
}
|
|
118
|
+
const path = requiredString(entry.path, "machineDiff.path").replaceAll("\\", "/");
|
|
119
|
+
const parts = path.split("/");
|
|
120
|
+
if (
|
|
121
|
+
path.startsWith("/") ||
|
|
122
|
+
parts.includes("..") ||
|
|
123
|
+
!SAFE_DIFF_ROOTS.has(parts[0]) ||
|
|
124
|
+
/(^|\/)(active|\.chainlesschain)(\/|$)/u.test(path)
|
|
125
|
+
) {
|
|
126
|
+
const error = new Error("machineDiff escaped the single candidate Skill");
|
|
127
|
+
error.code = "WIKI_PROPOSAL_UNSAFE_DIFF";
|
|
128
|
+
throw error;
|
|
129
|
+
}
|
|
130
|
+
return {
|
|
131
|
+
op: entry.op,
|
|
132
|
+
path,
|
|
133
|
+
beforeDigest: entry.beforeDigest ?? null,
|
|
134
|
+
afterDigest: entry.afterDigest ?? null,
|
|
135
|
+
};
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function validateProposal(output, descriptor, evidence) {
|
|
140
|
+
if (output?.status !== WIKI_PROPOSAL_STATUS.PROPOSAL) {
|
|
141
|
+
throw new TypeError("proposal output status is invalid");
|
|
142
|
+
}
|
|
143
|
+
if (output.skillName !== descriptor.targetSkillName) {
|
|
144
|
+
const error = new Error("proposer attempted to change more than the fixed Skill");
|
|
145
|
+
error.code = "WIKI_PROPOSAL_MULTI_SKILL";
|
|
146
|
+
throw error;
|
|
147
|
+
}
|
|
148
|
+
const knownRefs = new Set(evidence.map((item) => item.ref));
|
|
149
|
+
const purpose = {
|
|
150
|
+
summary: requiredString(output.purpose?.summary, "purpose.summary"),
|
|
151
|
+
patternRefs: stringList(output.purpose?.patternRefs, "purpose.patternRefs"),
|
|
152
|
+
sourceEvidenceRefs: stringList(
|
|
153
|
+
output.purpose?.sourceEvidenceRefs,
|
|
154
|
+
"purpose.sourceEvidenceRefs",
|
|
155
|
+
),
|
|
156
|
+
};
|
|
157
|
+
for (const ref of [...purpose.patternRefs, ...purpose.sourceEvidenceRefs]) {
|
|
158
|
+
if (!knownRefs.has(ref)) {
|
|
159
|
+
const error = new Error("PURPOSE references evidence outside the resolved set");
|
|
160
|
+
error.code = "WIKI_PROPOSAL_UNKNOWN_LINEAGE";
|
|
161
|
+
throw error;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
const contextCost = {
|
|
165
|
+
maxTokens: Number(output.contextCost?.maxTokens),
|
|
166
|
+
maxBytes: Number(output.contextCost?.maxBytes),
|
|
167
|
+
};
|
|
168
|
+
if (
|
|
169
|
+
!Number.isInteger(contextCost.maxTokens) ||
|
|
170
|
+
contextCost.maxTokens <= 0 ||
|
|
171
|
+
!Number.isInteger(contextCost.maxBytes) ||
|
|
172
|
+
contextCost.maxBytes <= 0
|
|
173
|
+
) {
|
|
174
|
+
throw new TypeError("contextCost must provide positive maxTokens/maxBytes");
|
|
175
|
+
}
|
|
176
|
+
return deepFreeze({
|
|
177
|
+
schema: WIKI_SKILL_PROPOSAL_SCHEMA,
|
|
178
|
+
status: WIKI_PROPOSAL_STATUS.PROPOSAL,
|
|
179
|
+
tenantId: descriptor.tenantId,
|
|
180
|
+
evolutionRunId: descriptor.evolutionRunId,
|
|
181
|
+
skillName: descriptor.targetSkillName,
|
|
182
|
+
purpose,
|
|
183
|
+
applicableWhen: stringList(output.applicableWhen, "applicableWhen"),
|
|
184
|
+
notApplicableWhen: stringList(output.notApplicableWhen, "notApplicableWhen"),
|
|
185
|
+
failureCounterexamples: stringList(
|
|
186
|
+
output.failureCounterexamples,
|
|
187
|
+
"failureCounterexamples",
|
|
188
|
+
),
|
|
189
|
+
rollbackSteps: stringList(output.rollbackSteps, "rollbackSteps"),
|
|
190
|
+
validationMethods: stringList(output.validationMethods, "validationMethods"),
|
|
191
|
+
requestedCapabilities: stringList(
|
|
192
|
+
output.requestedCapabilities,
|
|
193
|
+
"requestedCapabilities",
|
|
194
|
+
{ allowEmpty: true },
|
|
195
|
+
),
|
|
196
|
+
targetRuntimes: stringList(output.targetRuntimes, "targetRuntimes"),
|
|
197
|
+
contextCost,
|
|
198
|
+
machineDiff: validateDiff(output.machineDiff),
|
|
199
|
+
sourceEvidenceRefs: evidence.map(({ ref, digest }) => ({ ref, digest })),
|
|
200
|
+
wikiRevision: descriptor.wikiRevision,
|
|
201
|
+
proposerModel: descriptor.proposerModel,
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function abstention(status, reason, evidence = []) {
|
|
206
|
+
return deepFreeze({
|
|
207
|
+
schema: WIKI_SKILL_PROPOSAL_SCHEMA,
|
|
208
|
+
status,
|
|
209
|
+
reason,
|
|
210
|
+
sourceEvidenceRefs: evidence.map(({ ref, digest }) => ({ ref, digest })),
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export class WikiInformedSkillProposer {
|
|
215
|
+
constructor({ descriptor, policy, ports } = {}) {
|
|
216
|
+
this.descriptor = normalizeDescriptor(descriptor);
|
|
217
|
+
if (policy?.proposerWikiRead !== true || policy?.executionAgentWikiRead === true) {
|
|
218
|
+
throw new Error("capability policy must isolate Wiki reads to the proposer");
|
|
219
|
+
}
|
|
220
|
+
if (typeof ports?.readInitial !== "function")
|
|
221
|
+
throw new TypeError("readInitial port is required");
|
|
222
|
+
if (typeof ports?.readSelective !== "function")
|
|
223
|
+
throw new TypeError("readSelective port is required");
|
|
224
|
+
if (typeof ports?.generate !== "function")
|
|
225
|
+
throw new TypeError("generate port is required");
|
|
226
|
+
if (typeof ports?.createCandidate !== "function")
|
|
227
|
+
throw new TypeError("createCandidate port is required");
|
|
228
|
+
this._ports = ports;
|
|
229
|
+
Object.freeze(this);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async propose() {
|
|
233
|
+
const initial = [];
|
|
234
|
+
for (const kind of INITIAL_SOURCES) {
|
|
235
|
+
initial.push(verifyEnvelope(await this._ports.readInitial(kind), kind));
|
|
236
|
+
}
|
|
237
|
+
const wiki = initial.find((item) => item.kind === "wiki-index");
|
|
238
|
+
const training = initial.find((item) => item.kind === "training-summary");
|
|
239
|
+
if ((wiki.data?.contradictionRefs?.length ?? 0) > 0) {
|
|
240
|
+
return abstention(
|
|
241
|
+
WIKI_PROPOSAL_STATUS.NEEDS_EVIDENCE,
|
|
242
|
+
"wiki evidence is contradictory",
|
|
243
|
+
initial,
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
if (Number(training.data?.sampleCount) < this.descriptor.minEvidenceSamples) {
|
|
247
|
+
return abstention(
|
|
248
|
+
WIKI_PROPOSAL_STATUS.NEEDS_EVIDENCE,
|
|
249
|
+
"training evidence sample is insufficient",
|
|
250
|
+
initial,
|
|
251
|
+
);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
let evidence = [...initial];
|
|
255
|
+
let output = await this._ports.generate({
|
|
256
|
+
descriptor: this.descriptor,
|
|
257
|
+
evidence: deepFreeze([...evidence]),
|
|
258
|
+
});
|
|
259
|
+
if (output?.status === WIKI_PROPOSAL_STATUS.NO_PROPOSAL) {
|
|
260
|
+
return abstention(output.status, requiredString(output.reason, "reason"), evidence);
|
|
261
|
+
}
|
|
262
|
+
if (output?.status === WIKI_PROPOSAL_STATUS.NEEDS_EVIDENCE) {
|
|
263
|
+
const requests = output.requests;
|
|
264
|
+
if (
|
|
265
|
+
!Array.isArray(requests) ||
|
|
266
|
+
requests.length === 0 ||
|
|
267
|
+
requests.length > this.descriptor.maxSelectiveEvidence
|
|
268
|
+
) {
|
|
269
|
+
return abstention(output.status, "selective evidence request is invalid", evidence);
|
|
270
|
+
}
|
|
271
|
+
for (const request of requests) {
|
|
272
|
+
if (!SELECTIVE_SOURCES.has(request?.kind)) {
|
|
273
|
+
return abstention(output.status, "requested evidence scope is not allowed", evidence);
|
|
274
|
+
}
|
|
275
|
+
evidence.push(
|
|
276
|
+
verifyEnvelope(
|
|
277
|
+
await this._ports.readSelective(request.kind, request.ref),
|
|
278
|
+
request.kind,
|
|
279
|
+
),
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
output = await this._ports.generate({
|
|
283
|
+
descriptor: this.descriptor,
|
|
284
|
+
evidence: deepFreeze([...evidence]),
|
|
285
|
+
});
|
|
286
|
+
if (output?.status !== WIKI_PROPOSAL_STATUS.PROPOSAL) {
|
|
287
|
+
return abstention(
|
|
288
|
+
output?.status === WIKI_PROPOSAL_STATUS.NO_PROPOSAL
|
|
289
|
+
? output.status
|
|
290
|
+
: WIKI_PROPOSAL_STATUS.NEEDS_EVIDENCE,
|
|
291
|
+
requiredString(output?.reason, "reason"),
|
|
292
|
+
evidence,
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const proposal = validateProposal(output, this.descriptor, evidence);
|
|
298
|
+
const proposalDigest = hash(proposal);
|
|
299
|
+
const candidateInput = deepFreeze({
|
|
300
|
+
tenantId: proposal.tenantId,
|
|
301
|
+
skillName: proposal.skillName,
|
|
302
|
+
derivationMode: "wiki",
|
|
303
|
+
wikiRevision: proposal.wikiRevision,
|
|
304
|
+
proposerModel: proposal.proposerModel,
|
|
305
|
+
requestedCapabilities: proposal.requestedCapabilities,
|
|
306
|
+
sourceEvidenceRefs: proposal.sourceEvidenceRefs,
|
|
307
|
+
content: canonical(proposal),
|
|
308
|
+
});
|
|
309
|
+
const created = await this._ports.createCandidate(candidateInput);
|
|
310
|
+
const candidate = created?.candidate;
|
|
311
|
+
if (
|
|
312
|
+
typeof candidate?.candidateId !== "string" ||
|
|
313
|
+
typeof candidate?.contentDigest !== "string" ||
|
|
314
|
+
candidate.skillName !== proposal.skillName ||
|
|
315
|
+
candidate.content !== candidateInput.content ||
|
|
316
|
+
candidate.derivationMode !== "wiki" ||
|
|
317
|
+
candidate.wikiRevision !== proposal.wikiRevision ||
|
|
318
|
+
candidate.proposerModel !== proposal.proposerModel ||
|
|
319
|
+
canonical(candidate.requestedCapabilities) !==
|
|
320
|
+
canonical(proposal.requestedCapabilities) ||
|
|
321
|
+
canonical(candidate.targetRuntimes) !== canonical(proposal.targetRuntimes) ||
|
|
322
|
+
canonical(candidate.sourceEvidenceRefs) !==
|
|
323
|
+
canonical(proposal.sourceEvidenceRefs)
|
|
324
|
+
) {
|
|
325
|
+
const error = new Error(
|
|
326
|
+
"candidate sink did not return an exact immutable proposal binding",
|
|
327
|
+
);
|
|
328
|
+
error.code = "WIKI_PROPOSAL_CANDIDATE_UNCONFIRMED";
|
|
329
|
+
throw error;
|
|
330
|
+
}
|
|
331
|
+
return deepFreeze({
|
|
332
|
+
status: WIKI_PROPOSAL_STATUS.PROPOSAL,
|
|
333
|
+
proposal,
|
|
334
|
+
proposalDigest,
|
|
335
|
+
candidateId: candidate.candidateId,
|
|
336
|
+
contentDigest: candidate.contentDigest,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export function createWikiInformedSkillProposer(options) {
|
|
342
|
+
return new WikiInformedSkillProposer(options);
|
|
343
|
+
}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
1
3
|
import os from "node:os";
|
|
2
4
|
import path from "node:path";
|
|
3
5
|
|
|
4
6
|
export const FORMAL_QUALITY_HERMETIC_ENV = "CC_FORMAL_QUALITY_EVAL_HERMETIC";
|
|
5
7
|
export const FORMAL_QUALITY_PROVIDER_ENV = "CC_FORMAL_QUALITY_EVAL_PROVIDER";
|
|
8
|
+
export const FORMAL_QUALITY_ISOLATION_ROOT_ENV =
|
|
9
|
+
"CC_FORMAL_QUALITY_EVAL_ISOLATION_ROOT";
|
|
6
10
|
export const FORMAL_QUALITY_ALLOWED_FILES_ENV =
|
|
7
11
|
"CC_FORMAL_QUALITY_EVAL_ALLOWED_FILES";
|
|
8
12
|
export const FORMAL_QUALITY_FILE_TOOLS = Object.freeze([
|
|
@@ -34,6 +38,102 @@ export function isFormalQualityHermeticRuntime(environment = process.env) {
|
|
|
34
38
|
);
|
|
35
39
|
}
|
|
36
40
|
|
|
41
|
+
function formalQualityIsolationRoot(environment) {
|
|
42
|
+
if (!isFormalQualityHermeticRuntime(environment)) return null;
|
|
43
|
+
const configuredRoot = String(
|
|
44
|
+
environment?.[FORMAL_QUALITY_ISOLATION_ROOT_ENV] || "",
|
|
45
|
+
).trim();
|
|
46
|
+
if (!configuredRoot) {
|
|
47
|
+
throw new Error("formal quality isolation root is missing");
|
|
48
|
+
}
|
|
49
|
+
const temporaryRoot = path.resolve(os.tmpdir());
|
|
50
|
+
const resolvedRoot = path.resolve(configuredRoot);
|
|
51
|
+
const relation = path.relative(temporaryRoot, resolvedRoot);
|
|
52
|
+
const configuredHome = path.resolve(String(environment.CHAINLESSCHAIN_HOME));
|
|
53
|
+
const homeRelation = path.relative(resolvedRoot, configuredHome);
|
|
54
|
+
if (
|
|
55
|
+
!relation ||
|
|
56
|
+
relation === ".." ||
|
|
57
|
+
relation.startsWith(`..${path.sep}`) ||
|
|
58
|
+
path.isAbsolute(relation) ||
|
|
59
|
+
!homeRelation ||
|
|
60
|
+
homeRelation === ".." ||
|
|
61
|
+
homeRelation.startsWith(`..${path.sep}`) ||
|
|
62
|
+
path.isAbsolute(homeRelation)
|
|
63
|
+
) {
|
|
64
|
+
throw new Error("formal quality isolation root is invalid");
|
|
65
|
+
}
|
|
66
|
+
return resolvedRoot;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Give concurrent formal teammates separate ephemeral config/cache trees.
|
|
71
|
+
* Sharing one Windows config root makes independent processes contend on DACL
|
|
72
|
+
* repair and lets platform first-use caches leak into the benchmark cwd.
|
|
73
|
+
*/
|
|
74
|
+
export function formalQualityChildEnvironment(
|
|
75
|
+
identity,
|
|
76
|
+
environment = process.env,
|
|
77
|
+
) {
|
|
78
|
+
const isolationRoot = formalQualityIsolationRoot(environment);
|
|
79
|
+
if (!isolationRoot) return null;
|
|
80
|
+
const normalizedIdentity = String(identity || "").trim();
|
|
81
|
+
if (
|
|
82
|
+
!normalizedIdentity ||
|
|
83
|
+
normalizedIdentity.length > 256 ||
|
|
84
|
+
normalizedIdentity.includes("\0")
|
|
85
|
+
) {
|
|
86
|
+
throw new Error("formal quality child identity is invalid");
|
|
87
|
+
}
|
|
88
|
+
const identityDigest = createHash("sha256")
|
|
89
|
+
.update(normalizedIdentity, "utf8")
|
|
90
|
+
.digest("hex")
|
|
91
|
+
.slice(0, 24);
|
|
92
|
+
const childRoot = path.join(isolationRoot, "agent-homes", identityDigest);
|
|
93
|
+
const userHome = path.join(childRoot, "user-home");
|
|
94
|
+
const configHome = path.join(childRoot, "chainlesschain-home");
|
|
95
|
+
const appData = path.join(userHome, "app-data");
|
|
96
|
+
const localAppData = path.join(userHome, "local-app-data");
|
|
97
|
+
const xdgConfigHome = path.join(userHome, "xdg-config");
|
|
98
|
+
const xdgCacheHome = path.join(userHome, "xdg-cache");
|
|
99
|
+
const xdgDataHome = path.join(userHome, "xdg-data");
|
|
100
|
+
const dotnetHome = path.join(userHome, "dotnet-home");
|
|
101
|
+
const nugetPackages = path.join(userHome, "nuget-packages");
|
|
102
|
+
for (const directory of [
|
|
103
|
+
childRoot,
|
|
104
|
+
userHome,
|
|
105
|
+
configHome,
|
|
106
|
+
appData,
|
|
107
|
+
localAppData,
|
|
108
|
+
xdgConfigHome,
|
|
109
|
+
xdgCacheHome,
|
|
110
|
+
xdgDataHome,
|
|
111
|
+
dotnetHome,
|
|
112
|
+
nugetPackages,
|
|
113
|
+
]) {
|
|
114
|
+
fs.mkdirSync(directory, { recursive: true });
|
|
115
|
+
}
|
|
116
|
+
const childEnvironment = {
|
|
117
|
+
HOME: userHome,
|
|
118
|
+
USERPROFILE: userHome,
|
|
119
|
+
APPDATA: appData,
|
|
120
|
+
LOCALAPPDATA: localAppData,
|
|
121
|
+
XDG_CONFIG_HOME: xdgConfigHome,
|
|
122
|
+
XDG_CACHE_HOME: xdgCacheHome,
|
|
123
|
+
XDG_DATA_HOME: xdgDataHome,
|
|
124
|
+
CHAINLESSCHAIN_HOME: configHome,
|
|
125
|
+
DOTNET_CLI_HOME: dotnetHome,
|
|
126
|
+
NUGET_PACKAGES: nugetPackages,
|
|
127
|
+
POWERSHELL_TELEMETRY_OPTOUT: "1",
|
|
128
|
+
POWERSHELL_UPDATECHECK: "Off",
|
|
129
|
+
};
|
|
130
|
+
if (/^[A-Za-z]:[\\/]/u.test(userHome)) {
|
|
131
|
+
childEnvironment.HOMEDRIVE = userHome.slice(0, 2);
|
|
132
|
+
childEnvironment.HOMEPATH = userHome.slice(2);
|
|
133
|
+
}
|
|
134
|
+
return Object.freeze(childEnvironment);
|
|
135
|
+
}
|
|
136
|
+
|
|
37
137
|
/** Resolve the provider that the formal harness bound before any model call. */
|
|
38
138
|
export function formalQualityProvider(environment = process.env) {
|
|
39
139
|
if (!isFormalQualityHermeticRuntime(environment)) return null;
|
|
@@ -8,14 +8,15 @@ import {
|
|
|
8
8
|
normalizeGraphRetirementEvidence,
|
|
9
9
|
} from "./retirement-evidence.js";
|
|
10
10
|
import { graphStoreEvidenceDigest } from "./store-cutover-evidence.js";
|
|
11
|
+
import {
|
|
12
|
+
GRAPH_CUTOVER_LEDGER_SCHEMA,
|
|
13
|
+
GRAPH_CUTOVER_REQUIRED_PLATFORMS,
|
|
14
|
+
} from "./cutover-contract.js";
|
|
11
15
|
|
|
12
|
-
export
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"windows",
|
|
17
|
-
"macos",
|
|
18
|
-
]);
|
|
16
|
+
export {
|
|
17
|
+
GRAPH_CUTOVER_LEDGER_SCHEMA,
|
|
18
|
+
GRAPH_CUTOVER_REQUIRED_PLATFORMS,
|
|
19
|
+
} from "./cutover-contract.js";
|
|
19
20
|
|
|
20
21
|
const IDENTIFIER = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,159}$/u;
|
|
21
22
|
const DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
function stableValue(value, state = { seen: new WeakSet(), nodes: 0 }) {
|
|
4
|
+
state.nodes += 1;
|
|
5
|
+
if (state.nodes > 250_000) {
|
|
6
|
+
throw new TypeError("Graph evidence exceeds canonicalization limits");
|
|
7
|
+
}
|
|
8
|
+
if (Array.isArray(value))
|
|
9
|
+
return value.map((item) => stableValue(item, state));
|
|
10
|
+
if (!value || typeof value !== "object") {
|
|
11
|
+
if (typeof value === "number" && !Number.isFinite(value)) {
|
|
12
|
+
throw new TypeError("Graph evidence contains a non-finite number");
|
|
13
|
+
}
|
|
14
|
+
if (["bigint", "function", "symbol", "undefined"].includes(typeof value)) {
|
|
15
|
+
throw new TypeError("Graph evidence contains a non-JSON value");
|
|
16
|
+
}
|
|
17
|
+
return value;
|
|
18
|
+
}
|
|
19
|
+
if (state.seen.has(value)) {
|
|
20
|
+
throw new TypeError("Graph evidence contains a cycle or repeated object");
|
|
21
|
+
}
|
|
22
|
+
state.seen.add(value);
|
|
23
|
+
if (
|
|
24
|
+
Object.getPrototypeOf(value) !== Object.prototype &&
|
|
25
|
+
Object.getPrototypeOf(value) !== null
|
|
26
|
+
) {
|
|
27
|
+
throw new TypeError("Graph evidence must contain plain JSON objects");
|
|
28
|
+
}
|
|
29
|
+
return Object.fromEntries(
|
|
30
|
+
Object.keys(value)
|
|
31
|
+
.filter((key) => value[key] !== undefined)
|
|
32
|
+
.sort()
|
|
33
|
+
.map((key) => [key, stableValue(value[key], state)]),
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function canonicalGraphEvidenceJson(value) {
|
|
38
|
+
return JSON.stringify(stableValue(value));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function graphEvidenceDigest(value, domain) {
|
|
42
|
+
return `sha256:${createHash("sha256")
|
|
43
|
+
.update(domain)
|
|
44
|
+
.update("\0")
|
|
45
|
+
.update(canonicalGraphEvidenceJson(value))
|
|
46
|
+
.digest("hex")}`;
|
|
47
|
+
}
|
|
@@ -6,7 +6,14 @@
|
|
|
6
6
|
"ledgerSchema": "chainlesschain.graph-cutover-ledger/v1",
|
|
7
7
|
"scope": "entry",
|
|
8
8
|
"requiredPlatforms": ["linux", "windows", "macos"],
|
|
9
|
-
"existingCanonicalRunRollback": "retain_authority"
|
|
9
|
+
"existingCanonicalRunRollback": "retain_authority",
|
|
10
|
+
"legacyMutationErrorCodes": {
|
|
11
|
+
"browser": "CC_CLI_LEGACY_RUNTIME_READ_ONLY",
|
|
12
|
+
"cli_team": "CC_CLI_LEGACY_RUNTIME_READ_ONLY",
|
|
13
|
+
"cowork": "CC_CLI_LEGACY_RUNTIME_READ_ONLY",
|
|
14
|
+
"desktop": "CC_DESKTOP_LEGACY_RUNTIME_READ_ONLY",
|
|
15
|
+
"scheduler": "CC_CLI_LEGACY_RUNTIME_READ_ONLY"
|
|
16
|
+
}
|
|
10
17
|
},
|
|
11
18
|
"surfaces": [
|
|
12
19
|
{
|