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.
Files changed (103) hide show
  1. package/README.en.md +164 -78
  2. package/README.md +165 -79
  3. package/assets/dsh-ptc-plus-banner-en.webp +0 -0
  4. package/assets/dsh-ptc-plus-banner-zh.webp +0 -0
  5. package/assets/ptc-plus-icon.svg +5 -0
  6. package/client.js +854 -336
  7. package/compiler-core.cjs +161 -157
  8. package/compiler-core.cjs.map +3 -3
  9. package/docs/README.md +4 -1
  10. package/docs/adr/0005-temporary-rejected-cell-edit-transport.md +8 -7
  11. package/docs/adr/0008-define-agent-operating-contract.md +2 -2
  12. package/docs/adr/0010-session-log-derived-recovery-tips.md +7 -0
  13. package/docs/adr/0016-archive-resolved-review-findings.md +3 -3
  14. package/docs/adr/0019-plugin-settings-and-kill-switch.md +3 -3
  15. package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +2 -0
  16. package/docs/adr/0021-separate-host-bootstrap-from-session-runtime.md +14 -3
  17. package/docs/adr/0023-global-user-bindings.md +7 -7
  18. package/docs/adr/0025-use-versioned-logical-binding-identities.md +3 -3
  19. package/docs/adr/0026-persist-the-delivery-verdict-against-the-verified-candidate.md +23 -7
  20. package/docs/adr/0027-run-the-session-kernel-in-a-killable-helper-process.md +9 -5
  21. package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +26 -6
  22. package/docs/adr/0031-close-semantic-obligations-by-owner.md +29 -0
  23. package/docs/adr/README.md +4 -4
  24. package/docs/architecture.md +15 -10
  25. package/docs/binding-review-placement-design.md +1 -1
  26. package/docs/client-ui.md +9 -5
  27. package/docs/durability-design.md +12 -9
  28. package/docs/installation.md +27 -9
  29. package/docs/runtime-reference.md +23 -12
  30. package/docs/semantic-validation.md +7 -3
  31. package/docs/stateful-binding-updates-proposal.md +8 -4
  32. package/docs/user-bindings.en.md +10 -7
  33. package/docs/user-bindings.md +9 -6
  34. package/docs/value-wire.md +1 -1
  35. package/docs/verification-optimization-work.md +41 -0
  36. package/docs/verification.md +53 -2
  37. package/index.js +39 -34
  38. package/internal/async-local-storage-intrinsics.js +43 -0
  39. package/internal/binding-declaration-contract.js +8 -0
  40. package/internal/binding-source-analysis.js +381 -64
  41. package/internal/binding-update-policy.js +7 -1
  42. package/internal/callable-source-facts.js +37 -1
  43. package/internal/cell-analysis.js +85 -17
  44. package/internal/compiler-intrinsics.js +9 -43
  45. package/internal/compiler-module-links.js +7 -4
  46. package/internal/config-spec.js +1 -1
  47. package/internal/cordis-tools-owner.js +20 -10
  48. package/internal/dynamic-environment-integration.js +8 -4
  49. package/internal/dynamic-environment-runtime.js +24 -3
  50. package/internal/dynamic-native-calls.js +4 -1
  51. package/internal/dynamic-native-runtime.js +15 -1
  52. package/internal/edit-transport-owner.js +80 -20
  53. package/internal/execution-seam-compat.js +192 -30
  54. package/internal/failure-reporting.js +38 -30
  55. package/internal/isolated-worker.js +17 -10
  56. package/internal/kernel-worker.js +645 -393
  57. package/internal/message-sources.js +14 -0
  58. package/internal/module-compilation.js +7 -5
  59. package/internal/module-transform-contract.js +32 -2
  60. package/internal/record-utils.js +24 -15
  61. package/internal/repl-memory-projection.js +10 -0
  62. package/internal/repl-scope-normalizer.js +72 -35
  63. package/internal/repl-value-observer.js +145 -46
  64. package/internal/runtime-config.js +62 -2
  65. package/internal/runtime-intrinsics.js +104 -0
  66. package/internal/runtime-messages.js +6 -4
  67. package/internal/session-cell-executor.js +26 -2
  68. package/internal/session-journal-recovery.js +267 -67
  69. package/internal/session-journal-schema.js +30 -13
  70. package/internal/session-journal.js +485 -44
  71. package/internal/session-log-view.js +5 -4
  72. package/internal/session-runtime.js +46 -21
  73. package/internal/session-state.js +7 -29
  74. package/internal/settings-compat.js +66 -1
  75. package/internal/source-position-map.js +38 -0
  76. package/internal/stateful-root-compiler.js +3 -1
  77. package/internal/typescript-transform.js +4 -2
  78. package/internal/user-binding-console-worker.js +115 -41
  79. package/internal/user-binding-draft-projection.js +3 -2
  80. package/internal/user-bindings-owner.js +2 -1
  81. package/internal/user-bindings.js +16 -3
  82. package/internal/validated-parse-repair.js +6 -2
  83. package/internal/value-wire.js +189 -94
  84. package/internal/worker-client.js +99 -8
  85. package/internal/worker-cwd-virtualization.js +82 -54
  86. package/internal/worker-environment.js +20 -0
  87. package/internal/worker-output-capture.js +187 -0
  88. package/internal/worker-output-fence.js +26 -0
  89. package/internal/worker-realm-surfaces.js +197 -0
  90. package/internal/worker-repl-realm.js +140 -0
  91. package/package.json +37 -4
  92. package/src/client-activity.js +12 -2
  93. package/src/client-authoring-view.js +121 -62
  94. package/src/client-console.js +4 -2
  95. package/src/client-copy.js +4 -2
  96. package/src/client-feature-gates.js +7 -9
  97. package/src/client-host-compat.js +104 -27
  98. package/src/client-repl-view.js +3 -1
  99. package/src/client-styles.js +12 -1
  100. package/src/client-tool-view.js +3 -1
  101. package/src/client-transport.js +2 -2
  102. package/src/client-workbench.js +4 -3
  103. package/src/client.js +56 -17
