dsh-ptc-plus 0.4.10 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/README.en.md +65 -127
  2. package/README.md +65 -127
  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-repl-workspace-en.png +0 -0
  6. package/assets/ptc-plus-repl-workspace-zh.png +0 -0
  7. package/assets/ptc-plus-settings-en.png +0 -0
  8. package/assets/ptc-plus-settings-zh.png +0 -0
  9. package/client.cjs +42702 -0
  10. package/cordis.patch.yml +1 -0
  11. package/docs/README.md +6 -2
  12. package/docs/adr/0005-temporary-rejected-cell-edit-transport.md +31 -198
  13. package/docs/adr/0008-define-agent-operating-contract.md +5 -1
  14. package/docs/adr/0009-bound-expensive-acceptance-default.md +2 -2
  15. package/docs/adr/0016-archive-resolved-review-findings.md +1 -1
  16. package/docs/adr/0017-track-the-latest-dsh-public-surface.md +4 -4
  17. package/docs/adr/0019-plugin-settings-and-kill-switch.md +1 -1
  18. package/docs/adr/0020-optional-cordis-tools-in-ptc-mode.md +1 -1
  19. package/docs/adr/0022-stage-npm-releases-with-oidc.md +4 -2
  20. package/docs/adr/0023-global-user-bindings.md +2 -0
  21. package/docs/adr/0026-persist-the-delivery-verdict-against-the-verified-candidate.md +2 -0
  22. package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +25 -23
  23. package/docs/adr/0031-close-semantic-obligations-by-owner.md +1 -1
  24. package/docs/adr/0034-keep-program-values-separate-from-output-projections.md +29 -0
  25. package/docs/adr/0035-run-coverage-only-before-a-new-release.md +27 -0
  26. package/docs/adr/0036-separate-focused-development-from-delivery-verification.md +29 -0
  27. package/docs/adr/0037-keep-tool-hover-previews-passive.md +52 -0
  28. package/docs/adr/0038-freeze-session-capability-plans.md +71 -0
  29. package/docs/adr/0039-verify-documentation-without-runtime-suites.md +29 -0
  30. package/docs/adr/0040-separate-capability-configurations-from-session-observations.md +39 -0
  31. package/docs/adr/0041-record-cell-execution-directories.md +65 -0
  32. package/docs/adr/0042-persist-provider-availability-and-handback.md +41 -0
  33. package/docs/adr/0043-compose-capability-and-context-policies.md +37 -0
  34. package/docs/adr/0044-coexist-with-the-official-persistent-repl.md +35 -0
  35. package/docs/adr/README.md +8 -0
  36. package/docs/architecture.md +23 -25
  37. package/docs/capability-planning-components.md +93 -0
  38. package/docs/capability-projection.md +7 -0
  39. package/docs/client-ui.md +70 -23
  40. package/docs/client-visual-contract.md +26 -9
  41. package/docs/context-management.md +22 -0
  42. package/docs/context-optimization-plan.md +353 -0
  43. package/docs/context-public-interface-coverage.md +25 -0
  44. package/docs/durability-design.md +20 -15
  45. package/docs/evaluation.md +41 -6
  46. package/docs/evaluations/command-goat-deepseek-v4.1-flash-20261006.md +126 -0
  47. package/docs/evaluations/command-goat-deepseek-v4.1-flash.md +281 -0
  48. package/docs/installation.md +33 -10
  49. package/docs/program-data-plane.md +5 -3
  50. package/docs/publishing.md +7 -7
  51. package/docs/release-coverage.md +73 -0
  52. package/docs/release-notes.md +1 -1
  53. package/docs/review-procedure.md +56 -0
  54. package/docs/runtime-reference.md +53 -16
  55. package/docs/semantic-validation.md +14 -2
  56. package/docs/stateful-binding-updates-proposal.md +2 -2
  57. package/docs/user-bindings.md +1 -1
  58. package/docs/value-wire.md +11 -1
  59. package/docs/verification-optimization-work.md +26 -15
  60. package/docs/verification.md +30 -88
  61. package/index.js +146 -20
  62. package/internal/binding-toggle-receipt.js +24 -0
  63. package/internal/capability-command-receipt.js +31 -0
  64. package/internal/capability-environment.js +1253 -0
  65. package/internal/capability-plan.js +285 -0
  66. package/internal/capability-policy.js +96 -0
  67. package/internal/capability-statistics-store.js +180 -0
  68. package/internal/capability-statistics.js +214 -0
  69. package/internal/config-spec.js +89 -10
  70. package/internal/direct-surface-owner.js +27 -29
  71. package/internal/dynamic-environment-runtime.js +9 -9
  72. package/internal/edit-transport-owner.js +195 -140
  73. package/internal/execution-provider-owner.js +40 -12
  74. package/internal/execution-seam-compat.js +26 -8
  75. package/internal/kernel-worker.js +104 -32
  76. package/internal/native-root-dynamic.js +12 -13
  77. package/internal/official-repl-priority.js +51 -0
  78. package/internal/program-bindings.js +190 -0
  79. package/internal/recovery-tips.js +3 -2
  80. package/internal/rejected-cell-editor.js +8 -8
  81. package/internal/repl-observation-interest.js +11 -3
  82. package/internal/rpc-contract.js +1 -0
  83. package/internal/runtime-bridge-owner.js +275 -34
  84. package/internal/runtime-config.js +58 -0
  85. package/internal/runtime-contexts.js +74 -5
  86. package/internal/runtime-intrinsics.js +1 -0
  87. package/internal/runtime-messages.js +41 -0
  88. package/internal/sdk-projection.js +10 -82
  89. package/internal/session-cell-executor.js +42 -19
  90. package/internal/session-events.js +34 -0
  91. package/internal/session-journal-recovery.js +234 -11
  92. package/internal/session-journal-schema.js +6 -3
  93. package/internal/session-journal.js +31 -2
  94. package/internal/session-log-view.js +1 -1
  95. package/internal/session-runtime.js +119 -15
  96. package/internal/settings-compat.js +12 -5
  97. package/internal/stateful-module-compiler.js +3 -2
  98. package/internal/stateful-module-runtime.js +7 -3
  99. package/internal/stateful-root-runtime.js +9 -4
  100. package/internal/user-binding-authoring.js +2 -7
  101. package/internal/user-bindings-owner.js +19 -2
  102. package/internal/validated-parse-repair.js +1 -1
  103. package/internal/value-wire.js +68 -21
  104. package/internal/worker-cwd-virtualization.js +20 -18
  105. package/internal/worker-realm-surfaces.js +3 -3
  106. package/package.json +49 -30
  107. package/src/client-activity.js +3 -2
  108. package/src/client-authoring-view.js +67 -30
  109. package/src/client-binding-review.js +2 -1
  110. package/src/client-binding-toggle.js +18 -0
  111. package/src/client-capabilities-view.js +1555 -0
  112. package/src/client-capability-sort.js +29 -0
  113. package/src/client-copy.js +923 -8
  114. package/src/client-feature-gates.js +3 -0
  115. package/src/client-indicator-view.js +4 -6
  116. package/src/client-primitives.js +33 -2
  117. package/src/client-repl-view.js +20 -13
  118. package/src/client-settings-view.js +411 -41
  119. package/src/client-styles.js +112 -15
  120. package/src/client-tool-hover.js +185 -0
  121. package/src/client-tool-view.js +45 -9
  122. package/src/client-transport.js +44 -9
  123. package/src/client-workbench.js +6 -7
  124. package/src/client.js +76 -22
  125. package/client.js +0 -32479
