reploid 0.0.0-stage → 0.1.1

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.
Files changed (233) hide show
  1. package/apps/poolday/config/chat-files.json +27 -0
  2. package/apps/poolday/config/partition-generation.js +21 -0
  3. package/apps/poolday/config/partition-policy.json +74 -0
  4. package/apps/poolday/config/partition-releases.json +3 -0
  5. package/apps/poolday/config/work-profile.json +122 -0
  6. package/apps/poolday/host/chat-view.js +47 -0
  7. package/apps/poolday/host/earning/client.js +199 -0
  8. package/apps/poolday/host/earning/contribution.js +168 -0
  9. package/apps/poolday/host/partition-release.js +33 -0
  10. package/apps/poolday/host/work-partition-artifact-source.js +37 -0
  11. package/apps/poolday/host/work-partition-capsule.js +39 -0
  12. package/apps/poolday/host/work-partition-plan.js +167 -0
  13. package/apps/poolday/host/work-partition-tokenizer-guard.js +21 -0
  14. package/apps/poolday/infrastructure/model-storage-lock.js +22 -0
  15. package/apps/poolday/infrastructure/pack-release-storage.js +52 -0
  16. package/apps/poolday/pool/pack-operation.js +161 -0
  17. package/apps/poolday/pool/pack-release-policy.js +44 -0
  18. package/apps/poolday/pool/peer-pack-data-channel.js +217 -0
  19. package/apps/poolday/providers/work-adapter.js +67 -0
  20. package/apps/poolday/providers/work-device.js +33 -0
  21. package/apps/poolday/providers/work-generation-completion.js +55 -0
  22. package/apps/poolday/providers/work-provider.js +209 -0
  23. package/apps/poolday/providers/work-resident-provider.js +113 -0
  24. package/deploy/artifacts/doppler-gpu-0.7.1.tgz +0 -0
  25. package/docs/fleet-service.md +214 -0
  26. package/docs/native-participant.md +542 -0
  27. package/native-delivery.json +1174 -0
  28. package/package.json +29 -4
  29. package/packages/reploid/src/artifacts/binary.js +25 -0
  30. package/packages/reploid/src/artifacts/canonical-json.js +23 -0
  31. package/packages/reploid/src/artifacts/custody/exchange.js +402 -0
  32. package/packages/reploid/src/artifacts/custody/piece-acquisition.js +70 -0
  33. package/packages/reploid/src/artifacts/custody/runtime.js +404 -0
  34. package/packages/reploid/src/artifacts/custody/supply-budget.js +19 -0
  35. package/packages/reploid/src/artifacts/custody-certificate.js +123 -0
  36. package/packages/reploid/src/artifacts/delivery-attestation.js +64 -0
  37. package/packages/reploid/src/artifacts/generation-terminal.js +36 -0
  38. package/packages/reploid/src/artifacts/identity.js +91 -0
  39. package/packages/reploid/src/artifacts/participant-proofs.js +159 -0
  40. package/packages/reploid/src/artifacts/receipt.js +131 -0
  41. package/packages/reploid/src/artifacts/signatures.js +94 -0
  42. package/packages/reploid/src/artifacts/whole-model-receipt.js +42 -0
  43. package/packages/reploid/src/cancellation.js +44 -0
  44. package/packages/reploid/src/config/defaults.json +110 -0
  45. package/packages/reploid/src/config/index.js +209 -0
  46. package/packages/reploid/src/config/request-overrides.json +9 -0
  47. package/packages/reploid/src/config/transport-defaults.json +7 -0
  48. package/packages/reploid/src/hashing.js +30 -0
  49. package/packages/reploid/src/measurement/capacity-utilization.js +321 -0
  50. package/packages/reploid/src/measurement/index.js +5 -0
  51. package/packages/reploid/src/measurement/readiness-records.js +310 -0
  52. package/packages/reploid/src/mesh/computer-identity.js +50 -0
  53. package/packages/reploid/src/mesh/computer-identity.policy.json +8 -0
  54. package/packages/reploid/src/mesh/contribution.js +141 -0
  55. package/packages/reploid/src/mesh/generation-recovery.js +58 -0
  56. package/packages/reploid/src/mesh/gpu-signature-shader.js +27 -0
  57. package/packages/reploid/src/mesh/gpu-signature.js +136 -0
  58. package/packages/reploid/src/mesh/gpu-signature.policy.json +11 -0
  59. package/packages/reploid/src/mesh/index.js +66 -0
  60. package/packages/reploid/src/mesh/partitions/automatic-ordered-partitions.js +540 -0
  61. package/packages/reploid/src/mesh/partitions/automatic-partitions.js +298 -0
  62. package/packages/reploid/src/mesh/partitions/partition-attempt-evidence.js +282 -0
  63. package/packages/reploid/src/mesh/partitions/partition-attempt-queue-policy.json +6 -0
  64. package/packages/reploid/src/mesh/partitions/partition-attempt-queue.js +112 -0
  65. package/packages/reploid/src/mesh/partitions/partition-canonical-contract.js +167 -0
  66. package/packages/reploid/src/mesh/partitions/partition-canonical-execution.js +168 -0
  67. package/packages/reploid/src/mesh/partitions/partition-chat-canonical.js +49 -0
  68. package/packages/reploid/src/mesh/partitions/partition-chat.js +125 -0
  69. package/packages/reploid/src/mesh/partitions/partition-contract.js +192 -0
  70. package/packages/reploid/src/mesh/partitions/partition-device-admission.js +96 -0
  71. package/packages/reploid/src/mesh/partitions/partition-discovery.js +96 -0
  72. package/packages/reploid/src/mesh/partitions/partition-entry-publication.js +183 -0
  73. package/packages/reploid/src/mesh/partitions/partition-entry.js +434 -0
  74. package/packages/reploid/src/mesh/partitions/partition-generation-request.js +33 -0
  75. package/packages/reploid/src/mesh/partitions/partition-grants.js +277 -0
  76. package/packages/reploid/src/mesh/partitions/partition-link.js +103 -0
  77. package/packages/reploid/src/mesh/partitions/partition-network.js +109 -0
  78. package/packages/reploid/src/mesh/partitions/partition-ordered-chat.js +290 -0
  79. package/packages/reploid/src/mesh/partitions/partition-ordered-peer.js +415 -0
  80. package/packages/reploid/src/mesh/partitions/partition-ordered-publication.js +100 -0
  81. package/packages/reploid/src/mesh/partitions/partition-peer.js +314 -0
  82. package/packages/reploid/src/mesh/partitions/partition-placement.js +143 -0
  83. package/packages/reploid/src/mesh/partitions/partition-preparation-progress.js +25 -0
  84. package/packages/reploid/src/mesh/partitions/partition-receiver-policy.json +7 -0
  85. package/packages/reploid/src/mesh/partitions/partition-reservations.js +75 -0
  86. package/packages/reploid/src/mesh/partitions/partition-route-envelope-policy.json +16 -0
  87. package/packages/reploid/src/mesh/partitions/partition-route-envelope.js +74 -0
  88. package/packages/reploid/src/mesh/partitions/partition-route-execution.js +409 -0
  89. package/packages/reploid/src/mesh/partitions/partition-route-network.js +179 -0
  90. package/packages/reploid/src/mesh/partitions/partition-route-ranking.js +268 -0
  91. package/packages/reploid/src/mesh/partitions/partition-runner.js +319 -0
  92. package/packages/reploid/src/mesh/partitions/partition-stage-assignment.js +109 -0
  93. package/packages/reploid/src/mesh/partitions/partition-stage-commit.js +103 -0
  94. package/packages/reploid/src/mesh/partitions/partition-step-receiver.js +291 -0
  95. package/packages/reploid/src/mesh/partitions/partition-summary.js +122 -0
  96. package/packages/reploid/src/mesh/partitions/preparation-owner.js +40 -0
  97. package/packages/reploid/src/mesh/partitions/resident-error-codes.json +10 -0
  98. package/packages/reploid/src/mesh/partitions/resident-partition.js +333 -0
  99. package/packages/reploid/src/mesh/partitions/resident-route.js +46 -0
  100. package/packages/reploid/src/mesh/partitions/signed-resident-factory.js +59 -0
  101. package/packages/reploid/src/mesh/peer-generation.js +896 -0
  102. package/packages/reploid/src/mesh/peer-identity.js +87 -0
  103. package/packages/reploid/src/mesh/placement-beliefs.js +107 -0
  104. package/packages/reploid/src/mesh/preparation-progress.js +46 -0
  105. package/packages/reploid/src/mesh/provider-hardware.js +11 -0
  106. package/packages/reploid/src/mesh/remote-generation-requests.js +53 -0
  107. package/packages/reploid/src/mesh/swarm-coordination.js +140 -0
  108. package/packages/reploid/src/mesh/web-access-network.js +112 -0
  109. package/packages/reploid/src/mesh/web-access-policy.json +17 -0
  110. package/packages/reploid/src/retrieval/citations.js +156 -0
  111. package/packages/reploid/src/retrieval/claim-support.js +113 -0
  112. package/packages/reploid/src/retrieval/costs.js +101 -0
  113. package/packages/reploid/src/retrieval/fixed-provider.js +34 -0
  114. package/packages/reploid/src/retrieval/index.js +20 -0
  115. package/packages/reploid/src/retrieval/lexical-support.js +27 -0
  116. package/packages/reploid/src/retrieval/model-reviewer.js +67 -0
  117. package/packages/reploid/src/retrieval/page-fetch.json +10 -0
  118. package/packages/reploid/src/retrieval/page-text.js +182 -0
  119. package/packages/reploid/src/retrieval/passage.js +37 -0
  120. package/packages/reploid/src/retrieval/policy.json +14 -0
  121. package/packages/reploid/src/retrieval/retrieval.js +23 -0
  122. package/packages/reploid/src/retrieval/review-queue.js +76 -0
  123. package/packages/reploid/src/retrieval/sources.js +263 -0
  124. package/packages/reploid/src/retrieval/support-review.js +155 -0
  125. package/packages/reploid/src/retrieval/text.js +21 -0
  126. package/packages/reploid/src/rules/contribution.rules.json +8 -0
  127. package/packages/reploid/src/rules/routing.rules.json +24 -0
  128. package/packages/reploid/src/transport/assignment.js +571 -0
  129. package/packages/reploid/src/transport/bounded-channel-writer.js +46 -0
  130. package/packages/reploid/src/transport/index.js +11 -0
  131. package/packages/reploid/src/transport/introduction-admission.js +24 -0
  132. package/packages/reploid/src/transport/introduction-bootstrap.js +112 -0
  133. package/packages/reploid/src/transport/introduction-policy.json +12 -0
  134. package/packages/reploid/src/transport/introduction-records.js +90 -0
  135. package/packages/reploid/src/transport/introductions.js +209 -0
  136. package/packages/reploid/src/transport/partition-data-channel.js +421 -0
  137. package/packages/reploid/src/transport/partition-errors.json +16 -0
  138. package/packages/reploid/src/transport/retry-policy.js +36 -0
  139. package/packages/reploid/src/transport/room.js +502 -0
  140. package/packages/reploid/src/transport/sdp-fingerprint.js +5 -0
  141. package/packages/reploid/src/transport/signaling.js +571 -0
  142. package/packages/reploid/src/transport/swarm.js +1247 -0
  143. package/packages/reploid/src/transport/tool-offer-channel.js +137 -0
  144. package/server/browser-roots.js +42 -0
  145. package/server/browser-web-worker.js +94 -0
  146. package/server/chat-completions.js +45 -0
  147. package/server/fleet/browser-bridge.js +145 -0
  148. package/server/fleet/contract.js +42 -0
  149. package/server/fleet/credit-evidence.js +103 -0
  150. package/server/fleet/credit-recovery.js +175 -0
  151. package/server/fleet/credits.js +178 -0
  152. package/server/fleet/execution-admission.js +32 -0
  153. package/server/fleet/native-host.js +817 -0
  154. package/server/fleet/placement.js +132 -0
  155. package/server/fleet/requester.js +346 -0
  156. package/server/fleet/service.js +311 -0
  157. package/server/fleet/terminal-policy.js +83 -0
  158. package/server/fleet/text-api.js +94 -0
  159. package/server/hashing.js +35 -0
  160. package/server/http-request-owner.js +49 -0
  161. package/server/messages.js +57 -0
  162. package/server/native-canonical-epochs.js +90 -0
  163. package/server/native-change-log.js +40 -0
  164. package/server/native-earning.js +203 -0
  165. package/server/native-generation-journal.js +46 -0
  166. package/server/native-model-config.js +57 -0
  167. package/server/native-model-files.js +382 -0
  168. package/server/native-model-origin.js +54 -0
  169. package/server/native-model-origins.json +12 -0
  170. package/server/native-node.js +85 -0
  171. package/server/native-owner/controls.js +162 -0
  172. package/server/native-owner/monitor.js +251 -0
  173. package/server/native-owner/policy.js +273 -0
  174. package/server/native-owner/rate.js +92 -0
  175. package/server/native-participant.js +866 -0
  176. package/server/native-readiness-log.js +30 -0
  177. package/server/native-release-storage.js +64 -0
  178. package/server/native-shader-cache.js +369 -0
  179. package/server/native-supply-budget.js +66 -0
  180. package/server/native-whole-earning.js +67 -0
  181. package/server/native-whole-model-fill.js +182 -0
  182. package/server/native-whole-model.js +130 -0
  183. package/server/public-web-worker.js +66 -0
  184. package/server/responses.js +92 -0
  185. package/server/search/errors.js +47 -0
  186. package/server/search/page-fetch.js +185 -0
  187. package/server/text-api.js +83 -0
  188. package/server/text-recovery.js +45 -0
  189. package/server/text-request-options.js +23 -0
  190. package/server/text-requester.js +231 -0
  191. package/server/token-auth.js +9 -0
  192. package/server/whole-model-requester.js +99 -0
  193. package/shared/config/chat-models.json +4685 -0
  194. package/shared/config/doppler-execution-contracts.js +32 -0
  195. package/shared/config/doppler-execution-contracts.json +43 -0
  196. package/shared/config/doppler-generation-contract.js +223 -0
  197. package/shared/config/doppler-local-models.js +79 -0
  198. package/shared/config/doppler-package.json +7 -0
  199. package/shared/config/model-manifests/a0dc69e917133a82780823d17fc771c0f6b882d7c86c571deeaef45be2ff108b.json +6434 -0
  200. package/shared/config/model-manifests/e985e3cdad60d0cb57d84b436161e66ab5b3f6589a168de6f00b4610e5f1fb59.json +16534 -0
  201. package/shared/config/model-manifests/fa6eb7bbc3ba63571f8cede780b877d9272bde948697af93dd3d33837cb46137.json +7175 -0
  202. package/shared/config/model-pieces/qwen-0-8b-pieces.json +1506 -0
  203. package/shared/config/model-pieces/qwen-2b-pieces.json +4800 -0
  204. package/shared/config/model-pieces/qwen35b-q4_0-pieces.json +28880 -0
  205. package/shared/config/reploid-library.json +49 -0
  206. package/shared/config/swarm-bootstrap.json +21 -0
  207. package/shared/infrastructure/doppler-runtime-service.js +261 -0
  208. package/shared/pool/executable-pack.js +87 -0
  209. package/shared/pool/pack-operation-adapters.js +124 -0
  210. package/shared/pool/pack-operation-policy.js +75 -0
  211. package/shared/pool/pool-config.json +2280 -0
  212. package/shared/vendor/reploid/adapters/doppler-session.js +372 -0
  213. package/shared/vendor/reploid/artifacts/binary.js +25 -0
  214. package/shared/vendor/reploid/artifacts/canonical-json.js +23 -0
  215. package/shared/vendor/reploid/artifacts/delivery-attestation.js +64 -0
  216. package/shared/vendor/reploid/artifacts/identity.js +91 -0
  217. package/shared/vendor/reploid/artifacts/manifest-identity.js +17 -0
  218. package/shared/vendor/reploid/artifacts/participant-proofs.js +159 -0
  219. package/shared/vendor/reploid/artifacts/signatures.js +94 -0
  220. package/shared/vendor/reploid/config/defaults.json +110 -0
  221. package/shared/vendor/reploid/config/index.js +209 -0
  222. package/shared/vendor/reploid/config/request-overrides.json +9 -0
  223. package/shared/vendor/reploid/hashing.js +30 -0
  224. package/shared/vendor/reploid/mesh/generation-context-cache.js +97 -0
  225. package/shared/vendor/reploid/mesh/partitions/partition-attempt-evidence.js +282 -0
  226. package/shared/vendor/reploid/mesh/partitions/partition-contract.js +192 -0
  227. package/shared/vendor/reploid/mesh/partitions/partition-receiver-policy.json +7 -0
  228. package/shared/vendor/reploid/mesh/partitions/partition-route-ranking.js +268 -0
  229. package/shared/vendor/reploid/mesh/preparation-progress.js +46 -0
  230. package/shared/vendor/reploid/mesh/provider-hardware.js +11 -0
  231. package/shared/vendor/reploid/rules/routing.rules.json +24 -0
  232. package/shared/vendor/reploid/transport/partition-errors.json +16 -0
  233. package/README.md +0 -3