package/index.js CHANGED
@@ -14,12 +14,12 @@ import { PTC_DELIVERY_CONTEXT } from './internal/runtime-messages.js'
14
14
  import { createCordisToolsOwner } from './internal/cordis-tools-owner.js'
15
15
  import { createEditTransportOwner, EDIT_RUN_CODE } from './internal/edit-transport-owner.js'
16
16
  import { createRuntimeBridgeOwner, RUN_CODE } from './internal/runtime-bridge-owner.js'
17
- import { resolveConfig } from './internal/runtime-config.js'
17
+ import { resolveConfig, watchVolatileConfig } from './internal/runtime-config.js'
18
18
  import {
19
19
  CONFIG_FIELDS,
20
20
  SETTINGS_NAMESPACE,
21
21
  } from './internal/config-spec.js'
22
- import { installSettingsSectionCompat } from './internal/settings-compat.js'
22
+ import { configFieldSchema, installSettingsSectionCompat } from './internal/settings-compat.js'
23
23
  import { installExecutionSeam } from './internal/execution-seam-compat.js'
24
24
  import { valueLimitsFromConfig } from './internal/value-wire-schema.js'
25
25
  import { createReplMemoryProjection } from './internal/repl-memory-projection.js'
@@ -35,19 +35,13 @@ const INSTALL_CLEANUP = Symbol('ptc-plus install cleanup')
35
35
  /** Plugin name used by loader diagnostics. */
36
36
  export const name = 'ptc-plus'
37
37
 
38
- /** Runtime limits and behavior exposed to Cordis configuration. */
39
- function configSchemaField(field) {
40
- const base = field.type === 'boolean'
41
- ? Schema.boolean().default(field.default)
42
- : field.type === 'enum'
43
- // Keep omission visible until resolveConfig migrates legacy policies.
44
- ? Schema.union(field.options.map(option => Schema.const(option)))
45
- : Schema.number().step(1).min(field.min).max(field.max).default(field.default)
46
- return base.description(field.description)
47
- }
48
-
49
38
  export const Config = Schema.object(Object.fromEntries(
50
- CONFIG_FIELDS.map(field => [field.key, configSchemaField(field)]),
39
+ CONFIG_FIELDS.map(field => [
40
+ field.key,
41
+ // Runtime limits and behavior exposed to Cordis configuration. The shape
42
+ // each field takes is owned by the installed settings generation.
43
+ configFieldSchema({ Schema, field, settingsModule: dshSettings }),
44
+ ]),
51
45
  ))