@@ -13,10 +13,13 @@ const FEATURE_SETTINGS = Object.freeze({
13
13
  bindings: ['userBindingsEnabled'],
14
14
  // Enhanced run_code tool rows.
15
15
  toolView: ['enhancedToolView'],
16
+ toolHover: ['enhancedToolView', 'toolHoverPreviewEnabled'],
16
17
  // The REPL view tab; the session preset condition is added by its registration.
17
18
  replView: ['replViewEnabled'],
18
19
  // The composer authoring menu.
19
20
  authorButton: ['userBindingsEnabled', 'bindingAuthorButtonVisible'],
21
+ // Settings and capability refresh do not require Global User Bindings.
22
+ ptcMenu: ['bindingAuthorButtonVisible'],
20
23
  })
21
24
 
22
25
  /**
@@ -22,6 +22,7 @@ export function createIndicatorView(React, deps) {
22
22
  normalizeReplMemorySnapshot, unavailableReplMemorySnapshot,
23
23
  ReplMemoryCard, replPopoverIsOpen, placeReplPopover,
24
24
  catalogOwner, subscribeReset,
25
+ useObservedReplMemory, observeRepl,
25
26
  } = deps
26
27
  const h = React.createElement
27
28
 
@@ -225,13 +226,10 @@ export function createIndicatorView(React, deps) {
225
226
  }
226
227
  }
227
228
  }, [cancelClose, cancelOpen, schedulePlacement])
229
+ const memory = useObservedReplMemory({ sessionId, projected: projectionMemory,
230
+ active: expanded && sessionUsesPtcPreset(preset) && featureEnabled(settings, 'plugin'),
231
+ elementRef: popoverRef, observeRepl })
228
232
  if (!sessionUsesPtcPreset(preset) || !featureEnabled(settings, 'plugin')) return null
229
- let memory
230
- try {
231
- memory = normalizeReplMemorySnapshot(projectionMemory)
232
- } catch {
233
- memory = unavailableReplMemorySnapshot()
234
- }
235
233
  const popoverId = `ptc-plus-repl-${String(resolvedSessionId).replace(/[^A-Za-z0-9_-]/g, '-')}`
236
234
  const titleId = `${popoverId}-title`
237
235
  return h('span', { className: 'ptcPlusActiveShell', ref: shellRef },
@@ -1,4 +1,5 @@
1
1
  import { isHostComponent } from './client-host-compat.js'
2
+ import * as RadixSelect from '@radix-ui/react-select'
2
3
 
3
4
  /**
4
5
  * Resolve the Harness Client components this plugin renders against the
@@ -161,7 +162,7 @@ function createFallbackModal(React, createPortal = content => content) {
161
162
  const close = React.useRef(onClose)
162
163
  close.current = onClose
163
164
  const isComposing = useCompositionGuard(React, open)
164
- const focusable = 'button:not(:disabled),input:not(:disabled),textarea:not(:disabled),select:not(:disabled),[href],[tabindex]:not([tabindex="-1"])'
165
+ const focusable = 'button:not(:disabled),input:not(:disabled),textarea:not(:disabled),select:not(:disabled),[href],[tabindex]:not([tabindex="-1"]),[contenteditable=true],summary'
165
166
  React.useLayoutEffect(() => {
166
167
  if (!open) return undefined
167
168
  const previous = document.activeElement
@@ -187,7 +188,7 @@ function createFallbackModal(React, createPortal = content => content) {
187
188
  if (!event.repeat) close.current?.()
188
189
  } else if (event.key === 'Tab') {
189
190
  const controls = [...root.current.querySelectorAll(focusable)]
190
- .filter(control => control.getClientRects().length > 0)
191
+ .filter(control => control.getClientRects().length > 0 && !control.closest('[aria-hidden=true],[hidden]'))
191
192
  const target = event.shiftKey ? controls.at(-1) : controls[0]
192
193
  const boundary = event.shiftKey ? controls[0] : controls.at(-1)
193
194
  if (controls.length === 0 || document.activeElement === boundary || !root.current.contains(document.activeElement)) {
@@ -225,12 +226,42 @@ export function resolvePrimitives(primitives, React, createPortal) {
225
226
  DisclosureRow: primitives.DisclosureRow,
226
227
  Menu: isHostComponent(primitives.Menu) ? primitives.Menu : createFallbackMenu(React, createPortal),
227
228
  MenuFallback: createFallbackMenu(React, createPortal),
229
+ Select: createSelect(React),
228
230
  Modal: isHostComponent(primitives.Modal) ? primitives.Modal : createFallbackModal(React, createPortal),
229
231
  Toast: primitives.Toast,
230
232
  Tooltip: primitives.Tooltip,
231
233
  })
232
234
  }
233
235
 
236
+ /** Shared themed choice control; Radix owns listbox focus, typeahead, and dismissal. */
237
+ export function createSelect(React) {
238
+ const h = React.createElement
239
+ return function Select({ value, options, onChange, label, disabled = false, className = '',
240
+ placeholder, dataStrategy, autoFocus = false }) {
241
+ const [open, setOpen] = React.useState(false)
242
+ React.useEffect(() => { if (disabled) setOpen(false) }, [disabled])
243
+ const chosen = options.find(option => option.value === value)
244
+ let emptyToken = '__ptc_plus_empty_choice__'
245
+ while (options.some(option => option.value === emptyToken)) emptyToken += '_'
246
+ return h(RadixSelect.Root, { value: value === '' ? emptyToken : value, open, disabled,
247
+ onOpenChange: setOpen, onValueChange: next => onChange(next === emptyToken ? '' : next) },
248
+ h(RadixSelect.Trigger, { className: ['ptcPlusSelectTrigger', className].filter(Boolean).join(' '),
249
+ 'aria-label': label, 'data-strategy': dataStrategy, 'data-modal-autofocus': autoFocus || undefined },
250
+ h(RadixSelect.Value, { placeholder: placeholder ?? chosen?.label ?? '' }),
251
+ h(RadixSelect.Icon, { className: 'ptcPlusSelectChevron', 'aria-hidden': true },
252
+ h('svg', { viewBox: '0 0 16 16', width: 16, height: 16, fill: 'none' },
253
+ h('path', { d: 'm4 6 4 4 4-4', stroke: 'currentColor', strokeWidth: 1.5, strokeLinecap: 'round', strokeLinejoin: 'round' })))),
254
+ h(RadixSelect.Portal, null,
255
+ h(RadixSelect.Content, { className: 'ptcPlusSelectMenu', position: 'popper', sideOffset: 4,
256
+ onEscapeKeyDown: event => event.stopPropagation() },
257
+ h(RadixSelect.Viewport, { className: 'ptcPlusSelectViewport' },
258
+ ...options.map(option => h(RadixSelect.Item, { key: option.value, value: option.value === '' ? emptyToken : option.value,
259
+ disabled: option.disabled === true, className: 'ptcPlusSelectOption' },
260
+ h(RadixSelect.ItemText, null, option.label),
261
+ h(RadixSelect.ItemIndicator, { className: 'ptcPlusSelectCheck' }, '✓')))))))
262
+ }
263
+ }
264
+
234
265
  /** Adapt host action styling, or own it completely when the primitive is absent. */
