dsh-ptc-plus 0.5.2 → 0.5.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 (53) hide show
  1. package/README.en.md +3 -1
  2. package/README.md +3 -1
  3. package/client.cjs +165 -29
  4. package/docs/adr/0017-track-the-latest-dsh-public-surface.md +4 -2
  5. package/docs/adr/0019-plugin-settings-and-kill-switch.md +2 -2
  6. package/docs/adr/0023-global-user-bindings.md +12 -0
  7. package/docs/adr/0028-attach-to-the-host-ptc-execution-seam.md +1 -1
  8. package/docs/adr/0030-serve-both-typert-codec-generations-from-one-codec.md +2 -2
  9. package/docs/adr/0044-coexist-with-the-official-persistent-repl.md +4 -4
  10. package/docs/adr/0046-gate-the-commit-with-the-semantic-evidence-tier.md +1 -1
  11. package/docs/adr/0048-supersede-a-rewritten-cell.md +48 -0
  12. package/docs/adr/0049-prove-a-settlement-against-its-published-record.md +53 -0
  13. package/docs/adr/0050-read-host-surfaces-through-their-published-contract.md +48 -0
  14. package/docs/adr/README.md +7 -1
  15. package/docs/architecture.md +1 -1
  16. package/docs/durability-design.md +9 -2
  17. package/docs/installation.md +9 -9
  18. package/docs/releases/v0.5.2.md +26 -14
  19. package/docs/releases/v0.5.3.md +77 -0
  20. package/docs/runtime-reference.md +7 -1
  21. package/docs/user-bindings.en.md +15 -0
  22. package/docs/user-bindings.md +15 -0
  23. package/docs/v0.5.3-goals.md +117 -0
  24. package/docs/verification.md +4 -4
  25. package/index.js +67 -19
  26. package/internal/binding-adoption.js +136 -0
  27. package/internal/capability-command-receipt.js +18 -4
  28. package/internal/capability-delivery-proof.js +70 -0
  29. package/internal/capability-environment.js +38 -1
  30. package/internal/config-spec.js +14 -5
  31. package/internal/cordis-tools-owner.js +2 -1
  32. package/internal/direct-surface-owner.js +27 -13
  33. package/internal/edit-transport-owner.js +6 -5
  34. package/internal/execution-provider-owner.js +6 -0
  35. package/internal/execution-seam-compat.js +25 -0
  36. package/internal/host-tool-sdk.js +308 -0
  37. package/internal/official-repl-priority.js +31 -10
  38. package/internal/program-bindings.js +12 -1
  39. package/internal/repl-memory-projection.js +21 -2
  40. package/internal/runtime-bridge-owner.js +113 -8
  41. package/internal/runtime-messages.js +5 -0
  42. package/internal/session-journal-recovery.js +210 -32
  43. package/internal/session-journal-schema.js +3 -0
  44. package/internal/session-journal.js +46 -9
  45. package/internal/session-log-view.js +22 -2
  46. package/internal/session-runtime.js +106 -39
  47. package/internal/user-bindings-owner.js +109 -6
  48. package/package.json +15 -7
  49. package/src/client-capabilities-view.js +45 -3
  50. package/src/client-copy.js +24 -0
  51. package/src/client-indicator-view.js +2 -1
  52. package/src/client-repl-view.js +35 -16
  53. package/src/client.js +3 -1