52
46
 
53
47
  /**
@@ -408,22 +402,27 @@ function installPtCRuntime(ctx, resolvedConfig, seam, toolSchemasForAgent, sessi
408
402
  if (exec.name === EDIT_RUN_CODE) return editTransport.handleResult(exec, result)
409
403
  if (exec.name === RUN_CODE) return runtimeBridge.handleResult(exec, result)
410
404
  }))
411
- disposers.push(ctx.on('agent/disposed', async ({ agent }) => {
412
- directSurface.disposeAgent(agent)
413
- editTransport.disposeAgent(agent)
414
- await Promise.all([
415
- runtimeBridge.disposeAgent(agent),
416
- userBindings.clearAgentPresentation(agent),
417
- ])
418
- }))
419
- disposers.push(ctx.on('session/disposed', async (session) => {
420
- directSurface.disposeSession(session)
421
- editTransport.disposeSession(session)
422
- await Promise.all([
423
- runtimeBridge.disposeSession(session),
424
- userBindings.clearSessionPresentation(session?.id ?? session),
425
- ])
426
- }))
405
+ const disposeLifecycleOwners = async (operations, message) => {
406
+ const results = await Promise.allSettled(operations.map(operation => (
407
+ Promise.resolve().then(operation)
408
+ )))
409
+ const failures = results
410
+ .filter(result => result.status === 'rejected')
411
+ .map(result => result.reason)
412
+ if (failures.length > 0) throw new AggregateError(failures, message)
413
+ }
414
+ disposers.push(ctx.on('agent/disposed', ({ agent }) => disposeLifecycleOwners([
415
+ () => directSurface.disposeAgent(agent),
416
+ () => editTransport.disposeAgent(agent),
417
+ () => runtimeBridge.disposeAgent(agent),
418
+ () => userBindings.clearAgentPresentation(agent),
419
+ ], 'ptc-plus: agent disposal failed')))
420
+ disposers.push(ctx.on('session/disposed', session => disposeLifecycleOwners([
421
+ () => directSurface.disposeSession(session),
422
+ () => editTransport.disposeSession(session),
423
+ () => runtimeBridge.disposeSession(session),
424
+ () => userBindings.clearSessionPresentation(session?.id ?? session),
425
+ ], 'ptc-plus: session disposal failed')))
427
426
  disposers.push(ctx.on('agent-preset/selected', (sessionId) => {
428
427
  directSurface.resetSessionComposition(sessionId)
429
428
  const agent = ctx.agents?.get?.(String(sessionId))
@@ -512,18 +511,22 @@ function installPtCRuntime(ctx, resolvedConfig, seam, toolSchemasForAgent, sessi
512
511
  }
513
512
 
514
513
  /** Register the session-bound REPL runtime. */
