@entrorove/skill 0.1.62 → 0.1.64
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/CAPABILITY-MAP.md +7 -2
- package/CHANGELOG.md +10 -0
- package/IDE-EXECUTION.md +32 -3
- package/REUSE-DISCIPLINE.md +1 -1
- package/SKILL.md +6 -2
- package/cli-input.mjs +22 -0
- package/cli.mjs +2 -8
- package/cloud-task-client.mjs +10 -2
- package/cloud-task-images.mjs +39 -0
- package/ide-exit.mjs +49 -9
- package/ide-hook.mjs +2 -2
- package/local-contracts.mjs +4 -1
- package/local-discipline-gate.mjs +9 -1
- package/local-discipline-repository.mjs +11 -5
- package/local-finder-plist.mjs +87 -0
- package/local-finder-store.mjs +115 -0
- package/local-mutation-authority.mjs +11 -0
- package/local-mutation-completion-evidence.mjs +83 -0
- package/local-mutation-consumption.mjs +33 -10
- package/local-mutation-environment-observation.mjs +85 -0
- package/local-mutation-finder-observation.mjs +58 -0
- package/local-mutation-wire.mjs +26 -8
- package/local-scope-files.mjs +3 -1
- package/local-scope-font.mjs +45 -0
- package/local-scope-repository.mjs +16 -3
- package/local-scope-zip.mjs +93 -0
- package/manifest.json +1 -1
- package/member-producer-repair-authority.mjs +48 -0
- package/model-images.d.mts +9 -0
- package/model-images.mjs +87 -0
- package/mutation-challenge-refresh.mjs +51 -0
- package/mutation-client.mjs +42 -24
- package/mutation-connection-state.mjs +17 -0
- package/package.json +18 -2
- package/release-state.json +49 -33
- package/release.mjs +8 -0
- package/releases.json +12 -0
- package/remote-client.mjs +1 -1
- package/remote-transport.mjs +48 -16
- package/scope-amendment-client.mjs +1 -1
- package/scope-amendment-consumption.mjs +32 -0
- package/scope-amendment-mutation.mjs +2 -3
- package/scope-amendment-observer.mjs +2 -1
- package/scope-amendment-remote.mjs +12 -2
- package/scope-amendment-retirement.mjs +54 -0
- package/scope-amendment-state.mjs +7 -4
- package/task-entry-client.mjs +1 -0
- package/workflow-observation-client.mjs +11 -0
- package/workflow-observation-connection.mjs +2 -1
- package/workflow-observation-remote.mjs +26 -1
- package/workflow-observation-wire.mjs +6 -3
package/release-state.json
CHANGED
|
@@ -1,29 +1,45 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": "entrorove.release-state/1.0",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"digest": "
|
|
3
|
+
"version": "0.1.64",
|
|
4
|
+
"digest": "56a07e4deb7b361010313c592e4b95e5f9b3f2398726ea626f1172114dcff019",
|
|
5
5
|
"files": {
|
|
6
|
+
"cloud-task-images.mjs": "a260a94b6b1b47df97a8cc8657dfdce1fd37ec752f1cc2bad2542eaa28622bdb",
|
|
7
|
+
"model-images.mjs": "ab85ac0c44d857c1f460de3e9c06eb1d37b57688b4a6061405c0a44ae4d40bd7",
|
|
8
|
+
"model-images.d.mts": "f1506cfb8ad287869f92f4d9074c7c759c6c28b182aeb325dd5f22a38926f24c",
|
|
9
|
+
"cli-input.mjs": "44dc2692714023b622a9370c13cabc09c7c39e6aea6e7183b80ae5bcd2e8d24e",
|
|
10
|
+
"scope-amendment-retirement.mjs": "849f2b5fc8ec5204d7a58222f7ee775b7514244b854439ef3549563cd44c14c2",
|
|
11
|
+
"scope-amendment-consumption.mjs": "12a1dfd1429350cc9503957224398524c077aed6c697228c9870aa95c245ee7d",
|
|
12
|
+
"mutation-connection-state.mjs": "05bed65a4636a2128e9a48d2e910c5f5a25f0e990f181f58008dd09cac0fbcb5",
|
|
13
|
+
"mutation-challenge-refresh.mjs": "eac9b18bdfbd968d815321e66c4f6e482fb1be59662abb9dc8b02f35b9ced809",
|
|
14
|
+
"local-scope-font.mjs": "a69f9da932ed41aa4718036f98f75c0b17ba7f616a5c8bf5623fa9ed697499fa",
|
|
15
|
+
"local-scope-zip.mjs": "b8a5f2a75394c23e570c28218a8c0b3bcd626ccc87eba550e759b6c38a68871e",
|
|
16
|
+
"member-producer-repair-authority.mjs": "1e84e5e77ba5ee9a0dcaa4d843061c7b5447191852d7b2fb603b91cfa7c796e4",
|
|
17
|
+
"local-mutation-completion-evidence.mjs": "d894f7f7d3b5a906e4c869b02ab0abacbd16dc35987a2fe14ff8fa2cf264a62b",
|
|
18
|
+
"local-mutation-environment-observation.mjs": "8afffe21cb9a7f6cc889e5af9b5c9953684635a90ca4b98d797547bd7831bafb",
|
|
19
|
+
"local-mutation-finder-observation.mjs": "438dd33e62e03e02b55897a28b3ba59d12734b6e5142525b299f77c21537280b",
|
|
20
|
+
"local-finder-store.mjs": "227191c52174386ace6391e072b78a6e4cc658a6d9dd37036ffd7e97bbf4336a",
|
|
21
|
+
"local-finder-plist.mjs": "c83ddab2375a54d612d395a5518db8ae05212437d82bf3f8b76930a8859c8481",
|
|
6
22
|
"connected-cli.mjs": "79c3359303957a9ebb8987e3dfb181f189d380fa02ef4462683b786aedfc7802",
|
|
7
23
|
"local-approved-process.mjs": "442856df788e63f38757439ba0657d1c689aaf797631a955fae3dd639e844e6d",
|
|
8
24
|
"local-approved-supervisor.mjs": "87142a4c13d27c8265cc1fd7fc9088988da9bbb02134164e1a7c5417da926ac7",
|
|
9
|
-
"local-mutation-consumption.mjs": "
|
|
25
|
+
"local-mutation-consumption.mjs": "1b033655f817ec576410b7f91f1640b8651f3cff0668154fb8e6e14e7b31d8f4",
|
|
10
26
|
"workflow-local-acceptance.mjs": "743ae19c1edff473af2596c7356ddff3892ff9acfb3bcaa660b662eacba463a8",
|
|
11
|
-
"workflow-observation-client.mjs": "
|
|
12
|
-
"workflow-observation-connection.mjs": "
|
|
13
|
-
"workflow-observation-remote.mjs": "
|
|
27
|
+
"workflow-observation-client.mjs": "5032a6cd7d1e0fa6b80170a7c1298cf14f2c21cf017426465aa48e2a944bcf08",
|
|
28
|
+
"workflow-observation-connection.mjs": "b1958417d9f94bf7b9474c69acc82fa5de7f7c4e37aa7f3977a8f7e3836a82b1",
|
|
29
|
+
"workflow-observation-remote.mjs": "3a444cab88b426e6af018625cfb4aaddcc5d7c05c505ed18715494dd18a6e1de",
|
|
14
30
|
"workflow-observation-runner.mjs": "3eb8280ec7abffcb30398e3f4e5f7d0ec3df4385fa720f188ed83757b87cd977",
|
|
15
31
|
"workflow-observation-state.mjs": "a525046df9b3de75b10d2bf35c2b6d7719f12a647e4aee1f1e85dbdbfb167321",
|
|
16
|
-
"workflow-observation-wire.mjs": "
|
|
32
|
+
"workflow-observation-wire.mjs": "df0d5e4f8fde0be8bf06c6c4590cd158b4da05ebe6ef3169d2366db706f3327f",
|
|
17
33
|
"local-preserved-mutation-protection.mjs": "5186a2f682e66c6828d1504ee074554cbae0fda58a5f446fbadfb868e1682dae",
|
|
18
34
|
"local-preserved-mutation-signer.mjs": "2b0771cbdd18ba00267aa441b7892cd04feab9f8543ae5e2703430b1e580747f",
|
|
19
35
|
"local-preserved-mutation-state.mjs": "337a172b2d0a03b0d5a89b8483afdd9a043a4999fe38f87679633c98c450126b",
|
|
20
36
|
"local-preserved-mutation-wire.mjs": "6768ce5713d70f7c0bd05f2286bc4b32cd9b8bb1d3c8b9cc7a451cb9b176824d",
|
|
21
37
|
"local-delegated-modify-analysis.mjs": "f87148ddb023b79e241ca97db582991da8d0e1a51b26b1d9bc2799a76efd7297",
|
|
22
|
-
"mutation-client.mjs": "
|
|
38
|
+
"mutation-client.mjs": "da09b2aa301da8cbc7b830a3dfe1fbf2617798ae26e4ccddea802443a8253527",
|
|
23
39
|
"cloud-mutation-authority.mjs": "c7226e882a4f3be4d2f55728f515d5a815c0aa1f21aa5e4689314e6e6a8c66a2",
|
|
24
40
|
"ide-code-mode.mjs": "f8ba4de33632ab4c6df52dab52f392414b4632c7e94b218b8065677970c075c7",
|
|
25
41
|
"ide-command.mjs": "dbdb4cbf8e870c93a746ca176cbbdeffc0458de1293583d3eb9af4c256541370",
|
|
26
|
-
"ide-hook.mjs": "
|
|
42
|
+
"ide-hook.mjs": "f2a00be9293ce13ba8b8547142744a7edc43d4e2e82727e9f7923ba79a244d75",
|
|
27
43
|
"ide-install.mjs": "1c80e191ddc2ac8789f0c71edc7bc8c3c8cea6bfab537cdf6baffa4a6ce3419c",
|
|
28
44
|
"ide-session.mjs": "5277a6ea3445bfa9b2e28847372d963da77787d472d0414c0e253d4fe29f74ec",
|
|
29
45
|
"break-glass.mjs": "6ec9f97c5d68bb33121b2374c06b9d4c8eb3419b52d00849fec7124bc63e4582",
|
|
@@ -37,10 +53,10 @@
|
|
|
37
53
|
"local-scope-import-expressions.mjs": "20f1e065582c68d2334e0dfaa130a559ff19886a57f9038dc569f65993bb06c8",
|
|
38
54
|
"local-discipline-contracts.mjs": "ab0c11dcc4a6ffd3cb79b53862c19308eaf0d159deee7f9958266852d977363e",
|
|
39
55
|
"local-discipline-contracts.d.mts": "defc684c78dc88afa1c54340ab4a01ae36db7aa11257cbe1f5cd323f608c78c4",
|
|
40
|
-
"local-discipline-gate.mjs": "
|
|
56
|
+
"local-discipline-gate.mjs": "d7e92a541fbb5bce60285ab2e1a6e210d478a6b4c8404961f33e40ade962e829",
|
|
41
57
|
"local-discipline-native.mjs": "8b99b5ce951cab3c1426428ad807650c61c0ffb2c346d747b73b99057b382049",
|
|
42
58
|
"local-discipline-operations.mjs": "9fcb7b8889b7718d42e1d37936485d8198d5017d405e0cdbbabdbbd12fcc9d48",
|
|
43
|
-
"local-discipline-repository.mjs": "
|
|
59
|
+
"local-discipline-repository.mjs": "ca997be4289180600cb97ba2938b6b99210e5d5d5317374b130a886cb712d624",
|
|
44
60
|
"local-discipline-snapshot.mjs": "8fd35b2cfbece8f64579f144f589a66dec9b6022d50fe931c4c1f886cb83134d",
|
|
45
61
|
"local-runner-discipline.mjs": "8d4ada838f81d54963adbb7e433f1ca80ae1934ea126f90c59a49d29742979c4",
|
|
46
62
|
"local-integrity.d.mts": "21357f306234bd841c0d3d90bf2d09f7663f63746f897b9f38190428ae8198b3",
|
|
@@ -50,8 +66,8 @@
|
|
|
50
66
|
"runtime/validator-runtime-v7.0.44.d.mts": "7797edbfe2f7de24da370204dce4dfd22822a1bd80df93514fff900b98afe36f",
|
|
51
67
|
"snapshot-retention.mjs": "ca46aeb36b1a5a24fe7e967031a71b9a3d33f40cb715d344402cbe0dc9c425cb",
|
|
52
68
|
"snapshot-cleanup-journal.mjs": "76a9684cc95b4eb076e1298d78a9dff37948b00d9607b8f546c599072d3ed331",
|
|
53
|
-
"IDE-EXECUTION.md": "
|
|
54
|
-
"REUSE-DISCIPLINE.md": "
|
|
69
|
+
"IDE-EXECUTION.md": "e7e9c19f19f095f5483784bb8de1e610eb008e8e62504b4229e38a9728b89573",
|
|
70
|
+
"REUSE-DISCIPLINE.md": "377df04e93bca02731f15055857bd93b3b9656acdcf121735a46a0114516880c",
|
|
55
71
|
"reuse-discipline-release.mjs": "7f55ae10ec3396ed3bc5430a0c64f94c33c2dfbc57b32084caab92fd5fd1586f",
|
|
56
72
|
"local-final-gate16.mjs": "083aec470670e6cdb7ad2ab27b7a51b53a9ec3a8b4121cb9cbfa17d9940892c2",
|
|
57
73
|
"local-final-gate16-checks.mjs": "1dd30e9666d458d8b12ca6e4975f6f0ac8450c3ea9cbecc7401ae037f66b589a",
|
|
@@ -94,19 +110,19 @@
|
|
|
94
110
|
"local-autocoord17-waits.mjs": "2b0a713987822548a94e1ed3a9a891532db45383797dfc5d5bc8d1e35593cf25",
|
|
95
111
|
"local-validator-isolation17.mjs": "48e94604e28b8fddd567dfb35ff60b73fd094a5803bd49f076388b7f310f92aa",
|
|
96
112
|
"local-calctool-composition17.mjs": "ac89fcb41ab0d0d9b47c1b5696945281b0894eb064820775e36a011c76314e6a",
|
|
97
|
-
"cli.mjs": "
|
|
113
|
+
"cli.mjs": "2198b5b0bc6c9a5fcba8b2c488c548c22b63ed56c4f7cdbc93d41784a2650bdf",
|
|
98
114
|
"ide-selection.mjs": "e11e2b363c06444f1dcb4cdab1eaa0eb748a379b84354e0e71fd9c2dc79a4815",
|
|
99
|
-
"ide-exit.mjs": "
|
|
115
|
+
"ide-exit.mjs": "39d60a15b1517d402c208d22a17033976e43733be8a10dc6da386837c59b37b2",
|
|
100
116
|
"install-cleanup.mjs": "8a8e1a7dfe37427f86cd4d6e317890d0829894a9949d4216674a716b36edbc54",
|
|
101
117
|
"review-client.mjs": "3491eef68ed533174b31db3c53febb6519b8f088f71a9964644714a9a4c03c77",
|
|
102
118
|
"version.mjs": "1f392147d72c40af4b03b307ea607075fb815af5174fa07e254b95fe12dbf3e7",
|
|
103
|
-
"SKILL.md": "
|
|
104
|
-
"CAPABILITY-MAP.md": "
|
|
119
|
+
"SKILL.md": "3f1f4d586a712a790ebb4247840ce6345511226ead7b26154d76b0322f8b753a",
|
|
120
|
+
"CAPABILITY-MAP.md": "c8f211755d106acdc47ed512119089d406712088ed167847b791ca9c47ce103e",
|
|
105
121
|
"AGREEMENT.md": "f93a68e92c457200dd024610e65f74e478b8f60860f951da818b70561f1b9bf8",
|
|
106
122
|
"DELIVERY-BOUNDARIES.md": "9b9db50ed1bcce9e77ff6527b6bb7eaf12f3b913162ea9cb7fe90db06b393a4f",
|
|
107
|
-
"package.json": "
|
|
123
|
+
"package.json": "2ebbf6ceaf4c2622073e51659c91a6917cabe260d11b60aa370edc2a42c4464d",
|
|
108
124
|
"manifest.json": "ab06e307795bc9da5add926752b6c4dbdaf18625090261a035aa356a679c504f",
|
|
109
|
-
"release.mjs": "
|
|
125
|
+
"release.mjs": "046cff9905ed74a467bcc08227ece55e640950d06bf8a2d3268387691b493400",
|
|
110
126
|
"local-cli.mjs": "41e2a737c8587cb5ce469a7661f6d14b5ea4cd073f8286822fc4dc96b67f56a1",
|
|
111
127
|
"local-state-lock.mjs": "1dbf64264642a0851faf043e07ee9f66d2ad0508e9f799b0626246e42fae893e",
|
|
112
128
|
"local-execution.mjs": "185f34e917440a360b3c4bafd3af245243807d964ae3820b3cffaaa2e6348cc6",
|
|
@@ -144,8 +160,8 @@
|
|
|
144
160
|
"local-stage-boundary.mjs": "84c3bb5beab29306274c5ca8a78f19a83ed664ae1b93a8372bb493158b304fe3",
|
|
145
161
|
"local-scope-candidate.mjs": "8f0bd9606e70d4a0ebacdd3cd600ec3afed85e2bb3e1760aa1144cf55d4e028a",
|
|
146
162
|
"local-scope-context.mjs": "79753abfc6c76089d17f003a1be537dfaea10d6731c542f7fc53f2a9996ed164",
|
|
147
|
-
"local-scope-files.mjs": "
|
|
148
|
-
"local-scope-repository.mjs": "
|
|
163
|
+
"local-scope-files.mjs": "db8b3baf8118c6cfd5525cbc008e054f9f33390b9ffce5ba72ee986b832f33e3",
|
|
164
|
+
"local-scope-repository.mjs": "55f130f7c54a378cb12ab9b81c07b14bf17f96a8d994314b0c8f35803bbdca1c",
|
|
149
165
|
"local-scope-create-require.mjs": "6b6a209bfcad8fe1398e99c5c8cc3af189c120b9c38e244a73dd1a99c3d91295",
|
|
150
166
|
"local-scope-require-resolution.mjs": "b24596462c8776cbefa6f0a74749d665aa928d1643c68d44798eb93e2dd5ad42",
|
|
151
167
|
"local-scope-git.mjs": "53bbbb6c4795db711b5bc164591a6ad79a561427da046d6bbe997dae6eb82829",
|
|
@@ -178,15 +194,15 @@
|
|
|
178
194
|
"local-scope-state.mjs": "8b600a91fc0068d7a8c0bb752ddba7ed30ada93daafb118d6cba2368fd94cb27",
|
|
179
195
|
"local-scope-workspaces.mjs": "a44c34537e5ed2dcaf193a985e5bc05957989fbb160a650f9e37ba7d66eb2de8",
|
|
180
196
|
"local-task-routing.mjs": "6e2e506b2fb0e2e8d8c5147d7df32849b57a4e94a23634f01a355d45735858e4",
|
|
181
|
-
"remote-client.mjs": "
|
|
182
|
-
"cloud-task-client.mjs": "
|
|
197
|
+
"remote-client.mjs": "d1fdc4a65fb6d7f79af0bf5a6551319386f1127a0632927fd11600a178d41769",
|
|
198
|
+
"cloud-task-client.mjs": "603a7de8e1d56a77588f08f7d1ae93685b553b40815e268d7bd17018eb767c37",
|
|
183
199
|
"scope-runner-client.mjs": "2afcbb8bc8a26d03f26787cb2ffd9994c4377757d16d54aa0c83752a29e833ea",
|
|
184
|
-
"scope-amendment-client.mjs": "
|
|
185
|
-
"scope-amendment-state.mjs": "
|
|
200
|
+
"scope-amendment-client.mjs": "64a38deddc2dbfae543fead2cff8c9c78771b576391cc903aa58db925a138ad7",
|
|
201
|
+
"scope-amendment-state.mjs": "ad82af0ff06e4969f733328a68d18e1ff3553b8ed93400c19963744083918ab9",
|
|
186
202
|
"scope-amendment-wire.mjs": "3c4823e23bbdf330616bb675f07f9fcad7423266bd50b92e1134d226060e9b83",
|
|
187
|
-
"scope-amendment-remote.mjs": "
|
|
188
|
-
"scope-amendment-observer.mjs": "
|
|
189
|
-
"scope-amendment-mutation.mjs": "
|
|
203
|
+
"scope-amendment-remote.mjs": "15a0b3126248f3101a52e3d7742f9a816dd3d8e58f21bac33e99e810e86cc4fd",
|
|
204
|
+
"scope-amendment-observer.mjs": "473f08d66ebd35d87db7e651c0521d1d4bdb6fa337afaedb241bcf9c6289d9d3",
|
|
205
|
+
"scope-amendment-mutation.mjs": "fa24191df290efad29d41eca3d1a081981fefde02b7dc4a11c75c6118a69106e",
|
|
190
206
|
"scope-amendment-reference.mjs": "0537e53a1bea4b695f4804c5051261778c88f05b1ae4aff86c709dcfe83aa148",
|
|
191
207
|
"native-client.mjs": "6f5575909bae9daba643287f876ffa0f9ff1c53a367b32a40145d740456d6605",
|
|
192
208
|
"native-notification.mjs": "8859a26c6f13d222711f763acf49ed8546b3306cf71f990643ac31a5ccaf1ba1",
|
|
@@ -195,10 +211,10 @@
|
|
|
195
211
|
"cloud-event-stream.mjs": "e0eec9fc3e0613094523929634f25030df5ca5c5b5fe2c1e1a4586ab10574808",
|
|
196
212
|
"ide-presentation.mjs": "3bac21bfc824fcdad63aafb0d7c3326cd6456923f4224106dd5c38682060f315",
|
|
197
213
|
"automatic-feedback-client.mjs": "532312d29e66fa211ea3fe879d9add1dd48841ee5ce82800b4b06252a160a255",
|
|
198
|
-
"task-entry-client.mjs": "
|
|
214
|
+
"task-entry-client.mjs": "940fb068afe28a2a34fe96e285e149afdd9ba79649c0c65cde37ec4ed71ae39d",
|
|
199
215
|
"task-identity.mjs": "e0e6cf1f48bfa5ee3c5cb86a3c21adfce6d66b4220f4a164ca099263c7a09fb4",
|
|
200
216
|
"task-identity.d.mts": "55472e1ffc81b9d5e5c5bd56c0bf1d18ecde03ee5170a58a15ce9caf222d8761",
|
|
201
|
-
"remote-transport.mjs": "
|
|
217
|
+
"remote-transport.mjs": "cf0e31a0319518b6c7e1ce2ac99766a98fe9c936d26bbbec05952aaf0c33efb0",
|
|
202
218
|
"local-credential.mjs": "2a302a7f67b5ea8dc73453fc96ab33db349b59ca11fa9456e48ca1d9669d877c",
|
|
203
219
|
"local-invocations.mjs": "f6ac4c41c1a5ec34de358c4cca210ca8e403b3a913150a43bb55ec9be55d9998",
|
|
204
220
|
"local-task-handoff-fence.mjs": "5532a359ee29b885f7ce0cf7178f76dba0fc9245bdd92ef460982275baf0d557",
|
|
@@ -218,7 +234,7 @@
|
|
|
218
234
|
"workflow-local-request.mjs": "4e24c543ce386292a87dc9cd41f90d23375f12079cacffc515c8cd01fd571780",
|
|
219
235
|
"task-message-entry.mjs": "31d10056cb905237cd5649e8eb067009ff1612ec5dc1061e0373209fbc0b646a",
|
|
220
236
|
"task-message-cli.mjs": "3ca65e96c28129b3bd5cac962d106e0859a1f17df1f6a66ee543c6efc22f918d",
|
|
221
|
-
"local-contracts.mjs": "
|
|
237
|
+
"local-contracts.mjs": "e739967e3ffade96589c0a3fd519829452b44e1982aa3af11d6802ddfbb7f53a",
|
|
222
238
|
"local-contract-types.mjs": "85e71fa4dd67e351a4b67573c740bcdb1661cede53f097189f11837771e75e91",
|
|
223
239
|
"local-archguard-ast.mjs": "7ff7df9dab0d98ed62983add751c80edea598bc94ef4f38ede0ebd4d41226c87",
|
|
224
240
|
"local-archguard-checkpoint.mjs": "37896902520cc995720c96288e4a5ed3585952b55c9c35be281f91fa754c71ec",
|
|
@@ -248,10 +264,10 @@
|
|
|
248
264
|
"local-mutation-files.mjs": "087b00e8424a135e783eb432271012a71e55eeb4a5e30119490d1bc0b2160320",
|
|
249
265
|
"local-mutation-snapshot.mjs": "f9077539680fb8d3ff33a962657756a8fe6afa8409b6191334509534216ebfe8",
|
|
250
266
|
"local-mutation-audit.mjs": "5a30ee3446f632e032ffcfe46bcd97d6dfc0f099a76ea5185c3f9a9118c4f6cb",
|
|
251
|
-
"local-mutation-wire.mjs": "
|
|
267
|
+
"local-mutation-wire.mjs": "6d00400e531c693c3e8bfd0c2a24fcc486127f84aafc56ee450dcec7f534eb05",
|
|
252
268
|
"local-mutation-binding.mjs": "4440d792453a07a375b635fa5a91db607e58162824baced5c79a9a513f4ec918",
|
|
253
269
|
"local-mutation-pass-store.mjs": "1edc5fcc537dfa04b8ae8b07af554d61ea5911a5da281423ad57214ccf753ad4",
|
|
254
|
-
"local-mutation-authority.mjs": "
|
|
270
|
+
"local-mutation-authority.mjs": "e60e7150e6d887a51ce5903ab947606b30088231d22e85a0c8bf3f29f1d1fd1f",
|
|
255
271
|
"local-mutation-batch.mjs": "de27686b5f99a99b02f0218a3fa159e9469d6b19c595117287d6dd37a6efcb3b",
|
|
256
272
|
"local-mutation-batch-receipt.mjs": "b0e6a8522867255d899e60b66677885933f6a1c4c771cbb52f84dbbbdcf5e5c2",
|
|
257
273
|
"calctool-runtime-entry.mjs": "98d2bc8df38d16131fc56db0a3d4d260531ba4df412baa5ddc4b8b5c5ca99fe9",
|
package/release.mjs
CHANGED
|
@@ -47,6 +47,10 @@ const memberContinuationSourceFiles = Object.freeze([
|
|
|
47
47
|
'workflow-observation-wire.mjs',
|
|
48
48
|
])
|
|
49
49
|
const sourceFiles = [
|
|
50
|
+
'cloud-task-images.mjs', 'model-images.mjs', 'model-images.d.mts', 'cli-input.mjs',
|
|
51
|
+
'scope-amendment-retirement.mjs', 'scope-amendment-consumption.mjs', 'mutation-connection-state.mjs', 'mutation-challenge-refresh.mjs',
|
|
52
|
+
'local-scope-font.mjs', 'local-scope-zip.mjs', 'member-producer-repair-authority.mjs',
|
|
53
|
+
'local-mutation-completion-evidence.mjs', 'local-mutation-environment-observation.mjs', 'local-mutation-finder-observation.mjs', 'local-finder-store.mjs', 'local-finder-plist.mjs',
|
|
50
54
|
...memberContinuationSourceFiles,
|
|
51
55
|
...preservedMutationSourceFiles,
|
|
52
56
|
...REUSE_DISCIPLINE_SOURCE_FILES,
|
|
@@ -334,6 +338,10 @@ const archguardReleaseLabels = {
|
|
|
334
338
|
}
|
|
335
339
|
function releaseLabels() {
|
|
336
340
|
return withFinalGate16ReleaseLabels({ ...reuseDisciplineReleaseLabels, ...calctoolReleaseLabels, ...mutationReleaseLabels, ...swarmReleaseLabels, ...coordination17ReleaseLabels, ...nativeReadReleaseLabels, ...feedbackReleaseLabels, ...invocationReleaseLabels, ...chainReleaseLabels, ...taskEntryReleaseLabels, ...archguardReleaseLabels,
|
|
341
|
+
...Object.fromEntries(['cloud-task-images.mjs', 'model-images.mjs', 'model-images.d.mts', 'cli-input.mjs'].map(name => [name, { zh: '受限图片输入通道', en: 'bounded image input channel' }])),
|
|
342
|
+
...Object.fromEntries(['scope-amendment-retirement.mjs', 'scope-amendment-consumption.mjs', 'mutation-connection-state.mjs', 'mutation-challenge-refresh.mjs', 'member-producer-repair-authority.mjs'].map(name => [name, { zh: '原授权恢复与请求生命周期', en: 'original-authority recovery and request lifecycle' }])),
|
|
343
|
+
...Object.fromEntries(['local-scope-font.mjs', 'local-scope-zip.mjs'].map(name => [name, { zh: '字体与 ZIP 完整结构核验', en: 'font and ZIP structural verification' }])),
|
|
344
|
+
...Object.fromEntries(['local-mutation-completion-evidence.mjs', 'local-mutation-environment-observation.mjs', 'local-mutation-finder-observation.mjs', 'local-finder-store.mjs', 'local-finder-plist.mjs'].map(name => [name, { zh: '原写入完成证据与系统元数据观察', en: 'original write completion evidence and system metadata observation' }])),
|
|
337
345
|
'blueprint-criterion-wire.mjs': { zh: '蓝图验收标准执行授权', en: 'Blueprint criterion execution authority' },
|
|
338
346
|
'blueprint-criterion-runner.mjs': { zh: '蓝图验收标准实际执行器', en: 'Blueprint criterion process runner' },
|
|
339
347
|
'cli.mjs': { zh: '技能运行和受管安装', en: 'skill runtime and managed installation' },
|
package/releases.json
CHANGED
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "0.1.64",
|
|
4
|
+
"date": "2026-10-19",
|
|
5
|
+
"zh": "统一交付原合同连续执行与失败恢复修复:受限完整响应、原请求结算恢复、过期挑战与未用授权处理、已批准依赖与二进制核验、系统元数据观察;新增图片输入并适配 DeepSeek V4.1 Flash,完善中英文明确退出及无 IDE 记录的离线退出。保留范围、签名、预算及失败和未知记录;缺少进程终局证据的观察仍拒绝重跑。",
|
|
6
|
+
"en": "Deliver original-contract continuation and recovery fixes for bounded complete responses, original-request settlement, expired challenges and unused grants, approved dependencies, verified binary inputs and system metadata observations. Add image inputs for DeepSeek V4.1 Flash and bilingual explicit offline exit, including sessions without an IDE record. Preserve scope, signatures, budgets, failures and unknown outcomes; observations without terminal process evidence still cannot rerun."
|
|
7
|
+
},
|
|
8
|
+
{
|
|
9
|
+
"version": "0.1.63",
|
|
10
|
+
"date": "2026-10-18",
|
|
11
|
+
"zh": "修复精确大范围补正的组合回执保存;原 M 授权支持真实二进制字节,保留源代码分析、原路径及结算校验。范围风险提高必须另经原账号明确重评。",
|
|
12
|
+
"en": "Retain combined receipts for exact large scope amendments and write actual binary bytes through the original M authority, preserving source analysis, paths and settlement checks. Higher scope risk requires explicit original-owner reassessment."
|
|
13
|
+
},
|
|
2
14
|
{
|
|
3
15
|
"version": "0.1.62",
|
|
4
16
|
"date": "2026-10-18",
|
package/remote-client.mjs
CHANGED
|
@@ -35,7 +35,7 @@ function discoveredAjv() {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
export function buildInvocation(operation, input) {
|
|
38
|
-
if (!['capabilities', 'task-describe', 'message-route', 'message-accept', 'task-resume', 'task-checkpoint', 'flow-cancel', 'flow-abandon',
|
|
38
|
+
if (!['capabilities', 'scope-challenge-retire', 'task-describe', 'message-route', 'message-accept', 'task-resume', 'task-checkpoint', 'flow-cancel', 'flow-abandon',
|
|
39
39
|
'message-status', 'message-delivery-start', 'message-delivery-report', 'message-resolve', 'message-complete',
|
|
40
40
|
'handoff-prepare', 'handoff-release', 'handoff-claim', 'handoff-status', 'handoff-resume', 'handoff-execution-authority', 'mutation-snapshot-challenge', 'mutation-pass-issue', 'mutation-pass-settle',
|
|
41
41
|
'member-observation-admit', 'member-observation-report', 'member-observation-status',
|
package/remote-transport.mjs
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import http from 'node:http';
|
|
2
2
|
import https from 'node:https';
|
|
3
|
+
import { createGunzip } from 'node:zlib';
|
|
3
4
|
|
|
4
5
|
const PRE_CONNECT = new Set(['ECONNREFUSED', 'ECONNRESET', 'EAI_AGAIN', 'ENOTFOUND', 'ENETUNREACH',
|
|
5
6
|
'ENETDOWN', 'EHOSTUNREACH', 'ETIMEDOUT', 'ECONNABORTED']);
|
|
6
|
-
|
|
7
|
+
// A scope response retains its exact role map, signed S/W proof and recovery
|
|
8
|
+
// records together. Bound the whole envelope rather than one embedded record.
|
|
9
|
+
const MAX_BYTES = 8_388_608;
|
|
10
|
+
const RESPONSE_CODES = new Set(['RESPONSE_TOO_LARGE', 'RESPONSE_INTERRUPTED',
|
|
11
|
+
'RESPONSE_ENCODING_INVALID', 'RESPONSE_ENCODING_UNSUPPORTED']);
|
|
7
12
|
|
|
8
13
|
export function trustedOrigin(value) {
|
|
9
14
|
let url;
|
|
@@ -15,34 +20,60 @@ export function trustedOrigin(value) {
|
|
|
15
20
|
return url.origin;
|
|
16
21
|
}
|
|
17
22
|
|
|
18
|
-
function failure(code, established) {
|
|
19
|
-
return Object.assign(new Error(
|
|
23
|
+
function failure(code, established, detail = {}) {
|
|
24
|
+
return Object.assign(new Error(code === 'RESPONSE_TOO_LARGE' ? 'Entrorove response exceeds the bounded eight MiB envelope limit'
|
|
25
|
+
: code === 'RESPONSE_ENCODING_INVALID' ? 'Entrorove response has invalid compressed content'
|
|
26
|
+
: code === 'RESPONSE_ENCODING_UNSUPPORTED' ? 'Entrorove response uses an unnegotiated content encoding'
|
|
27
|
+
: established ? 'Entrorove response was interrupted after connection establishment'
|
|
20
28
|
: 'Entrorove connection failed before request transmission'), {
|
|
21
29
|
code: 'ENTROROVE_TRANSPORT', established, retryableBeforeTransmission: !established && PRE_CONNECT.has(code),
|
|
22
|
-
transportCode: PRE_CONNECT.has(code) ? code : 'CONNECTION_REJECTED',
|
|
30
|
+
transportCode: PRE_CONNECT.has(code) || RESPONSE_CODES.has(code) ? code : 'CONNECTION_REJECTED',
|
|
31
|
+
...(code === 'RESPONSE_TOO_LARGE' ? { responseLimitBytes: MAX_BYTES, receivedBytes: detail.receivedBytes } : {}),
|
|
23
32
|
});
|
|
24
33
|
}
|
|
25
34
|
|
|
35
|
+
function readResponse(response, request, done) {
|
|
36
|
+
const encoding = response.headers['content-encoding']?.trim().toLowerCase();
|
|
37
|
+
const decoded = encoding === 'gzip' ? createGunzip() : response;
|
|
38
|
+
const chunks = []; let size = 0; let wireBytes = 0; let ended = false;
|
|
39
|
+
const fail = cause => {
|
|
40
|
+
if (ended) return; ended = true; done(cause);
|
|
41
|
+
if (decoded !== response) decoded.destroy(); response.destroy(); request.destroy();
|
|
42
|
+
};
|
|
43
|
+
response.on('aborted', () => fail({ code: 'RESPONSE_INTERRUPTED' }));
|
|
44
|
+
response.on('error', cause => fail(cause));
|
|
45
|
+
if (encoding && !['identity', 'gzip'].includes(encoding)) {
|
|
46
|
+
fail({ code: 'RESPONSE_ENCODING_UNSUPPORTED' }); return;
|
|
47
|
+
}
|
|
48
|
+
if (decoded !== response) decoded.on('error', () => fail({ code: 'RESPONSE_ENCODING_INVALID' }));
|
|
49
|
+
response.on('data', chunk => {
|
|
50
|
+
if (ended) return; wireBytes += chunk.length;
|
|
51
|
+
if (wireBytes > MAX_BYTES) fail({ code: 'RESPONSE_TOO_LARGE', receivedBytes: wireBytes });
|
|
52
|
+
});
|
|
53
|
+
decoded.on('data', chunk => {
|
|
54
|
+
if (ended) return; size += chunk.length;
|
|
55
|
+
if (size > MAX_BYTES) fail({ code: 'RESPONSE_TOO_LARGE', receivedBytes: size });
|
|
56
|
+
else chunks.push(chunk);
|
|
57
|
+
});
|
|
58
|
+
decoded.on('end', () => {
|
|
59
|
+
if (ended) return; ended = true;
|
|
60
|
+
done(null, { ok: response.statusCode >= 200 && response.statusCode < 300,
|
|
61
|
+
status: response.statusCode, headers: response.headers, body: Buffer.concat(chunks).toString('utf8') });
|
|
62
|
+
});
|
|
63
|
+
if (decoded !== response) response.pipe(decoded);
|
|
64
|
+
}
|
|
65
|
+
|
|
26
66
|
async function attempt(url, options) {
|
|
27
67
|
return new Promise((resolve, reject) => {
|
|
28
68
|
let established = false; let settled = false;
|
|
29
69
|
const done = (cause, result) => {
|
|
30
70
|
if (settled) return; settled = true; clearTimeout(timer);
|
|
31
|
-
if (cause) reject(failure(cause.code, established)); else resolve(result);
|
|
71
|
+
if (cause) reject(failure(cause.code, established, cause)); else resolve(result);
|
|
32
72
|
};
|
|
33
73
|
const client = url.protocol === 'https:' ? https : http;
|
|
34
74
|
const request = client.request(url, { method: options.method, headers: options.headers,
|
|
35
75
|
agent: false }, response => {
|
|
36
|
-
established = true;
|
|
37
|
-
response.on('data', chunk => {
|
|
38
|
-
size += chunk.length;
|
|
39
|
-
if (size > MAX_BYTES) { done({ code: 'RESPONSE_TOO_LARGE' }); response.destroy(); request.destroy(); }
|
|
40
|
-
else chunks.push(chunk);
|
|
41
|
-
});
|
|
42
|
-
response.on('aborted', () => done({ code: 'RESPONSE_INTERRUPTED' }));
|
|
43
|
-
response.on('error', cause => done(cause));
|
|
44
|
-
response.on('end', () => done(null, { ok: response.statusCode >= 200 && response.statusCode < 300,
|
|
45
|
-
status: response.statusCode, headers: response.headers, body: Buffer.concat(chunks).toString('utf8') }));
|
|
76
|
+
established = true; readResponse(response, request, done);
|
|
46
77
|
});
|
|
47
78
|
request.on('socket', socket => {
|
|
48
79
|
socket.once(url.protocol === 'https:' ? 'secureConnect' : 'connect', () => { established = true; });
|
|
@@ -57,7 +88,8 @@ export async function requestTransport(origin, pathname, options = {}) {
|
|
|
57
88
|
const trusted = trustedOrigin(origin);
|
|
58
89
|
if (typeof pathname !== 'string' || !pathname.startsWith('/api/') || pathname.includes('://')) throw new Error('Invalid Entrorove API path');
|
|
59
90
|
const url = new URL(pathname, trusted);
|
|
60
|
-
const configured = { timeoutMs: 15_000, method: 'GET', ...options
|
|
91
|
+
const configured = { timeoutMs: 15_000, method: 'GET', ...options,
|
|
92
|
+
headers: { ...options.headers, 'accept-encoding': 'gzip' } };
|
|
61
93
|
const originalGeneration = configured.method === 'GET' && /^\/api\/skill\/feedback\/[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(url.pathname)
|
|
62
94
|
&& /^\?generation=[1-9][0-9]{0,14}$/.test(url.search) && Number.isSafeInteger(Number(url.searchParams.get('generation')));
|
|
63
95
|
if (url.origin !== trusted || url.hash || url.search && !originalGeneration) throw new Error('Invalid Entrorove API path');
|
|
@@ -113,7 +113,7 @@ export async function runScopeAmend(repositoryRoot, input, dependencies) {
|
|
|
113
113
|
return { schemaVersion, status: 'blocked', flowId: input?.flowId,
|
|
114
114
|
code: error?.code?.startsWith('ENTROROVE_') ? error.code : 'ENTROROVE_SCOPE_AMENDMENT_PREREQUISITE',
|
|
115
115
|
message: ['ENTROROVE_SCOPE_AMENDMENT_BINDING', 'ENTROROVE_SCOPE_AMENDMENT_STATE', 'ENTROROVE_SCOPE_AMENDMENT_UNKNOWN',
|
|
116
|
-
'ENTROROVE_SCOPE_AMENDMENT_NOT_SENT'].includes(error?.code) ? error.message
|
|
116
|
+
'ENTROROVE_SCOPE_AMENDMENT_NOT_SENT', 'ENTROROVE_SCOPE_AMENDMENT_MUTATION_PENDING'].includes(error?.code) ? error.message
|
|
117
117
|
: 'Scope amendment stopped; preserve the original proposal, signer, journal and actual evidence.',
|
|
118
118
|
...(requestId ? { requestId } : {}), ...(error?.output ? { output: error.output } : {}),
|
|
119
119
|
...(error?.feedback ? { feedback: error.feedback } : {}),
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { canonical, sha256 } from './local-integrity.mjs';
|
|
3
|
+
import { withStateLock } from './local-state-lock.mjs';
|
|
4
|
+
import { mutationFail14, privateMutationDirectory14 } from './local-mutation-files.mjs';
|
|
5
|
+
import { preservedMutationConsumptionState, attestMutationConsumption14 } from './local-mutation-consumption.mjs';
|
|
6
|
+
import { readMutationConnection } from './mutation-connection-state.mjs';
|
|
7
|
+
|
|
8
|
+
export async function observeScopeMutationConsumption(location, state, pass) {
|
|
9
|
+
// A pending S keeps its exact old attestation and is recovered with GET. A
|
|
10
|
+
// new signed S challenge can observe the same physical writes afresh, but
|
|
11
|
+
// must not fork an unresolved settlement of that original M receipt.
|
|
12
|
+
if (state.pending || state.attestation) mutationFail14('ENTROROVE_SCOPE_AMENDMENT_MUTATION_PENDING',
|
|
13
|
+
'Recover the original pending scope request before observing its M consumption again');
|
|
14
|
+
const input = { repositoryRoot: location.root, home: location.home,
|
|
15
|
+
flowId: pass.flowId, taskId: pass.taskId, stepId: pass.stepId, gatePassPath: location.identity.gatePassPath };
|
|
16
|
+
const original = await preservedMutationConsumptionState(input), { binding } = original;
|
|
17
|
+
if (canonical(original.pass) !== canonical(pass)) mutationFail14('ENTROROVE_SCOPE_AMENDMENT_BINDING', 'Original mutation pass changed');
|
|
18
|
+
const directory = path.join(binding.directory, 'settlements');
|
|
19
|
+
await privateMutationDirectory14(directory, { privateFrom: binding.stateRoot });
|
|
20
|
+
const journal = { ...binding, file: path.join(directory, `${pass.passId}.json`) };
|
|
21
|
+
const identity = { flowId: pass.flowId, stepId: pass.stepId, passDigest: sha256(canonical(pass)),
|
|
22
|
+
repositoryRoot: binding.root, apiOrigin: location.identity.apiOrigin, mutationKeyId: binding.binding.keyId };
|
|
23
|
+
return withStateLock(journal.file, async () => {
|
|
24
|
+
const settlement = await readMutationConnection(journal, identity);
|
|
25
|
+
if (settlement.pending || settlement.settled) mutationFail14('ENTROROVE_SCOPE_AMENDMENT_MUTATION_PENDING',
|
|
26
|
+
'Recover the original mutation-settle request before a fresh scope observation; do not replace its receipt');
|
|
27
|
+
// Renewal re-reads every original target and protected file, verifies the
|
|
28
|
+
// old signature and write times, and archives the expired observation.
|
|
29
|
+
// The original pass, write ledger and their expiry remain unchanged.
|
|
30
|
+
return attestMutationConsumption14(input, { renewExpired: true });
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { mutationPass14 } from './local-mutation-wire.mjs';
|
|
2
2
|
import { readMutationJson14 } from './local-mutation-files.mjs';
|
|
3
|
-
import {
|
|
3
|
+
import { observeScopeMutationConsumption } from './scope-amendment-consumption.mjs';
|
|
4
4
|
import { amendmentFail } from './scope-amendment-wire.mjs';
|
|
5
5
|
import path from 'node:path';
|
|
6
6
|
import { sha256 } from './local-integrity.mjs';
|
|
@@ -20,7 +20,6 @@ export async function scopeAmendmentMutation(location, state, challenge, facts)
|
|
|
20
20
|
|| pass.memberScopeKeyId !== challenge.keyId || pass.memberScopeBindingDigest !== challenge.originalBindingDigest
|
|
21
21
|
|| pass.scopeRevisionDigest !== challenge.authorityRevisionDigest
|
|
22
22
|
|| changed.some(file => !pass.paths.includes(file.path))) amendmentFail('Scope refresh cannot replace its actual original mutation pass or approved write paths');
|
|
23
|
-
const observed = await
|
|
24
|
-
flowId: pass.flowId, taskId: pass.taskId, stepId: pass.stepId, gatePassPath }, { allowExpiredReplay: true });
|
|
23
|
+
const observed = await observeScopeMutationConsumption(location, state, pass);
|
|
25
24
|
return { passId: pass.passId, consumptionReceipt: observed.consumptionReceipt };
|
|
26
25
|
}
|
|
@@ -27,7 +27,8 @@ export async function observeScopeAmendment(location, state) {
|
|
|
27
27
|
if (!state.snapshotId) { state.snapshotId = `scope-amend-${randomUUID()}`; await saveScopeAmendmentState(location, state); }
|
|
28
28
|
const input = { repositoryRoot: location.root, home: location.home, flowId: challenge.flowId, stepId: challenge.stepId,
|
|
29
29
|
snapshotId: state.snapshotId, paths: challenge.files.map(file => file.path).sort(),
|
|
30
|
-
contractDigest: challenge.proposalDigest, importContexts: location.binding.importContexts
|
|
30
|
+
contractDigest: challenge.proposalDigest, importContexts: location.binding.importContexts,
|
|
31
|
+
scopeCreatePaths: challenge.files.filter(file => file.access === 'create').map(file => file.path) };
|
|
31
32
|
if (!state.snapshot) {
|
|
32
33
|
if (!state.snapshotStarted) {
|
|
33
34
|
state.snapshotStarted = true; await saveScopeAmendmentState(location, state);
|
|
@@ -6,6 +6,7 @@ import { acknowledgeAutomaticFeedback, queryAutomaticFeedback, verifyAutomaticFe
|
|
|
6
6
|
import { readInvocations } from './local-invocations.mjs';
|
|
7
7
|
import { saveScopeAmendmentState } from './scope-amendment-state.mjs';
|
|
8
8
|
import { amendmentFail } from './scope-amendment-wire.mjs';
|
|
9
|
+
import { retireMissingChallenge } from './scope-amendment-retirement.mjs';
|
|
9
10
|
|
|
10
11
|
const unknown = requestId => Object.assign(new Error('Scope amendment outcome is unknown; recover the original request with GET only'),
|
|
11
12
|
{ code: 'ENTROROVE_SCOPE_AMENDMENT_UNKNOWN', outcomeUnknown: true, requestId });
|
|
@@ -15,13 +16,16 @@ async function recover(pending, dependencies) {
|
|
|
15
16
|
const response = await requestTransport(origin, `/api/skill/status/${pending.requestId}`, {
|
|
16
17
|
headers: { authorization: `Bearer ${token}`, ...ideClientHeaders() } });
|
|
17
18
|
const result = parseTransportResponse(response, 'original scope amendment status');
|
|
19
|
+
if (response.status === 404 && result?.error === 'request-not-found') {
|
|
20
|
+
throw Object.assign(unknown(pending.requestId), { requestNotFound: true });
|
|
21
|
+
}
|
|
18
22
|
if (result?.output?.requestId !== pending.requestId || response.status >= 500
|
|
19
23
|
|| ['running', 'pending'].includes(result.output.status)) throw unknown(pending.requestId);
|
|
20
24
|
result.feedback ??= await queryAutomaticFeedback(pending.requestId, dependencies);
|
|
21
25
|
verifyAutomaticFeedback(result.feedback, pending.requestId, pending.requestId);
|
|
22
26
|
result.feedback = await acknowledgeAutomaticFeedback(result.feedback, origin, token, ideClientHeaders());
|
|
23
27
|
return { response, result };
|
|
24
|
-
} catch { throw unknown(pending.requestId); }
|
|
28
|
+
} catch (error) { throw error?.requestNotFound ? error : unknown(pending.requestId); }
|
|
25
29
|
}
|
|
26
30
|
async function notSent(pending, home) {
|
|
27
31
|
try {
|
|
@@ -36,7 +40,13 @@ export async function amendmentRemote(stage, operation, payload, state, location
|
|
|
36
40
|
if (state.pending.stage !== stage || state.pending.requestId !== requestId || canonical(state.pending.input) !== canonical(input)) {
|
|
37
41
|
amendmentFail('Recover the original amendment request before another operation');
|
|
38
42
|
}
|
|
39
|
-
(
|
|
43
|
+
if (state.challengeRetirement) await retireMissingChallenge(state, location, dependencies, recover, notSent);
|
|
44
|
+
try { ({ response, result } = await recover(state.pending, dependencies)); }
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (!error?.requestNotFound || stage !== 'challenged') throw error;
|
|
47
|
+
await retireMissingChallenge(state, location, dependencies, recover, notSent);
|
|
48
|
+
({ response, result } = await recover(state.pending, dependencies));
|
|
49
|
+
}
|
|
40
50
|
} else {
|
|
41
51
|
state.pending = { stage, operation: 'continue', input, requestId };
|
|
42
52
|
await saveScopeAmendmentState(location, state);
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { canonical, sha256 } from './local-integrity.mjs';
|
|
2
|
+
import { buildInvocation, invokeRemoteResult } from './remote-client.mjs';
|
|
3
|
+
import { scopeRevisionAuthority, amendmentFail } from './scope-amendment-wire.mjs';
|
|
4
|
+
import { saveScopeAmendmentState } from './scope-amendment-state.mjs';
|
|
5
|
+
|
|
6
|
+
export async function retireMissingChallenge(state, location, dependencies, recover, notSent) {
|
|
7
|
+
const original = state.pending;
|
|
8
|
+
if (original.stage !== 'challenged' || original.input.operation !== 'workflow-scope-challenge') {
|
|
9
|
+
amendmentFail('Only the original missing challenge preparation has a retirement path');
|
|
10
|
+
}
|
|
11
|
+
const input = { requestId: original.requestId, flowId: original.input.flowId, payload: original.input.payload };
|
|
12
|
+
const call = buildInvocation('scope-challenge-retire', input);
|
|
13
|
+
let attempt = state.challengeRetirement;
|
|
14
|
+
if (attempt && (attempt.requestId !== call.requestId || canonical(attempt.input) !== canonical(input))) {
|
|
15
|
+
amendmentFail('Challenge retirement must retain its original preparation envelope');
|
|
16
|
+
}
|
|
17
|
+
if (!attempt) {
|
|
18
|
+
attempt = state.challengeRetirement = { requestId: call.requestId, input, state: 'pending' };
|
|
19
|
+
await saveScopeAmendmentState(location, state);
|
|
20
|
+
try {
|
|
21
|
+
const { result } = await invokeRemoteResult({ operation: 'scope-challenge-retire', input }, dependencies);
|
|
22
|
+
attempt.output = result.output; attempt.feedback = result.feedback; attempt.state = 'completed';
|
|
23
|
+
await saveScopeAmendmentState(location, state);
|
|
24
|
+
} catch (error) {
|
|
25
|
+
if (await notSent(attempt, dependencies.home)) {
|
|
26
|
+
attempt.state = 'not-sent'; await saveScopeAmendmentState(location, state);
|
|
27
|
+
}
|
|
28
|
+
throw error;
|
|
29
|
+
}
|
|
30
|
+
} else if (attempt.state !== 'completed') {
|
|
31
|
+
// A retirement with an uncertain outcome has its own original GET. Neither
|
|
32
|
+
// the original challenge nor the retirement is retransmitted here.
|
|
33
|
+
if (attempt.state === 'not-sent') {
|
|
34
|
+
delete state.challengeRetirement; await saveScopeAmendmentState(location, state);
|
|
35
|
+
return retireMissingChallenge(state, location, dependencies, recover, notSent);
|
|
36
|
+
}
|
|
37
|
+
const { result } = await recover(attempt, dependencies);
|
|
38
|
+
attempt.output = result.output; attempt.feedback = result.feedback; attempt.state = 'completed';
|
|
39
|
+
await saveScopeAmendmentState(location, state);
|
|
40
|
+
}
|
|
41
|
+
const output = attempt.output;
|
|
42
|
+
if (output?.requestId !== call.requestId) amendmentFail('Retirement lost its original request identity');
|
|
43
|
+
if (output.status === 'blocked' && output.result?.reason === 'original-admission-already-recorded') return;
|
|
44
|
+
if (output.status !== 'succeeded' || output.result?.retired !== true) amendmentFail('The server did not retire this original missing preparation');
|
|
45
|
+
const receipt = scopeRevisionAuthority(output.result.retirement, 'entrorove.scope-challenge-retirement/1.0');
|
|
46
|
+
if (receipt.purpose !== 'scope-challenge-retirement' || receipt.requestId !== original.requestId
|
|
47
|
+
|| receipt.retirementRequestId !== call.requestId || receipt.flowId !== input.flowId
|
|
48
|
+
|| receipt.proposalId !== input.payload.proposalId || receipt.proposalDigest !== input.payload.proposalDigest
|
|
49
|
+
|| receipt.receiverId !== input.payload.receiverId || receipt.attemptId !== input.payload.attemptId
|
|
50
|
+
|| receipt.originalInputDigest !== sha256(canonical(original.input)) || receipt.outcome !== 'retired-before-admission'
|
|
51
|
+
|| ['claimsOriginalExecution', 'grantsExecutionAuthority', 'grantsWriteAuthority', 'claimsCompletion'].some(key => receipt[key] !== false)) {
|
|
52
|
+
amendmentFail('Challenge retirement changed its exact original preparation or authority boundary');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -10,11 +10,14 @@ import { trustedOrigin } from './remote-transport.mjs';
|
|
|
10
10
|
|
|
11
11
|
const fail = message => scopeFail('ENTROROVE_SCOPE_AMENDMENT_STATE', message);
|
|
12
12
|
const maximumStateBytes = 1_000_000;
|
|
13
|
-
|
|
13
|
+
// A journal retains the challenge, S proof, original pending request and full
|
|
14
|
+
// signed response together. Each signed authority retains its own 1 MB bound.
|
|
15
|
+
const maximumJournalBytes = 8_000_000;
|
|
16
|
+
async function privateItem(file, final = 'file', maximumBytes = maximumStateBytes) {
|
|
14
17
|
const value = await mutationFile14(file, { final });
|
|
15
18
|
if (process.getuid && value.stat.uid !== process.getuid()
|
|
16
19
|
|| process.platform !== 'win32' && value.stat.mode & 0o077
|
|
17
|
-
|| final === 'file' && (value.stat.nlink !== 1 || value.stat.size >
|
|
20
|
+
|| final === 'file' && (value.stat.nlink !== 1 || value.stat.size > maximumBytes)) {
|
|
18
21
|
fail('Scope amendment controls must be bounded private files owned by the current OS account');
|
|
19
22
|
}
|
|
20
23
|
return value;
|
|
@@ -80,7 +83,7 @@ export async function scopeAmendmentLocation(repositoryRoot, input, dependencies
|
|
|
80
83
|
}
|
|
81
84
|
export async function readScopeAmendmentState(location) {
|
|
82
85
|
let value;
|
|
83
|
-
try { await privateItem(location.file); value = await readMutationJson14(location.file); }
|
|
86
|
+
try { await privateItem(location.file, 'file', maximumJournalBytes); value = await readMutationJson14(location.file); }
|
|
84
87
|
catch (error) { if (error.code !== 'ENOENT') throw error; }
|
|
85
88
|
if (!value) return { schemaVersion: 'entrorove.scope-amendment-state/1.0', identity: location.identity };
|
|
86
89
|
if (value.schemaVersion !== 'entrorove.scope-amendment-state/1.0'
|
|
@@ -89,6 +92,6 @@ export async function readScopeAmendmentState(location) {
|
|
|
89
92
|
return value;
|
|
90
93
|
}
|
|
91
94
|
export async function saveScopeAmendmentState(location, value) {
|
|
92
|
-
if (Buffer.byteLength(canonical(value)) >
|
|
95
|
+
if (Buffer.byteLength(canonical(value)) + 1 > maximumJournalBytes) fail('Scope amendment state exceeds its bounded private file limit');
|
|
93
96
|
return atomicMutationJson14(location.file, value, { privateFrom: location.stateRoot, replace: true });
|
|
94
97
|
}
|
package/task-entry-client.mjs
CHANGED
|
@@ -28,5 +28,6 @@ export async function routeTaskEntry(data, token, dependencies) {
|
|
|
28
28
|
if (!task || typeof task.goal !== 'string') throw new Error('Task entry requires the original task goal');
|
|
29
29
|
const ideTaskId = ideTaskIdentity(data.ideTaskId);
|
|
30
30
|
return runCloudTask({ goal: task.goal, task,
|
|
31
|
+
...(data.images === undefined ? {} : { images: data.images }),
|
|
31
32
|
...(ideTaskId ? { ideTaskId } : {}),...(choice ? { sandboxChoice: choice } : {}) },dependencies);
|
|
32
33
|
}
|
|
@@ -5,6 +5,7 @@ const safeId = value => typeof value === 'string' && /^[A-Za-z0-9][A-Za-z0-9._:-
|
|
|
5
5
|
const safeRequest = value => typeof value === 'string' && /^[a-f0-9]{64}$/.test(value);
|
|
6
6
|
const messages = {
|
|
7
7
|
ENTROROVE_LOCAL_OBSERVATION_UNKNOWN: 'Original observation outcome is unknown; recover its original GET without repeating execution',
|
|
8
|
+
ENTROROVE_LOCAL_OBSERVATION_REJECTED: 'Original observation request failed and was acknowledged; repair its cause and read the original live task guidance',
|
|
8
9
|
ENTROROVE_LOCAL_OBSERVATION_NOT_SENT: 'Observation was not transmitted; repair its local or discovery prerequisite and reuse the original input',
|
|
9
10
|
ENTROROVE_LOCAL_OBSERVATION_PREREQUISITE: 'Local observation requires cloud sandbox disabled and its original live execution lease',
|
|
10
11
|
ENTROROVE_SCOPE_RECEIPT_EXPIRED: 'Refresh the original scope evidence and reuse the original observation input',
|
|
@@ -24,6 +25,11 @@ function blocked(error, input) {
|
|
|
24
25
|
'ENTROROVE_SCOPE_RUNNER_REQUIRED', 'ENTROROVE_SCOPE_SNAPSHOT_REQUIRED', 'ENTROROVE_SCOPE_AFTER_WRITE_REQUIRED'].includes(code));
|
|
25
26
|
const reason = ['sandbox-enabled', 'cloud-sandbox-enabled', 'lease-expired', 'receipt-expired', 'after-write-observation-required'].includes(output?.reason)
|
|
26
27
|
? output.reason : undefined;
|
|
28
|
+
const rejected = code === 'ENTROROVE_LOCAL_OBSERVATION_REJECTED' && cause.knownTerminalFailure === true
|
|
29
|
+
&& requestId && cause.rejection?.status === 'failed' && cause.rejection.acknowledged === true
|
|
30
|
+
&& /^[a-f0-9-]{36}$/.test(cause.rejection.receiptId ?? '')
|
|
31
|
+
&& Number.isSafeInteger(cause.rejection.generation) && cause.rejection.generation > 0
|
|
32
|
+
&& ['member-observation-admit', 'member-observation-report'].includes(cause.rejection.operation);
|
|
27
33
|
return { schemaVersion: 'entrorove.local-observation-connection/1.0', status: 'blocked',
|
|
28
34
|
...(safeId(input?.flowId) ? { flowId: input.flowId } : {}), independentValidation: 'pending', code,
|
|
29
35
|
message: messages[code] ?? 'Local observation could not continue; its original command and result remain preserved',
|
|
@@ -33,6 +39,11 @@ function blocked(error, input) {
|
|
|
33
39
|
...(safeRequest(output.requestId) ? { resumeRequestId: output.requestId } : {}) } } } : {}),
|
|
34
40
|
...(cause.outcomeUnknown === true && requestId ? { outcomeUnknown: true, requestId, repeatPost: false,
|
|
35
41
|
nextAction: { operation: 'workflow-observe-step', reuseOriginalInput: true, method: 'GET' } } : {}),
|
|
42
|
+
...(rejected ? { outcomeUnknown: false, requestId, repeatPost: false, grantsExecutionAuthority: false,
|
|
43
|
+
rejection: { operation: cause.rejection.operation, status: 'failed', receiptId: cause.rejection.receiptId,
|
|
44
|
+
generation: cause.rejection.generation, acknowledged: true, effects: 'not-inferred' },
|
|
45
|
+
nextAction: { operation: 'task-resume', input: { flowId: input.flowId }, preserveOriginalFlow: true,
|
|
46
|
+
localProcessMayStart: false, originalRequestRetained: true } } : {}),
|
|
36
47
|
...(cause.knownBeforeTransmission === true && requestId ? { requestId, knownBeforeTransmission: true } : {}) };
|
|
37
48
|
}
|
|
38
49
|
export async function runWorkflowObserveStep(repositoryRoot, input, dependencies) {
|
|
@@ -9,7 +9,8 @@ import { verifyWorkflowLocalAcceptance } from './workflow-local-acceptance.mjs';
|
|
|
9
9
|
import { buildInvocation } from './remote-client.mjs';
|
|
10
10
|
|
|
11
11
|
async function connect(input, state, location, dependencies) {
|
|
12
|
-
const fields = ['taskId', 'flowId', 'stepId', 'leaseId', 'generation', ...(Object.hasOwn(input, 'settlementId') ? ['settlementId'] : [])
|
|
12
|
+
const fields = ['taskId', 'flowId', 'stepId', 'leaseId', 'generation', ...(Object.hasOwn(input, 'settlementId') ? ['settlementId'] : []),
|
|
13
|
+
...(Object.hasOwn(input, 'dependencyRepairDigest') ? ['dependencyRepairDigest'] : [])];
|
|
13
14
|
const original = Object.fromEntries(fields.map(key => [key, input[key]]));
|
|
14
15
|
const admitted = state.admitted ?? await observationRemote('admitted', 'member-observation-admit', original, state, location, dependencies);
|
|
15
16
|
const admission = observationAdmission(admitted.admission, input, { allowExpired: Boolean(state.result) });
|