@@ -244,6 +244,17 @@ const CHROME_COPY = Object.freeze({
244
244
  'capabilities.receipt.off': '能力管理已关闭;会话 {session} 沿用宿主能力。',
245
245
  'capabilities.receipt.unavailable': '请选择仍活跃的 PTC 会话。',
246
246
  'capabilities.receipt.usage': '使用 /capabilities 查看,或 /capabilities refresh 同步已保存设置。',
247
+ 'capabilities.proof.title': '三层事实',
248
+ 'capabilities.proof.line': '已保存:{saved};已投递:{delivery};已可用:{usability}。',
249
+ 'capabilities.proof.saved.yes': '是,全局设置记录了这项选择',
250
+ 'capabilities.proof.saved.no': '否,这条命令没有改动全局设置',
251
+ 'capabilities.proof.delivery.delivered': '是,模型可见目录已在受理的步骤发布该项',
252
+ 'capabilities.proof.delivery.pending': '尚未,已保存的设置要到下一个受理步骤才进入目录',
253
+ 'capabilities.proof.delivery.absent': '否,目录没有列出该项,模型没有收到它',
254
+ 'capabilities.proof.usability.proven': '已证明,本会话有完成的执行取到了它',
255
+ 'capabilities.proof.usability.unproven': '未证明,本会话没有完成的执行取到过它;保存或发布都不构成证明',
256
+ 'capabilities.proof.observed': '来自 {command} 返回的收据。',
257
+ 'capabilities.proof.unobserved': '本面板还没有这项能力的投递与可用性证据;应用一次改动,或回到会话查看命令收据。',
247
258
  'bindings.toggleEnabled': '已保存“{name}”的启用选择;模型目录在下一次获准步骤更新,程序值尚未证明初始化。',
248
259
  'bindings.toggleDisabled': '已保存“{name}”的停用选择;模型目录在下一次获准步骤撤销,不撤销已经发生的效果。',
249
260
  'capabilities.observationGroup': '只读会话观察',
@@ -684,6 +695,7 @@ const CHROME_COPY = Object.freeze({
684
695
  'memory.globalCount': '{count} 个全局条目',
685
696
  'memory.empty': '当前没有可复用绑定',
686
697
  'memory.unavailable': '当前绑定状态尚不可确认',
698
+ 'memory.previousRuntime': '这份清单来自上一个运行期,不再代表当前环境;执行一格即可重新观察',
687
699
  'memory.more': '另有 {count} 个绑定未显示',
688
700
  'memory.reuseCount': '复用 {count} 次',
689
701
  'memory.reuseTotal': '共复用 {count} 次',
@@ -958,6 +970,17 @@ const CHROME_COPY = Object.freeze({
958
970
  'capabilities.receipt.off': 'Capability management is off; session {session} stays with the Host capabilities.',
959
971
  'capabilities.receipt.unavailable': 'Select an active PTC session.',
960
972
  'capabilities.receipt.usage': 'Use /capabilities to inspect or /capabilities refresh to apply saved settings.',
973
+ 'capabilities.proof.title': 'Three separate facts',
974
+ 'capabilities.proof.line': 'Saved: {saved}; delivered: {delivery}; usable: {usability}.',
975
+ 'capabilities.proof.saved.yes': 'yes, the global configuration records this choice',
976
+ 'capabilities.proof.saved.no': 'no, this command did not change the global configuration',
977
+ 'capabilities.proof.delivery.delivered': 'yes, the model-visible catalog published it at an accepted step',
978
+ 'capabilities.proof.delivery.pending': 'not yet, the saved configuration reaches the catalog at the next accepted step',
979
+ 'capabilities.proof.delivery.absent': 'no, the catalog does not list it, so the model never received it',
980
+ 'capabilities.proof.usability.proven': 'proven, a completed execution in this session reached it',
981
+ 'capabilities.proof.usability.unproven': 'unproven, no completed execution in this session reached it; a save or a published entry does not prove it',
982
+ 'capabilities.proof.observed': 'From the receipt {command} returned.',
983
+ 'capabilities.proof.unobserved': 'This panel holds no delivery or usability evidence for this capability yet; apply a change, or read the command receipt in the conversation.',
961
984
  'bindings.toggleEnabled': 'Enabled “{name}” in saved configuration. The model catalog updates at the next accepted step; worker initialization is not yet established.',
962
985
  'bindings.toggleDisabled': 'Disabled “{name}” in saved configuration. The model catalog withdraws it at the next accepted step; earlier effects are unchanged.',
963
986
  'capabilities.observationGroup': 'Read-only session observation',
@@ -1395,6 +1418,7 @@ const CHROME_COPY = Object.freeze({
1395
1418
  'memory.globalCount': '{count} global entries',
1396
1419
  'memory.empty': 'No reusable bindings',
1397
1420
  'memory.unavailable': 'Current binding state cannot be confirmed',
1421
+ 'memory.previousRuntime': 'This inventory came from a previous runtime and no longer describes the current environment; run a cell to observe it again',
1398
1422
  'memory.more': '{count} more bindings not shown',
1399
1423
  // Number-neutral so a single reuse stays grammatical without a plural rule.
1400
1424
  'memory.reuseCount': 'reused {count}\u00d7',
@@ -226,7 +226,7 @@ export function createIndicatorView(React, deps) {
226
226
  }
227
227
  }
228
228
  }, [cancelClose, cancelOpen, schedulePlacement])
229
- const memory = useObservedReplMemory({ sessionId, projected: projectionMemory,
229
+ const { memory, provenance } = useObservedReplMemory({ sessionId, projected: projectionMemory,
230
230
  active: expanded && sessionUsesPtcPreset(preset) && featureEnabled(settings, 'plugin'),
231
231
  elementRef: popoverRef, observeRepl })
232
232
  if (!sessionUsesPtcPreset(preset) || !featureEnabled(settings, 'plugin')) return null
@@ -251,6 +251,7 @@ export function createIndicatorView(React, deps) {
251
251
  }, h('span', { className: 'ptcPlusActiveLabel' }, 'PTC Plus')),
252
252
  h(ReplMemoryCard, {
253
253
  memory,
254
+ provenance,
254
255
  globalEnabled,
255
256
  globalBindings,
256
257
  loadGlobalBinding: id => callUserBindings('load', { id }),
@@ -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, Select, featureEnabled, normalizeReplMemorySnapshot,
10
+ CodeBlock, Select, featureEnabled, normalizeReplMemorySnapshot, normalizeReplMemoryView,
11
11
  unavailableReplMemorySnapshot, useSessionPreset, sessionUsesPtcPreset,
12
12
  useWorkbenchController, UserBindingsWorkbench,
13
13
  icons: { search: IconSearchOutline16, chevron: IconChevronDownOutline14 },
@@ -16,21 +16,37 @@ export function createReplView(React, deps) {
16
16
 
17
17
  function ReplComposer() { return null }
18
18
 
19
+ /**
20
+ * The projection's own observation, marked with the runtime that produced it.
21
+ *
22
+ * Freshness and provenance are different questions. A projection refresh inside
23
+ * one runtime can drop the memory while the observation still describes that
24
+ * runtime's environment, and falling back to the empty snapshot there would flip
25
+ * a populated panel to "cannot be confirmed" for no visible reason. A snapshot
26
+ * carrying a different runtime is the opposite case: the environment it describes
27
+ * no longer exists, so the panel must say that instead of showing it as current.
28
+ */
19
29
  function useObservedReplMemory({ sessionId, projected, active, elementRef, observeRepl }) {
20
- const memory = React.useMemo(() => {
21
- try { return normalizeReplMemorySnapshot(projected) } catch { return unavailableReplMemorySnapshot() }
30
+ const view = React.useMemo(() => {
31
+ try { return normalizeReplMemoryView(projected) } catch { return undefined }
22
32
  }, [projected])
33
+ const memory = view?.memory ?? unavailableReplMemorySnapshot()
23
34
  const [observed, setObserved] = React.useState(null)
24
35
  React.useEffect(() => active && typeof observeRepl === 'function'
25
36
  ? observeRepl(sessionId, elementRef.current, memory,
26
- value => setObserved({ sessionId, source: memory, value }))
27
- : undefined, [active, observeRepl, sessionId, memory, elementRef])
28
- if (observed?.sessionId !== sessionId) return memory
29
- // The projection can drop its REPL memory while a live observation still holds
30
- // the last confirmed inventory; falling back to the empty snapshot there would
31
- // flip a populated panel to "state cannot be confirmed" for no visible reason.
32
- if (!memory.available && observed.value?.available === true) return observed.value
33
- return observed.source === memory ? observed.value : memory
37
+ value => setObserved({ sessionId, runtime: view?.runtime, source: memory, value }))
38
+ : undefined, [active, observeRepl, sessionId, memory, view, elementRef])
39
+ if (observed?.sessionId !== sessionId) return { memory, provenance: 'current' }
40
+ if (view !== undefined && observed.runtime !== view.runtime
41
+ && !(observed.runtime === undefined && view.runtime === undefined)) {
42
+ return { memory, provenance: 'previous-runtime' }
43
+ }
44
+ // Same runtime: the observation is a fresher reading of the same environment,
45
+ // so it outlives a projection refresh that lost the inventory.
46
+ if (observed.runtime === view?.runtime && !memory.available && observed.value?.available === true) {
47
+ return { memory: observed.value, provenance: 'refreshed' }
48
+ }
49
+ return { memory: observed.source === memory ? observed.value : memory, provenance: 'current' }
34
50
  }
35
51
 
36
52
  function ReplBindingInspector({ entry, preview, t }) {
@@ -50,7 +66,7 @@ export function createReplView(React, deps) {
50
66
  : h('p', { className: 'ptcPlusObservationUnavailable' }, t(preview === undefined ? 'console.unobservedValue' : 'console.unreadable')))
51
67
  }
52
68
 
53
- function ReplSessionBindings({ memory, t }) {
69
+ function ReplSessionBindings({ memory, provenance, t }) {
54
70
  const [query, setQuery] = React.useState('')
55
71
  const [kind, setKind] = React.useState('all')
56
72
  const [selectedName, setSelectedName] = React.useState(null)
@@ -70,7 +86,8 @@ export function createReplView(React, deps) {
70
86
  h('span', { className: 'ptcPlusObservationTime' }, observation === undefined
71
87
  ? t('console.unobserved') : t('console.observed', { time: new Date(observation.at).toLocaleString() }))),
72
88
  memory.entries.length === 0 ? h('div', { className: 'ptcPlusSessionEmpty' },
73
- t(memory.available ? 'memory.empty' : 'memory.unavailable'))
89
+ t(!memory.available ? provenance === 'previous-runtime' ? 'memory.previousRuntime' : 'memory.unavailable'
90
+ : 'memory.empty'))
74
91
  : h('div', { className: 'ptcPlusObservationGrid', 'data-empty': selected === undefined },
75
92
  h('div', { className: 'ptcPlusObservationCatalog' },
76
93
  h('div', { className: 'ptcPlusObservationFilters' },
@@ -115,13 +132,13 @@ export function createReplView(React, deps) {
115
132
  const workbench = useWorkbenchController({ enabled: globalEnabled, active: true, callUserBindings })
116
133
  const eligible = featureEnabled(settings, 'replView') && sessionUsesPtcPreset(preset)
117
134
  const observationRegion = React.useRef(null)
118
- const memory = useObservedReplMemory({ sessionId, projected, active: eligible,
135
+ const { memory, provenance } = useObservedReplMemory({ sessionId, projected, active: eligible,
119
136
  elementRef: observationRegion, observeRepl })
120
137
  React.useEffect(() => eligible ? hideComposer(sessionId) : undefined, [eligible, hideComposer, sessionId])
121
138
  if (!eligible) return null
122
139
  return h('div', { className: 'ptcPlusConsole', 'data-conversation-composer-overlay': '' },
123
140
  h('div', { className: 'ptcPlusConsoleSection', ref: observationRegion }, h(ReplSessionBindings, {
124
- key: sessionId, memory, t })),
141
+ key: sessionId, memory, provenance, t })),
125
142
  globalEnabled ? h('div', { className: 'ptcPlusConsoleSection ptcPlusBindingsSurface' },
126
143
  h(UserBindingsWorkbench, { controller: workbench, t, headingLabel: t('console.global') })) : null)
127
144
  }
@@ -161,6 +178,7 @@ export function createReplView(React, deps) {
161
178
 
162
179
  function ReplMemoryCard({
163
180
  memory,
181
+ provenance,
164
182
  globalEnabled,
165
183
  globalBindings,
166
184
  loadGlobalBinding,
@@ -246,7 +264,8 @@ export function createReplView(React, deps) {
246
264
  )))
247
265
  )
248
266
  : !memory.available
249
- ? h('span', { className: 'ptcPlusReplEmpty' }, t('memory.unavailable'))
267
+ ? h('span', { className: 'ptcPlusReplEmpty' }, t(provenance === 'previous-runtime'
268
+ ? 'memory.previousRuntime' : 'memory.unavailable'))
250
269
  : memory.entries.length === 0
251
270
  ? h('span', { className: 'ptcPlusReplEmpty' }, t('memory.empty'))
252
271
  : h('ul', { className: 'ptcPlusReplList' }, memory.entries.map((binding, index) => {
package/src/client.js CHANGED
@@ -24,6 +24,7 @@ import {
24
24
  } from './client-host-compat.js'
25
25
  import {
26
26
  normalizeReplMemorySnapshot,
27
+ normalizeReplMemoryView,
27
28
  unavailableReplMemorySnapshot,
28
29
  } from '../internal/repl-memory-projection.js'
29
30
  import { createBindingReviews } from './client-binding-review.js'
@@ -212,7 +213,8 @@ export function createClientPlugin(require) {
212
213
  icons: { search: IconSearchOutline16, chevron: IconChevronDownOutline14 },
213
214
  })
214
215
  const { ReplComposer, ReplConsole, ReplMemoryCard, replPopoverIsOpen, placeReplPopover, useObservedReplMemory } = createReplView(React, {
215
- CodeBlock, Select, featureEnabled, normalizeReplMemorySnapshot, unavailableReplMemorySnapshot,
216
+ CodeBlock, Select, featureEnabled, normalizeReplMemorySnapshot, normalizeReplMemoryView,
217
+ unavailableReplMemorySnapshot,
216
218
  useSessionPreset, sessionUsesPtcPreset, useWorkbenchController, UserBindingsWorkbench,
217
219
  icons: { search: IconSearchOutline16, chevron: IconChevronDownOutline14 },
218
220
  })