515
- export function apply(ctx, config = {}) {
514
+ export const apply = (ctx, config = {}) => {
516
515
  // Configuration is validated before the plugin waits for the host's seam, so
517
516
  // an unusable configuration fails at the load call rather than later.
518
517
  const resolvedConfig = resolveConfig(config)
519
518
  return installExecutionSeam(ctx, {
520
519
  services: inject,
521
- attach: (scope, seam) => applyWithExecutionSeam(scope, resolvedConfig, seam),
520
+ attach: (scope, seam) => applyWithExecutionSeam(scope, resolvedConfig, seam, ctx, config),
521
+ reportFailure: (error, seamName) => ctx.logger?.warn?.(
522
+ `ptc-plus: execution seam ${seamName} failed to attach`,
523
+ error,
524
+ ),
522
525
  })
523
526
  }
524
527
 
525
528
  /** Install the plugin into the scope of the seam the host registered. */
526
- function applyWithExecutionSeam(ctx, resolvedConfig, seam) {
529
+ function applyWithExecutionSeam(ctx, resolvedConfig, seam, volatileHost, volatileConfig) {
527
530
  const toolSchemasForAgent = agent => typeof ctx.tools.schemas === 'function'
528
531
  ? ctx.tools.schemas(agent)
529
532
  : []
@@ -767,7 +770,7 @@ function applyWithExecutionSeam(ctx, resolvedConfig, seam) {
767
770
  ctx.effect(() => ctx.on('agent/disposed', ({ agent }) => messageOwner.disposeAgent(agent)), 'ptc-plus message agent disposal')
768
771
  ctx.effect(() => () => messageOwner.dispose(), 'ptc-plus dynamic message lifecycle')
769
772
 
770
- let configSource = () => resolvedConfig
773
+ let configSource = () => resolveConfig(volatileConfig ?? resolvedConfig)
771
774
  let configurationGeneration = 0
772
775
  let settingsWriter
773
776
  let configurationRollback = false
@@ -826,6 +829,7 @@ function applyWithExecutionSeam(ctx, resolvedConfig, seam) {
826
829
  if (typeof ctx.inject === 'function') {
827
830
  installSettingsSectionCompat({
828
831
  ctx,
832
+ ownerFiber: volatileHost.fiber,
829
833
  settingsModule: dshSettings,
830
834
  namespace: SETTINGS_NAMESPACE,
831
835
  schema: Config,
@@ -841,5 +845,6 @@ function applyWithExecutionSeam(ctx, resolvedConfig, seam) {
841
845
  },
842
846
  })
843
847
  }
848
+ watchVolatileConfig(volatileHost, ctx, volatileConfig, () => reconcile())
844
849
  if (configurationGeneration === 0) return reconcile(settingsWriter === undefined)
845
850
  }
@@ -0,0 +1,43 @@
1
+ import { AsyncLocalStorage } from 'node:async_hooks'
2
+ import { WORKER_REALM_MUTATION, defineWorkerRealmProperty } from './worker-realm-surfaces.js'
3
+
4
+ const bind = Function.prototype.call.bind(Function.prototype.bind)
5
+ const getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor
6
+ const apply = Reflect.apply
7
+ const nativeGetStore = AsyncLocalStorage.prototype.getStore
8
+ const nativeEnterWith = AsyncLocalStorage.prototype.enterWith
9
+ const nativeRun = AsyncLocalStorage.prototype.run
10
+ const nativeRunDescriptor = getOwnPropertyDescriptor(AsyncLocalStorage.prototype, 'run')
11
+
12
+ function protect(scope) {
13
+ defineWorkerRealmProperty(WORKER_REALM_MUTATION.STABLE, 'private AsyncLocalStorage receiver methods',
14
+ scope, 'getStore', { value: bind(nativeGetStore, scope) })
15
+ defineWorkerRealmProperty(WORKER_REALM_MUTATION.STABLE, 'private AsyncLocalStorage receiver methods',
16
+ scope, 'enterWith', { value: bind(nativeEnterWith, scope) })
17
+ defineWorkerRealmProperty(WORKER_REALM_MUTATION.STABLE, 'private AsyncLocalStorage receiver methods',
18
+ scope, 'run', { value: bind(nativeRun, scope) })
19
+ return scope
20
+ }
21
+
22
+ export function createPrivateAsyncLocalStorage() {
23
+ return protect(new AsyncLocalStorage())
24
+ }
25
+
26
+ export function protectNextAsyncLocalStorageRun(invoke) {
27
+ let scope
28
+ defineWorkerRealmProperty(WORKER_REALM_MUTATION.TEMPORARY, 'AsyncLocalStorage.prototype.run',
29
+ AsyncLocalStorage.prototype, 'run', {
30
+ ...nativeRunDescriptor,
31
+ value: function (...args) {
32
+ scope ??= protect(this)
33
+ return apply(nativeRun, this, args)
34
+ },
35
+ })
36
+ try {
37
+ invoke()
38
+ } finally {
39
+ defineWorkerRealmProperty(WORKER_REALM_MUTATION.RESTORE, 'AsyncLocalStorage.prototype.run',
40
+ AsyncLocalStorage.prototype, 'run', nativeRunDescriptor)
41
+ }
42
+ return scope
43
+ }
@@ -0,0 +1,8 @@
1
+ const BINDING_TYPE_NAMESPACE_TOKEN = '__ptcBindingTypes'
2
+
3
+ export function bindingTypeNamespaceToken(source) {
4
+ let token = BINDING_TYPE_NAMESPACE_TOKEN
5
+ let suffix = 0
6
+ while (source.includes(token)) token = `${BINDING_TYPE_NAMESPACE_TOKEN}_${++suffix}`
7
+ return token
8
+ }