235
266
  export function createActionButton(React, Button) {
236
267
  const h = React.createElement
@@ -7,7 +7,7 @@ import { isHostComponent, isHostIconComponent } from './client-host-compat.js'
7
7
  */
8
8
  export function createReplView(React, deps) {
9
9
  const {
10
- CodeBlock, featureEnabled, normalizeReplMemorySnapshot,
10
+ CodeBlock, Select, featureEnabled, normalizeReplMemorySnapshot,
11
11
  unavailableReplMemorySnapshot, useSessionPreset, sessionUsesPtcPreset,
12
12
  useWorkbenchController, UserBindingsWorkbench,
13
13
  icons: { search: IconSearchOutline16, chevron: IconChevronDownOutline14 },
@@ -16,6 +16,18 @@ export function createReplView(React, deps) {
16
16
 
17
17
  function ReplComposer() { return null }
18
18
 
19
+ function useObservedReplMemory({ sessionId, projected, active, elementRef, observeRepl }) {
20
+ const memory = React.useMemo(() => {
21
+ try { return normalizeReplMemorySnapshot(projected) } catch { return unavailableReplMemorySnapshot() }
22
+ }, [projected])
23
+ const [observed, setObserved] = React.useState(null)
24
+ React.useEffect(() => active && typeof observeRepl === 'function'
25
+ ? observeRepl(sessionId, elementRef.current, memory,
26
+ value => setObserved({ sessionId, source: memory, value }))
27
+ : undefined, [active, observeRepl, sessionId, memory, elementRef])
28
+ return observed?.sessionId === sessionId && observed.source === memory ? observed.value : memory
29
+ }
30
+
19
31
  function ReplBindingInspector({ entry, preview, t }) {
20
32
  const readable = preview?.status === 'readable'
21
33
  return h('aside', { className: 'ptcPlusBindingInspector', 'aria-label': entry.name },
@@ -61,10 +73,9 @@ export function createReplView(React, deps) {
61
73
  isHostIconComponent(IconSearchOutline16) ? h(IconSearchOutline16, { size: 16 }) : null,
62
74
  h('input', { value: query, onChange: event => setQuery(event.target.value),
63
75
  placeholder: t('console.search'), 'aria-label': t('console.search') })),
64
- h('select', { className: 'ptcPlusSelect', value: kind, onChange: event => setKind(event.target.value),
65
- 'aria-label': t('console.kind') },
66
- ['all', 'variable', 'function', 'class', 'import'].map(value => h('option', { key: value, value },
67
- t(value === 'all' ? 'console.allKinds' : `memory.kind.${value}`))))),
76
+ h(Select, { value: kind, onChange: setKind, label: t('console.kind'),
77
+ options: ['all', 'variable', 'function', 'class', 'import'].map(value => ({ value,
78
+ label: t(value === 'all' ? 'console.allKinds' : `memory.kind.${value}`) })) })),
68
79
  h('div', { className: 'ptcPlusObservations' },
69
80
  h('table', { className: 'ptcPlusObservationTable', 'aria-label': t('console.session') },
70
81
  h('thead', null, h('tr', null,
@@ -98,18 +109,14 @@ export function createReplView(React, deps) {
98
109
  const globalEnabled = featureEnabled(settings, 'bindings')
99
110
  const workbench = useWorkbenchController({ enabled: globalEnabled, active: true, callUserBindings })
100
111
  const eligible = featureEnabled(settings, 'replView') && sessionUsesPtcPreset(preset)
101
- const memory = React.useMemo(() => {
102
- try { return normalizeReplMemorySnapshot(projected) } catch { return unavailableReplMemorySnapshot() }
103
- }, [projected])
104
- const [observed, setObserved] = React.useState(null)
105
112
  const observationRegion = React.useRef(null)
113
+ const memory = useObservedReplMemory({ sessionId, projected, active: eligible,
114
+ elementRef: observationRegion, observeRepl })
106
115
  React.useEffect(() => eligible ? hideComposer(sessionId) : undefined, [eligible, hideComposer, sessionId])
107
- React.useEffect(() => eligible ? observeRepl(sessionId, observationRegion.current, memory,
108
- value => setObserved({ sessionId, source: memory, value })) : undefined, [eligible, observeRepl, sessionId, memory])
109
116
  if (!eligible) return null
110
117
  return h('div', { className: 'ptcPlusConsole', 'data-conversation-composer-overlay': '' },
111
118
  h('div', { className: 'ptcPlusConsoleSection', ref: observationRegion }, h(ReplSessionBindings, {
112
- key: sessionId, memory: observed?.sessionId === sessionId && observed.source === memory ? observed.value : memory, t })),
119
+ key: sessionId, memory, t })),
113
120
  globalEnabled ? h('div', { className: 'ptcPlusConsoleSection ptcPlusBindingsSurface' },
114
121
  h(UserBindingsWorkbench, { controller: workbench, t, headingLabel: t('console.global') })) : null)
115
122
  }
@@ -290,5 +297,5 @@ export function createReplView(React, deps) {
290
297
  : h('span', { className: 'ptcPlusReplMore' }, t('memory.more', { count: memory.omitted }))))
291
298
  }
292
299
 
293
- return { ReplComposer, ReplConsole, ReplMemoryCard, replPopoverIsOpen, placeReplPopover }
300
+ return { ReplComposer, ReplConsole, ReplMemoryCard, replPopoverIsOpen, placeReplPopover, useObservedReplMemory }
294
301
  }