dsh-ptc-plus 0.3.2 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +63 -80
- package/README.md +63 -80
- package/assets/ptc-plus-bindings-en.png +0 -0
- package/assets/ptc-plus-bindings-zh.png +0 -0
- package/assets/ptc-plus-repair-en.png +0 -0
- package/assets/ptc-plus-repair-zh.png +0 -0
- package/assets/ptc-plus-repl-workspace-en.png +0 -0
- package/assets/ptc-plus-repl-workspace-zh.png +0 -0
- package/assets/ptc-plus-settings-en.png +0 -0
- package/assets/ptc-plus-settings-zh.png +0 -0
- package/client.js +30827 -742
- package/compiler-amaro.cjs +5 -0
- package/compiler-amaro.cjs.map +6 -0
- package/compiler-asset-124f80c1bba92ff5fe79cfec6e8ad518f476de4a42514cae3919538887f510e8.txt +1 -0
- package/compiler-assets.json +3 -0
- package/compiler-core.cjs +556 -0
- package/compiler-core.cjs.map +6 -0
- package/compiler-platform.cjs +2 -0
- package/compiler-platform.cjs.map +6 -0
- package/compiler-typescript.cjs +388 -0
- package/compiler-typescript.cjs.map +6 -0
- package/docs/README.md +7 -0
- package/docs/adr/0004-declare-program-bindings-at-the-host.md +1 -1
- package/docs/adr/0006-rewrite-module-syntax-with-an-ast.md +5 -3
- package/docs/adr/0007-separate-worker-transport-from-session-semantics.md +1 -1
- package/docs/adr/0009-bound-expensive-acceptance-default.md +2 -0
- package/docs/adr/0010-session-log-derived-recovery-tips.md +59 -5
- package/docs/adr/0011-isolate-the-local-recovery-tip-provider.md +1 -1
- package/docs/adr/0012-preserve-mixed-destructuring-initialization.md +3 -1
- package/docs/adr/0013-isolate-repl-redeclaration-convenience.md +3 -1
- package/docs/adr/0014-persist-cell-rewrite-policy.md +6 -2
- package/docs/adr/0015-preserve-source-positions-through-rewrites.md +1 -1
- package/docs/adr/0016-archive-resolved-review-findings.md +1 -1
- package/docs/adr/0017-track-the-latest-dsh-public-surface.md +49 -0
- package/docs/adr/0018-use-versioned-fixture-for-ab-benchmark.md +3 -3
- package/docs/adr/0019-plugin-settings-and-kill-switch.md +5 -3
- package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +2 -2
- package/docs/adr/0021-separate-host-bootstrap-from-session-runtime.md +12 -0
- package/docs/adr/0023-global-user-bindings.md +104 -0
- package/docs/adr/0024-repl-console-observation.md +33 -0
- package/docs/adr/0025-use-versioned-logical-binding-identities.md +119 -0
- package/docs/adr/0026-persist-the-delivery-verdict-against-the-verified-candidate.md +21 -0
- package/docs/adr/0027-run-the-session-kernel-in-a-killable-helper-process.md +37 -0
- package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +103 -0
- package/docs/adr/0029-keep-plugin-unavailability-out-of-the-host-agent-lifecycle.md +27 -0
- package/docs/adr/0030-serve-both-typert-codec-generations-from-one-codec.md +27 -0
- package/docs/architecture.md +77 -21
- package/docs/binding-review-placement-design.md +200 -0
- package/docs/capability-projection.md +1 -1
- package/docs/client-ui.md +95 -19
- package/docs/durability-design.md +28 -10
- package/docs/evaluation.md +78 -6
- package/docs/installation.md +41 -6
- package/docs/publishing.md +5 -3
- package/docs/runtime-reference.md +76 -25
- package/docs/semantic-validation.md +29 -0
- package/docs/stateful-binding-updates-proposal.md +759 -0
- package/docs/user-bindings.en.md +66 -0
- package/docs/user-bindings.md +66 -0
- package/docs/value-wire.md +3 -3
- package/docs/verification-optimization-work.md +41 -0
- package/docs/verification.md +71 -0
- package/index.js +369 -92
- package/internal/ast-traversal.js +5 -2
- package/internal/async-local-storage-intrinsics.js +38 -0
- package/internal/binding-declaration-contract.js +8 -0
- package/internal/binding-descriptors.js +1 -0
- package/internal/binding-pattern-traversal.js +25 -0
- package/internal/binding-pattern.js +26 -29
- package/internal/binding-source-analysis.js +708 -0
- package/internal/binding-update-policy.js +72 -0
- package/internal/bounded-worker-round.js +56 -0
- package/internal/callable-definition-environment.js +42 -0
- package/internal/callable-source-catalog.js +129 -0
- package/internal/callable-source-encoding.js +47 -0
- package/internal/callable-source-facts.js +459 -0
- package/internal/callable-source-format.js +2 -0
- package/internal/callable-source-lowering.js +123 -0
- package/internal/cell-analysis-contract.js +25 -0
- package/internal/cell-analysis.js +253 -290
- package/internal/cell-completion.js +15 -0
- package/internal/cell-error.js +7 -0
- package/internal/cell-parser.js +66 -0
- package/internal/cell-rewriter.js +3 -677
- package/internal/commonjs-export-evidence.js +63 -0
- package/internal/commonjs-source-evidence.js +72 -0
- package/internal/compiler-amaro.cjs +2 -0
- package/internal/compiler-compression.js +12 -0
- package/internal/compiler-data.js +58 -0
- package/internal/compiler-descriptors.js +54 -0
- package/internal/compiler-dynamic-cache.js +48 -0
- package/internal/compiler-entry.js +35 -0
- package/internal/compiler-generated-names.js +17 -0
- package/internal/compiler-intrinsics.js +50 -0
- package/internal/compiler-module-links.js +37 -0
- package/internal/compiler-operations.js +61 -0
- package/internal/compiler-platform-factory.js +84 -0
- package/internal/compiler-platform.js +136 -0
- package/internal/compiler-record-roles.js +53 -0
- package/internal/compiler-region-output.js +259 -0
- package/internal/compiler-resource-lowering.js +103 -0
- package/internal/compiler-scope-facts.js +115 -0
- package/internal/compiler-service.js +109 -0
- package/internal/compiler-source-cache.js +32 -0
- package/internal/compiler-source-pieces.js +93 -0
- package/internal/compiler-source-regions.js +132 -0
- package/internal/compiler-storage-source.js +54 -0
- package/internal/compiler-text.js +15 -0
- package/internal/compiler-typescript.cjs +2 -0
- package/internal/config-spec.js +83 -27
- package/internal/cordis-tools-owner.js +130 -21
- package/internal/diagnostic.js +27 -1
- package/internal/direct-surface-owner.js +76 -23
- package/internal/dynamic-binding-evidence.js +16 -0
- package/internal/dynamic-environment-compiler.js +779 -0
- package/internal/dynamic-environment-integration.js +91 -0
- package/internal/dynamic-environment-runtime.js +383 -0
- package/internal/dynamic-native-calls.js +153 -0
- package/internal/dynamic-native-runtime.js +262 -0
- package/internal/dynamic-scope-analysis.js +90 -0
- package/internal/edit-transport-owner.js +27 -2
- package/internal/execution-seam-compat.js +193 -0
- package/internal/failure-reporting.js +136 -28
- package/internal/host-rpc.js +66 -0
- package/internal/isolated-worker.js +555 -0
- package/internal/kernel-child.js +139 -0
- package/internal/kernel-worker.js +1179 -233
- package/internal/language-semantics.js +14 -0
- package/internal/legacy-binding-catalog.js +48 -0
- package/internal/legacy-cell-analysis.js +600 -0
- package/internal/legacy-cell-parser.js +50 -0
- package/internal/legacy-cell-rewriter.js +631 -0
- package/internal/legacy-repl-convenience.js +291 -0
- package/internal/managed-module-operations.js +170 -0
- package/internal/module-compilation.js +322 -0
- package/internal/module-runtime-platform.js +19 -0
- package/internal/module-transform-contract.js +42 -0
- package/internal/native-await-declarations.js +68 -0
- package/internal/native-root-compilation.js +54 -0
- package/internal/native-root-dynamic.js +67 -0
- package/internal/record-utils.js +24 -15
- package/internal/recovery-tips.js +27 -15
- package/internal/rejected-cell-editor.js +13 -8
- package/internal/repl-convenience.js +2 -289
- package/internal/repl-memory-projection.js +81 -12
- package/internal/repl-observation-interest.js +70 -0
- package/internal/repl-rewrite-contract.js +6 -0
- package/internal/repl-scope-normalizer.js +2091 -0
- package/internal/repl-value-observer.js +117 -0
- package/internal/rpc-contract.js +52 -0
- package/internal/runtime-bridge-owner.js +172 -28
- package/internal/runtime-config.js +48 -52
- package/internal/runtime-contexts.js +82 -10
- package/internal/runtime-intrinsics.js +101 -0
- package/internal/runtime-messages.js +111 -0
- package/internal/session-cell-executor.js +402 -87
- package/internal/session-journal-recovery.js +684 -0
- package/internal/session-journal-schema.js +123 -0
- package/internal/session-journal.js +199 -654
- package/internal/session-log-view.js +42 -9
- package/internal/session-runtime.js +257 -95
- package/internal/session-state.js +247 -71
- package/internal/source-position-map.js +230 -71
- package/internal/stateful-module-compiler.js +154 -0
- package/internal/stateful-module-runtime.js +303 -0
- package/internal/stateful-root-compiler.js +600 -0
- package/internal/stateful-root-runtime.js +340 -0
- package/internal/typert-codec-compat.js +28 -0
- package/internal/typescript-transform.js +31 -0
- package/internal/user-binding-authoring.js +70 -0
- package/internal/user-binding-console-worker.js +244 -0
- package/internal/user-binding-console.js +148 -0
- package/internal/user-binding-draft-projection.js +335 -0
- package/internal/user-binding-model-context.js +31 -0
- package/internal/user-binding-runner.js +56 -0
- package/internal/user-bindings-owner.js +1065 -0
- package/internal/user-bindings-store.js +293 -0
- package/internal/user-bindings.js +361 -0
- package/internal/value-wire-schema.js +28 -0
- package/internal/value-wire.js +130 -91
- package/internal/worker-client.js +57 -67
- package/internal/worker-cwd-virtualization.js +80 -53
- package/internal/worker-environment.js +65 -0
- package/internal/worker-output-relay.js +29 -0
- package/internal/worker-repl-realm.js +134 -0
- package/internal/worker-shutdown.js +14 -0
- package/package.json +76 -7
- package/src/client-activity.js +95 -53
- package/src/client-authoring-view.js +580 -0
- package/src/client-binding-review.js +230 -0
- package/src/client-bindings-data.js +29 -0
- package/src/client-catalog.js +127 -0
- package/src/client-code-editor.js +84 -0
- package/src/client-console.js +112 -0
- package/src/client-copy.js +370 -0
- package/src/client-feature-gates.js +62 -0
- package/src/client-host-compat.js +150 -0
- package/src/client-indicator-view.js +267 -0
- package/src/client-repl-view.js +292 -0
- package/src/client-rpc.js +20 -0
- package/src/client-settings-view.js +221 -0
- package/src/client-styles.js +106 -0
- package/src/client-tool-view.js +108 -0
- package/src/client-transport.js +159 -0
- package/src/client-workbench.js +521 -0
- package/src/client.js +233 -615
|
@@ -2,12 +2,15 @@ import {
|
|
|
2
2
|
decodeValue,
|
|
3
3
|
encodeValue,
|
|
4
4
|
normalizeValueWire,
|
|
5
|
-
|
|
5
|
+
prepareValueWire,
|
|
6
6
|
valueWiresEqual,
|
|
7
7
|
} from './value-wire.js'
|
|
8
8
|
import { diagnostic, renderDiagnostic } from './diagnostic.js'
|
|
9
|
+
import { normalizeBindingDescriptors } from './binding-descriptors.js'
|
|
9
10
|
import {
|
|
10
11
|
firstLine,
|
|
12
|
+
cellPosition,
|
|
13
|
+
exceptionOriginPosition,
|
|
11
14
|
limitLogs,
|
|
12
15
|
LONG_CELL_CODE_UNITS,
|
|
13
16
|
markBindingFailure,
|
|
@@ -16,15 +19,22 @@ import {
|
|
|
16
19
|
oneLineMessage,
|
|
17
20
|
safeProperty,
|
|
18
21
|
} from './failure-reporting.js'
|
|
19
|
-
import { assertStateName } from './session-journal.js'
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
22
|
+
import { assertStateName, LIVE_USER_BINDINGS_REUSE_POLICY } from './session-journal.js'
|
|
23
|
+
import { LIVE_USER_BINDINGS_SHADOW_POLICY, normalizeUserBindingNames } from './session-journal-schema.js'
|
|
24
|
+
import { PreflightError, prepareProgram } from './compiler-service.js'
|
|
25
|
+
import { executionPolicies } from './binding-update-policy.js'
|
|
26
|
+
import { createReplMemorySnapshot } from './repl-memory-projection.js'
|
|
27
|
+
import { ModuleRewriteError } from './cell-error.js'
|
|
23
28
|
import { mapSourcePosition } from './source-position-map.js'
|
|
24
29
|
import { durabilityState, transitionDurability } from './session-state.js'
|
|
30
|
+
import { dynamicBindingOrigin } from './dynamic-binding-evidence.js'
|
|
25
31
|
import { validatedEofClosureRepair } from './validated-parse-repair.js'
|
|
32
|
+
import {
|
|
33
|
+
normalizeUserBindingsSnapshot,
|
|
34
|
+
selectUserBindingsSnapshot,
|
|
35
|
+
} from './user-bindings.js'
|
|
26
36
|
|
|
27
|
-
const OUTPUT_LIMIT_MESSAGE = bytes => `output exceeded ${bytes} bytes;
|
|
37
|
+
const OUTPUT_LIMIT_MESSAGE = bytes => `output exceeded ${bytes} bytes; this cell was discarded and the worker reset. Only bindings in the verified recovery frontier can be restored. External effects may already have occurred and are not undone. For future cells, bound console output and return a smaller value; do not assume this cell's values remain available.`
|
|
28
38
|
|
|
29
39
|
function earlyResult(kind, message) {
|
|
30
40
|
return { logs: [], error: { kind, message } }
|
|
@@ -52,16 +62,15 @@ function isBindingReferenceError(error) {
|
|
|
52
62
|
|| /Cannot access ['"][^'"]+['"] before initialization/.test(error.message))
|
|
53
63
|
}
|
|
54
64
|
|
|
65
|
+
/**
|
|
66
|
+
* Parse failures carry original cell coordinates in ModuleRewriteError.cellPosition; the rewriter
|
|
67
|
+
* owns any generated-source mapping, so the executor never re-applies wrapper offsets.
|
|
68
|
+
*/
|
|
55
69
|
function parseCellPosition(error) {
|
|
56
70
|
const cellPosition = error instanceof ModuleRewriteError ? error.cellPosition : undefined
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
:
|
|
60
|
-
const column = Number.isSafeInteger(cellPosition?.column)
|
|
61
|
-
? cellPosition.column
|
|
62
|
-
: Number.isSafeInteger(error?.loc?.column) ? error.loc.column + 1 : undefined
|
|
63
|
-
return line !== undefined && line >= 1 && column !== undefined
|
|
64
|
-
? { line, column }
|
|
71
|
+
return Number.isSafeInteger(cellPosition?.line) && cellPosition.line >= 1
|
|
72
|
+
&& Number.isSafeInteger(cellPosition?.column) && cellPosition.column >= 1
|
|
73
|
+
? { line: cellPosition.line, column: cellPosition.column }
|
|
65
74
|
: undefined
|
|
66
75
|
}
|
|
67
76
|
|
|
@@ -81,7 +90,7 @@ function parseDiagnostic(error, source, position, repair) {
|
|
|
81
90
|
: ['this cell was not executed; correct the reported syntax and retry only this cell with run_code']
|
|
82
91
|
: [
|
|
83
92
|
`this cell was not executed; validated syntax repair: append ${JSON.stringify(repair.delimiter)} at the end of this cell`,
|
|
84
|
-
`when edit_run_code is declared
|
|
93
|
+
`when this correction matches your intent and edit_run_code is declared, prefer the direct tool call ${repair.invocation} with its target guard to run the complete corrected cell; validation proves syntax/preflight acceptance, not intended behavior; otherwise submit corrected source in run_code`,
|
|
85
94
|
],
|
|
86
95
|
})
|
|
87
96
|
}
|
|
@@ -121,6 +130,106 @@ function committedRedeclarationSet(message, prepared) {
|
|
|
121
130
|
return committed
|
|
122
131
|
}
|
|
123
132
|
|
|
133
|
+
/** Accept value-free worker facts only for this compilation's logical root. */
|
|
134
|
+
function completedRootBindingFacts(message, prepared, committed) {
|
|
135
|
+
if (prepared.rootRuntimeName === undefined && prepared.rootBindingFacts !== true) return undefined
|
|
136
|
+
if (!Array.isArray(message.rootBindingFacts)) throw new TypeError('kernel returned invalid root binding facts')
|
|
137
|
+
const established = new Map(prepared.rootBindings.established)
|
|
138
|
+
const initialized = new Set(prepared.declarations.filter(declaration => committed.has(declaration.commitDependency)
|
|
139
|
+
&& (prepared.languageSemantics !== 'legacy-v1' || established.has(declaration.name)))
|
|
140
|
+
.map(declaration => declaration.name))
|
|
141
|
+
const candidates = new Map(prepared.rootBindings.candidates)
|
|
142
|
+
const dynamicOrigins = new Set(prepared.rootBindings.dynamicOrigins)
|
|
143
|
+
const available = new Set([...prepared.rootBindings.known, ...established.keys(), ...initialized])
|
|
144
|
+
const allowed = new Set([...available, ...candidates.values()])
|
|
145
|
+
const required = new Set([...established.keys(), ...initialized])
|
|
146
|
+
const imports = new Set([...prepared.rootBindings.legacyImports.map(([name]) => name),
|
|
147
|
+
...[...established].filter(([, source]) => source === 'import').map(([name]) => name),
|
|
148
|
+
...prepared.declarations.filter(declaration => declaration.kind === 'import' && committed.has(declaration.commitDependency))
|
|
149
|
+
.map(declaration => declaration.name)])
|
|
150
|
+
const seen = new Set()
|
|
151
|
+
const facts = message.rootBindingFacts.map(fact => {
|
|
152
|
+
const dynamicOrigin = dynamicBindingOrigin(fact?.write, fact?.name, dynamicOrigins)
|
|
153
|
+
if (fact === null || typeof fact !== 'object' || Array.isArray(fact)
|
|
154
|
+
|| Object.keys(fact).length !== (Object.hasOwn(fact, 'write') ? 3 : 2)
|
|
155
|
+
|| !Object.hasOwn(fact, 'name') || !Object.hasOwn(fact, 'source')
|
|
156
|
+
|| typeof fact.name !== 'string' || !allowed.has(fact.name) && dynamicOrigin === undefined || seen.has(fact.name)
|
|
157
|
+
|| !['local', 'import', 'absent'].includes(fact.source)
|
|
158
|
+
|| Object.hasOwn(fact, 'write') && (typeof fact.write !== 'string'
|
|
159
|
+
|| candidates.get(fact.write) !== fact.name && dynamicOrigin === undefined || fact.source === 'import')
|
|
160
|
+
|| !available.has(fact.name) && !Object.hasOwn(fact, 'write')
|
|
161
|
+
|| fact.source === 'import' && !imports.has(fact.name)
|
|
162
|
+
|| fact.source === 'absent' && initialized.has(fact.name)) throw new TypeError('kernel returned invalid root binding facts')
|
|
163
|
+
seen.add(fact.name)
|
|
164
|
+
required.delete(fact.name)
|
|
165
|
+
return { name: fact.name, source: fact.source, ...(Object.hasOwn(fact, 'write') ? { write: fact.write } : {}) }
|
|
166
|
+
})
|
|
167
|
+
if (required.size !== 0) throw new TypeError('kernel returned incomplete root binding facts')
|
|
168
|
+
return facts
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function completedUserBindingNames(active, message, snapshot) {
|
|
172
|
+
const facts = normalizeUserBindingNames(message.userBindingNames)
|
|
173
|
+
const required = active.userBindingBaseCatalog.userBindingNameSet(snapshot)
|
|
174
|
+
const allowed = active.userBindingBaseCatalog.userBindingNameSet(snapshot, true)
|
|
175
|
+
const providers = new Map((snapshot?.entries ?? []).flatMap(entry => (
|
|
176
|
+
(entry.scope === 'namespace' ? [entry.name] : entry.symbols).map(name => [name, entry.id])
|
|
177
|
+
)))
|
|
178
|
+
for (const fact of facts) {
|
|
179
|
+
if (!allowed.has(fact.name) || (fact.state === 'provider'
|
|
180
|
+
&& (providers.get(fact.name) !== fact.entryId || active.request.bindingDescriptors.reservedNames.has(fact.name)))) {
|
|
181
|
+
throw new TypeError('kernel returned user binding name evidence with invalid ownership')
|
|
182
|
+
}
|
|
183
|
+
required.delete(fact.name)
|
|
184
|
+
}
|
|
185
|
+
if (required.size !== 0) throw new TypeError('kernel returned incomplete user binding name evidence')
|
|
186
|
+
if (active.replay !== undefined && JSON.stringify(facts) !== JSON.stringify(active.replay.userBindingNames)) {
|
|
187
|
+
throw new TypeError('cell replay produced different user binding name evidence')
|
|
188
|
+
}
|
|
189
|
+
return facts
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function validateUserBindingActivation(active, message, ids) {
|
|
193
|
+
if (!Array.isArray(message.userBindingFailures)) throw new TypeError('kernel returned invalid user binding failures')
|
|
194
|
+
const expected = new Set(active.userBindings.entries.map(entry => entry.id))
|
|
195
|
+
for (const id of ids) expected.delete(id)
|
|
196
|
+
for (const failure of message.userBindingFailures) {
|
|
197
|
+
if (failure === null || typeof failure !== 'object' || Object.keys(failure).length !== 2
|
|
198
|
+
|| typeof failure.error !== 'string' || !expected.delete(failure.id)) {
|
|
199
|
+
throw new TypeError('kernel returned invalid user binding failures')
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
if (expected.size !== 0) throw new TypeError('kernel omitted user binding activation outcomes')
|
|
203
|
+
if ([...ids].some(id => active.userBindingFailures.some(failure => failure.id === id))) {
|
|
204
|
+
throw new TypeError('kernel activated a request-owned user binding name')
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/** A reserved program binding (`tools` and the injected error classes) is not shadowable at the
|
|
209
|
+
* session root, so a collision on it is not a repeated declaration. The collision producer records
|
|
210
|
+
* that reason, and rendering the recorded reason keeps "top-level bindings already exist" from
|
|
211
|
+
* implying the cell redeclared a name the session never created. */
|
|
212
|
+
const RESERVED_BINDING_REASON = 'reserved-program-binding-not-shadowable'
|
|
213
|
+
/** Reasons whose only remaining guidance is to reuse the binding already in session state. */
|
|
214
|
+
const REUSE_BINDING_REASONS = new Set([
|
|
215
|
+
'variable-redeclarations-disabled', 'redeclaration-splitting-disabled', 'protected-root-redeclaration',
|
|
216
|
+
'import-binding-redeclaration', RESERVED_BINDING_REASON,
|
|
217
|
+
])
|
|
218
|
+
|
|
219
|
+
function reservedBindingNote(collisions) {
|
|
220
|
+
const reserved = [...new Set(collisions.filter(collision => collision.reason === RESERVED_BINDING_REASON)
|
|
221
|
+
.map(collision => collision.name))]
|
|
222
|
+
return reserved.length === 0
|
|
223
|
+
? ''
|
|
224
|
+
: ` ${reserved.join(', ')} cannot be redeclared or overwritten because reserved program bindings are not shadowable.`
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** The model-visible structured form of every recorded collision, reduced to public fields. */
|
|
228
|
+
function collisionRecords(collisions) {
|
|
229
|
+
return collisions.map(collision => ({ name: collision.name, kind: collision.kind,
|
|
230
|
+
reason: collision.reason, start: collision.start, end: collision.end }))
|
|
231
|
+
}
|
|
232
|
+
|
|
124
233
|
function collisionDiagnostic(collisions) {
|
|
125
234
|
const names = [...new Set(collisions.map(item => item.name))]
|
|
126
235
|
const reasons = new Set(collisions.map(item => item.reason).filter(Boolean))
|
|
@@ -136,7 +245,7 @@ function collisionDiagnostic(collisions) {
|
|
|
136
245
|
: disabledKinds.has('class')
|
|
137
246
|
? ['assign a class expression to the existing writable binding']
|
|
138
247
|
: []),
|
|
139
|
-
...((reasons.size === 0 || reasons.has(
|
|
248
|
+
...((reasons.size === 0 || [...reasons].some(reason => REUSE_BINDING_REASONS.has(reason)))
|
|
140
249
|
? ['reuse the existing bindings']
|
|
141
250
|
: []),
|
|
142
251
|
]
|
|
@@ -147,14 +256,16 @@ function collisionDiagnostic(collisions) {
|
|
|
147
256
|
...(alternatives.length === 0 ? [] : [alternatives.join('; ')]),
|
|
148
257
|
'place one-off declarations inside a block',
|
|
149
258
|
]
|
|
259
|
+
const reservedNote = reservedBindingNote(collisions)
|
|
150
260
|
return diagnostic({
|
|
151
261
|
code: 'PTC-N001',
|
|
152
262
|
severity: 'error',
|
|
153
263
|
phase: 'preflight',
|
|
154
|
-
message: `top-level bindings already exist: ${names.join(', ')}
|
|
264
|
+
message: `top-level bindings already exist: ${names.join(', ')}.${reservedNote} This cell was not executed; the REPL state is unchanged.`,
|
|
155
265
|
stateEffect: 'unchanged',
|
|
156
266
|
source: { cell: 'current', start: first.start, end: first.end },
|
|
157
267
|
help,
|
|
268
|
+
collisions: collisionRecords(collisions),
|
|
158
269
|
})
|
|
159
270
|
}
|
|
160
271
|
|
|
@@ -164,6 +275,8 @@ function exceptionDiagnostic({
|
|
|
164
275
|
position,
|
|
165
276
|
declared,
|
|
166
277
|
longCellFailure = false,
|
|
278
|
+
failureOrigin,
|
|
279
|
+
languageSemantics = 'legacy-v1',
|
|
167
280
|
}) {
|
|
168
281
|
const missingPath = error.name === 'ToolCallError' ? missingDescriptionPath(error) : undefined
|
|
169
282
|
const missingDescription = missingPath !== undefined
|
|
@@ -188,20 +301,24 @@ function exceptionDiagnostic({
|
|
|
188
301
|
...(cause === undefined ? {} : { cause }),
|
|
189
302
|
...(source === undefined ? {} : { source }),
|
|
190
303
|
help: [
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
304
|
+
'earlier statements or the failing operation may have caused effects; choose continuation using the operation owner\'s retry/idempotence contract and available execution facts; a thrown call or recorded-value replay does not prove a live retry is safe',
|
|
305
|
+
...(failureOrigin === 'lease'
|
|
306
|
+
? ['this REPL-captured capability reference belongs to an ended cell; obtain the member from the current program namespace, and have retained helpers resolve it at invocation']
|
|
307
|
+
: failureOrigin === 'capability'
|
|
308
|
+
? ['inspect the current capability with capabilities.tree(), capabilities.find(), or capabilities.inspect(); availability may have changed']
|
|
309
|
+
: missingDescription
|
|
310
|
+
? ['add a string `description` property to the nested native-tool argument object']
|
|
311
|
+
: []),
|
|
194
312
|
...(error.name === 'ToolCallError'
|
|
195
313
|
&& typeof error.toolName === 'string'
|
|
196
314
|
&& error.toolName.startsWith('cordis_')
|
|
197
315
|
? ['bindings assigned before this Cordis failure remain live; reuse them instead of resending large source']
|
|
198
|
-
:
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
: ['use fresh names for one-off top-level bindings after partial execution; later declarations may be uninitialized']),
|
|
316
|
+
: longCellFailure
|
|
317
|
+
? ['inspect relevant live state in a new short `run_code` cell; edit_run_code executes the complete corrected cell, not only the failing expression']
|
|
318
|
+
: languageSemantics !== 'legacy-v1'
|
|
319
|
+
? ['completed declarations and actual assignments remain available; correct the failed initializer and continue with the same binding names']
|
|
320
|
+
: declared.size === 0 ? []
|
|
321
|
+
: ['use fresh names for one-off top-level bindings after partial execution; later declarations may be uninitialized']),
|
|
205
322
|
],
|
|
206
323
|
})
|
|
207
324
|
}
|
|
@@ -214,12 +331,18 @@ function invalidOutputDiagnostic(detail) {
|
|
|
214
331
|
message: `cell result could not cross the PTC Value V1 boundary: ${firstLine(detail, 'unknown output encoding failure')}`,
|
|
215
332
|
stateEffect: 'partially-applied',
|
|
216
333
|
help: [
|
|
217
|
-
'
|
|
334
|
+
'the worker remains live; inspect a retained binding in a later cell without rerunning the failed cell',
|
|
218
335
|
'reduce the returned graph when it exceeds the configured value budget',
|
|
219
336
|
],
|
|
220
337
|
})
|
|
221
338
|
}
|
|
222
339
|
|
|
340
|
+
/** Retain validated recorded wording while still comparing the actual failure. */
|
|
341
|
+
function replayFailureDiagnostic(actual, replay) {
|
|
342
|
+
const recorded = replay?.diagnostics?.find(item => item.code === actual.code)
|
|
343
|
+
return recorded?.message === actual.message ? recorded : actual
|
|
344
|
+
}
|
|
345
|
+
|
|
223
346
|
function stateArguments(value) {
|
|
224
347
|
if (value === null || typeof value !== 'object' || Array.isArray(value)) {
|
|
225
348
|
throw new TypeError('repl.state expects an object')
|
|
@@ -253,30 +376,61 @@ export class SessionCellExecutor {
|
|
|
253
376
|
return result
|
|
254
377
|
}
|
|
255
378
|
|
|
256
|
-
|
|
257
|
-
const
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
379
|
+
let userBindings
|
|
380
|
+
const userBindingsShadowPolicy = replayRecord?.userBindingsShadowPolicy ?? LIVE_USER_BINDINGS_SHADOW_POLICY
|
|
381
|
+
const perNameUserBindings = userBindingsShadowPolicy === LIVE_USER_BINDINGS_SHADOW_POLICY
|
|
382
|
+
let userBindingBaseCatalog = kernel.bindingCatalog
|
|
383
|
+
let userBindingPlan
|
|
384
|
+
let userBindingFailures = []
|
|
385
|
+
try {
|
|
386
|
+
userBindings = request.userBindings === undefined
|
|
387
|
+
? undefined
|
|
388
|
+
: normalizeUserBindingsSnapshot(request.userBindings)
|
|
389
|
+
if (userBindings === undefined) {
|
|
390
|
+
const catalog = kernel.bindingCatalog.withoutUserBindings()
|
|
391
|
+
userBindingPlan = perNameUserBindings ? kernel.bindingCatalog.userBindings(undefined, undefined, userBindingsShadowPolicy) : {
|
|
392
|
+
catalog,
|
|
393
|
+
shadowedNames: catalog.inputs().knownBindings,
|
|
394
|
+
}
|
|
395
|
+
} else {
|
|
396
|
+
const activeEntryIds = new Set()
|
|
397
|
+
for (const entry of userBindings.entries) {
|
|
398
|
+
const names = entry.scope === 'namespace' ? [entry.name] : entry.symbols
|
|
399
|
+
const conflict = names.find(name => request.bindingDescriptors.reservedNames.has(name))
|
|
400
|
+
if (conflict === undefined) activeEntryIds.add(entry.id)
|
|
401
|
+
else {
|
|
402
|
+
userBindingFailures.push(Object.freeze({
|
|
403
|
+
id: entry.id,
|
|
404
|
+
error: `conflicts with request-owned program binding ${JSON.stringify(conflict)}`,
|
|
405
|
+
}))
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
userBindingPlan = kernel.bindingCatalog.userBindings(userBindings, activeEntryIds, userBindingsShadowPolicy)
|
|
409
|
+
}
|
|
410
|
+
} catch (error) {
|
|
411
|
+
const result = earlyResult('exception', `invalid user binding snapshot: ${messageOf(error)}`)
|
|
412
|
+
kernel.completeJournal(request.journal, 'noop', result)
|
|
413
|
+
return result
|
|
414
|
+
}
|
|
415
|
+
const priorBindingCatalog = userBindingPlan.catalog
|
|
416
|
+
const catalog = priorBindingCatalog.inputs()
|
|
417
|
+
const { bindingPolicy, rewritesEnabled, moduleSemantics, languageSemantics, moduleTransform } = executionPolicies(config, replayRecord)
|
|
418
|
+
const prepareCell = program => prepareProgram(program, {
|
|
419
|
+
knownBindings: catalog.knownBindings,
|
|
272
420
|
bindingPolicy,
|
|
273
|
-
|
|
421
|
+
languageSemantics,
|
|
422
|
+
reservedBindings: request.bindingDescriptors.reservedNames,
|
|
274
423
|
rewritesEnabled,
|
|
275
|
-
catalog.importBindings,
|
|
276
|
-
catalog.importNamespaces,
|
|
277
|
-
catalog.writableBindings,
|
|
424
|
+
importBindings: catalog.importBindings,
|
|
425
|
+
importNamespaces: catalog.importNamespaces,
|
|
426
|
+
writableBindings: catalog.writableBindings,
|
|
427
|
+
nativeBindings: catalog.nativeBindings,
|
|
428
|
+
nativeLexicalBindings: catalog.nativeLexicalBindings,
|
|
429
|
+
rootCandidates: catalog.rootCandidates,
|
|
430
|
+
dynamicOrigins: catalog.dynamicOrigins,
|
|
431
|
+
establishedRoots: catalog.establishedRoots,
|
|
278
432
|
moduleSemantics,
|
|
279
|
-
)
|
|
433
|
+
})
|
|
280
434
|
let prepared
|
|
281
435
|
try {
|
|
282
436
|
prepared = prepareCell(request.program)
|
|
@@ -322,7 +476,9 @@ export class SessionCellExecutor {
|
|
|
322
476
|
const result = earlyResult('abort', String(request.signal.reason))
|
|
323
477
|
kernel.completeJournal(request.journal, 'discarded', result)
|
|
324
478
|
kernel.rollbackToDurable()
|
|
325
|
-
|
|
479
|
+
// A refused reclamation stays recorded on the kernel so disposal remains
|
|
480
|
+
// observable instead of becoming an unhandled rejection after this abort.
|
|
481
|
+
kernel.resetWorker(worker)
|
|
326
482
|
return result
|
|
327
483
|
}
|
|
328
484
|
|
|
@@ -332,9 +488,9 @@ export class SessionCellExecutor {
|
|
|
332
488
|
const bindings = this.withControlBinding(request.bindingDescriptors, journal, replayRecord)
|
|
333
489
|
const id = ++kernel.sequence
|
|
334
490
|
return new Promise((resolve) => {
|
|
335
|
-
const started = worker.performance.eventLoopUtilization()
|
|
336
491
|
const active = {
|
|
337
492
|
id,
|
|
493
|
+
started: false,
|
|
338
494
|
request: { ...request, bindings: bindings.namespaces },
|
|
339
495
|
finish: resolve,
|
|
340
496
|
computeTimer: undefined,
|
|
@@ -363,41 +519,112 @@ export class SessionCellExecutor {
|
|
|
363
519
|
control: { names: new Set(kernel.history.checkpoints.keys()) },
|
|
364
520
|
rewrites: prepared.rewrites,
|
|
365
521
|
prepared,
|
|
366
|
-
priorBindingCatalog
|
|
522
|
+
priorBindingCatalog,
|
|
523
|
+
userBindingBaseCatalog,
|
|
524
|
+
userBindings,
|
|
525
|
+
userBindingsShadowPolicy,
|
|
526
|
+
userBindingFailures,
|
|
527
|
+
userBindingSnapshot: userBindings,
|
|
367
528
|
worker,
|
|
529
|
+
settled: false,
|
|
368
530
|
}
|
|
369
531
|
active.resolve = (result, terminate = false) => kernel.settleCell(active, result, terminate)
|
|
370
532
|
active.onAbort = () => active.resolve(
|
|
371
533
|
earlyResult('abort', String(request.signal?.reason)),
|
|
372
534
|
true,
|
|
373
535
|
)
|
|
374
|
-
active.
|
|
375
|
-
|
|
376
|
-
|
|
536
|
+
active.budgetsStarted = false
|
|
537
|
+
active.startBudgets = () => {
|
|
538
|
+
if (active.budgetsStarted) return active.budgetsReady
|
|
539
|
+
active.budgetsStarted = true
|
|
540
|
+
// The wall bound starts at the request, while the compute baseline is
|
|
541
|
+
// sampled from the worker instead of reusing the helper's last periodic
|
|
542
|
+
// cache. Work that completed before this request must not be charged to
|
|
543
|
+
// the new cell, and work after the sample must remain counted.
|
|
544
|
+
active.wallTimer = setTimeout(() => {
|
|
545
|
+
active.resolve(earlyResult('timeout', `wall-clock ceiling reached (${config.maxWallMs}ms); split long-running work into smaller cells`), true)
|
|
546
|
+
}, config.maxWallMs)
|
|
547
|
+
active.budgetsReady = (async () => {
|
|
548
|
+
let started
|
|
549
|
+
try {
|
|
550
|
+
started = await worker.sampleUtilization()
|
|
551
|
+
} catch (error) {
|
|
552
|
+
// No fresh baseline means this request cannot be measured. Use the
|
|
553
|
+
// existing worker-exit route instead of pretending the last cache
|
|
554
|
+
// sample is this request's starting point.
|
|
555
|
+
active.resolve(earlyResult('worker-exit', messageOf(error)), true)
|
|
556
|
+
return
|
|
557
|
+
}
|
|
558
|
+
if (active.settled) return
|
|
559
|
+
active.computeTimer = setInterval(() => {
|
|
560
|
+
if (active.settled) return
|
|
561
|
+
if (worker.performance.eventLoopUtilization(started).active > config.computeMs) {
|
|
562
|
+
active.resolve(earlyResult('timeout', `compute budget exhausted (${config.computeMs}ms event-loop active, including synchronous blocking); this measure does not establish CPU use or the specific cause. Use asynchronous waiting for long waits, or a DSH-owned managed job if available. This cell was discarded and the worker reset; external effects or processes may continue.`), true)
|
|
563
|
+
}
|
|
564
|
+
}, Math.min(100, config.computeMs))
|
|
565
|
+
})()
|
|
566
|
+
return active.budgetsReady
|
|
567
|
+
}
|
|
568
|
+
active.start = async () => {
|
|
569
|
+
if (active.started) return
|
|
570
|
+
active.started = true
|
|
571
|
+
kernel.workerObservation = undefined
|
|
572
|
+
await active.startBudgets()
|
|
573
|
+
if (active.settled) return
|
|
574
|
+
try {
|
|
575
|
+
kernel.client.post({
|
|
576
|
+
type: 'run', id, program: prepared.code, namespaces: bindings.workerDescriptors,
|
|
577
|
+
moduleLoads: prepared.moduleLoads,
|
|
578
|
+
languageSemantics,
|
|
579
|
+
moduleTransform,
|
|
580
|
+
rootRuntimeName: prepared.rootRuntimeName,
|
|
581
|
+
rootBindings: prepared.rootBindings,
|
|
582
|
+
importBindingNamespaces: new Map([...catalog.importBindings].map(([name, binding]) => [name, binding.namespace])),
|
|
583
|
+
preparedImportBindingNamespaces: new Map([...prepared.imports].map(([name, binding]) => [name, binding.namespace])),
|
|
584
|
+
returnSignal: prepared.returnSignal,
|
|
585
|
+
asyncCompletion: prepared.asyncCompletion,
|
|
586
|
+
commitSignal: prepared.commitSignal,
|
|
587
|
+
maxOutputBytes: config.maxOutputBytes,
|
|
588
|
+
valueLimits,
|
|
589
|
+
durability,
|
|
590
|
+
observeNames: replayRecord === undefined && kernel.observeValues()
|
|
591
|
+
? createReplMemorySnapshot(
|
|
592
|
+
priorBindingCatalog.advance(prepared, request.program).snapshot(),
|
|
593
|
+
).entries.map(entry => entry.name)
|
|
594
|
+
: [],
|
|
595
|
+
userBindings,
|
|
596
|
+
userBindingsShadowPolicy,
|
|
597
|
+
userBindingsReusePolicy: replayRecord === undefined
|
|
598
|
+
? LIVE_USER_BINDINGS_REUSE_POLICY
|
|
599
|
+
: replayRecord.userBindingsReusePolicy,
|
|
600
|
+
...(userBindings === undefined ? {} : { userBindingsCwd: kernel.userBindingsCwd }),
|
|
601
|
+
userBindingFailures,
|
|
602
|
+
shadowedUserBindingNames: [...new Set([
|
|
603
|
+
...userBindingPlan.shadowedNames,
|
|
604
|
+
...request.bindingDescriptors.reservedNames,
|
|
605
|
+
])],
|
|
606
|
+
})
|
|
607
|
+
} catch (error) {
|
|
608
|
+
active.resolve(earlyResult('worker-exit', messageOf(error)), true)
|
|
377
609
|
}
|
|
378
|
-
}
|
|
379
|
-
active.wallTimer = setTimeout(() => {
|
|
380
|
-
active.resolve(earlyResult('timeout', `wall-clock ceiling reached (${config.maxWallMs}ms); split long-running work into smaller cells`), true)
|
|
381
|
-
}, config.maxWallMs)
|
|
610
|
+
}
|
|
382
611
|
kernel.active = active
|
|
383
612
|
request.signal?.addEventListener('abort', active.onAbort, { once: true })
|
|
384
613
|
if (request.signal?.aborted) {
|
|
385
614
|
active.onAbort()
|
|
386
615
|
return
|
|
387
616
|
}
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
active.resolve(earlyResult('worker-exit', messageOf(error)), true)
|
|
400
|
-
}
|
|
617
|
+
void (async () => {
|
|
618
|
+
try {
|
|
619
|
+
// Only worker-confirmed observation may defer these budgets; never restart them.
|
|
620
|
+
if (kernel.workerObservation?.worker !== worker
|
|
621
|
+
|| kernel.workerObservation.started !== true) await active.startBudgets()
|
|
622
|
+
if (active.settled) return
|
|
623
|
+
kernel.client.post({ type: 'prepare', id })
|
|
624
|
+
} catch (error) {
|
|
625
|
+
active.resolve(earlyResult('worker-exit', messageOf(error)), true)
|
|
626
|
+
}
|
|
627
|
+
})()
|
|
401
628
|
})
|
|
402
629
|
}
|
|
403
630
|
|
|
@@ -418,7 +645,7 @@ export class SessionCellExecutor {
|
|
|
418
645
|
reservedNames: bindingDescriptors.reservedNames,
|
|
419
646
|
workerDescriptors: Object.freeze([
|
|
420
647
|
...bindingDescriptors.workerDescriptors,
|
|
421
|
-
|
|
648
|
+
...normalizeBindingDescriptors([namespace]).workerDescriptors,
|
|
422
649
|
]),
|
|
423
650
|
})
|
|
424
651
|
}
|
|
@@ -456,6 +683,30 @@ export class SessionCellExecutor {
|
|
|
456
683
|
}
|
|
457
684
|
|
|
458
685
|
onMessage(message) {
|
|
686
|
+
if (message?.type === 'observation-started') {
|
|
687
|
+
const kernel = this.kernel
|
|
688
|
+
const observation = kernel.workerObservation
|
|
689
|
+
if (observation !== undefined && observation.id === message.id
|
|
690
|
+
&& observation.worker === kernel.client.worker) observation.started = true
|
|
691
|
+
return
|
|
692
|
+
}
|
|
693
|
+
if (message?.type === 'ready') {
|
|
694
|
+
const inspection = this.kernel.pendingInspection
|
|
695
|
+
if (inspection !== undefined && inspection.id === message.id) inspection.start()
|
|
696
|
+
const active = this.kernel.active
|
|
697
|
+
if (active !== undefined && active.id === message.id) void active.start()
|
|
698
|
+
return
|
|
699
|
+
}
|
|
700
|
+
if (message?.type === 'observation') {
|
|
701
|
+
const kernel = this.kernel
|
|
702
|
+
const observation = kernel.workerObservation
|
|
703
|
+
if (observation !== undefined && observation.id === message.id) {
|
|
704
|
+
kernel.workerObservation = undefined
|
|
705
|
+
if (kernel.active?.worker === observation.worker) kernel.active.startBudgets()
|
|
706
|
+
}
|
|
707
|
+
kernel.finishObservation(message)
|
|
708
|
+
return
|
|
709
|
+
}
|
|
459
710
|
if (message === null || typeof message !== 'object') return
|
|
460
711
|
const handler = {
|
|
461
712
|
volatile: this.handleVolatile,
|
|
@@ -515,6 +766,53 @@ export class SessionCellExecutor {
|
|
|
515
766
|
active.resolve({ logs, error: { kind: 'recovery', message: 'session log replay consumed a different host-call transcript' } }, true)
|
|
516
767
|
return
|
|
517
768
|
}
|
|
769
|
+
let activatedUserBindings
|
|
770
|
+
const perNameUserBindings = active.userBindingsShadowPolicy === LIVE_USER_BINDINGS_SHADOW_POLICY
|
|
771
|
+
try {
|
|
772
|
+
if (active.userBindings === undefined) {
|
|
773
|
+
active.userBindingSnapshot = undefined
|
|
774
|
+
active.priorBindingCatalog = active.userBindingBaseCatalog.withoutUserBindings()
|
|
775
|
+
} else {
|
|
776
|
+
const ids = Array.isArray(message.activatedUserBindings)
|
|
777
|
+
&& message.activatedUserBindings.every(id => typeof id === 'string')
|
|
778
|
+
? new Set(message.activatedUserBindings)
|
|
779
|
+
: undefined
|
|
780
|
+
if (ids === undefined || ids.size !== message.activatedUserBindings.length) {
|
|
781
|
+
throw new TypeError('kernel returned an invalid activated user binding set')
|
|
782
|
+
}
|
|
783
|
+
const expected = new Set(active.userBindings.entries.map(entry => entry.id))
|
|
784
|
+
if ([...ids].some(id => !expected.has(id))) {
|
|
785
|
+
throw new TypeError('kernel activated an unknown user binding entry')
|
|
786
|
+
}
|
|
787
|
+
if (perNameUserBindings) validateUserBindingActivation(active, message, ids)
|
|
788
|
+
activatedUserBindings = selectUserBindingsSnapshot(active.userBindings, ids)
|
|
789
|
+
active.userBindingSnapshot = activatedUserBindings
|
|
790
|
+
active.priorBindingCatalog = active.userBindingBaseCatalog.userBindings(active.userBindings, ids, active.userBindingsShadowPolicy).catalog
|
|
791
|
+
if (!perNameUserBindings) {
|
|
792
|
+
const shadowed = Array.isArray(message.shadowedUserBindings)
|
|
793
|
+
&& message.shadowedUserBindings.every(name => typeof name === 'string')
|
|
794
|
+
? new Set(message.shadowedUserBindings)
|
|
795
|
+
: undefined
|
|
796
|
+
const activeNames = new Set(activatedUserBindings.entries.flatMap(entry => (
|
|
797
|
+
entry.scope === 'namespace' ? [entry.name] : entry.symbols
|
|
798
|
+
)))
|
|
799
|
+
if (shadowed === undefined || shadowed.size !== message.shadowedUserBindings.length
|
|
800
|
+
|| [...shadowed].some(name => !activeNames.has(name))) {
|
|
801
|
+
throw new TypeError('kernel returned an invalid shadowed user binding set')
|
|
802
|
+
}
|
|
803
|
+
active.priorBindingCatalog = active.priorBindingCatalog.shadowUserBindings(shadowed)
|
|
804
|
+
}
|
|
805
|
+
if (active.replay !== undefined
|
|
806
|
+
&& activatedUserBindings.fingerprint !== active.userBindings.fingerprint) {
|
|
807
|
+
active.resolve({ logs, error: { kind: 'recovery', message: 'recorded user bindings could not be reactivated' } }, true)
|
|
808
|
+
return
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
if (perNameUserBindings) active.userBindingNames = completedUserBindingNames(active, message, activatedUserBindings)
|
|
812
|
+
} catch (error) {
|
|
813
|
+
active.resolve(earlyResult('worker-exit', messageOf(error)), true)
|
|
814
|
+
return
|
|
815
|
+
}
|
|
518
816
|
const bytes = Buffer.byteLength(JSON.stringify({ logs, value: message.value }), 'utf8')
|
|
519
817
|
if (bytes > active.config.maxOutputBytes) {
|
|
520
818
|
active.resolve({
|
|
@@ -524,8 +822,10 @@ export class SessionCellExecutor {
|
|
|
524
822
|
return
|
|
525
823
|
}
|
|
526
824
|
let committed
|
|
825
|
+
let rootBindingFacts
|
|
527
826
|
try {
|
|
528
827
|
committed = committedRedeclarationSet(message, active.prepared)
|
|
828
|
+
rootBindingFacts = completedRootBindingFacts(message, active.prepared, committed)
|
|
529
829
|
} catch (error) {
|
|
530
830
|
active.resolve(earlyResult('worker-exit', messageOf(error)), true)
|
|
531
831
|
return
|
|
@@ -536,7 +836,14 @@ export class SessionCellExecutor {
|
|
|
536
836
|
active.prepared,
|
|
537
837
|
active.request.program,
|
|
538
838
|
committed,
|
|
839
|
+
rootBindingFacts,
|
|
539
840
|
)
|
|
841
|
+
if (perNameUserBindings) {
|
|
842
|
+
active.appliedBindingCatalog = active.appliedBindingCatalog.reconcileUserBindingNames(
|
|
843
|
+
activatedUserBindings, active.userBindingNames, active.request.program,
|
|
844
|
+
)
|
|
845
|
+
}
|
|
846
|
+
active.observing = message.observing === true
|
|
540
847
|
if (typeof message.error === 'string') {
|
|
541
848
|
const rawError = {
|
|
542
849
|
kind: 'exception',
|
|
@@ -547,30 +854,38 @@ export class SessionCellExecutor {
|
|
|
547
854
|
const actualFailure = exceptionDiagnostic({
|
|
548
855
|
error: rawError,
|
|
549
856
|
cause: message.cause,
|
|
857
|
+
// A diagnostic caret must exist in the submitted cell. A native frame
|
|
858
|
+
// is mapped first; an unmappable frame falls back to the recorded
|
|
859
|
+
// source origin rather than attaching an out-of-range position.
|
|
550
860
|
position: message.moduleLoadFailed === true
|
|
551
|
-
? message.position
|
|
552
|
-
:
|
|
553
|
-
|
|
554
|
-
|
|
861
|
+
? cellPosition(message.position, active.request.program)
|
|
862
|
+
: cellPosition(
|
|
863
|
+
mapSourcePosition(
|
|
864
|
+
message.position,
|
|
865
|
+
active.prepared.code,
|
|
866
|
+
active.request.program,
|
|
867
|
+
active.prepared.sourceMap,
|
|
868
|
+
),
|
|
555
869
|
active.request.program,
|
|
556
|
-
|
|
557
|
-
),
|
|
870
|
+
) ?? exceptionOriginPosition(message.exceptionOrigins, active.request.program),
|
|
558
871
|
declared: message.moduleLoadFailed === true ? new Set() : active.prepared.declared,
|
|
872
|
+
languageSemantics: active.prepared.languageSemantics,
|
|
559
873
|
longCellFailure: active.request.program.length >= LONG_CELL_CODE_UNITS,
|
|
874
|
+
failureOrigin: message.failureOrigin,
|
|
560
875
|
})
|
|
561
|
-
const
|
|
562
|
-
const failure = recordedFailure?.message === actualFailure.message ? recordedFailure : actualFailure
|
|
876
|
+
const failure = replayFailureDiagnostic(actualFailure, active.replay)
|
|
563
877
|
const error = {
|
|
564
878
|
kind: 'exception',
|
|
565
879
|
message: renderDiagnostic(failure, active.request.program),
|
|
566
880
|
}
|
|
567
881
|
if (isBindingReferenceError(rawError)) markBindingFailure(error)
|
|
882
|
+
else if (message.failureOrigin === 'capability') markBindingFailure(error, 'capability')
|
|
568
883
|
active.diagnostics.push(failure)
|
|
569
884
|
active.resolve({ logs, error })
|
|
570
885
|
return
|
|
571
886
|
}
|
|
572
887
|
if (typeof message.invalidOutput === 'string') {
|
|
573
|
-
const failure = invalidOutputDiagnostic(message.invalidOutput)
|
|
888
|
+
const failure = replayFailureDiagnostic(invalidOutputDiagnostic(message.invalidOutput), active.replay)
|
|
574
889
|
const error = { kind: 'invalid-output', message: renderDiagnostic(failure, active.request.program) }
|
|
575
890
|
active.diagnostics.push(failure)
|
|
576
891
|
active.resolve({ logs, error })
|
|
@@ -581,23 +896,23 @@ export class SessionCellExecutor {
|
|
|
581
896
|
|| (message.hasValue ? message.value === undefined : message.value !== undefined)) {
|
|
582
897
|
throw new TypeError('invalid PTC completion envelope')
|
|
583
898
|
}
|
|
584
|
-
const
|
|
899
|
+
const completion = message.hasValue ? prepareValueWire(message.value, active.valueLimits) : undefined
|
|
585
900
|
active.completion = {
|
|
586
901
|
hasValue: message.hasValue,
|
|
587
|
-
...(message.hasValue ? { value } : {}),
|
|
902
|
+
...(message.hasValue ? { value: completion.wire } : {}),
|
|
588
903
|
}
|
|
589
904
|
if (active.replay?.completion?.kind === 'return'
|
|
590
905
|
&& (active.replay.completion.hasValue !== message.hasValue
|
|
591
|
-
|| (message.hasValue && !valueWiresEqual(active.replay.completion.value,
|
|
906
|
+
|| (message.hasValue && !valueWiresEqual(active.replay.completion.value, completion.wire, active.valueLimits)))) {
|
|
592
907
|
active.resolve({ logs, error: { kind: 'recovery', message: 'cell replay produced a different completion value' } }, true)
|
|
593
908
|
return
|
|
594
909
|
}
|
|
595
910
|
active.resolve({
|
|
596
911
|
logs,
|
|
597
|
-
...(message.hasValue ? { value:
|
|
912
|
+
...(message.hasValue ? { value: completion.projectedValue } : {}),
|
|
598
913
|
})
|
|
599
914
|
} catch (error) {
|
|
600
|
-
const failure = invalidOutputDiagnostic(messageOf(error))
|
|
915
|
+
const failure = replayFailureDiagnostic(invalidOutputDiagnostic(messageOf(error)), active.replay)
|
|
601
916
|
const invalid = { kind: 'invalid-output', message: renderDiagnostic(failure, active.request.program) }
|
|
602
917
|
active.diagnostics.push(failure)
|
|
603
918
|
active.resolve({ logs, error: invalid })
|