dsh-ptc-plus 0.4.1 → 0.4.3
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 +164 -78
- package/README.md +165 -79
- package/assets/dsh-ptc-plus-banner-en.webp +0 -0
- package/assets/dsh-ptc-plus-banner-zh.webp +0 -0
- package/assets/ptc-plus-icon.svg +5 -0
- package/client.js +854 -336
- package/compiler-core.cjs +161 -157
- package/compiler-core.cjs.map +3 -3
- package/docs/README.md +4 -1
- package/docs/adr/0005-temporary-rejected-cell-edit-transport.md +8 -7
- package/docs/adr/0008-define-agent-operating-contract.md +2 -2
- package/docs/adr/0010-session-log-derived-recovery-tips.md +7 -0
- package/docs/adr/0016-archive-resolved-review-findings.md +3 -3
- package/docs/adr/0019-plugin-settings-and-kill-switch.md +3 -3
- package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +2 -0
- package/docs/adr/0021-separate-host-bootstrap-from-session-runtime.md +14 -3
- package/docs/adr/0023-global-user-bindings.md +7 -7
- package/docs/adr/0025-use-versioned-logical-binding-identities.md +3 -3
- package/docs/adr/0026-persist-the-delivery-verdict-against-the-verified-candidate.md +23 -7
- package/docs/adr/0027-run-the-session-kernel-in-a-killable-helper-process.md +9 -5
- package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +26 -6
- package/docs/adr/0031-close-semantic-obligations-by-owner.md +29 -0
- package/docs/adr/README.md +4 -4
- package/docs/architecture.md +15 -10
- package/docs/binding-review-placement-design.md +1 -1
- package/docs/client-ui.md +9 -5
- package/docs/durability-design.md +12 -9
- package/docs/installation.md +27 -9
- package/docs/runtime-reference.md +23 -12
- package/docs/semantic-validation.md +7 -3
- package/docs/stateful-binding-updates-proposal.md +8 -4
- package/docs/user-bindings.en.md +10 -7
- package/docs/user-bindings.md +9 -6
- package/docs/value-wire.md +1 -1
- package/docs/verification-optimization-work.md +41 -0
- package/docs/verification.md +53 -2
- package/index.js +39 -34
- package/internal/async-local-storage-intrinsics.js +43 -0
- package/internal/binding-declaration-contract.js +8 -0
- package/internal/binding-source-analysis.js +381 -64
- package/internal/binding-update-policy.js +7 -1
- package/internal/callable-source-facts.js +37 -1
- package/internal/cell-analysis.js +85 -17
- package/internal/compiler-intrinsics.js +9 -43
- package/internal/compiler-module-links.js +7 -4
- package/internal/config-spec.js +1 -1
- package/internal/cordis-tools-owner.js +20 -10
- package/internal/dynamic-environment-integration.js +8 -4
- package/internal/dynamic-environment-runtime.js +24 -3
- package/internal/dynamic-native-calls.js +4 -1
- package/internal/dynamic-native-runtime.js +15 -1
- package/internal/edit-transport-owner.js +80 -20
- package/internal/execution-seam-compat.js +192 -30
- package/internal/failure-reporting.js +38 -30
- package/internal/isolated-worker.js +17 -10
- package/internal/kernel-worker.js +645 -393
- package/internal/message-sources.js +14 -0
- package/internal/module-compilation.js +7 -5
- package/internal/module-transform-contract.js +32 -2
- package/internal/record-utils.js +24 -15
- package/internal/repl-memory-projection.js +10 -0
- package/internal/repl-scope-normalizer.js +72 -35
- package/internal/repl-value-observer.js +145 -46
- package/internal/runtime-config.js +62 -2
- package/internal/runtime-intrinsics.js +104 -0
- package/internal/runtime-messages.js +6 -4
- package/internal/session-cell-executor.js +26 -2
- package/internal/session-journal-recovery.js +267 -67
- package/internal/session-journal-schema.js +30 -13
- package/internal/session-journal.js +485 -44
- package/internal/session-log-view.js +5 -4
- package/internal/session-runtime.js +46 -21
- package/internal/session-state.js +7 -29
- package/internal/settings-compat.js +66 -1
- package/internal/source-position-map.js +38 -0
- package/internal/stateful-root-compiler.js +3 -1
- package/internal/typescript-transform.js +4 -2
- package/internal/user-binding-console-worker.js +115 -41
- package/internal/user-binding-draft-projection.js +3 -2
- package/internal/user-bindings-owner.js +2 -1
- package/internal/user-bindings.js +16 -3
- package/internal/validated-parse-repair.js +6 -2
- package/internal/value-wire.js +189 -94
- package/internal/worker-client.js +99 -8
- package/internal/worker-cwd-virtualization.js +82 -54
- package/internal/worker-environment.js +20 -0
- package/internal/worker-output-capture.js +187 -0
- package/internal/worker-output-fence.js +26 -0
- package/internal/worker-realm-surfaces.js +197 -0
- package/internal/worker-repl-realm.js +140 -0
- package/package.json +37 -4
- package/src/client-activity.js +12 -2
- package/src/client-authoring-view.js +121 -62
- package/src/client-console.js +4 -2
- package/src/client-copy.js +4 -2
- package/src/client-feature-gates.js +7 -9
- package/src/client-host-compat.js +104 -27
- package/src/client-repl-view.js +3 -1
- package/src/client-styles.js +12 -1
- package/src/client-tool-view.js +3 -1
- package/src/client-transport.js +2 -2
- package/src/client-workbench.js +4 -3
- package/src/client.js +56 -17
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { runtimeIntrinsics as internal } from './runtime-intrinsics.js'
|
|
2
|
+
|
|
3
|
+
const { Error, TypeError, includes, objectFreeze,
|
|
4
|
+
objectGetOwnPropertyDescriptor, objectHasOwn, toString, Reflect: privateReflect } = internal
|
|
5
|
+
|
|
6
|
+
export const WORKER_REALM_MUTATION = objectFreeze({
|
|
7
|
+
STABLE: 'stable-native-divergence',
|
|
8
|
+
TEMPORARY: 'temporary-compiler-name',
|
|
9
|
+
PROGRAM: 'per-cell-program-binding',
|
|
10
|
+
USER: 'user-declaration-binding',
|
|
11
|
+
RESTORE: 'restoration-only',
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
const MUTATION_CLASSES = objectFreeze([
|
|
15
|
+
WORKER_REALM_MUTATION.STABLE,
|
|
16
|
+
WORKER_REALM_MUTATION.TEMPORARY,
|
|
17
|
+
WORKER_REALM_MUTATION.PROGRAM,
|
|
18
|
+
WORKER_REALM_MUTATION.USER,
|
|
19
|
+
WORKER_REALM_MUTATION.RESTORE,
|
|
20
|
+
])
|
|
21
|
+
|
|
22
|
+
export const PROCESS_CONTROL_ERROR_CODE = 'ERR_PTC_PROCESS_CONTROL'
|
|
23
|
+
export const WORKER_REALM_SURFACE_CONTRACT = objectFreeze([
|
|
24
|
+
objectFreeze({
|
|
25
|
+
surface: 'console',
|
|
26
|
+
owner: 'internal/kernel-worker.js and internal/user-binding-console-worker.js',
|
|
27
|
+
classification: WORKER_REALM_MUTATION.STABLE,
|
|
28
|
+
contract: 'native Console methods; output enters the per-cell log budget',
|
|
29
|
+
reference: 'plain Node worker console methods',
|
|
30
|
+
verification: 'console-methods',
|
|
31
|
+
}),
|
|
32
|
+
objectFreeze({
|
|
33
|
+
surface: 'process.stdout.write/process.stderr.write',
|
|
34
|
+
owner: 'internal/kernel-worker.js',
|
|
35
|
+
classification: WORKER_REALM_MUTATION.STABLE,
|
|
36
|
+
contract: 'captured per cell as writable own methods; direct descriptor output remains covered by the helper transport',
|
|
37
|
+
reference: 'plain Node worker stream descriptors',
|
|
38
|
+
verification: 'stream-descriptors',
|
|
39
|
+
}),
|
|
40
|
+
objectFreeze({
|
|
41
|
+
surface: 'process.cwd',
|
|
42
|
+
owner: 'internal/worker-cwd-virtualization.js',
|
|
43
|
+
classification: WORKER_REALM_MUTATION.STABLE,
|
|
44
|
+
contract: 'recorded cwd; immutable and non-configurable when a session cwd exists',
|
|
45
|
+
reference: 'plain Node worker process descriptor',
|
|
46
|
+
verification: 'cwd-descriptor',
|
|
47
|
+
}),
|
|
48
|
+
objectFreeze({
|
|
49
|
+
surface: 'cwd-projected Node builtins',
|
|
50
|
+
owner: 'internal/worker-cwd-virtualization.js',
|
|
51
|
+
classification: WORKER_REALM_MUTATION.STABLE,
|
|
52
|
+
contract: 'relative fs, path, and child-process calls use the recorded cwd while retaining callable descriptors',
|
|
53
|
+
reference: 'plain Node worker fs, fs/promises, path, and child_process callable descriptors',
|
|
54
|
+
verification: 'cwd-projected-builtins',
|
|
55
|
+
}),
|
|
56
|
+
objectFreeze({
|
|
57
|
+
surface: 'process.exit/abort/kill/chdir',
|
|
58
|
+
owner: 'internal/worker-realm-surfaces.js',
|
|
59
|
+
classification: WORKER_REALM_MUTATION.STABLE,
|
|
60
|
+
contract: `immutable lifecycle guards; failures use ${PROCESS_CONTROL_ERROR_CODE}`,
|
|
61
|
+
reference: 'plain Node worker process descriptors',
|
|
62
|
+
verification: 'process-controls',
|
|
63
|
+
}),
|
|
64
|
+
objectFreeze({
|
|
65
|
+
surface: 'fd 1/2 and inherited child output',
|
|
66
|
+
owner: 'internal/worker-client.js and internal/worker-output-capture.js',
|
|
67
|
+
classification: 'transport-boundary',
|
|
68
|
+
contract: 'captured in the acknowledged per-cell dual-stream fence window; out-of-round output resets the worker',
|
|
69
|
+
reference: 'helper stdout/stderr transport contract in ADR 0027',
|
|
70
|
+
verification: 'descriptor-output',
|
|
71
|
+
}),
|
|
72
|
+
objectFreeze({
|
|
73
|
+
surface: 'cell module metadata',
|
|
74
|
+
owner: 'internal/session-cell-executor.js and internal/kernel-worker.js and internal/user-binding-console-worker.js',
|
|
75
|
+
classification: WORKER_REALM_MUTATION.STABLE,
|
|
76
|
+
contract: 'current cells expose import.meta url/filename/dirname; require subset exists without ambient CommonJS wrapper globals',
|
|
77
|
+
reference: 'plain Node worker CommonJS surface and the session module parent',
|
|
78
|
+
verification: 'module-surface',
|
|
79
|
+
}),
|
|
80
|
+
objectFreeze({
|
|
81
|
+
surface: 'private AsyncLocalStorage receiver methods',
|
|
82
|
+
owner: 'internal/async-local-storage-intrinsics.js',
|
|
83
|
+
classification: WORKER_REALM_MUTATION.STABLE,
|
|
84
|
+
contract: 'immutable captured getStore, enterWith, and run methods on plugin-private receivers',
|
|
85
|
+
reference: 'the corresponding native AsyncLocalStorage methods bound to a fresh receiver',
|
|
86
|
+
verification: 'private-async-local-storage',
|
|
87
|
+
}),
|
|
88
|
+
objectFreeze({
|
|
89
|
+
surface: 'AsyncLocalStorage.prototype.run',
|
|
90
|
+
owner: 'internal/async-local-storage-intrinsics.js',
|
|
91
|
+
classification: WORKER_REALM_MUTATION.TEMPORARY,
|
|
92
|
+
contract: 'native at rest; synchronously replaced only during private REPL bootstrap',
|
|
93
|
+
reference: 'plain Node worker AsyncLocalStorage descriptors',
|
|
94
|
+
verification: 'async-local-storage',
|
|
95
|
+
}),
|
|
96
|
+
])
|
|
97
|
+
|
|
98
|
+
function assertMutation(classification, surface) {
|
|
99
|
+
if (!includes(MUTATION_CLASSES, classification)) {
|
|
100
|
+
throw new TypeError(`unknown worker realm mutation classification: ${classification}`)
|
|
101
|
+
}
|
|
102
|
+
if (classification !== WORKER_REALM_MUTATION.STABLE) return
|
|
103
|
+
let registered = false
|
|
104
|
+
for (let index = 0; index < WORKER_REALM_SURFACE_CONTRACT.length; index += 1) {
|
|
105
|
+
const entry = WORKER_REALM_SURFACE_CONTRACT[index]
|
|
106
|
+
if (entry.surface === surface && entry.classification === classification) registered = true
|
|
107
|
+
}
|
|
108
|
+
if (!registered) {
|
|
109
|
+
throw new TypeError(`stable worker realm mutation requires a matching registered classification: ${surface}`)
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/** The only supported write boundary for worker globals, process surfaces and native prototypes. */
|
|
114
|
+
export function defineWorkerRealmProperty(classification, surface, owner, property, descriptor) {
|
|
115
|
+
assertMutation(classification, surface)
|
|
116
|
+
if (!privateReflect.defineProperty(owner, property, descriptor)) {
|
|
117
|
+
throw new TypeError(`worker realm property ${toString(property)} could not be defined`)
|
|
118
|
+
}
|
|
119
|
+
return owner
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function assignWorkerRealmProperty(classification, surface, owner, property, value) {
|
|
123
|
+
assertMutation(classification, surface)
|
|
124
|
+
if (!privateReflect.set(owner, property, value)) {
|
|
125
|
+
throw new TypeError(`worker realm property ${toString(property)} could not be assigned`)
|
|
126
|
+
}
|
|
127
|
+
return value
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function deleteWorkerRealmProperty(classification, surface, owner, property) {
|
|
131
|
+
assertMutation(classification, surface)
|
|
132
|
+
return privateReflect.deleteProperty(owner, property)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function codedError(code, message) {
|
|
136
|
+
const error = new Error(message)
|
|
137
|
+
privateReflect.defineProperty(error, 'code', {
|
|
138
|
+
configurable: true,
|
|
139
|
+
enumerable: true,
|
|
140
|
+
writable: true,
|
|
141
|
+
value: code,
|
|
142
|
+
})
|
|
143
|
+
return error
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function installProjectedProcessCwd(processObject, cwd) {
|
|
147
|
+
defineWorkerRealmProperty(WORKER_REALM_MUTATION.STABLE, 'process.cwd', processObject, 'cwd', {
|
|
148
|
+
configurable: false,
|
|
149
|
+
enumerable: true,
|
|
150
|
+
writable: false,
|
|
151
|
+
value: () => cwd,
|
|
152
|
+
})
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function installProcessControlGuards(processObject, properties) {
|
|
156
|
+
for (let index = 0; index < properties.length; index += 1) {
|
|
157
|
+
const property = properties[index]
|
|
158
|
+
const descriptor = objectGetOwnPropertyDescriptor(processObject, property)
|
|
159
|
+
defineWorkerRealmProperty(
|
|
160
|
+
WORKER_REALM_MUTATION.STABLE,
|
|
161
|
+
'process.exit/abort/kill/chdir',
|
|
162
|
+
processObject,
|
|
163
|
+
property,
|
|
164
|
+
{
|
|
165
|
+
configurable: false,
|
|
166
|
+
enumerable: descriptor?.enumerable ?? true,
|
|
167
|
+
writable: false,
|
|
168
|
+
value: () => {
|
|
169
|
+
throw codedError(PROCESS_CONTROL_ERROR_CODE, `process.${property} is forbidden inside the REPL kernel`)
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** Stable facts consumed by the conformance test and runtime documentation. */
|
|
177
|
+
export function workerRealmSurfaceFacts(processObject) {
|
|
178
|
+
const descriptor = (owner, name) => {
|
|
179
|
+
const value = objectGetOwnPropertyDescriptor(owner, name)
|
|
180
|
+
return value === undefined ? undefined : {
|
|
181
|
+
configurable: value.configurable,
|
|
182
|
+
enumerable: value.enumerable,
|
|
183
|
+
writable: value.writable,
|
|
184
|
+
own: true,
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
const controls = []
|
|
188
|
+
for (const name of ['exit', 'abort', 'kill', 'chdir']) controls.push([name, descriptor(processObject, name)])
|
|
189
|
+
return {
|
|
190
|
+
cwd: descriptor(processObject, 'cwd'),
|
|
191
|
+
controls,
|
|
192
|
+
stdoutWrite: descriptor(processObject.stdout, 'write'),
|
|
193
|
+
stderrWrite: descriptor(processObject.stderr, 'write'),
|
|
194
|
+
stdoutWriteOwn: objectHasOwn(processObject.stdout, 'write'),
|
|
195
|
+
stderrWriteOwn: objectHasOwn(processObject.stderr, 'write'),
|
|
196
|
+
}
|
|
197
|
+
}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { createContext, runInContext, runInThisContext } from 'node:vm'
|
|
2
|
+
import { types } from 'node:util'
|
|
3
|
+
import { protectNextAsyncLocalStorageRun } from './async-local-storage-intrinsics.js'
|
|
4
|
+
import {
|
|
5
|
+
WORKER_REALM_MUTATION,
|
|
6
|
+
defineWorkerRealmProperty,
|
|
7
|
+
deleteWorkerRealmProperty,
|
|
8
|
+
} from './worker-realm-surfaces.js'
|
|
9
|
+
|
|
10
|
+
export const WORKER_REPL_OPTIONS = Object.freeze({ useGlobal: true })
|
|
11
|
+
const NativeMap = Map
|
|
12
|
+
const ownKeys = Reflect.ownKeys
|
|
13
|
+
const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor
|
|
14
|
+
const createObject = Object.create
|
|
15
|
+
const hasOwn = Object.hasOwn
|
|
16
|
+
const sameValue = Object.is
|
|
17
|
+
const isMap = types.isMap
|
|
18
|
+
const mapSet = Function.prototype.call.bind(Map.prototype.set)
|
|
19
|
+
const mapHas = Function.prototype.call.bind(Map.prototype.has)
|
|
20
|
+
const mapForEach = Function.prototype.call.bind(Map.prototype.forEach)
|
|
21
|
+
const DESCRIPTOR_FIELDS = ['configurable', 'enumerable', 'writable', 'value', 'get', 'set']
|
|
22
|
+
|
|
23
|
+
/** Snapshot the native worker surface before Node installs REPL conveniences. */
|
|
24
|
+
export function captureWorkerReplGlobals(globalObject = globalThis) {
|
|
25
|
+
const baseline = new NativeMap()
|
|
26
|
+
const keys = ownKeys(globalObject)
|
|
27
|
+
for (let index = 0; index < keys.length; index += 1) {
|
|
28
|
+
mapSet(baseline, keys[index], getOwnPropertyDescriptor(globalObject, keys[index]))
|
|
29
|
+
}
|
|
30
|
+
return baseline
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function descriptorsEqual(left, right) {
|
|
34
|
+
const field = (descriptor, name) => descriptor !== undefined && hasOwn(descriptor, name)
|
|
35
|
+
? descriptor[name] : undefined
|
|
36
|
+
return left !== undefined && right !== undefined
|
|
37
|
+
&& field(left, 'configurable') === field(right, 'configurable')
|
|
38
|
+
&& field(left, 'enumerable') === field(right, 'enumerable')
|
|
39
|
+
&& field(left, 'writable') === field(right, 'writable')
|
|
40
|
+
&& sameValue(field(left, 'value'), field(right, 'value'))
|
|
41
|
+
&& field(left, 'get') === field(right, 'get')
|
|
42
|
+
&& field(left, 'set') === field(right, 'set')
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function detachedDescriptor(descriptor) {
|
|
46
|
+
const detached = createObject(null)
|
|
47
|
+
for (let index = 0; index < DESCRIPTOR_FIELDS.length; index += 1) {
|
|
48
|
+
const name = DESCRIPTOR_FIELDS[index]
|
|
49
|
+
if (hasOwn(descriptor, name)) detached[name] = descriptor[name]
|
|
50
|
+
}
|
|
51
|
+
return detached
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Remove Node's REPL-only module shortcuts and restore changed native globals. */
|
|
55
|
+
export function restoreWorkerReplGlobals(baseline, globalObject = globalThis) {
|
|
56
|
+
if (!isMap(baseline)) throw new TypeError('worker REPL global baseline must be a Map')
|
|
57
|
+
const keys = ownKeys(globalObject)
|
|
58
|
+
for (let index = 0; index < keys.length; index += 1) {
|
|
59
|
+
const key = keys[index]
|
|
60
|
+
if (typeof key === 'string' && !mapHas(baseline, key)
|
|
61
|
+
&& !deleteWorkerRealmProperty(WORKER_REALM_MUTATION.RESTORE, undefined, globalObject, key)) {
|
|
62
|
+
throw new Error(`worker REPL added a non-configurable global ${String(key)}`)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
mapForEach(baseline, (descriptor, key) => {
|
|
66
|
+
if (!descriptorsEqual(getOwnPropertyDescriptor(globalObject, key), descriptor)) {
|
|
67
|
+
defineWorkerRealmProperty(
|
|
68
|
+
WORKER_REALM_MUTATION.RESTORE, undefined, globalObject, key, detachedDescriptor(descriptor),
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
})
|
|
72
|
+
return globalObject
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/** A dedicated worker is the native realm shared by its REPL and Node modules. */
|
|
76
|
+
export function workerReplContext(server) {
|
|
77
|
+
if (server.context !== globalThis) {
|
|
78
|
+
throw new Error('worker REPL did not use its native global realm')
|
|
79
|
+
}
|
|
80
|
+
return server.context
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let replAsyncContextProtected = false
|
|
84
|
+
|
|
85
|
+
/** Newer Node REPLs own an AsyncLocalStorage instance whose public prototype
|
|
86
|
+
* remains user-mutable. Give only that platform instance its native operations
|
|
87
|
+
* before the first user evaluation. */
|
|
88
|
+
export function protectWorkerReplAsyncContext(server) {
|
|
89
|
+
if (replAsyncContextProtected) return
|
|
90
|
+
let callbackError
|
|
91
|
+
const scope = protectNextAsyncLocalStorageRun(() => {
|
|
92
|
+
server.eval('void 0\n', server.context, 'ptc-plus-repl-bootstrap', error => { callbackError = error })
|
|
93
|
+
})
|
|
94
|
+
if (callbackError !== null && callbackError !== undefined) throw callbackError
|
|
95
|
+
replAsyncContextProtected = true
|
|
96
|
+
return scope !== undefined
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function runInWorkerReplRealm(source, options) {
|
|
100
|
+
return runInThisContext(source, options)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** Control promises stay outside the user-mutable worker realm. */
|
|
104
|
+
export function createWorkerControlPromise() {
|
|
105
|
+
return runInContext('Promise', createContext())
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/** PTC owns settlement; the REPL's legacy domain would run Node bookkeeping
|
|
109
|
+
* through user-mutable prototypes in the shared worker realm. */
|
|
110
|
+
export function disableWorkerReplDomain(domain) {
|
|
111
|
+
domain.enter = () => domain
|
|
112
|
+
domain.exit = () => domain
|
|
113
|
+
return domain
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** Newer REPLs format errors before the eval callback unless an owned
|
|
117
|
+
* evaluation consumes the original thrown value through handleError. */
|
|
118
|
+
export function createWorkerReplErrorHandler(evaluationScope, settle) {
|
|
119
|
+
return error => {
|
|
120
|
+
const finish = evaluationScope.getStore()
|
|
121
|
+
if (finish === undefined) return 'unhandled'
|
|
122
|
+
settle(finish, error)
|
|
123
|
+
return 'ignore'
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** Older REPLs can bypass handleError. Keep their process-level fallback
|
|
128
|
+
* directly testable without requiring a version-specific uncaught event. */
|
|
129
|
+
export function createWorkerUncaughtExceptionHandler(evaluationScope, listenerOwner = process) {
|
|
130
|
+
const handleUncaughtException = error => {
|
|
131
|
+
const finish = evaluationScope.getStore()
|
|
132
|
+
if (finish !== undefined) {
|
|
133
|
+
finish(true, error)
|
|
134
|
+
return
|
|
135
|
+
}
|
|
136
|
+
listenerOwner.removeListener('uncaughtException', handleUncaughtException)
|
|
137
|
+
throw error
|
|
138
|
+
}
|
|
139
|
+
return handleUncaughtException
|
|
140
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-ptc-plus",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
4
|
+
"icon": "assets/ptc-plus-icon.svg",
|
|
4
5
|
"description": "A session-bound agent-native REPL for DeepSeek Harness PTC mode.",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"main": "./index.js",
|
|
@@ -25,6 +26,7 @@
|
|
|
25
26
|
"src",
|
|
26
27
|
"internal",
|
|
27
28
|
"docs",
|
|
29
|
+
"assets/ptc-plus-icon.svg",
|
|
28
30
|
"assets/dsh-ptc-plus-banner-en.webp",
|
|
29
31
|
"assets/dsh-ptc-plus-banner-zh.webp",
|
|
30
32
|
"assets/ptc-plus-bindings-en.png",
|
|
@@ -61,7 +63,7 @@
|
|
|
61
63
|
"@codemirror/language": "^6.12.4",
|
|
62
64
|
"@codemirror/state": "^6.7.4",
|
|
63
65
|
"@codemirror/view": "^6.43.11",
|
|
64
|
-
"@deepseek-ai/schemastery": "^3.18.
|
|
66
|
+
"@deepseek-ai/schemastery": "^3.18.3",
|
|
65
67
|
"@jridgewell/trace-mapping": "^0.3.31",
|
|
66
68
|
"@lezer/highlight": "^1.2.3",
|
|
67
69
|
"acorn": "^8.15.0",
|
|
@@ -87,16 +89,24 @@
|
|
|
87
89
|
"build:check": "node scripts/client-bundle.mjs check && node scripts/compiler-bundle.mjs check",
|
|
88
90
|
"test:client": "vitest run --config scripts/client-test.config.mjs",
|
|
89
91
|
"test:semantics": "node --test --test-concurrency=1 test/semantic-test262.test.js test/semantic-dialect.test.js test/semantic-boundaries.test.js",
|
|
92
|
+
"semantic:check": "node scripts/semantic-obligations.mjs",
|
|
90
93
|
"test:client:web": "node scripts/client-web-smoke.mjs",
|
|
91
94
|
"test:client:layout": "node scripts/client-binding-layout.mjs",
|
|
92
95
|
"prepack": "npm run build:check",
|
|
93
96
|
"hooks:install": "node scripts/review-findings.mjs install-hook",
|
|
94
97
|
"review:new": "node scripts/review-findings.mjs create",
|
|
98
|
+
"review:plan:new": "node scripts/review-findings.mjs plan-create",
|
|
99
|
+
"review:plan": "node scripts/review-findings.mjs plan",
|
|
100
|
+
"review:status": "node scripts/review-findings.mjs status",
|
|
101
|
+
"review:lane": "node scripts/review-findings.mjs lane-verdict",
|
|
102
|
+
"review:finalize": "node scripts/review-findings.mjs finalize",
|
|
103
|
+
"review:clear": "node scripts/review-findings.mjs review-clear",
|
|
95
104
|
"review:validate": "node scripts/review-findings.mjs validate",
|
|
96
105
|
"review:gate": "node scripts/review-findings.mjs gate",
|
|
97
106
|
"session:migrate": "node scripts/migrate-session-log.mjs",
|
|
98
107
|
"coverage": "node scripts/coverage.mjs",
|
|
99
|
-
"
|
|
108
|
+
"coverage:focus": "node scripts/coverage.mjs --focus",
|
|
109
|
+
"verify": "npm run review:validate && npm run semantic:check && npm run build:check && node --check index.js && node --check internal/kernel-worker.js && node --check scripts/migrate-session-log.mjs && node --check scripts/expensive-headless-acceptance.mjs && node --check scripts/ab-headless-trajectories.mjs && npm run test:client && npm run coverage",
|
|
100
110
|
"check": "node scripts/review-findings.mjs check",
|
|
101
111
|
"test:expensive": "node scripts/expensive-headless-acceptance.mjs",
|
|
102
112
|
"test:ab": "node scripts/ab-headless-trajectories.mjs"
|
|
@@ -156,6 +166,8 @@
|
|
|
156
166
|
"@deepseek-ai/dsh-commands": "next",
|
|
157
167
|
"@deepseek-ai/dsh-home-paths": "next",
|
|
158
168
|
"@deepseek-ai/dsh-llm": "next",
|
|
169
|
+
"@deepseek-ai/dsh-session-format-catalog": "next",
|
|
170
|
+
"@deepseek-ai/dsh-session-format-v0-to-v1": "next",
|
|
159
171
|
"@deepseek-ai/dsh-session-persistence-jsonl": "next",
|
|
160
172
|
"@deepseek-ai/dsh-settings": "next",
|
|
161
173
|
"@deepseek-ai/dsh-skill-filesystem": "next",
|
|
@@ -163,15 +175,36 @@
|
|
|
163
175
|
"@deepseek-ai/dsh-tools": "next",
|
|
164
176
|
"@deepseek-ai/dsh-typert-protocol": "next",
|
|
165
177
|
"@deepseek-ai/dsh-typert-registry": "next",
|
|
178
|
+
"@deepseek-ai/dsh-util-workspace-path": "next",
|
|
179
|
+
"@shikijs/langs": "^4.3.1",
|
|
166
180
|
"@testing-library/react": "^16.3.3",
|
|
181
|
+
"anser": "^2.3.5",
|
|
167
182
|
"c8": "^12.0.0",
|
|
183
|
+
"clsx": "^2.0.0",
|
|
168
184
|
"convert-source-map": "^2.0.0",
|
|
185
|
+
"diff": "^9.0.0",
|
|
169
186
|
"esbuild": "0.28.2",
|
|
187
|
+
"immer": "^10.1.1",
|
|
170
188
|
"jsdom": "^29.1.1",
|
|
189
|
+
"katex": "^0.16.47",
|
|
190
|
+
"mdast-util-from-markdown": "^2.0.3",
|
|
191
|
+
"mdast-util-gfm": "^3.1.0",
|
|
192
|
+
"mdast-util-math": "^3.0.0",
|
|
193
|
+
"micromark-core-commonmark": "^2.0.3",
|
|
194
|
+
"micromark-extension-gfm": "^3.0.0",
|
|
195
|
+
"micromark-extension-math": "^3.1.0",
|
|
196
|
+
"micromark-factory-space": "^2.0.1",
|
|
197
|
+
"micromark-util-character": "^2.1.1",
|
|
198
|
+
"micromark-util-classify-character": "^2.0.1",
|
|
199
|
+
"micromark-util-sanitize-uri": "^2.0.1",
|
|
200
|
+
"micromark-util-symbol": "^2.0.1",
|
|
171
201
|
"playwright": "^1.63.0",
|
|
172
202
|
"react": "^18.3.1",
|
|
173
203
|
"react-dom": "^18.3.1",
|
|
204
|
+
"shiki": "^4.3.1",
|
|
205
|
+
"simple-icons": "16.31.0",
|
|
174
206
|
"vitest": "^5.0.0",
|
|
175
|
-
"yaml": "^2.9.0"
|
|
207
|
+
"yaml": "^2.9.0",
|
|
208
|
+
"zustand": "~4.4.7"
|
|
176
209
|
}
|
|
177
210
|
}
|
package/src/client-activity.js
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
STATUSES as JOURNAL_STATUSES,
|
|
4
4
|
BINDING_MODES,
|
|
5
5
|
JOURNAL_FIELDS,
|
|
6
|
+
LANGUAGE_SEMANTICS_JOURNAL_FIELDS,
|
|
6
7
|
PER_NAME_JOURNAL_FIELDS,
|
|
7
8
|
LANGUAGE_SEMANTICS_JOURNAL_VERSION,
|
|
8
9
|
WHOLE_ENTRY_JOURNAL_FIELDS,
|
|
@@ -33,6 +34,7 @@ import {
|
|
|
33
34
|
USER_BINDINGS_REUSE_POLICIES,
|
|
34
35
|
} from '../internal/session-journal-schema.js'
|
|
35
36
|
import { normalizeLanguageSemantics } from '../internal/language-semantics.js'
|
|
37
|
+
import { normalizeModuleTransform } from '../internal/module-transform-contract.js'
|
|
36
38
|
import {
|
|
37
39
|
VALUE_CODEC,
|
|
38
40
|
DEFAULT_VALUE_LIMITS,
|
|
@@ -103,7 +105,7 @@ function isLine(value) {
|
|
|
103
105
|
}
|
|
104
106
|
|
|
105
107
|
function isSafeSequence(value) {
|
|
106
|
-
return Number.isSafeInteger(value) && value >= 0
|
|
108
|
+
return Number.isSafeInteger(value) && value >= 0 && !Object.is(value, -0)
|
|
107
109
|
}
|
|
108
110
|
|
|
109
111
|
function isValidPosition(value) {
|
|
@@ -185,6 +187,7 @@ function isValidValueWire(value) {
|
|
|
185
187
|
nodeCount: value.nodes.length,
|
|
186
188
|
discovered: new Set(),
|
|
187
189
|
edges: 0,
|
|
190
|
+
arraySlots: 0,
|
|
188
191
|
textBytes: 0,
|
|
189
192
|
}
|
|
190
193
|
if (!isValidValueAtom(value.root, state)) return false
|
|
@@ -194,6 +197,8 @@ function isValidValueWire(value) {
|
|
|
194
197
|
if (!hasExactOrderedFields(node, VALUE_ARRAY_FIELDS)
|
|
195
198
|
|| !Number.isSafeInteger(node.length) || node.length < 0 || node.length > MAX_ARRAY_LENGTH
|
|
196
199
|
|| !Array.isArray(node.entries)) return false
|
|
200
|
+
state.arraySlots += node.length
|
|
201
|
+
if (state.arraySlots > MAX_ARRAY_LENGTH) return false
|
|
197
202
|
let previous = -1
|
|
198
203
|
for (const entry of node.entries) {
|
|
199
204
|
if (!Array.isArray(entry) || entry.length !== 2 || !Number.isSafeInteger(entry[0])
|
|
@@ -292,7 +297,8 @@ function isReadableJournalUnchecked(value) {
|
|
|
292
297
|
: value.version === 4 ? RELATIONLESS_JOURNAL_FIELDS
|
|
293
298
|
: value.version === 5 ? FINGERPRINT_REUSE_JOURNAL_FIELDS
|
|
294
299
|
: value.version < PER_NAME_USER_BINDINGS_JOURNAL_VERSION ? WHOLE_ENTRY_JOURNAL_FIELDS
|
|
295
|
-
|
|
300
|
+
: value.version < LANGUAGE_SEMANTICS_JOURNAL_VERSION ? PER_NAME_JOURNAL_FIELDS
|
|
301
|
+
: value.version === LANGUAGE_SEMANTICS_JOURNAL_VERSION ? LANGUAGE_SEMANTICS_JOURNAL_FIELDS : JOURNAL_FIELDS
|
|
296
302
|
const required = predecessor
|
|
297
303
|
? ['version', 'bindingMode', 'status', 'calls', 'operations', 'diagnostics']
|
|
298
304
|
: ['version', 'bindingPolicy', 'rewritePolicy', 'moduleSemantics', 'status', 'calls', 'operations', 'diagnostics']
|
|
@@ -307,6 +313,10 @@ function isReadableJournalUnchecked(value) {
|
|
|
307
313
|
required.push('languageSemantics')
|
|
308
314
|
normalizeLanguageSemantics(value.languageSemantics)
|
|
309
315
|
}
|
|
316
|
+
if (value.version > LANGUAGE_SEMANTICS_JOURNAL_VERSION) {
|
|
317
|
+
required.push('moduleTransform')
|
|
318
|
+
normalizeModuleTransform(value.moduleTransform, value.languageSemantics)
|
|
319
|
+
}
|
|
310
320
|
if (!hasClosedFields(value, fields, required)
|
|
311
321
|
|| (predecessor && !BINDING_MODES.has(value.bindingMode))
|
|
312
322
|
|| (value.version >= 4 && !isValidBindingPolicy(value.bindingPolicy))
|