@@ -0,0 +1,112 @@
1
+ import queuePolicy from './partition-attempt-queue-policy.json' with { type: 'json' };
2
+ import { assertPartition as assert, partitionFailure } from './partition-contract.js';
3
+
4
+ export const ATTEMPT_QUEUE_POLICY_SCHEMA = 'reploid.partition-attempt-queue-policy/v1';
5
+ const POLICY_KEYS = Object.freeze(['schema', 'maxQueuedAttempts', 'maxQueuedPerRequester', 'maxQueueWaitMs']);
6
+ const positive = value => Number.isSafeInteger(value) && value > 0;
7
+
8
+ /** Every member is required and nothing is defaulted in JavaScript. */
9
+ export function validateAttemptQueuePolicy(policy) {
10
+ const keys = policy && typeof policy === 'object' && !Array.isArray(policy) ? Object.keys(policy) : [];
11
+ assert(keys.length === POLICY_KEYS.length && POLICY_KEYS.every(key => keys.includes(key))
12
+ && policy.schema === ATTEMPT_QUEUE_POLICY_SCHEMA
13
+ && ['maxQueuedAttempts', 'maxQueuedPerRequester', 'maxQueueWaitMs'].every(key => positive(policy[key]))
14
+ && policy.maxQueuedPerRequester <= policy.maxQueuedAttempts && policy.maxQueueWaitMs <= 2147483647,
15
+ `Explicit ${ATTEMPT_QUEUE_POLICY_SCHEMA} required: ${POLICY_KEYS.join(', ')}`);
16
+ return Object.freeze({ ...policy });
17
+ }
18
+
19
+ /** The partitions component's own waiting bounds, checked when this module loads. */
20
+ export const ATTEMPT_QUEUE_POLICY = validateAttemptQueuePolicy(queuePolicy);
21
+
22
+ /**
23
+ * Coordinator admission for already-authorized ordered attempts. An attempt whose route has no
24
+ * free slot waits here instead of failing; while it waits nothing is tokenized, reserved, granted
25
+ * or disclosed to any stage. Entries are admitted in arrival order: the earliest waiting entry
26
+ * whose route can run it now goes first, so one route's limit never idles another route's
27
+ * capacity and later entries of the same route never overtake earlier ones.
28
+ *
29
+ * `admit()` resolves with a ticket the route owner holds until the attempt's coordinator-side
30
+ * work ends (`release()`); `opened()` marks that the attempt now holds the coordinator stage's
31
+ * own reservation, so a gate can count tickets that have not yet reserved it. Each gate
32
+ * `check({ admitted, opening })` sees its key's live tickets and every ticket not yet opened, and
33
+ * returns true to admit, false to keep waiting, or throws to refuse an entry its route can no
34
+ * longer run (that error is the entry's failure).
35
+ *
36
+ * Bounds fail explicitly: a full queue (overall or for one authenticated requester) with
37
+ * CAPACITY_QUEUE_FULL; a wait reaching the policy limit, or the attempt's own deadline (its
38
+ * disclosure window) first, with CAPACITY_QUEUE_TIMEOUT and `bound` 'policy' or 'authorization'.
39
+ * Cancellation removes the entry with the signal's reason; nothing was held, so nothing settles.
40
+ */
41
+ export function createPartitionAttemptQueue({ policy, now = Date.now }) {
42
+ const bounds = validateAttemptQueuePolicy(policy);
43
+ assert(typeof now === 'function', 'Queue clock required');
44
+ const waiting = [], tickets = new Set();
45
+ let opening = 0;
46
+ const admittedFor = key => [...tickets].filter(ticket => ticket.key === key).length;
47
+ const ask = entry => entry.check({ admitted: admittedFor(entry.key), opening });
48
+ function grant(key, queuedAt) {
49
+ const record = { key, opened: false };
50
+ tickets.add(record); opening++;
51
+ const queuedMs = queuedAt === null ? 0 : Math.max(0, now() - queuedAt);
52
+ return Object.freeze({ queued: queuedAt !== null, queuedMs,
53
+ opened() { if (!record.opened && tickets.has(record)) { record.opened = true; opening--; } },
54
+ release() {
55
+ if (!tickets.delete(record)) return;
56
+ if (!record.opened) { record.opened = true; opening--; }
57
+ pump();
58
+ } });
59
+ }
60
+ function settle(entry, error) {
61
+ const index = waiting.indexOf(entry);
62
+ if (index < 0) return;
63
+ waiting.splice(index, 1);
64
+ clearTimeout(entry.timer); entry.signal?.removeEventListener('abort', entry.onAbort);
65
+ if (error) entry.reject(error); else entry.resolve(grant(entry.key, entry.queuedAt));
66
+ }
67
+ function pump() {
68
+ for (const entry of [...waiting]) {
69
+ if (!waiting.includes(entry)) continue;
70
+ let admit;
71
+ try { admit = ask(entry) === true; } catch (error) { settle(entry, error); continue; }
72
+ if (admit) settle(entry, null);
73
+ }
74
+ }
75
+ return Object.freeze({
76
+ policy: bounds,
77
+ // Async so every refusal, including an already-aborted signal, is a rejection; the decision and
78
+ // any enqueueing still happen synchronously, in call order.
79
+ async admit({ key, attemptId, requesterId, deadlineAt = Infinity, signal, check, onQueued = () => {} }) {
80
+ assert(key !== undefined && key !== null && typeof attemptId === 'string' && attemptId.length > 0
81
+ && typeof requesterId === 'string' && requesterId.length > 0 && typeof check === 'function'
82
+ && typeof onQueued === 'function' && (deadlineAt === Infinity || Number.isFinite(deadlineAt)),
83
+ 'Queued attempt key, identity, authenticated requester and admission check required');
84
+ signal?.throwIfAborted();
85
+ assert(!waiting.some(entry => entry.attemptId === attemptId), 'Attempt is already waiting for admission');
86
+ // Earlier arrivals take any capacity first; an entry that fits after them is admitted at once.
87
+ pump();
88
+ const entry = { key, attemptId, requesterId, check, signal, queuedAt: null };
89
+ let fits;
90
+ try { fits = ask(entry) === true; } catch (error) { return Promise.reject(error); }
91
+ if (fits) return Promise.resolve(grant(key, null));
92
+ const at = now(), policyAt = at + bounds.maxQueueWaitMs, limit = Math.min(policyAt, deadlineAt);
93
+ const bound = deadlineAt < policyAt ? 'authorization' : 'policy';
94
+ if (limit <= at) return Promise.reject(partitionFailure('CAPACITY_QUEUE_TIMEOUT', { bound }));
95
+ if (waiting.length >= bounds.maxQueuedAttempts
96
+ || waiting.filter(row => row.requesterId === requesterId).length >= bounds.maxQueuedPerRequester) {
97
+ return Promise.reject(partitionFailure('CAPACITY_QUEUE_FULL'));
98
+ }
99
+ const { promise, resolve, reject } = Promise.withResolvers();
100
+ Object.assign(entry, { resolve, reject, queuedAt: at });
101
+ entry.timer = setTimeout(() => settle(entry, partitionFailure('CAPACITY_QUEUE_TIMEOUT', { bound })), limit - at);
102
+ entry.onAbort = () => settle(entry, signal.reason ?? new Error('Queued attempt cancelled'));
103
+ signal?.addEventListener('abort', entry.onAbort, { once: true });
104
+ waiting.push(entry);
105
+ try { onQueued({ position: waiting.length, queuedAt: at, waitUntil: limit }); } catch {}
106
+ return promise;
107
+ },
108
+ /** Re-evaluate waiting entries after capacity may have changed. */
109
+ pump,
110
+ getState: () => ({ queued: waiting.length, admitted: tickets.size, opening, ...bounds })
111
+ });
112
+ }
@@ -0,0 +1,167 @@
1
+ import { assertPartition as assert, samePartitionIdentity, canonicalPartitionBinding,
2
+ partitionActivationContract, matchingPartitionActivation } from './partition-contract.js';
3
+ import { verifyPartitionStageCommit } from './partition-stage-commit.js';
4
+ import { PUBLICATION_RECEIPT_SCHEMA } from './partition-ordered-publication.js';
5
+ import { sha256Hex } from '../../artifacts/signatures.js';
6
+
7
+ const SCHEMA = 'reploid.canonical-partition-request/v1';
8
+ const stepKeys = ['schema', 'operation', 'phase', 'identity', 'canonicalAttempt', 'generationId', 'sequence',
9
+ 'step', 'tokenPosition', 'inputTokenCount', 'inputTokenIds', 'baseCursorId', 'baseCursor', 'grant', 'continuation'];
10
+ const exact = (value, keys) => assert(value && typeof value === 'object' && !Array.isArray(value)
11
+ && Object.keys(value).length === keys.length && keys.every(key => Object.hasOwn(value, key)), 'Invalid canonical wire fields');
12
+
13
+ /** Wire admission only. Doppler owns the declared tensor/cursor/publication contracts. */
14
+ export function createCanonicalPartitionContract({ runtime, plan, planId, modelIdentity }) {
15
+ for (const name of ['metadataDigest', 'tokenDigest', 'residentAttemptDigest', 'validateResidentAttemptIdentity',
16
+ 'validateResidentCursor', 'validateOrdinaryActivation', 'validateExecutionPublication', 'validateAdmissionPublication',
17
+ 'serializeActivationFrame', 'validateActivationFrameForPlan']) assert(typeof runtime?.[name] === 'function', `Canonical partition capability required: ${name}`);
18
+ plan = structuredClone(plan);
19
+ const layout = partitionActivationContract(runtime, plan);
20
+ const hash = (schema, value) => runtime.metadataDigest(schema, value);
21
+ const equal = (a, b) => hash('reploid.canonical-wire-value/v1', a) === hash('reploid.canonical-wire-value/v1', b);
22
+ const binding = request => {
23
+ assert(equal(request.identity, canonicalPartitionBinding(request.identity)), 'Unknown canonical identity fields');
24
+ assert(request.schema === SCHEMA && request.identity.modelId === plan.modelId && request.identity.modelIdentity === modelIdentity
25
+ && request.identity.planId === planId, 'Canonical wire model/plan mismatch');
26
+ const attempt = runtime.validateResidentAttemptIdentity(request.canonicalAttempt);
27
+ assert(attempt.routeKind === 'two-stage-layer' && attempt.attemptId === request.identity.attemptId
28
+ && attempt.requesterId === request.identity.requesterId && attempt.generationId === request.generationId
29
+ && attempt.stages[0].participantId === request.identity.participantA && attempt.stages[1].participantId === request.identity.participantB,
30
+ 'Canonical wire attempt mismatch');
31
+ assert(equal(attempt, request.grant.claim.canonicalAttempt) && request.grant.claim.vocabSize === plan.vocabSize
32
+ && request.grant.claim.generation.generationId === attempt.generationId, 'Canonical wire grant binding mismatch');
33
+ assert(Number.isSafeInteger(request.sequence) && request.sequence >= 0 && request.step === request.sequence,
34
+ 'Canonical wire sequence mismatch');
35
+ return attempt;
36
+ };
37
+ const activationHeader = (request, byteLength, payloadDigest) => {
38
+ const attempt = binding(request);
39
+ assert(Number.isSafeInteger(request.tokenPosition) && request.tokenPosition >= 0
40
+ && Number.isSafeInteger(request.inputTokenCount) && request.inputTokenCount > 0
41
+ && Array.isArray(request.inputTokenIds) && request.inputTokenIds.length === request.inputTokenCount,
42
+ 'Canonical token row mismatch');
43
+ const inputDigest = runtime.tokenDigest(request.inputTokenIds, plan.vocabSize, request.grant.claim.limits.maxPromptTokens);
44
+ let tokenContextDigest = inputDigest;
45
+ if (request.sequence === 0) assert(request.baseCursor === null && request.baseCursorId === null && request.tokenPosition === 0 && attempt.inputDigest === inputDigest,
46
+ 'Canonical bootstrap parent mismatch');
47
+ else {
48
+ const cursor = runtime.validateResidentCursor(request.baseCursor, request.grant.claim.generation.policy, plan.vocabSize);
49
+ assert(cursor.cursorId === request.baseCursorId && cursor.generationId === attempt.generationId && !cursor.terminal
50
+ && cursor.revision + 1 === request.sequence && cursor.materializedTokenCount === request.tokenPosition
51
+ && request.inputTokenCount === 1 && request.inputTokenIds[0] === cursor.pendingTokenId, 'Canonical decode parent mismatch');
52
+ tokenContextDigest = cursor.acceptedTokenDigest;
53
+ }
54
+ const expectedBytes = request.inputTokenCount * plan.hiddenSize * layout.elementStrideBytes;
55
+ assert(Number.isSafeInteger(expectedBytes) && byteLength === expectedBytes
56
+ && byteLength <= request.grant.claim.limits.maxActivationBytes && /^sha256:[a-f0-9]{64}$/.test(payloadDigest),
57
+ 'Canonical activation byte bound mismatch');
58
+ return { schema: 'doppler.ordinary-activation/v1', attemptDigest: runtime.residentAttemptDigest(attempt),
59
+ sequence: request.sequence, baseCursorId: request.baseCursorId, proposalId: null,
60
+ sourceStageId: attempt.stages[0].stageId, destinationStageId: attempt.stages[1].stageId,
61
+ rows: { start: request.tokenPosition, end: request.tokenPosition + request.inputTokenCount }, tokenContextDigest,
62
+ layout: { dtype: layout.dtype, precision: layout.precision, components: layout.components,
63
+ elementStrideBytes: layout.elementStrideBytes, hiddenSize: plan.hiddenSize, byteOrder: 'little-endian' },
64
+ payloadBytes: byteLength, payloadDigest };
65
+ };
66
+ const validateHeader = (request, byteLength) => {
67
+ try {
68
+ hash(SCHEMA, request); exact(request, [...stepKeys, 'frame']);
69
+ const frame = request.frame;
70
+ exact(frame.metadata, ['identity', 'activation']);
71
+ assert(samePartitionIdentity(frame.metadata.identity, request.identity)
72
+ && equal(frame.metadata.identity, canonicalPartitionBinding(request.identity)), 'Canonical frame identity mismatch');
73
+ assert(request.phase === 'step' && request.operation === 'step' && frame.schema === layout.schema
74
+ && matchingPartitionActivation(frame, layout, true) && frame.step === request.step && frame.seqOffset === request.tokenPosition
75
+ && equal(frame.shape, [1, request.inputTokenCount, plan.hiddenSize]) && frame.byteLength === byteLength,
76
+ 'Canonical tensor header mismatch');
77
+ return equal(frame.metadata.activation, activationHeader(request, byteLength, frame.metadata.activation.payloadDigest));
78
+ } catch { return false; }
79
+ };
80
+ return Object.freeze({
81
+ schema: SCHEMA, validateBinding: binding, validateHeader,
82
+ validateControl(request) {
83
+ try {
84
+ hash(SCHEMA, request); const attempt = binding(request);
85
+ if (request.operation === 'settle') {
86
+ exact(request, ['schema', 'operation', 'identity', 'canonicalAttempt', 'generationId', 'sequence', 'step', 'grant']);
87
+ return true;
88
+ }
89
+ if (request.operation === 'published') {
90
+ exact(request, [...stepKeys, 'publication', 'receipt', 'commits']);
91
+ return request.phase === 'published';
92
+ }
93
+ exact(request, stepKeys);
94
+ return ['reserve', 'admit'].includes(request.operation) && request.phase === 'admit'
95
+ && request.sequence === 0 && request.tokenPosition === 0 && request.baseCursor === null && request.baseCursorId === null
96
+ && request.inputTokenIds?.length === request.inputTokenCount
97
+ && runtime.tokenDigest(request.inputTokenIds, plan.vocabSize, request.grant.claim.limits.maxPromptTokens) === attempt.inputDigest;
98
+ } catch { return false; }
99
+ },
100
+ async fingerprint(request) {
101
+ const { payload = new Uint8Array(), ...metadata } = structuredClone(request);
102
+ assert(payload instanceof Uint8Array, 'Canonical payload bytes required');
103
+ return hash('reploid.canonical-partition-request-digest/v1', { metadata,
104
+ payloadBytes: payload.byteLength, payloadDigest: await sha256Hex(payload) });
105
+ },
106
+ async serializeActivation(request) {
107
+ const { activationTensor: source, ...metadata } = request;
108
+ hash(SCHEMA, metadata);
109
+ assert(source?.data?.byteLength <= request.grant.claim.limits.maxActivationBytes, 'Canonical activation exceeds grant');
110
+ const { activationTensor, ...control } = structuredClone(request);
111
+ request = control;
112
+ assert(activationTensor?.data?.byteLength <= request.grant.claim.limits.maxActivationBytes, 'Canonical activation exceeds grant');
113
+ const frame = { ...runtime.serializeActivationFrame({ ...activationTensor, metadata: {} }) };
114
+ const payload = new Uint8Array(frame.buffer);
115
+ frame.metadata = { identity: canonicalPartitionBinding(request.identity),
116
+ activation: activationHeader(request, payload.byteLength, await sha256Hex(payload)) };
117
+ const { buffer, ...header } = frame;
118
+ assert(validateHeader({ ...request, frame: header }, payload.byteLength), 'Canonical serialized header mismatch');
119
+ runtime.validateOrdinaryActivation(frame.metadata.activation, payload,
120
+ { maxRows: request.grant.claim.limits.maxPromptTokens, maxBytes: request.grant.claim.limits.maxActivationBytes });
121
+ runtime.validateActivationFrameForPlan(frame, plan);
122
+ return frame;
123
+ },
124
+ validatePayload(request, payload) {
125
+ const { payload: _receivedBytes, ...metadata } = request;
126
+ request = metadata;
127
+ assert(validateHeader(request, payload.byteLength), 'Canonical activation header rejected');
128
+ const validated = runtime.validateOrdinaryActivation(request.frame.metadata.activation, payload,
129
+ { maxRows: request.grant.claim.limits.maxPromptTokens, maxBytes: request.grant.claim.limits.maxActivationBytes });
130
+ return runtime.validateActivationFrameForPlan({ ...request.frame, buffer: validated.bytes.buffer }, plan);
131
+ },
132
+ async verifyPublication(request, retained) {
133
+ try {
134
+ hash('reploid.canonical-publication-ack/v1', { request, retained });
135
+ request = structuredClone(request); retained = structuredClone(retained);
136
+ exact(request, [...stepKeys, 'publication', 'receipt', 'commits']);
137
+ assert(request.operation === 'published' && request.phase === 'published', 'Publication phase mismatch');
138
+ const attempt = binding(request), { publication, receipt, commits } = request;
139
+ assert(publication.sequence === request.sequence, 'Publication acknowledgment sequence mismatch');
140
+ if (publication.schema === 'doppler.admission-publication/v1') {
141
+ runtime.validateAdmissionPublication(publication, attempt, request.grant.claim.generation.policy, plan.vocabSize);
142
+ assert(equal(publication.result, retained) && Array.isArray(commits) && commits.length === 0, 'Admission publication mismatch');
143
+ } else {
144
+ runtime.validateExecutionPublication(publication, attempt, request.grant.claim.generation.policy, plan.vocabSize, request.baseCursor);
145
+ assert(Array.isArray(commits) && commits.length === attempt.stages.length, 'Publication evidence cardinality mismatch');
146
+ assert(new Set(commits.map(commit => commit.acknowledgment.stageId)).size === commits.length, 'Duplicate publication evidence');
147
+ for (const stage of attempt.stages) {
148
+ const commit = commits.find(item => item.acknowledgment.stageId === stage.stageId);
149
+ const acknowledgment = publication.acknowledgments.find(item => item.stageId === stage.stageId);
150
+ assert(commit && equal(commit.acknowledgment, acknowledgment)
151
+ && await verifyPartitionStageCommit({ runtime, attempt, stage, ...commit,
152
+ transition: retained.transition, sequence: request.sequence, baseCursorId: request.baseCursorId }),
153
+ 'Publication stage evidence mismatch');
154
+ }
155
+ assert(equal(retained.commit, commits.find(item => item.acknowledgment.stageId === attempt.stages[1].stageId)), 'Publication differs from retained output-stage result');
156
+ }
157
+ exact(receipt, ['schema', 'conversationId', 'writerEpoch', 'index', 'coordinatorEpoch', 'attemptId', 'sequence', 'publicationDigest', 'receiptDigest']);
158
+ const { receiptDigest, ...body } = receipt;
159
+ return body.schema === PUBLICATION_RECEIPT_SCHEMA && body.conversationId === request.identity.threadId
160
+ && body.writerEpoch === attempt.publisherEpoch && body.coordinatorEpoch === attempt.coordinatorEpoch
161
+ && body.attemptId === attempt.attemptId && body.sequence === request.sequence
162
+ && body.publicationDigest === publication.publicationDigest && Number.isSafeInteger(body.index) && body.index >= 0
163
+ && receiptDigest === hash(body.schema, body);
164
+ } catch { return false; }
165
+ },
166
+ });
167
+ }
@@ -0,0 +1,168 @@
1
+ import { createCanonicalPartitionContract } from './partition-canonical-contract.js';
2
+ import { verifyPartitionStageCommit } from './partition-stage-commit.js';
3
+ import { assertPartition as assert } from './partition-contract.js';
4
+
5
+ /** One ordinary canonical attempt, inside the existing runner's allocation,
6
+ * FIFO lease and settlement owner. No scheduler, sampler or recovery loop. */
7
+ export async function executeCanonicalPartition({ runtime, plan, deviceA, deviceB, policy, binding, authority,
8
+ canonical, tokenIds, signal, lease, permit, onDelta, receipt, ownDevice }) {
9
+ assert(runtime.hashLayerPartitionPlan(plan) === binding.planId, 'Canonical selected plan identity mismatch');
10
+ const publicationOwner = canonical.publication;
11
+ assert(publicationOwner?.requiresCommitEvidence === true
12
+ && ['admitAttempt', 'publish', 'reconcile', 'cancel'].every(name => typeof publicationOwner[name] === 'function'),
13
+ 'Canonical execution requires durable authenticated publication');
14
+ const hash = (domain, value) => runtime.metadataDigest(domain, value);
15
+ const same = (a, b) => hash('reploid.canonical-execution-value/v1', a) === hash('reploid.canonical-execution-value/v1', b);
16
+ hash('reploid.canonical-execution-input/v1', { attempt: canonical.attempt, generation: canonical.generation,
17
+ deadlineAt: canonical.deadlineAt });
18
+ const { attempt: selected, generation: supplied, deadlineAt } = structuredClone({ attempt: canonical.attempt,
19
+ generation: canonical.generation, deadlineAt: canonical.deadlineAt });
20
+ const attempt = runtime.validateResidentAttemptIdentity(selected);
21
+ const generation = runtime.canonicalGenerationIdentity(supplied.policy, supplied.executionIdentity, plan.vocabSize);
22
+ assert(same(generation, supplied) && attempt.generationId === generation.generationId
23
+ && attempt.attemptId === binding.attemptId && attempt.requesterId === binding.requesterId
24
+ && attempt.routeKind === 'two-stage-layer' && attempt.stages.length === 2
25
+ && attempt.inputDigest === runtime.tokenDigest(tokenIds, plan.vocabSize, policy.maxPromptTokens),
26
+ 'Canonical attempt or effective prompt mismatch');
27
+ assert(generation.policy.maxGeneratedTokens <= policy.maxTokens
28
+ && generation.policy.maxVisibleOutputUtf16 <= policy.maxOutputCharacters
29
+ && Number.isSafeInteger(deadlineAt) && deadlineAt > Date.now(), 'Canonical allocation or deadline mismatch');
30
+ for (const [index, device] of [deviceA, deviceB].entries()) {
31
+ assert(same(device.getCanonicalGeneration(), generation) && same(device.getCanonicalStage(), attempt.stages[index])
32
+ && device.id === attempt.stages[index].participantId, 'Canonical resident generation or stage changed');
33
+ }
34
+ const contract = createCanonicalPartitionContract({ runtime, plan, planId: binding.planId, modelIdentity: binding.modelIdentity });
35
+ const expectedAdmission = runtime.admitResidentPrompt(tokenIds, generation.policy, plan.vocabSize, generation.generationId);
36
+ let cursor = null, previous = null, continuationA = null, continuationB = null, admitted = false, cancellation = null;
37
+ let content = '', activationBytes = 0, input = [...tokenIds], position = 0, stopReason = null;
38
+ const tokens = [], steps = [], publications = [];
39
+ const cancel = () => {
40
+ if (!cancellation && admitted) cancellation = publicationOwner.cancel(attempt.attemptId, attempt.coordinatorEpoch)
41
+ .then(() => null, error => error);
42
+ return cancellation;
43
+ };
44
+ const wire = (sequence, phase = 'step') => ({ schema: contract.schema, operation: phase === 'admit' ? 'admit' : 'step', phase,
45
+ identity: binding, canonicalAttempt: attempt, generationId: generation.generationId, sequence, step: sequence,
46
+ tokenPosition: position, inputTokenCount: input.length, inputTokenIds: [...input], baseCursorId: cursor?.cursorId ?? null,
47
+ baseCursor: cursor, grant: authority.executionB, continuation: continuationB });
48
+ const authorize = async request => {
49
+ for (const [action, name] of [['mesh.execute_partition_a', 'executionA'], ['mesh.execute_partition_b', 'executionB'],
50
+ ['mesh.transfer_intermediate_activation', 'activation'], ['mesh.transfer_token_context', 'tokenContext'],
51
+ ['mesh.transfer_partition_output', 'output']]) {
52
+ await permit(action, authority[name], { step: request.step, sequence: request.sequence, phase: request.phase,
53
+ tokenPosition: request.tokenPosition, inputTokenCount: request.inputTokenCount,
54
+ maxTokens: generation.policy.maxGeneratedTokens, canonicalAttempt: attempt, generationId: generation.generationId });
55
+ }
56
+ };
57
+ const publish = async (request, body, commits) => {
58
+ const publication = { ...body, publicationDigest: hash(body.schema, body) };
59
+ await authorize(request);
60
+ const saved = await publicationOwner.publish(publication, { evidence: commits.map(c => c.evidence) });
61
+ publications.push({ publication, receipt: saved, commits });
62
+ // A transaction receipt is not an ephemeral peer acknowledgment. No next
63
+ // step or UI delivery occurs until the retained B result accepts this one.
64
+ await deviceB.acknowledgeCanonicalPublication({ ...request, publication, receipt: saved, commits, signal });
65
+ previous = publication.publicationDigest;
66
+ return saved;
67
+ };
68
+ try {
69
+ signal.throwIfAborted();
70
+ const request = wire(0, 'admit');
71
+ contract.validateBinding(request);
72
+ await authorize(request);
73
+ const state = await publicationOwner.reconcile(); previous = state.head;
74
+ assert(Array.isArray(state.attempts) && !state.attempts.some(item => item.identity.attemptId === attempt.attemptId
75
+ && item.identity.coordinatorEpoch === attempt.coordinatorEpoch), 'Canonical attempt was already admitted; retries require a fresh identity');
76
+ await publicationOwner.admitAttempt({ identity: attempt, generationPolicy: generation.policy,
77
+ executionIdentity: generation.executionIdentity, vocabSize: plan.vocabSize, deadlineAt });
78
+ admitted = true; signal.addEventListener('abort', cancel, { once: true }); signal.throwIfAborted();
79
+ await authorize(request);
80
+ ownDevice(deviceA.id);
81
+ receipt.reservations.push(structuredClone(await deviceA.reserve(binding)));
82
+ ownDevice(deviceB.id);
83
+ const reserved = await deviceB.reserveCanonical({ ...request, signal });
84
+ receipt.reservations.push(structuredClone(reserved.reservation));
85
+ await lease(async () => {
86
+ await authorize(request);
87
+ const a = await deviceA.admitCanonicalPrompt({ identity: binding, tokenIds: [...tokenIds], generationId: generation.generationId, signal });
88
+ const b = await deviceB.admitCanonicalPrompt({ ...request, signal });
89
+ assert(same(a, expectedAdmission) && same(b, expectedAdmission), 'Canonical participant prompt admission differs');
90
+ });
91
+ if (!('kind' in expectedAdmission)) {
92
+ await publish(request, { schema: 'doppler.admission-publication/v1', attemptId: attempt.attemptId,
93
+ coordinatorEpoch: attempt.coordinatorEpoch, attemptDigest: runtime.residentAttemptDigest(attempt), sequence: 0,
94
+ expectedRevision: null, previousPublicationDigest: previous, result: expectedAdmission }, []);
95
+ stopReason = expectedAdmission.stopReason;
96
+ } else {
97
+ for (let sequence = 0; sequence < generation.policy.maxGeneratedTokens; sequence++) {
98
+ const queuedAt = performance.now();
99
+ const delivery = await lease(async () => {
100
+ const started = performance.now(), request = wire(sequence);
101
+ const leaseWaitMs = started - queuedAt;
102
+ await authorize(request);
103
+ const a = structuredClone(await deviceA.executeCanonicalGroup0({ identity: binding, canonicalAttempt: attempt,
104
+ tokenIds: [...input], continuation: continuationA, generationId: generation.generationId,
105
+ baseCursorId: request.baseCursorId, sequence, step: sequence, tokenPosition: position,
106
+ inputTokenCount: input.length, executionGrant: authority.executionA, signal }));
107
+ signal.throwIfAborted();
108
+ const frame = await contract.serializeActivation({ ...request, activationTensor: a.activationTensor });
109
+ assert(frame.byteLength <= policy.maxActivationBytes, 'Canonical activation exceeds allocation');
110
+ await authorize(request);
111
+ const b = structuredClone(await deviceB.executeCanonicalFrame({ ...request, frame, signal }));
112
+ signal.throwIfAborted();
113
+ assert(b && same(b.identity, binding) && b.step === sequence && b.tokenPosition === position
114
+ && await verifyPartitionStageCommit({ runtime, attempt, stage: attempt.stages[1], ...b.commit,
115
+ transition: b.transition, sequence, baseCursorId: request.baseCursorId }), 'Unauthenticated canonical output decision');
116
+ await authorize(request);
117
+ const committed = structuredClone(await deviceA.commitCanonicalTransition({ identity: binding, canonicalAttempt: attempt,
118
+ generationId: generation.generationId, sequence, baseCursorId: request.baseCursorId,
119
+ transition: b.transition, targetCommit: b.commit, signal }));
120
+ assert(same(committed.transition, b.transition) && await verifyPartitionStageCommit({ runtime, attempt,
121
+ stage: attempt.stages[0], ...committed.commit, transition: b.transition, sequence, baseCursorId: request.baseCursorId }),
122
+ 'Canonical input stage did not commit the authenticated decision');
123
+ const transition = committed.transition;
124
+ assert(transition.acceptedTokenIds.length === 1 && typeof transition.delta === 'string'
125
+ && content.length + transition.delta.length <= policy.maxOutputCharacters, 'Canonical ordinary result exceeds allocation');
126
+ const body = { schema: 'doppler.execution-publication/v2', attemptId: attempt.attemptId,
127
+ coordinatorEpoch: attempt.coordinatorEpoch, attemptDigest: runtime.residentAttemptDigest(attempt), sequence,
128
+ expectedRevision: cursor?.revision ?? null, previousPublicationDigest: previous, baseCursorId: request.baseCursorId,
129
+ decisionId: committed.commit.acknowledgment.decisionId, acceptedTokenIds: transition.acceptedTokenIds,
130
+ tokenRange: transition.tokenRange, successor: transition.successor,
131
+ delta: { text: transition.delta, outputDigest: transition.outputDigest }, stoppingOutcome: transition.successor.stopReason,
132
+ acknowledgments: [committed.commit.acknowledgment, b.commit.acknowledgment] };
133
+ const value = { ...body, publicationDigest: hash(body.schema, body) };
134
+ runtime.validateExecutionPublication(value, attempt, generation.policy, plan.vocabSize, cursor);
135
+ return { request, body, commits: [committed.commit, b.commit], transition,
136
+ continuationA: a.continuation, continuationB: b.continuation, bytes: frame.byteLength,
137
+ leaseWaitMs, elapsedMs: performance.now() - started };
138
+ });
139
+ // Durable storage and remote acknowledgment retain this attempt's parent
140
+ // barrier, but must not hold another conversation's numerical lease.
141
+ await publish(delivery.request, delivery.body, delivery.commits);
142
+ cursor = delivery.transition.successor;
143
+ continuationA = delivery.continuationA; continuationB = delivery.continuationB;
144
+ tokens.push(...delivery.transition.acceptedTokenIds); content += delivery.transition.delta;
145
+ activationBytes += delivery.bytes;
146
+ steps.push({ sequence, step: sequence, tokenPosition: position, inputTokenCount: input.length,
147
+ tokenId: delivery.transition.acceptedTokenIds[0], activationBytes: delivery.bytes, leaseWaitMs: delivery.leaseWaitMs,
148
+ elapsedMs: delivery.elapsedMs, outputDeliveryMs: 0 });
149
+ position = cursor.materializedTokenCount; input = [cursor.pendingTokenId]; stopReason = cursor.stopReason;
150
+ signal.throwIfAborted();
151
+ if (delivery.transition.delta) {
152
+ const started = performance.now();
153
+ try { await onDelta(delivery.transition.delta); } finally { steps.at(-1).outputDeliveryMs = performance.now() - started; }
154
+ }
155
+ signal.throwIfAborted();
156
+ if (cursor.terminal) break;
157
+ }
158
+ assert(cursor?.terminal, 'Canonical generation did not reach its declared stopping outcome');
159
+ }
160
+ return { content, tokenIds: tokens, logits: null, stopReason,
161
+ execution: { schema: 'reploid.mesh.canonical-partition-execution/v1', ...binding, canonicalAttempt: attempt,
162
+ placement: 'two-device-layer-partition', splitLayer: plan.splitLayer, activationBytes, steps, publications, settlement: receipt } };
163
+ } catch (error) {
164
+ const cancellationError = await cancel();
165
+ if (cancellationError) throw new AggregateError([error, cancellationError], 'Canonical execution and publication settlement failed');
166
+ throw error;
167
+ } finally { signal.removeEventListener('abort', cancel); }
168
+ }
@@ -0,0 +1,49 @@
1
+ import { assertPartition as assert, canonicalPartitionJson } from './partition-contract.js';
2
+ import { validateEntryPublicationContext } from './partition-entry-publication.js';
3
+
4
+ /** Fixed two-stage chat composition. Actual residents supply generation/stages;
5
+ * Doppler and the existing grant owner supply attempt and disclosure identities. */
6
+ export function createCanonicalChatBinding({ runtime, local, remote, authority, model, plan, planId, limits, coordinatorEpoch }) {
7
+ assert(/^[a-f0-9]{32}$/.test(coordinatorEpoch) && ['metadataDigest', 'canonicalGenerationIdentity',
8
+ 'validateResidentAttemptIdentity', 'tokenDigest', 'hashLayerPartitionPlan'].every(name => typeof runtime[name] === 'function')
9
+ && ['canonicalScope', 'issueCanonical'].every(name => typeof authority[name] === 'function')
10
+ && [local, remote].every(device => ['getCanonicalStage', 'getCanonicalGeneration'].every(name => typeof device[name] === 'function')),
11
+ 'Canonical chat requires declared runtime, grant and resident capabilities');
12
+ assert(runtime.hashLayerPartitionPlan(plan) === planId, 'Canonical chat plan mismatch');
13
+ const same = (a, b) => canonicalPartitionJson(a) === canonicalPartitionJson(b);
14
+ const grantLimits = Object.fromEntries(['maxTokens', 'maxPromptTokens', 'maxActivationBytes', 'maxOutputCharacters']
15
+ .map(key => [key, limits[key]]));
16
+ const describe = () => {
17
+ const supplied = local.getCanonicalGeneration(), target = remote.getCanonicalGeneration();
18
+ const stages = [local.getCanonicalStage(), remote.getCanonicalStage()];
19
+ if (!supplied || !target || stages.some(stage => !stage)) return null;
20
+ const generation = runtime.canonicalGenerationIdentity(supplied.policy, supplied.executionIdentity, plan.vocabSize);
21
+ assert(same(generation, supplied) && same(generation, target), 'Canonical stages use different generation contracts');
22
+ assert(generation.policy.maxGeneratedTokens <= limits.maxTokens
23
+ && generation.policy.maxVisibleOutputUtf16 <= limits.maxOutputCharacters, 'Canonical generation exceeds chat allocation');
24
+ const routeId = runtime.metadataDigest('reploid.canonical-chat-route/v1', { meshId: authority.meshId,
25
+ modelId: model.id, modelIdentity: model.identity, planId, coordinatorEpoch, stages, generationId: generation.generationId });
26
+ return { coordinatorEpoch, routeId, stages, generation, vocabSize: plan.vocabSize };
27
+ };
28
+ const check = (context, binding, publication) => {
29
+ validateEntryPublicationContext(context, binding);
30
+ const current = describe();
31
+ assert(current && Object.keys(current).every(key => same(current[key], context[key])), 'Canonical chat placement or generation changed');
32
+ assert(context.deadlineAt > Date.now() && publication?.requiresCommitEvidence === true
33
+ && ['reconcile', 'admitAttempt', 'publish', 'cancel'].every(name => typeof publication[name] === 'function'),
34
+ 'Canonical requester publication or deadline unavailable');
35
+ return structuredClone(context);
36
+ };
37
+ return Object.freeze({ describe, check,
38
+ attempt({ context, binding, publication, tokenIds }) {
39
+ context = check(context, binding, publication);
40
+ return runtime.validateResidentAttemptIdentity({ schema: 'doppler.resident-attempt/v2', attemptId: binding.attemptId,
41
+ requesterId: binding.requesterId, inputDigest: runtime.tokenDigest(tokenIds, plan.vocabSize, limits.maxPromptTokens),
42
+ authorizationScope: authority.canonicalScope({ identity: binding, limits: grantLimits,
43
+ disclosure: 'partition-activations-and-tokens', generationId: context.generation.generationId }),
44
+ routeId: context.routeId, generationId: context.generation.generationId, coordinatorEpoch, publisherEpoch: context.publisherEpoch,
45
+ routeKind: 'two-stage-layer', stages: context.stages });
46
+ },
47
+ grantLimits: Object.freeze(grantLimits),
48
+ });
49
+ }
@@ -0,0 +1,125 @@
1
+ import { partitionAdapterIdentities, samePartitionAdapters } from './partition-contract.js';
2
+ import { TEXT_GENERATION_CAPABILITY, requireGenerationCapability, boundedGeneration, tokenUsage } from './partition-generation-request.js';
3
+ import { createOrderedPartitionChat } from './partition-ordered-chat.js';
4
+ import { createCanonicalChatBinding } from './partition-chat-canonical.js';
5
+ import { createLayerPartitionRunner } from './partition-runner.js';
6
+ import { assertPartition as assert, canonicalPartitionJson, canonicalPartitionBinding, partitionFingerprint } from './partition-contract.js';
7
+
8
+ /** Conversation adapter for a fixed, explicitly prepared local A and authenticated remote B. */
9
+ export function createPartitionChat({ runtime, local, remote, authority, model, plan, planId, limits, grantTtlMs, canonical = null, ordered = null, authorizeRequester = null, now = Date.now }) {
10
+ if (ordered !== null) {
11
+ assert(canonical === null, 'Ordered chat does not enable canonical decoding; it publishes through the requester-owned writer');
12
+ return createOrderedPartitionChat({ runtime, authority, model, plan, planId, limits, grantTtlMs, ordered, authorizeRequester, now });
13
+ }
14
+ assert(local.index === 0 && local.id === authority.participantId && remote.id !== local.id,
15
+ 'Partition chat requires the input owner at A and a distinct authenticated B');
16
+ assert(Number.isSafeInteger(grantTtlMs) && grantTtlMs > 0, 'Explicit partition grant lifetime required');
17
+ // Requesters select a prepared route; opening artifacts and execution policy
18
+ // remain with its contributor. Signed Capsule evidence can exceed the control
19
+ // frame budget and must not be copied into capability advertisements/history.
20
+ assert(canonicalPartitionJson(plan.adapterIdentities || []) === canonicalPartitionJson(partitionAdapterIdentities(model)), 'Partition plan adapter binding mismatch');
21
+ const selection = { id: model.id, name: model.name, identity: model.identity,
22
+ adapters: structuredClone(model.adapters || []), selectionId: model.id + '/partition/' + planId,
23
+ partition: { planId, participantA: local.id, participantB: remote.id } };
24
+ for (const key of ['provider', 'contextLength', 'quantization', 'size', 'recommended']) {
25
+ if (model[key] !== undefined) selection[key] = structuredClone(model[key]);
26
+ }
27
+ const policy = structuredClone(limits);
28
+ const canonicalBinding = canonical === null ? null : createCanonicalChatBinding({ runtime, local, remote, authority,
29
+ model, plan, planId, limits: policy, coordinatorEpoch: canonical.coordinatorEpoch });
30
+ const listeners = new Set();
31
+ let closed = false;
32
+ const models = () => {
33
+ const description = canonicalBinding?.describe() ?? null;
34
+ return [{ ...structuredClone(selection), ...(canonicalBinding ? {} : {textGeneration: TEXT_GENERATION_CAPABILITY}), ...(description ? { canonical: description } : {}),
35
+ availability: closed || canonicalBinding && !description ? 'unavailable' : local.getState().ready && remote.getState().ready ? 'ready'
36
+ : local.getState().phase === 'loading' ? 'loading' : 'unavailable',
37
+ providerIds: [local.id, remote.id], placement: 'two-device-layer-partition' }];
38
+ };
39
+ const notify = () => { for (const listener of listeners) { try { listener(models()); } catch {} } };
40
+ const unsubscribers = [local.subscribe(notify), remote.subscribe(notify)];
41
+ const runner = createLayerPartitionRunner({ runtime, plan, deviceA: local, deviceB: remote, limits: policy, canonical: canonicalBinding !== null,
42
+ authorize: request => (local.canAccept ? local.canAccept(request) : local.getState().ready)
43
+ ? authority.verify(request.grant, canonicalBinding ? { identity: canonicalPartitionBinding(request), action: request.action,
44
+ canonicalAttempt: request.canonicalAttempt, generationId: request.generationId, phase: request.phase,
45
+ step: request.step, inputTokenCount: request.inputTokenCount } : { ...request, identity: request }) : Promise.resolve(false) });
46
+ return Object.freeze({
47
+ getModels: models,
48
+ getState: () => runner.getState(),
49
+ subscribe(listener) { listeners.add(listener); listener(models()); return () => listeners.delete(listener); },
50
+ async refresh(options) { await remote.refresh(options); notify(); return models(); },
51
+ async generate(request, controls) {
52
+ // Keep caller-owned request metadata stable through approval and tokenization.
53
+ request = structuredClone(request);
54
+ const requested = requireGenerationCapability(models()[0], request.generationRequest, !!canonicalBinding);
55
+ assert(!requested || requested.maxOutputTokens <= policy.maxTokens, 'Caller token limit exceeds route budget');
56
+ const delegated = request.participantId !== local.id;
57
+ assert(!!canonicalBinding === (request.canonical !== undefined), 'Explicit canonical chat context required');
58
+ assert(!closed && request.meshId === authority.meshId && request.model.id === selection.id
59
+ && request.model.identity === selection.identity && samePartitionAdapters(request.model, selection)
60
+ && request.model.partition && canonicalPartitionJson(request.model.partition) === canonicalPartitionJson(selection.partition), 'Partition chat selection mismatch');
61
+ if (delegated) assert(typeof authorizeRequester === 'function'
62
+ && await authorizeRequester(request, controls.signal) === true
63
+ && Number.isSafeInteger(request.placementGeneration) && request.placementGeneration >= 0,
64
+ 'Remote input owner must authorize this execution placement');
65
+ assert(request.permissions?.sharingScope && request.permissions.sharingScope !== 'local', 'Partition disclosure is disabled');
66
+ controls.signal.throwIfAborted();
67
+ await remote.refresh({ signal: controls.signal });
68
+ assert(models()[0].availability === 'ready', 'No ready contributors for this partition plan');
69
+ const identity = { ...selection.partition, modelId: selection.id, modelIdentity: selection.identity,
70
+ threadId: request.threadId, attemptId: request.attemptId,
71
+ ...(delegated || canonicalBinding ? { requesterId: request.participantId, placementGeneration: request.placementGeneration ?? 0 } : {}) };
72
+ const context = canonicalBinding?.check(request.canonical, identity, controls.publication);
73
+ const approved = await controls.requestApproval({ id: crypto.randomUUID(), threadId: request.threadId,
74
+ attemptId: request.attemptId, peerId: remote.id, recipientIdentity: remote.id,
75
+ modelId: selection.id, modelIdentity: selection.identity, adapterIdentities: partitionAdapterIdentities(selection),
76
+ operation: 'generate-partition', disclosure: 'partition-activations-and-tokens', ...selection.partition,
77
+ expiresAt: now() + grantTtlMs,
78
+ input: { messages: structuredClone(request.messages), ...(requested ? {generationRequest: requested} : {}),
79
+ disclosure: 'Intermediate model activations and prompt token context are disclosed to the selected participant for sampling.' } });
80
+ controls.signal.throwIfAborted();
81
+ assert(approved === true, 'Partition disclosure was declined');
82
+ assert(!closed, 'Partition chat closed during approval');
83
+ let grant = null;
84
+ let sequence = 0;
85
+ try {
86
+ const input = await local.tokenize({ messages: request.messages, identity, signal: controls.signal });
87
+ controls.signal.throwIfAborted();
88
+ assert(!closed, 'Partition chat closed during tokenization');
89
+ assert(input.modelIdentity === selection.identity, 'Doppler tokenization model mismatch');
90
+ if (!canonicalBinding) assert(input.generation
91
+ && Number.isSafeInteger(input.generation.maxTokens) && input.generation.maxTokens > 0
92
+ && input.generation.maxTokens <= policy.maxTokens, 'Doppler tokenization or generation contract mismatch');
93
+ const generation = boundedGeneration(input.generation, requested);
94
+ if (requested) {
95
+ await controls.onUsage?.({threadId: request.threadId, attemptId: request.attemptId, ...tokenUsage(input.tokenIds.length, 0, requested)});
96
+ controls.signal.throwIfAborted();
97
+ }
98
+ const attempt = canonicalBinding?.attempt({ context, binding: identity, publication: controls.publication, tokenIds: input.tokenIds });
99
+ grant = canonicalBinding
100
+ ? await authority.issueCanonical(identity, canonicalBinding.grantLimits, { approved: true, ttlMs: grantTtlMs,
101
+ disclosure: 'partition-activations-and-tokens', generation: context.generation, canonicalAttempt: attempt, vocabSize: plan.vocabSize })
102
+ : await authority.issue(identity, policy, { approved: true, ttlMs: grantTtlMs,
103
+ disclosure: 'partition-activations-and-tokens', generationDigest: await partitionFingerprint(generation) });
104
+ controls.onState({ threadId: request.threadId, attemptId: request.attemptId, status: 'executing',
105
+ execution: { placement: 'two-device-layer-partition', ...selection.partition } });
106
+ const run = { tokenIds: input.tokenIds, identity,
107
+ grants: { executionA: grant, executionB: grant, activation: grant, tokenContext: grant, output: grant }, signal: controls.signal,
108
+ onDelta: text => controls.onDelta({ threadId: request.threadId, attemptId: request.attemptId, sequence: sequence++, text }) };
109
+ const result = canonicalBinding
110
+ ? await runner.executeCanonical({ ...run, canonical: { attempt, generation: context.generation,
111
+ publication: controls.publication, deadlineAt: context.deadlineAt } })
112
+ : await runner.execute({ ...run, generation, maxTokens: generation.maxTokens });
113
+ return { threadId: request.threadId, attemptId: request.attemptId, modelId: result.execution.modelId,
114
+ modelIdentity: result.execution.modelIdentity, adapterIdentities: partitionAdapterIdentities(selection), content: result.content,
115
+ ...(requested ? {usage: tokenUsage(input.tokenIds.length, result.tokenIds.length, requested)} : {}),
116
+ execution: { ...result.execution, provider: 'peer', transport: remote.getState().receipt } };
117
+ } finally {
118
+ if (grant) authority.revoke(grant);
119
+ // Also settles tokenization failure before the runner acquired an attempt.
120
+ await local.closeAttempt({ identity });
121
+ }
122
+ },
123
+ async close() { closed = true; unsubscribers.forEach(unsubscribe => unsubscribe()); await runner.close(); listeners.clear(); }
124
+ });
125
+ }