dsh-ptc-plus 0.5.3 → 0.5.4

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 (40) hide show
  1. package/README.en.md +1 -1
  2. package/README.md +1 -1
  3. package/client.cjs +3326 -2881
  4. package/compiler-core.cjs +127 -127
  5. package/compiler-core.cjs.map +2 -2
  6. package/docs/README.md +1 -0
  7. package/docs/capability-planning-components.md +6 -6
  8. package/docs/capability-projection.md +1 -1
  9. package/docs/capability-surface.md +133 -0
  10. package/docs/client-ui.md +17 -15
  11. package/docs/client-visual-contract.md +7 -7
  12. package/docs/installation.md +9 -2
  13. package/docs/panel-concept.md +171 -0
  14. package/docs/releases/v0.5.4.md +75 -0
  15. package/docs/runtime-reference.md +14 -0
  16. package/docs/verification.md +1 -1
  17. package/index.js +117 -30
  18. package/internal/binding-adoption.js +103 -11
  19. package/internal/capability-command-receipt.js +99 -15
  20. package/internal/capability-environment.js +1108 -348
  21. package/internal/capability-plan.js +18 -2
  22. package/internal/capability-policy.js +13 -0
  23. package/internal/capability-selection.js +330 -0
  24. package/internal/direct-surface-owner.js +17 -4
  25. package/internal/message-sources.js +21 -0
  26. package/internal/program-bindings.js +13 -4
  27. package/internal/runtime-bridge-owner.js +5 -1
  28. package/internal/runtime-config.js +10 -0
  29. package/internal/session-log-view.js +47 -5
  30. package/internal/settings-compat.js +6 -0
  31. package/internal/user-bindings-owner.js +20 -3
  32. package/package.json +45 -31
  33. package/src/client-authoring-view.js +7 -8
  34. package/src/client-capabilities-view.js +871 -948
  35. package/src/client-capability-sort.js +22 -9
  36. package/src/client-copy.js +116 -294
  37. package/src/client-settings-view.js +90 -33
  38. package/src/client-styles.js +67 -19
  39. package/src/client.js +46 -21
  40. package/internal/capability-delivery-proof.js +0 -70
@@ -1,5 +1,6 @@
1
1
  import { CONFIG_DEFAULTS, CONFIG_FIELDS, CONFIG_GROUPS, CONFIG_MODULES } from '../internal/config-spec.js'
2
2
  import { CAPABILITY_CONFIGURATION_KEYS, capabilityProfileConfiguration, resolveConfig } from '../internal/runtime-config.js'
3
+ import { capabilityPolicyForConfig, capabilityPolicyFromRecord, changeCapabilityRule } from '../internal/capability-policy.js'
3
4
  import { featureEnabled } from './client-feature-gates.js'
4
5
  import { isHostIconComponent } from './client-host-compat.js'
5
6
  import { capabilityPlanReason, createCapabilitySettingsViews } from './client-capabilities-view.js'
@@ -24,8 +25,8 @@ function settingsScrollGeometry(element) {
24
25
  * action only while global bindings are eligible.
25
26
  */
26
27
  export function createPtcSettingsView(React, deps) {
27
- const { ActionButton, BindingsDialog, Modal, Select, useWorkbenchController, icons, inspectCapabilityPlans, inspectCapabilityCatalog,
28
- inspectCapabilityTargets, inspectCapabilityAllocation, CapabilityRefreshButton } = deps
28
+ const { ActionButton, BindingsDialog, Modal, Select, useWorkbenchController, icons, inspectCapabilityPlans,
29
+ inspectCapabilityTargets, inspectCapabilityAllocation, CapabilityRefreshButton, CapabilitySurface } = deps
29
30
  const h = React.createElement
30
31
  const enabledField = CONFIG_FIELDS.find(field => field.key === 'enabled')
31
32
 
@@ -44,13 +45,6 @@ export function createPtcSettingsView(React, deps) {
44
45
  className: 'ptcPlusSettingsNavIcon' }, ...paths[section].map((d, key) => h('path', { key, d })))
45
46
  }
46
47
 
47
- function SearchIcon() {
48
- return isHostIconComponent(icons.search) ? h(icons.search, { size: 16, 'aria-hidden': true })
49
- : h('svg', { width: 16, height: 16, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor',
50
- strokeWidth: 1.6, strokeLinecap: 'round', 'aria-hidden': true },
51
- h('circle', { cx: 10.5, cy: 10.5, r: 6.5 }), h('path', { d: 'm16 16 5 5' }))
52
- }
53
-
54
48
  function NavigationArrow() {
55
49
  return isHostIconComponent(icons.chevron) ? h(icons.chevron, { size: 12 })
56
50
  : h('svg', { width: 12, height: 12, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor',
@@ -111,7 +105,7 @@ export function createPtcSettingsView(React, deps) {
111
105
  : saved.invalid && draft === saved.settings ? h('p', { role: 'status', className: 'ptcPlusMessage' }, t('capabilities.savedStatisticsInvalid')) : null)
112
106
  }
113
107
 
114
- const { CapabilityWorkbench } = createCapabilitySettingsViews(React, { SearchIcon, Select, Modal })
108
+ const { CapabilityWorkbench } = createCapabilitySettingsViews(React, { Select, Modal })
115
109
 
116
110
  function fieldInput(field, value, disabled, onChange, label) {
117
111
  if (field.type === 'boolean') {
@@ -153,8 +147,6 @@ export function createPtcSettingsView(React, deps) {
153
147
  const [plansError, setPlansError] = React.useState(null)
154
148
  const [plansPending, setPlansPending] = React.useState(false)
155
149
  const [plansObservedConfiguration, setPlansObservedConfiguration] = React.useState(null)
156
- const [catalog, setCatalog] = React.useState(null)
157
- const [catalogError, setCatalogError] = React.useState(null)
158
150
  const [planRevision, setPlanRevision] = React.useState(0)
159
151
  const [targets, setTargets] = React.useState(null)
160
152
  const [targetsError, setTargetsError] = React.useState(null)
@@ -203,24 +195,6 @@ export function createPtcSettingsView(React, deps) {
203
195
  })
204
196
  return () => controller.abort()
205
197
  }, [enabled, open, view, planRevision])
206
- React.useEffect(() => {
207
- if (!enabled) {
208
- setCatalog(null)
209
- setCatalogError(null)
210
- return
211
- }
212
- if (!(open || view === 'page' || view === 'dialog') || !inspectCapabilityCatalog) return
213
- const controller = new AbortController()
214
- setCatalogError(null)
215
- Promise.resolve().then(() => inspectCapabilityCatalog(controller.signal)).then(available => {
216
- if (controller.signal.aborted) return
217
- setCatalog(available)
218
- }, error => {
219
- if (controller.signal.aborted) return
220
- setCatalogError(String(error?.message ?? error))
221
- })
222
- return () => controller.abort()
223
- }, [enabled, open, view, planConfiguration, planRevision])
224
198
  React.useEffect(() => {
225
199
  if (!plansEnabled) {
226
200
  setPlans(null)
@@ -340,6 +314,79 @@ export function createPtcSettingsView(React, deps) {
340
314
  const fieldDisabled = field => unavailable
341
315
  || pending.has(field.key)
342
316
  || (field.key !== 'enabled' && !enabled)
317
+ /**
318
+ * The saved address's one writer.
319
+ *
320
+ * The capability surface states values, so a cell writes the value its address
321
+ * holds for that object; the rule chain is what answers the objects this address
322
+ * has not decided one by one. The receipt the surface shows is the record this
323
+ * call wrote, named the way every other capability write names one.
324
+ *
325
+ * The decision is merged into the policy the document holds when the write runs, not
326
+ * into the one this page last rendered: two cells changed before the settings
327
+ * snapshot republishes compose instead of the second rebuilding the policy from the
328
+ * older snapshot and dropping the first.
329
+ */
330
+ const policyAtWrite = React.useRef(null)
331
+ const renderedPolicy = React.useRef(value.capabilityPolicy)
332
+ if (value.capabilityPolicy !== renderedPolicy.current) {
333
+ renderedPolicy.current = value.capabilityPolicy
334
+ policyAtWrite.current = null
335
+ }
336
+ // The newest published snapshot, for a write that runs after the render that made it. A
337
+ // queued write closes over its own render, and that snapshot may already be replaced by the
338
+ // time it composes, so the document it starts from is read from here.
339
+ const latestValue = React.useRef(value)
340
+ React.useEffect(() => { latestValue.current = value })
341
+ const writeSavedCapability = ({ id, dimension, selection }) => {
342
+ if (!updateCapabilityConfiguration) return Promise.reject(new Error(t('capabilities.configurationUnavailable')))
343
+ const field = CONFIG_FIELDS.find(candidate => candidate.key === 'capabilityPolicy')
344
+ const operation = writeTail.current.then(async () => {
345
+ setPending(current => new Set([...current, field.key]))
346
+ setCapabilityStatus(null)
347
+ let key = null
348
+ try {
349
+ // A configuration that saved no policy has only a synthesized document, whose bottom
350
+ // layer the capability-management switch shaped. Writing that document would freeze the
351
+ // switch's answer into the record and turn untouched cells into it, so a first saved
352
+ // write starts from the words the record itself wrote: the declared defaults plus the
353
+ // layers the override record holds, which `capabilityPolicyForConfig` folds into a
354
+ // document while the synthesis switches are neutral. The resolved config always carries
355
+ // a policy string, so the provenance marker — not the field's absence — decides which
356
+ // document is the record's.
357
+ const document = () => policyAtWrite.current
358
+ ?? (latestValue.current.capabilityPolicySaved === true
359
+ ? capabilityPolicyForConfig(latestValue.current) : capabilityPolicyFromRecord(latestValue.current))
360
+ const policy = changeCapabilityRule(document(), id, dimension, selection)
361
+ const written = JSON.stringify(policy)
362
+ key = await updateSetting(field.key, written)
363
+ // A null answer means either "this scope is not writable" or "the record already holds
364
+ // this value". The second is not a refusal: the decision the reader made is the state
365
+ // the record is in, so nothing is written and nothing failed.
366
+ if (key === null) {
367
+ if (latestValue.current.capabilityPolicy !== written) throw new Error(t('capabilities.configurationUnavailable'))
368
+ key = 'status.applied'
369
+ }
370
+ if (key === 'status.applied') policyAtWrite.current = policy
371
+ } catch (error) {
372
+ recordStatus({ key: 'status.failed', fieldKey: field.key,
373
+ params: { error: error instanceof Error ? error.message : String(error) } })
374
+ throw error
375
+ } finally {
376
+ setPending(current => {
377
+ const next = new Set(current)
378
+ next.delete(field.key)
379
+ return next
380
+ })
381
+ }
382
+ // The settings page keeps stating its own outcome; the cell states the refusal.
383
+ recordStatus({ key, fieldKey: field.key })
384
+ if (key !== 'status.applied') throw new Error(t('capabilities.configurationUnavailable'))
385
+ return { id, dimension, selection }
386
+ })
387
+ writeTail.current = operation.catch(() => {})
388
+ return operation
389
+ }
343
390
  const renderField = key => {
344
391
  const field = CONFIG_FIELDS.find(candidate => candidate.key === key)
345
392
  if (field === undefined) return null
@@ -381,7 +428,7 @@ export function createPtcSettingsView(React, deps) {
381
428
  h('table', null, h('thead', null, h('tr', null,
382
429
  ...['member', 'selection', 'reason', 'coverage'].map(key => h('th', { key }, t(`capabilities.${key}`))))),
383
430
  h('tbody', null, ...plan.effective.entries.map(entry => h('tr', { key: entry.id },
384
- h('td', null, entry.id), h('td', null, t(`capabilities.${entry.selection}`)),
431
+ h('td', null, entry.id), h('td', null, t(`capabilities.word.${entry.selection}`)),
385
432
  h('td', null, capabilityPlanReason(t, entry)),
386
433
  h('td', null, entry.evidence ? `${entry.evidence.used}/${entry.evidence.eligible} (${entry.evidence.scope})` : '—')))))))) : null
387
434
 
@@ -428,12 +475,22 @@ export function createPtcSettingsView(React, deps) {
428
475
  onChange: event => persist(CONFIG_FIELDS.find(field => field.key === 'capabilityContextEnabled'), event.target.checked) }))) : heading,
429
476
  ...(group.key === 'capabilities' ? [
430
477
  h(CapabilityWorkbench, { key: 'capability-workbench', id: `${groupIdPrefix}-capability-workbench`,
431
- value, configurationReady: snapshot.status === 'ready', catalog, catalogError, plans: plansEnabled ? plans : null, plansError, plansPending,
478
+ value, configurationReady: snapshot.status === 'ready', plans: plansEnabled ? plans : null, plansError, plansPending,
432
479
  plansStale: plansObservedConfiguration !== planConfiguration,
433
480
  disabled: key => fieldDisabled({ key }), onChange: persist,
434
481
  onReload: () => setPlanRevision(current => current + 1), t, renderField, renderPlans, renderRefresh,
435
482
  selectedSessionId: refreshSessionId, onSessionSelect: setRefreshSessionId,
436
- allocation, allocationError, allocationPending, saving: [...pending].some(key => CAPABILITY_CONFIGURATION_KEYS.includes(key) || key === 'capabilityProfiles'), saveStatus: capabilityStatus, configurationWritable: !unavailable && enabled, onApplyConfiguration: updateCapabilityConfiguration ? persistConfiguration : undefined })]
483
+ allocation, allocationError, allocationPending, saving: [...pending].some(key => CAPABILITY_CONFIGURATION_KEYS.includes(key) || key === 'capabilityProfiles'), saveStatus: capabilityStatus, configurationWritable: !unavailable && enabled, onApplyConfiguration: updateCapabilityConfiguration ? persistConfiguration : undefined,
484
+ // The one capability surface, mounted with the address this entrance fixes:
485
+ // the new-session default. Its row set is the Host's own declaration — the
486
+ // process-scope object set, not a session's full declared face (capability-surface
487
+ // §8.9), because this entrance names no session — so an observation target changes
488
+ // only what the observation reads, never these rows, and a target whose supply
489
+ // cannot be read leaves the rows and their controls in place.
490
+ surface: CapabilitySurface ? h(CapabilitySurface, { key: 'capability-surface', entrance: 'settings', inline: true,
491
+ t, writable: !unavailable && enabled, revision: planConfiguration,
492
+ onReload: () => setPlanRevision(current => current + 1),
493
+ savedCommands: { run: writeSavedCapability } }) : null })]
437
494
  : fields.map(renderField)))
438
495
  }
439
496
 
@@ -26,12 +26,12 @@ const CLIENT_CSS = `
26
26
  .ptcPlusGroup+.ptcPlusGroup{margin-top:20px;padding-top:12px;border-top:1px solid var(--dsw-alias-border-l2)}.ptcPlusGroupTitle{margin:0;padding:8px 0;color:var(--dsw-alias-label-secondary);font-size:13px;font-weight:600;letter-spacing:0;line-height:20px}.ptcPlusGroup[data-experimental=true]{padding:14px 16px;border:1px solid color-mix(in srgb,var(--dsw-alias-state-warn-primary,#a15c00) 25%,var(--dsw-alias-border-l2));border-radius:12px;background:var(--dsw-alias-bg-layer-3)}.ptcPlusGroupTitle[data-experimental-label]{display:flex;align-items:center;gap:8px}.ptcPlusGroupTitle[data-experimental-label]::after{content:attr(data-experimental-label);padding:2px 7px;border-radius:999px;background:color-mix(in srgb,var(--dsw-alias-state-warn-primary,#a15c00) 12%,transparent);color:color-mix(in srgb,var(--dsw-alias-state-warn-primary,#a15c00) 60%,var(--dsw-alias-label-primary));font-size:10px;font-weight:600;line-height:15px}.ptcPlusRow{display:flex;align-items:center;gap:12px;min-height:48px;border-top:0.5px solid var(--dsw-alias-border-l2)}.ptcPlusGroupTitle+.ptcPlusRow{border-top:0}.ptcPlusMain{flex:1;min-width:0}.ptcPlusLabel{font-size:13px;font-weight:500;line-height:1.5}.ptcPlusDetail,.ptcPlusMessage{color:var(--dsw-alias-label-tertiary);font-size:12px;line-height:1.5;overflow-wrap:anywhere}.ptcPlusInput{box-sizing:border-box;min-width:72px;width:140px;height:34px;padding:0 12px;border:0.5px solid var(--dsw-alias-border-l4);border-radius:8px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;line-height:1.5}.ptcPlusInput:focus-visible{border-color:var(--dsw-alias-brand-primary);outline:none}.ptcPlusCheck{appearance:none;position:relative;flex:0 0 auto;box-sizing:border-box;width:36px;height:20px;margin:0;padding:2px;border:0;border-radius:999px;corner-shape:round;background:var(--dsw-alias-border-l3);cursor:pointer}.ptcPlusCheck:checked{background:var(--dsw-alias-brand-primary)}.ptcPlusCheck::before{position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;corner-shape:round;background:var(--dsw-alias-switch-thumb);content:'';transition:transform 120ms ease}.ptcPlusCheck:checked::before{background:var(--dsw-alias-label-primary-foreground);transform:translateX(16px)}.ptcPlusCheck:disabled{cursor:default;opacity:.5}.ptcPlusCheck:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary);outline-offset:2px}
27
27
  .ptcPlusSettingsLayout .ptcPlusGroup[data-experimental=true]{background:var(--dsw-alias-bg-layer-3);border-color:var(--dsw-alias-border-l2)}.ptcPlusCapabilityHead{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px}.ptcPlusCapabilityHead .ptcPlusGroupTitle{margin:0}.ptcPlusCapabilityManagement{display:flex;align-items:center;gap:8px;font-size:12px}
28
28
  .ptcPlusCapabilityWorkbench{container:ptcPlusCapabilities/inline-size;min-width:0;font-size:13px}
29
- .ptcPlusCapabilityTabs{display:flex;gap:8px;overflow:auto;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusCapabilityTabs button{appearance:none;flex:none;padding:10px 14px;border:0;border-bottom:2px solid transparent;background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;text-align:center;cursor:pointer}.ptcPlusCapabilityTabs [aria-selected=true]{border-bottom-color:var(--dsw-alias-state-business-primary,#4d6bfe);color:var(--dsw-alias-state-business-primary,#4d6bfe)}.ptcPlusCapabilityPane{padding-top:16px;min-width:0}.ptcPlusCapabilityPane[hidden],.ptcPlusContextContent>[hidden]{display:none}
29
+ .ptcPlusCapabilityTabs{display:flex;gap:8px;overflow-x:auto;overflow-y:hidden;overscroll-behavior-x:contain;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusCapabilityTabs button{appearance:none;flex:none;padding:10px 14px;border:0;border-bottom:2px solid transparent;background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;text-align:center;cursor:pointer}.ptcPlusCapabilityTabs [aria-selected=true]{border-bottom-color:var(--dsw-alias-state-business-primary,#4d6bfe);color:var(--dsw-alias-state-business-primary,#4d6bfe)}.ptcPlusCapabilityPane{padding-top:16px;min-width:0}.ptcPlusCapabilityPane[hidden],.ptcPlusContextContent>[hidden]{display:none}
30
30
  .ptcPlusTaskHead{display:flex;flex-wrap:wrap;align-items:center;gap:10px}.ptcPlusTaskHead h4{margin:0;flex:1;font-size:16px}.ptcPlusCapabilityManagement{display:flex;align-items:center;gap:8px;font-size:12px}.ptcPlusCapabilitySaveState{color:var(--dsw-alias-label-secondary);font-size:11px}.ptcPlusCapabilityPane>.ptcPlusDetail{margin:8px 0 16px}
31
- .ptcPlusCapabilityToolbar{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin:12px 0}.ptcPlusCapabilityToolbar>.ptcPlusSearch{flex:1 1 220px;min-width:0}.ptcPlusCapabilityTypes{display:flex;flex-wrap:wrap;gap:5px}.ptcPlusCapabilityTypes button{appearance:none;padding:6px 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;text-align:center;cursor:pointer}.ptcPlusCapabilityTypes [aria-pressed=true]{border-color:transparent;background:var(--dsw-alias-state-business-primary,#4d6bfe);color:var(--dsw-alias-bg-base,#fff)}
32
- .ptcPlusCapabilityFilter{display:flex;flex-direction:column;min-width:0;gap:6px;font-size:12px;color:var(--dsw-alias-label-secondary)}.ptcPlusCapabilityFilter>.ptcPlusSelectTrigger{width:100%;max-width:100%;font-size:12px}.ptcPlusCapabilityFilterFields{display:flex;align-items:flex-end;flex-wrap:wrap;gap:12px;padding:12px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px}.ptcPlusCapabilityFilterFields>.ptcPlusCapabilityFilter{flex:1 1 160px}.ptcPlusCapabilityOnlyCommon{display:flex;align-items:center;gap:6px;font-size:12px}.ptcPlusCapabilityOnlyCommon input{width:16px;height:16px;margin:0}.ptcPlusCapabilityResultLine,.ptcPlusActiveFilters{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;margin:8px 0;color:var(--dsw-alias-label-secondary);font-size:11px}.ptcPlusCapabilityLink{appearance:none;padding:4px 0;border:0;background:transparent;color:var(--dsw-alias-state-business-primary,#4d6bfe);font:inherit;font-size:12px;cursor:pointer}.ptcPlusCapabilityLink:disabled{opacity:.5;cursor:default}
33
- .ptcPlusCapabilityTable{min-width:0;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;overflow:hidden}.ptcPlusCapabilityColumns,.ptcPlusCapabilityItem{display:grid;grid-template-columns:minmax(140px,1.6fr) 54px minmax(65px,.75fr) minmax(92px,1fr) minmax(104px,1fr);align-items:center;gap:10px;padding:10px 12px}.ptcPlusCapabilityColumns{color:var(--dsw-alias-label-tertiary);font-size:11px;background:var(--dsw-alias-bg-layer-2)}.ptcPlusCapabilitySort{appearance:none;display:inline-flex;align-items:center;justify-content:flex-start;gap:4px;width:100%;min-height:28px;padding:3px 0;border:0;border-radius:4px;background:transparent;color:inherit;font:inherit;text-align:start;cursor:pointer}.ptcPlusCapabilitySort>span{display:inline-flex;flex:none;align-items:center;justify-content:center;width:11px;height:11px;font-size:10px;line-height:1}.ptcPlusCapabilityColumns [aria-sort=ascending],.ptcPlusCapabilityColumns [aria-sort=descending]{color:var(--dsw-alias-state-business-primary,#4d6bfe)}.ptcPlusCapabilityContextCell>.ptcPlusCapabilityContext{width:100%}.ptcPlusCapabilityList{max-height:480px;overflow:auto;overscroll-behavior:contain;scrollbar-gutter:stable}.ptcPlusCapabilityItem{border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusCapabilityItem:last-child{border-bottom:0}.ptcPlusCapabilityItem[data-selected=true]{background:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 6%,transparent)}.ptcPlusCapabilityItem:not([data-selected=true]){cursor:pointer}.ptcPlusCapabilityItem:not([data-selected=true]):hover{background:var(--dsw-alias-interactive-bg-hover)}.ptcPlusCapabilityItem>*{min-width:0}.ptcPlusCapabilityIdentity{display:flex;flex-direction:column;gap:3px;min-width:0}.ptcPlusCapabilityName{font-size:13px;overflow-wrap:anywhere}.ptcPlusCapabilityIdentity code{color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:15px;overflow-wrap:anywhere}.ptcPlusCapabilitySource{color:var(--dsw-alias-label-secondary);font-size:11px;overflow-wrap:anywhere}.ptcPlusCapabilityBadge{justify-self:start;padding:2px 6px;border-radius:4px;background:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 8%,transparent);color:var(--dsw-alias-state-business-primary,#4d6bfe);font-size:10px;line-height:17px}.ptcPlusCapabilityBadge[data-kind=skill]{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2)}.ptcPlusCapabilityAvailability{display:flex;align-items:center;gap:6px;font-size:11px}.ptcPlusCapabilityAvailability[data-state=closed],.ptcPlusCapabilityAvailability[data-state=unapplied],.ptcPlusCapabilityAvailability[data-state=source-closed],.ptcPlusCapabilityAvailability[data-state=unknown],.ptcPlusCapabilityAvailability[data-state=unavailable]{color:var(--dsw-alias-label-tertiary)}.ptcPlusCapabilityContext{appearance:none;display:flex;align-items:center;justify-content:center;gap:6px;padding:5px 2px;border:0;border-radius:5px;background:transparent;color:var(--dsw-alias-label-secondary);font:inherit;font-size:12px;text-align:center;cursor:pointer}.ptcPlusCapabilityContext{justify-content:space-between;text-align:start}.ptcPlusCapabilityContext svg{flex:none;color:var(--dsw-alias-label-tertiary)}.ptcPlusCapabilityWorkbench button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}
34
- .ptcPlusCapabilityEditorFields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin-top:14px}
31
+
32
+ .ptcPlusCapabilityFilter{display:flex;flex-direction:column;min-width:0;gap:6px;font-size:12px;color:var(--dsw-alias-label-secondary)}.ptcPlusCapabilityFilter>.ptcPlusSelectTrigger{width:100%;max-width:100%;font-size:12px}.ptcPlusCapabilityResultLine,.ptcPlusActiveFilters{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:8px;margin:8px 0;color:var(--dsw-alias-label-secondary);font-size:11px}.ptcPlusCapabilityLink{appearance:none;padding:4px 0;border:0;background:transparent;color:var(--dsw-alias-state-business-primary,#4d6bfe);font:inherit;font-size:12px;cursor:pointer}.ptcPlusCapabilityLink:disabled{opacity:.5;cursor:default}
33
+ .ptcPlusCapabilityColumns,.ptcPlusCapabilityItem{display:grid;grid-template-columns:minmax(140px,1.6fr) 54px minmax(65px,.75fr) minmax(92px,1fr) minmax(104px,1fr);align-items:center;gap:10px;padding:10px 12px}.ptcPlusCapabilityColumns{color:var(--dsw-alias-label-tertiary);font-size:11px;background:var(--dsw-alias-bg-layer-2)}.ptcPlusCapabilityItem{box-sizing:border-box;min-height:54px;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusCapabilityItem:last-child{border-bottom:0}.ptcPlusCapabilityItem[data-selected=true]{background:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 6%,transparent)}.ptcPlusCapabilityItem:not([data-selected=true]){cursor:pointer}.ptcPlusCapabilityItem:not([data-selected=true]):hover{background:var(--dsw-alias-interactive-bg-hover)}.ptcPlusCapabilityItem>*{min-width:0}.ptcPlusCapabilityIdentity{display:flex;flex-direction:column;gap:3px;min-width:0}.ptcPlusCapabilityIdentity code{color:var(--dsw-alias-label-tertiary);font-size:10px;line-height:15px;overflow-wrap:anywhere}.ptcPlusCapabilityIdentityText{display:flex;flex-direction:column;justify-content:center;gap:3px;min-width:0;min-height:32px}.ptcPlusCapabilityIdentityText>span,.ptcPlusCapabilityIdentityText>code{display:block;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ptcPlusCapabilitySource{color:var(--dsw-alias-label-secondary);font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ptcPlusCapabilityBadge{justify-self:start;padding:2px 6px;border-radius:4px;background:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 8%,transparent);color:var(--dsw-alias-state-business-primary,#4d6bfe);font-size:10px;line-height:17px}.ptcPlusCapabilityBadge[data-kind=skill]{color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-2)}.ptcPlusCapabilityWorkbench button:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover)}
34
+
35
35
  .ptcPlusPromptText{display:flex;flex-direction:column;gap:12px;min-width:0}
36
36
  .ptcPlusPromptHeader{display:flex;align-items:flex-start;gap:8px;min-width:0}
37
37
  .ptcPlusPromptHeaderIcon{display:inline-flex;align-items:center;justify-content:center;flex:none;width:20px;height:20px;color:var(--dsw-alias-label-secondary)}
@@ -100,8 +100,8 @@ const CLIENT_CSS = `
100
100
  .ptcPlusConfigurationProfiles{display:grid;grid-template-columns:minmax(180px,34%) minmax(0,1fr);gap:18px;margin-top:14px;min-width:0}.ptcPlusConfigurationLibrary,.ptcPlusConfigurationDetail{min-width:0;padding:14px;border:1px solid var(--dsw-alias-border-l2);border-radius:8px}.ptcPlusConfigurationProfiles h4{margin:0 0 12px;font-size:15px}.ptcPlusConfigurationList{max-height:320px;overflow:auto;overscroll-behavior:contain}.ptcPlusConfigurationChoice{appearance:none;display:block;width:100%;padding:12px 10px;border:0;border-left:3px solid transparent;border-radius:5px;background:transparent;color:inherit;font:inherit;text-align:start;overflow-wrap:anywhere;cursor:pointer}.ptcPlusConfigurationChoice[aria-pressed=true]{border-left-color:var(--dsw-alias-state-business-primary,#4d6bfe);background:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 6%,transparent)}.ptcPlusConfigurationSave.ptcPlusButton{width:100%;margin-top:14px;border:1px dashed var(--dsw-alias-border-l2);justify-content:center}.ptcPlusConfigurationSave::before{content:'+';font-size:20px;line-height:16px}.ptcPlusConfigurationLibraryActions{display:flex;align-items:start;gap:8px;margin-top:10px}.ptcPlusConfigurationLibraryActions>.ptcPlusButton{flex:1}.ptcPlusConfigurationSummary{margin-top:14px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;overflow:hidden}.ptcPlusConfigurationSummaryRow{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:12px;padding:10px;font-size:12px;border-bottom:1px solid var(--dsw-alias-border-l2);overflow-wrap:anywhere}.ptcPlusConfigurationSummaryRow:last-child{border:0}.ptcPlusConfigurationSummaryRow>span:first-child{color:var(--dsw-alias-label-secondary)}.ptcPlusConfigurationAction{display:flex;flex-direction:column;gap:10px;margin-top:14px}.ptcPlusConfigurationAction .ptcPlusInput{width:100%;box-sizing:border-box}.ptcPlusTaskFeedback{grid-column:1/-1;margin:8px 0;font-size:12px;overflow-wrap:anywhere}
101
101
  .ptcPlusCapabilityEvidenceTable{max-height:480px;overflow:auto}.ptcPlusCapabilityEvidenceTable table,.ptcPlusCapabilityPlans table{width:100%;table-layout:fixed;border-collapse:collapse;font-size:12px}.ptcPlusCapabilityEvidenceTable th,.ptcPlusCapabilityEvidenceTable td,.ptcPlusCapabilityPlans th,.ptcPlusCapabilityPlans td{padding:10px;text-align:start;border-bottom:1px solid var(--dsw-alias-border-l2);overflow-wrap:anywhere}.ptcPlusCapabilityEvidenceTable th{color:var(--dsw-alias-label-tertiary);font-weight:500;background:var(--dsw-alias-bg-layer-2)}.ptcPlusCapabilityEvidenceTable progress{display:block;width:100%;height:5px;margin-top:5px;accent-color:var(--dsw-alias-state-business-primary,#4d6bfe)}.ptcPlusCapabilityStatistics .ptcPlusInput{width:100%}.ptcPlusCapabilityStatistics .ptcPlusBindingFields{margin-top:10px}
102
102
  .ptcPlusStatisticsParameters{margin-top:12px}.ptcPlusStatisticsParameters h5{margin:0;font-size:12px;line-height:20px;font-weight:600}.ptcPlusStatisticsObservationHeading{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 12px;min-width:0;line-height:20px}.ptcPlusStatisticsObservationHeading>span:first-child{flex:none}.ptcPlusStatisticsObservationHint{flex:1 1 260px;min-width:0;color:var(--dsw-alias-label-tertiary);white-space:normal;overflow-wrap:anywhere}
103
- @container ptcPlusCapabilities (max-width:760px){.ptcPlusCapabilityColumns{display:flex;flex-wrap:wrap;gap:4px 12px}.ptcPlusCapabilityItem{grid-template-columns:minmax(0,1fr) auto;gap:8px 12px}.ptcPlusCapabilityIdentity{grid-column:1}.ptcPlusCapabilityBadge{grid-column:2}.ptcPlusCapabilitySource{grid-column:1;grid-row:2}.ptcPlusCapabilityAvailability{grid-column:1;grid-row:3}.ptcPlusCapabilityContextCell{grid-column:1/3;grid-row:3}.ptcPlusContextLayout{grid-template-columns:minmax(100px,27%) minmax(0,1fr);gap:12px}.ptcPlusContextNavigation button{padding:10px 6px}.ptcPlusConfigurationProfiles{grid-template-columns:1fr}.ptcPlusConfigurationList{max-height:220px}}
104
- @container ptcPlusCapabilities (max-width:480px){.ptcPlusCapabilityTabs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));overflow:visible}.ptcPlusCapabilityTabs button{min-width:0;padding:8px;overflow-wrap:anywhere}.ptcPlusCapabilityIdentity{grid-column:1/3}.ptcPlusCapabilityBadge{grid-row:2}.ptcPlusCapabilityAvailability{grid-column:1/-1}.ptcPlusCapabilityContextCell{grid-column:1/-1;grid-row:4}.ptcPlusCapabilityToolbar>.ptcPlusSearch{flex-basis:100%}.ptcPlusCapabilityTypes button{padding:6px 8px}.ptcPlusCapabilityList{max-height:360px}.ptcPlusCapabilityStatistics .ptcPlusBindingFields{grid-template-columns:minmax(0,1fr)}.ptcPlusContextLayout{grid-template-columns:1fr;gap:8px}.ptcPlusContextNavigation{flex-direction:column;border-right:0;border-bottom:1px solid var(--dsw-alias-border-l2);padding:0 0 8px}.ptcPlusContextNavigation button{min-width:0;font-size:12px}.ptcPlusContextNavigation button>span{max-width:100%;white-space:normal;overflow-wrap:anywhere}.ptcPlusContextNavigation button>span:first-child{flex:1;min-width:0}.ptcPlusContextState{flex:none;text-align:end}.ptcPlusCapabilitySaveState{flex-basis:100%}}
103
+ @container ptcPlusCapabilities (max-width:760px){.ptcPlusCapabilityColumns{display:flex;flex-wrap:wrap;gap:4px 12px}.ptcPlusCapabilityItem{grid-template-columns:minmax(0,1fr) auto;gap:8px 12px}.ptcPlusCapabilityIdentity{grid-column:1}.ptcPlusCapabilityBadge{grid-column:2}.ptcPlusCapabilitySource{grid-column:1;grid-row:2}.ptcPlusContextLayout{grid-template-columns:minmax(100px,27%) minmax(0,1fr);gap:12px}.ptcPlusContextNavigation button{padding:10px 6px}.ptcPlusConfigurationProfiles{grid-template-columns:1fr}.ptcPlusConfigurationList{max-height:220px}}
104
+ @container ptcPlusCapabilities (max-width:480px){.ptcPlusCapabilityTabs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));overflow:visible}.ptcPlusCapabilityTabs button{min-width:0;padding:8px;overflow-wrap:anywhere}.ptcPlusCapabilityIdentity{grid-column:1/3}.ptcPlusCapabilityBadge{grid-row:2}.ptcPlusCapabilityStatistics .ptcPlusBindingFields{grid-template-columns:minmax(0,1fr)}.ptcPlusContextLayout{grid-template-columns:1fr;gap:8px}.ptcPlusContextNavigation{flex-direction:column;border-right:0;border-bottom:1px solid var(--dsw-alias-border-l2);padding:0 0 8px}.ptcPlusContextNavigation button{min-width:0;font-size:12px}.ptcPlusContextNavigation button>span{max-width:100%;white-space:normal;overflow-wrap:anywhere}.ptcPlusContextNavigation button>span:first-child{flex:1;min-width:0}.ptcPlusContextState{flex:none;text-align:end}.ptcPlusCapabilitySaveState{flex-basis:100%}}
105
105
  .ptcPlusFooter{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:8px}.ptcPlusButton{appearance:none;display:inline-flex;align-items:center;justify-content:center;gap:5px;min-height:32px;padding:4px 14px;border:0.5px solid var(--dsw-alias-border-l3);border-radius:8px;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer;font:inherit;font-size:13px;line-height:1.5;transition:color .16s ease,border-color .16s ease,background-color .16s ease}.ptcPlusButton:hover:not(:disabled){border-color:var(--dsw-alias-label-dimmed);color:var(--dsw-alias-label-primary)}.ptcPlusButton[data-kind=primary]{background:var(--dsw-alias-label-primary);border-color:transparent;color:var(--dsw-alias-bg-layer-3)}.ptcPlusButton[data-kind=primary]:hover:not(:disabled){background:var(--dsw-alias-label-primary-dimmed);border-color:transparent;color:var(--dsw-alias-bg-layer-3)}.ptcPlusButton[data-kind=ghost]{border-color:transparent}.ptcPlusButton[data-kind=ghost]:hover:not(:disabled){border-color:var(--dsw-alias-border-l3)}.ptcPlusButton[data-kind=danger]{color:var(--dsw-alias-state-error-primary)}.ptcPlusButton[data-kind=danger]:hover:not(:disabled){background:var(--dsw-alias-interactive-bg-hover-danger);border-color:var(--dsw-alias-state-error-primary);color:var(--dsw-alias-state-error-primary)}.ptcPlusButton:disabled,.ptcPlusInput:disabled,.ptcPlusCheck:disabled{cursor:not-allowed;opacity:.4}
106
106
  .ptcPlusSettingAction{padding:4px 0 12px}
107
107
  .ptcPlusSettingsModal.ptcPlusSettingsModal{container:ptcPlusSettingsModal/size;box-sizing:border-box;width:min(1440px,calc(100vw - 48px));height:min(1040px,calc(100dvh - 48px));max-width:100%;max-height:100%;min-height:0;display:flex;flex-direction:column;padding:0;gap:0;overflow:hidden;border-radius:16px}
@@ -192,30 +192,79 @@ const CLIENT_CSS = `
192
192
  .ptcPlusFallbackModalHead{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:12px}.ptcPlusFallbackModalHead h2{margin:0;font-size:17px;line-height:24px}
193
193
 
194
194
  .ptcPlusCapabilityCommandNotice{box-sizing:border-box;min-width:0;margin:8px 0;padding:0;border:0;background:transparent;color:var(--dsw-alias-label-secondary);font:13px/20px var(--dsw-font-family,system-ui,sans-serif);overflow-wrap:anywhere}.ptcPlusCapabilityCommandNotice[data-state=error]{color:var(--dsw-alias-state-error-primary)}
195
+ .ptcPlusCapabilityCommandNotice[data-kind=writes]{display:flex;flex-direction:column;gap:6px;margin:8px 0;padding:10px 12px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary)}
196
+ .ptcPlusCapabilityCommandNoticeHead{margin:0;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px}
197
+ .ptcPlusCapabilityCommandNoticeList{display:flex;flex-direction:column;gap:4px;margin:0;padding:0;list-style:none}
198
+ .ptcPlusCapabilityCommandNoticeRow{color:var(--dsw-alias-label-primary);font-size:13px;line-height:20px;overflow-wrap:anywhere}
195
199
 
196
- .ptcPlusCapabilityReceipt{box-sizing:border-box;min-width:0;margin:8px 0;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:13px/20px var(--dsw-font-family,system-ui,sans-serif);overflow-wrap:anywhere}.ptcPlusCapabilityReceiptHead{display:flex;align-items:center;gap:12px;justify-content:space-between}.ptcPlusCapabilityReceiptHead>code{min-width:0;font:12px/18px var(--ds-font-family-code,ui-monospace,SFMono-Regular,Consolas,monospace);font-weight:500}.ptcPlusCapabilityReceiptState{flex:none;font-size:11px;color:var(--dsw-alias-label-secondary)}.ptcPlusCapabilityReceiptState[data-state=error]{color:var(--dsw-alias-state-error-primary)}.ptcPlusCapabilityReceipt p{margin:6px 0 0}.ptcPlusCapabilityReceiptSummary{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.ptcPlusCapabilityReceipt details{margin-top:8px}.ptcPlusCapabilityReceipt summary{width:fit-content;color:var(--dsw-alias-label-secondary);font-size:12px;cursor:pointer}.ptcPlusCapabilityReceipt summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:2px}.ptcPlusCapabilityReceipt pre{box-sizing:border-box;max-height:280px;overflow:auto;overscroll-behavior:contain;margin:8px 0 0;padding:10px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;background:var(--dsw-alias-bg-layer-1);font:12px/18px var(--ds-font-family-code,ui-monospace,SFMono-Regular,Consolas,monospace);white-space:pre-wrap;overflow-wrap:anywhere}.ptcPlusCapabilityReceiptTable{max-height:320px;overflow:auto;overscroll-behavior:contain;margin-top:8px}.ptcPlusCapabilityReceipt table{width:100%;min-width:480px;table-layout:fixed;border-collapse:collapse;font:12px/18px var(--dsw-font-family,system-ui,sans-serif)}.ptcPlusCapabilityReceipt th,.ptcPlusCapabilityReceipt td{padding:8px;text-align:start;vertical-align:top;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusCapabilityReceipt th{position:sticky;top:0;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);font-weight:500}.ptcPlusCapabilityReceipt th:first-child{width:44%}.ptcPlusCapabilityReceipt td strong{display:block;font-weight:500}.ptcPlusCapabilityReceipt td small{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;margin-top:3px;color:var(--dsw-alias-label-secondary);font-size:11px}.ptcPlusAllocationEvidence,.ptcPlusConfigurationProfiles{min-width:0;margin-top:20px;padding-top:16px;border-top:1px solid var(--dsw-alias-border-l2)}.ptcPlusAllocationEvidence h4,.ptcPlusConfigurationProfiles h4{margin:0;font-size:14px}.ptcPlusAllocationMetrics{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:16px 0}.ptcPlusAllocationMetrics>div{display:flex;min-width:0;flex-direction:column;gap:4px;padding:12px;border-radius:8px;background:var(--dsw-alias-bg-layer-2)}.ptcPlusAllocationMetrics strong{font-size:18px;overflow-wrap:anywhere}.ptcPlusAllocationMetrics span{font-size:11px;color:var(--dsw-alias-label-secondary)}.ptcPlusAllocationEvidence progress{width:100%;height:6px;accent-color:var(--dsw-alias-brand-primary)}.ptcPlusCapabilityEvidenceTable{max-height:440px;overflow:auto;overscroll-behavior:contain;margin-top:12px}.ptcPlusCapabilityEvidenceTable table{width:100%;table-layout:fixed;border-collapse:collapse;font-size:12px}.ptcPlusCapabilityEvidenceTable td,.ptcPlusCapabilityEvidenceTable th{padding:10px 6px;text-align:start;overflow-wrap:anywhere;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusCapabilityEvidenceTable th{color:var(--dsw-alias-label-secondary);font-weight:500}.ptcPlusCapabilityFilterFields{align-items:flex-end}
200
+ .ptcPlusCapabilityReceipt{box-sizing:border-box;min-width:0;margin:8px 0;padding:12px 14px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);font:13px/20px var(--dsw-font-family,system-ui,sans-serif);overflow-wrap:anywhere}.ptcPlusCapabilityReceiptHead{display:flex;align-items:center;gap:12px;justify-content:space-between}.ptcPlusCapabilityReceiptHead>code{min-width:0;font:12px/18px var(--ds-font-family-code,ui-monospace,SFMono-Regular,Consolas,monospace);font-weight:500}.ptcPlusCapabilityReceiptState{flex:none;font-size:11px;color:var(--dsw-alias-label-secondary)}.ptcPlusCapabilityReceiptState[data-state=error]{color:var(--dsw-alias-state-error-primary)}.ptcPlusCapabilityReceipt p{margin:6px 0 0}.ptcPlusCapabilityReceiptSummary{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}.ptcPlusCapabilityReceipt details{margin-top:8px}.ptcPlusCapabilityReceipt summary{width:fit-content;color:var(--dsw-alias-label-secondary);font-size:12px;cursor:pointer}.ptcPlusCapabilityReceipt summary:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:2px}.ptcPlusCapabilityReceipt pre{box-sizing:border-box;max-height:280px;overflow:auto;overscroll-behavior:contain;margin:8px 0 0;padding:10px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;background:var(--dsw-alias-bg-layer-1);font:12px/18px var(--ds-font-family-code,ui-monospace,SFMono-Regular,Consolas,monospace);white-space:pre-wrap;overflow-wrap:anywhere}.ptcPlusCapabilityReceiptTable{max-height:320px;overflow:auto;overscroll-behavior:contain;margin-top:8px}.ptcPlusCapabilityReceipt table{width:100%;min-width:480px;table-layout:fixed;border-collapse:collapse;font:12px/18px var(--dsw-font-family,system-ui,sans-serif)}.ptcPlusCapabilityReceipt th,.ptcPlusCapabilityReceipt td{padding:8px;text-align:start;vertical-align:top;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusCapabilityReceipt th{position:sticky;top:0;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-secondary);font-weight:500}.ptcPlusCapabilityReceipt th:first-child{width:44%}.ptcPlusCapabilityReceipt td strong{display:block;font-weight:500}.ptcPlusCapabilityReceipt td small{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;margin-top:3px;color:var(--dsw-alias-label-secondary);font-size:11px}.ptcPlusAllocationEvidence,.ptcPlusConfigurationProfiles{min-width:0;margin-top:20px;padding-top:16px;border-top:1px solid var(--dsw-alias-border-l2)}.ptcPlusAllocationEvidence h4,.ptcPlusConfigurationProfiles h4{margin:0;font-size:14px}.ptcPlusAllocationMetrics{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:12px;margin:16px 0}.ptcPlusAllocationMetrics>div{display:flex;min-width:0;flex-direction:column;gap:4px;padding:12px;border-radius:8px;background:var(--dsw-alias-bg-layer-2)}.ptcPlusAllocationMetrics strong{font-size:18px;overflow-wrap:anywhere}.ptcPlusAllocationMetrics span{font-size:11px;color:var(--dsw-alias-label-secondary)}.ptcPlusAllocationEvidence progress{width:100%;height:6px;accent-color:var(--dsw-alias-brand-primary)}.ptcPlusCapabilityEvidenceTable{max-height:440px;overflow:auto;overscroll-behavior:contain;margin-top:12px}.ptcPlusCapabilityEvidenceTable table{width:100%;table-layout:fixed;border-collapse:collapse;font-size:12px}.ptcPlusCapabilityEvidenceTable td,.ptcPlusCapabilityEvidenceTable th{padding:10px 6px;text-align:start;overflow-wrap:anywhere;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusCapabilityEvidenceTable th{color:var(--dsw-alias-label-secondary);font-weight:500}
197
201
  @container ptcPlusCapabilities (max-width:600px){.ptcPlusAllocationMetrics{grid-template-columns:repeat(2,minmax(0,1fr))}}
198
202
 
199
203
  .ptcPlusSessionCapabilityModal.ptcPlusSessionCapabilityModal{box-sizing:border-box;width:min(1180px,calc(100vw - 48px));height:min(800px,calc(100dvh - 48px));max-height:100%;max-width:100%;display:flex;flex-direction:column;gap:0;padding:0;border-radius:16px;overflow:hidden;background:var(--dsw-alias-bg-layer-1,var(--dsw-alias-bg-base,#fff));color:var(--dsw-alias-label-primary,#18191c);font:13px/20px var(--dsw-font-family,system-ui,sans-serif)}
200
204
  .ptcPlusSessionCapabilityModal>div{min-height:0}
201
- .ptcPlusSessionCapabilityColumns.ptcPlusCapabilityColumns,.ptcPlusSessionCapabilityRow.ptcPlusCapabilityItem{grid-template-columns:minmax(140px,1.3fr) 54px minmax(75px,.75fr) minmax(72px,.7fr) minmax(84px,.8fr) minmax(100px,1fr);gap:10px;padding:10px 12px}
205
+ .ptcPlusSessionCapabilityColumns.ptcPlusCapabilityColumns,.ptcPlusSessionCapabilityRow.ptcPlusCapabilityItem{grid-template-columns:minmax(140px,1.25fr) 58px minmax(70px,.6fr) minmax(88px,.62fr) minmax(112px,.85fr) minmax(96px,.7fr) minmax(118px,.85fr);gap:10px;padding:10px 12px}.ptcPlusSessionCapabilityColumns.ptcPlusSessionCapabilityColumns-8,.ptcPlusSessionCapabilityRow.ptcPlusSessionCapabilityRow-8{grid-template-columns:minmax(140px,1.25fr) 58px minmax(70px,.6fr) minmax(88px,.62fr) minmax(112px,.85fr) minmax(96px,.7fr) minmax(118px,.85fr) minmax(130px,.95fr)}.ptcPlusSessionCapabilityColumns.ptcPlusSessionCapabilityColumns-5,.ptcPlusSessionCapabilityRow.ptcPlusSessionCapabilityRow-5{grid-template-columns:minmax(160px,1.4fr) 70px minmax(90px,.8fr) minmax(120px,.9fr) minmax(150px,1.1fr)}
202
206
  .ptcPlusSessionCapabilityColumns{position:sticky;top:0;z-index:1;border-bottom:1px solid var(--dsw-alias-border-l2)}
203
- .ptcPlusSessionCapabilityBack{display:none}
207
+ .ptcPlusSessionCapabilityMessage{box-sizing:border-box;margin:0;padding:16px 24px;color:var(--dsw-alias-label-secondary);font-size:12px;line-height:18px;overflow-wrap:anywhere}
204
208
  .ptcPlusSessionCapabilityHead{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:18px 24px;border-bottom:1px solid var(--dsw-alias-border-l2)}
205
209
  .ptcPlusSessionCapabilityHead h2{margin:0;font-size:18px;line-height:26px}.ptcPlusSessionCapabilityHead p{margin:2px 0 0;color:var(--dsw-alias-label-secondary);font-size:12px;overflow-wrap:anywhere}
206
- .ptcPlusSessionCapabilityToolbar{display:grid;grid-template-columns:minmax(180px,1.6fr) repeat(3,minmax(120px,1fr));gap:10px;align-items:end;padding:12px 24px;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusSessionCapabilityToolbar .ptcPlusCapabilityFilter{min-width:0}.ptcPlusSessionCapabilityToolbar .ptcPlusSearch{min-width:0}
207
- .ptcPlusSessionCapabilityWorkspace{display:grid;grid-template-columns:minmax(0,2.2fr) minmax(280px,1fr);min-height:0;overflow:hidden;flex:1 1 0}.ptcPlusSessionCapabilityList,.ptcPlusSessionCapabilityDetail{min-width:0;min-height:0;overflow:auto;overscroll-behavior:contain}.ptcPlusSessionCapabilityList{padding:0;border-right:1px solid var(--dsw-alias-border-l2)}.ptcPlusSessionCapabilityGroup h3{margin:0;padding:10px 12px 6px;color:var(--dsw-alias-label-secondary);font-size:11px;font-weight:600}.ptcPlusSessionCapabilityRow{box-sizing:border-box;min-height:54px;width:100%;border-left:3px solid transparent;font-size:12px}.ptcPlusSessionCapabilityRow[data-selected=true]{border-left-color:var(--dsw-alias-brand-primary)}.ptcPlusSessionCapabilityName{appearance:none;min-width:0;padding:0;border:0;border-radius:4px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:13px;text-align:left;cursor:pointer;overflow-wrap:anywhere}.ptcPlusSessionCapabilityName:hover{color:var(--dsw-alias-brand-primary)}.ptcPlusSessionCapabilityRow button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityContext{font-size:11px}.ptcPlusSessionCapabilityPending{font-size:11px;color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere}.ptcPlusSessionCapabilityDetail{padding:22px 24px}.ptcPlusSessionCapabilityDetail h3{margin:0 0 6px;font-size:16px;overflow-wrap:anywhere}.ptcPlusSessionCapabilityDetail code{display:block;overflow-wrap:anywhere;color:var(--dsw-alias-label-secondary);font-size:11px}.ptcPlusSessionCapabilityDetail p{margin:16px 0;font-size:13px;line-height:21px;overflow-wrap:anywhere;color:var(--dsw-alias-label-secondary)}.ptcPlusSessionCapabilityDetail dl{display:grid;grid-template-columns:100px minmax(0,1fr);column-gap:16px;row-gap:12px;margin:20px 0;padding:16px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:var(--dsw-alias-bg-layer-2);font-size:12px;line-height:20px}.ptcPlusSessionCapabilityDetail dt{color:var(--dsw-alias-label-secondary)}.ptcPlusSessionCapabilityDetail dd{margin:0;overflow-wrap:anywhere;color:var(--dsw-alias-label-primary);font-weight:500}.ptcPlusSessionCapabilityChildren{margin-bottom:18px}.ptcPlusSessionCapabilityChildren h4{margin:0 0 6px;font-size:12px}.ptcPlusSessionCapabilityChildren ul{margin:0;padding-left:18px;font-size:12px;line-height:1.8}.ptcPlusSessionCapabilityFooter{display:flex;align-items:center;justify-content:flex-end;gap:10px;padding:12px 24px;border-top:1px solid var(--dsw-alias-border-l2)}.ptcPlusSessionCapabilityFooter [role=status]{margin-right:auto;font-size:12px;overflow-wrap:anywhere}.ptcPlusSessionCapabilityFooter button{flex:none}
208
- @media(max-width:900px){.ptcPlusSessionCapabilityToolbar{grid-template-columns:repeat(3,minmax(0,1fr))}.ptcPlusSessionCapabilityToolbar .ptcPlusSearch{grid-column:1/-1}.ptcPlusSessionCapabilityWorkspace{grid-template-columns:minmax(0,1fr) minmax(240px,.8fr)}.ptcPlusSessionCapabilityColumns.ptcPlusCapabilityColumns{display:flex;gap:4px 12px;overflow-x:auto;overscroll-behavior:contain;padding-block:4px}.ptcPlusSessionCapabilityColumns>span{flex:none}.ptcPlusSessionCapabilityRow.ptcPlusCapabilityItem{grid-template-columns:minmax(0,1fr) auto;gap:4px 12px}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityIdentity{grid-column:1/-1}.ptcPlusSessionCapabilityRow .ptcPlusCapabilitySource{grid-column:1;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityBadge{grid-column:2;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityAvailability{grid-column:1;grid-row:3}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityContextCell{grid-column:2;grid-row:3}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityPending{grid-column:1/-1;grid-row:4}.ptcPlusSessionCapabilityPending[data-changed=true]:before{content:attr(data-label) ": "}.ptcPlusSessionCapabilityPending[data-changed=false]{display:none}}
209
- @media(max-width:650px){.ptcPlusSessionCapabilityModal.ptcPlusSessionCapabilityModal{width:calc(100vw - 16px);height:calc(100dvh - 16px);max-height:100%}.ptcPlusSessionCapabilityHead,.ptcPlusSessionCapabilityToolbar,.ptcPlusSessionCapabilityFooter{padding-left:14px;padding-right:14px}.ptcPlusSessionCapabilityHead{padding-top:10px;padding-bottom:10px}.ptcPlusSessionCapabilityToolbar{gap:5px;padding-top:7px;padding-bottom:7px}.ptcPlusSessionCapabilityWorkspace{display:block;flex:1 1 0;min-height:0;overflow:hidden}.ptcPlusSessionCapabilityList,.ptcPlusSessionCapabilityDetail{box-sizing:border-box;height:100%;border:0}.ptcPlusSessionCapabilityWorkspace[data-pane=list] .ptcPlusSessionCapabilityDetail,.ptcPlusSessionCapabilityWorkspace[data-pane=detail] .ptcPlusSessionCapabilityList{display:none}.ptcPlusSessionCapabilityDetail{padding:14px}.ptcPlusSessionCapabilityBack{display:inline-block;margin:0 0 14px;padding:0;border:0;background:transparent;color:var(--dsw-alias-brand-primary);font:inherit;cursor:pointer}.ptcPlusSessionCapabilityFooter{flex-wrap:wrap;gap:6px;padding-top:7px;padding-bottom:7px}.ptcPlusSessionCapabilityFooter [role=status]{flex-basis:100%}.ptcPlusSessionCapabilityFooter button{flex:1;min-width:0;width:auto}}
210
- @media(max-width:650px) and (max-height:480px){.ptcPlusSessionCapabilityModal.ptcPlusSessionCapabilityModal{height:calc(100dvh - 8px);max-height:100%}.ptcPlusSessionCapabilityHead{padding-top:2px;padding-bottom:2px}.ptcPlusSessionCapabilityHead h2{font-size:12px;line-height:16px}.ptcPlusSessionCapabilityHead .ptcPlusDialogClose{width:22px;height:22px}.ptcPlusSessionCapabilityHead p{display:none}.ptcPlusSessionCapabilityToolbar .ptcPlusCapabilityFilter>span{display:none}.ptcPlusSessionCapabilityToolbar{display:flex;gap:6px;overflow-x:auto;overscroll-behavior:contain;padding-top:2px;padding-bottom:2px}.ptcPlusSessionCapabilityToolbar .ptcPlusSearch{flex:0 0 145px;height:27px}.ptcPlusSessionCapabilityToolbar{padding-block:1px}.ptcPlusSessionCapabilityToolbar .ptcPlusCapabilityFilter{flex:0 0 130px}.ptcPlusSessionCapabilityToolbar .ptcPlusSelectTrigger{height:27px}.ptcPlusSessionCapabilityColumns.ptcPlusCapabilityColumns{padding-block:0}.ptcPlusSessionCapabilityColumns .ptcPlusCapabilitySort{min-height:24px;padding-block:1px}.ptcPlusSessionCapabilityList{padding-block:0}.ptcPlusSessionCapabilityGroup h3{padding-top:0;padding-bottom:0;line-height:10px}.ptcPlusSessionCapabilityRow.ptcPlusCapabilityItem{grid-template-columns:minmax(0,1fr) auto auto;min-height:30px;padding-block:2px;gap:0 8px;line-height:16px}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityIdentity{grid-column:1/3;grid-row:1}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityName{font-size:12px;line-height:16px}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityBadge{grid-column:3;grid-row:1;padding-block:0}.ptcPlusSessionCapabilityRow .ptcPlusCapabilitySource{grid-column:1;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityAvailability{grid-column:2;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityContextCell{grid-column:3;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityPending{grid-row:3}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityIdentity code{display:none}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityContext{padding-block:0}.ptcPlusSessionCapabilityFooter{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:4px;padding:4px 6px}.ptcPlusSessionCapabilityFooter [role=status]{grid-column:1/-1;font-size:10px;line-height:12px}.ptcPlusSessionCapabilityFooter button{min-width:0;width:100%;min-height:28px;padding:3px 10px;font-size:10px;line-height:14px;white-space:normal}}
210
+ .ptcPlusSessionCapabilityToolbar{display:grid;grid-template-columns:minmax(180px,1.6fr) repeat(3,minmax(120px,1fr));gap:10px;align-items:end;padding:12px 24px;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusSessionCapabilityToolbar .ptcPlusCapabilityFilter{min-width:0}.ptcPlusSessionCapabilityToolbar .ptcPlusSearch{min-width:0}.ptcPlusSessionCapabilityGroup h3{margin:0;padding:10px 12px 6px;color:var(--dsw-alias-label-secondary);font-size:11px;font-weight:600}.ptcPlusSessionCapabilityRow{box-sizing:border-box;min-height:54px;width:100%;border-left:3px solid transparent;font-size:12px}.ptcPlusSessionCapabilityName{min-width:0;color:var(--dsw-alias-label-primary);font-size:13px;overflow-wrap:anywhere}.ptcPlusSessionCapabilityRow button:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.ptcPlusSessionCapabilityTable{min-width:0}.ptcPlusBindingGroup{margin-top:6px;padding-top:4px;border-top:1px solid var(--dsw-alias-border-l2)}.ptcPlusBindingGroup .ptcPlusBindingToggle{appearance:none;flex:none;padding:4px 10px;border:1px solid var(--dsw-alias-border-l2);border-radius:6px;background:transparent;color:var(--dsw-alias-label-primary);font:inherit;font-size:11px;cursor:pointer}.ptcPlusBindingGroup .ptcPlusBindingToggle[data-kind=use]{border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-brand-primary)}.ptcPlusBindingGroup .ptcPlusBindingToggle[data-kind=disabled]{color:var(--dsw-alias-label-secondary);cursor:default}.ptcPlusBindingGroup .ptcPlusBindingToggle:focus-visible{outline:2px solid var(--dsw-alias-brand-primary);outline-offset:2px}.ptcPlusBindingGroup .ptcPlusBindingToggle:disabled{cursor:default;opacity:.55}.ptcPlusBindingGroup .ptcPlusBindingToggle[aria-busy=true]{cursor:progress;opacity:.75}.ptcPlusSessionCapabilityFooter{display:flex;flex:none;align-items:center;justify-content:flex-end;gap:10px;padding:12px 24px;border-top:1px solid var(--dsw-alias-border-l2)}.ptcPlusSessionCapabilityFooter [role=status]{flex:0 1 auto;min-width:0;margin-right:auto;max-height:40px;overflow-y:auto;overscroll-behavior:contain;font-size:12px;overflow-wrap:anywhere}.ptcPlusSessionCapabilityFooter button{flex:none}
211
+ .ptcPlusSessionCapabilityList{flex:1 1 0;min-width:0;min-height:0;padding:0;overflow:auto;overscroll-behavior:contain}
212
+ .ptcPlusSessionCapabilitySaved{font-size:12px;color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere}
213
+ .ptcPlusSessionCapabilityAvailability,.ptcPlusSessionCapabilityDisclosure{display:flex;flex-wrap:nowrap;align-items:center;gap:6px;min-width:0}
214
+ .ptcPlusSessionCapabilityAvailability .ptcPlusSelectTrigger,.ptcPlusSessionCapabilityDisclosure .ptcPlusSelectTrigger{flex:1 1 0;min-width:0;width:auto}
215
+ .ptcPlusSessionCapabilitySavedDisclosure{font-size:12px;color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere}
216
+ .ptcPlusSessionCapabilitySaved,.ptcPlusSessionCapabilitySavedDisclosure{min-width:0;overflow:hidden}.ptcPlusSessionCapabilitySavedDisclosure .ptcPlusSelectTrigger,.ptcPlusSessionCapabilitySaved .ptcPlusSelectTrigger{width:100%;min-width:0;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
217
+ .ptcPlusSessionCapabilityReceipt{font-size:11px;color:var(--dsw-alias-label-secondary);overflow-wrap:anywhere}
218
+ .ptcPlusSessionCapabilityAddresses{margin:2px 0 0;color:var(--dsw-alias-label-secondary);font-size:12px;overflow-wrap:anywhere}
219
+ .ptcPlusSessionCapabilityRow[data-session-state=enabled]{border-left-color:var(--dsw-alias-state-success-primary,#12a150)}.ptcPlusSessionCapabilityRow[data-session-state=use]{border-left-color:var(--dsw-alias-state-success-primary,#12a150)}.ptcPlusSessionCapabilityRow[data-session-state=automatic]{border-left-color:var(--dsw-alias-state-business-primary,#4d6bfe)}.ptcPlusSessionCapabilityRow[data-session-state=closed]{border-left-color:var(--dsw-alias-state-error-primary,#e5484d)}.ptcPlusSessionCapabilityRow[data-session-state=damaged]{border-left-color:var(--dsw-alias-state-error-primary,#e5484d)}.ptcPlusSessionCapabilityRow[data-session-state=inherit]{border-left-color:var(--dsw-alias-border-l2)}.ptcPlusSessionCapabilityRow[data-session-state=skip]{border-left-color:var(--dsw-alias-border-l2)}
220
+ .ptcPlusSessionCapabilityRow[data-session-state=closed] .ptcPlusSessionCapabilityName,.ptcPlusSessionCapabilityRow[data-session-state=closed] .ptcPlusCapabilitySource,.ptcPlusSessionCapabilityRow[data-session-state=skip] .ptcPlusSessionCapabilityName{opacity:.6}
221
+ .ptcPlusSessionStateMark{flex:none;box-sizing:border-box;width:9px;height:9px;border-radius:50%;border:1.5px solid var(--dsw-alias-label-tertiary);background:transparent}
222
+ .ptcPlusSessionCapabilityAvailability[data-state=enabled] .ptcPlusSessionStateMark,.ptcPlusSessionCapabilityAvailability[data-state=use] .ptcPlusSessionStateMark{border-color:var(--dsw-alias-state-success-primary,#12a150);background:var(--dsw-alias-state-success-primary,#12a150)}
223
+ .ptcPlusSessionCapabilityAvailability[data-state=automatic] .ptcPlusSessionStateMark{border-color:var(--dsw-alias-state-business-primary,#4d6bfe);background:var(--dsw-alias-state-business-primary,#4d6bfe)}
224
+ .ptcPlusSessionCapabilityAvailability[data-state=closed] .ptcPlusSessionStateMark,.ptcPlusSessionCapabilityAvailability[data-state=damaged] .ptcPlusSessionStateMark{border-color:var(--dsw-alias-state-error-primary,#e5484d);background:linear-gradient(135deg,transparent 42%,var(--dsw-alias-state-error-primary,#e5484d) 42% 58%,transparent 58%)}
225
+ /* A cell states its state with the control it owns: the trigger keeps the label colour and
226
+ carries a tinted fill and border, and a word-only cell states the same state as a chip. The
227
+ state's own colour never reaches the text, and the mark plus the word still carry the state on
228
+ their own, so the difference does not depend on a tint alone. The secondary label colour below
229
+ states precedence (a layer above this cell decided, not this cell), not a state. */
230
+ .ptcPlusSessionCapabilityAvailability[data-state=enabled] .ptcPlusSelectTrigger,.ptcPlusSessionCapabilityAvailability[data-state=use] .ptcPlusSelectTrigger,.ptcPlusSessionCapabilitySaved[data-state=enabled] .ptcPlusSelectTrigger,.ptcPlusSessionCapabilityAvailability[data-state=use] .ptcPlusBindingToggle{border-color:color-mix(in srgb,var(--dsw-alias-state-success-primary,#12a150) 42%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-success-primary,#12a150) 10%,transparent)}
231
+ .ptcPlusSessionCapabilityAvailability[data-state=automatic] .ptcPlusSelectTrigger,.ptcPlusSessionCapabilitySaved[data-state=automatic] .ptcPlusSelectTrigger{border-color:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 42%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 10%,transparent)}
232
+ .ptcPlusSessionCapabilityAvailability[data-state=closed] .ptcPlusSelectTrigger,.ptcPlusSessionCapabilityAvailability[data-state=damaged] .ptcPlusSelectTrigger,.ptcPlusSessionCapabilitySaved[data-state=closed] .ptcPlusSelectTrigger,.ptcPlusSessionCapabilityAvailability[data-state=closed] .ptcPlusBindingToggle,.ptcPlusSessionCapabilityAvailability[data-state=damaged] .ptcPlusBindingToggle{border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary,#e5484d) 42%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-error-primary,#e5484d) 10%,transparent)}
233
+ .ptcPlusSessionCapabilityAvailability[data-state=inherit] .ptcPlusSelectTrigger,.ptcPlusSessionCapabilityDisclosure[data-state=inherit] .ptcPlusSelectTrigger{color:var(--dsw-alias-label-secondary)}.ptcPlusSessionCapabilityAvailability[data-state=skip] .ptcPlusBindingToggle{color:var(--dsw-alias-label-secondary)}
234
+ span.ptcPlusSessionCapabilitySaved[data-state=enabled],span.ptcPlusSessionCapabilitySaved[data-state=automatic],span.ptcPlusSessionCapabilitySaved[data-state=closed]{box-sizing:border-box;justify-self:start;display:inline-flex;align-items:center;height:16px;padding:0 7px;border-radius:999px;border:1px solid transparent;font-size:inherit;line-height:14px}
235
+ span.ptcPlusSessionCapabilitySaved[data-state=enabled]{background:color-mix(in srgb,var(--dsw-alias-state-success-primary,#12a150) 10%,transparent);border-color:color-mix(in srgb,var(--dsw-alias-state-success-primary,#12a150) 42%,transparent)}
236
+ span.ptcPlusSessionCapabilitySaved[data-state=automatic]{background:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 10%,transparent);border-color:color-mix(in srgb,var(--dsw-alias-state-business-primary,#4d6bfe) 42%,transparent)}
237
+ span.ptcPlusSessionCapabilitySaved[data-state=closed]{background:color-mix(in srgb,var(--dsw-alias-state-error-primary,#e5484d) 10%,transparent);border-color:color-mix(in srgb,var(--dsw-alias-state-error-primary,#e5484d) 42%,transparent)}
238
+ .ptcPlusCapabilitySurface-inline{border:1px solid var(--dsw-alias-border-l2);border-radius:10px;overflow:clip}
239
+ /* The settings entrance is a page section, not a bounded dialog: the page owns the vertical
240
+ wheel. A clipping box that is also a scroll container (overflow:hidden) or an inner list that
241
+ keeps its own vertical scrolling captures the wheel while it cannot move, so the page stops
242
+ under the pointer. clip only trims the corners, and the inline list gives up both its own
243
+ scrolling and its scroll chaining rule. The strips this surface does scroll sideways -- the
244
+ settings tabs, the column header and, on a short viewport, the toolbar -- contain only that
245
+ axis, so a vertical wheel over them still reaches the page. */
246
+ .ptcPlusCapabilitySurface-inline .ptcPlusSessionCapabilityList{flex:none;max-height:none;overflow:visible;overscroll-behavior:auto}
247
+ .ptcPlusCapabilitySurface-inline .ptcPlusSessionCapabilityHead{padding-top:10px;padding-bottom:10px}
248
+ .ptcPlusCapabilityRulesEntry{display:flex;justify-content:flex-end;padding:0 0 8px}
249
+ .ptcPlusBindingTable{min-width:0}
250
+ @media(max-width:900px){.ptcPlusSessionCapabilityRow.ptcPlusCapabilityItem{grid-template-columns:minmax(0,1fr) auto;gap:6px 12px}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityIdentity{grid-column:1/-1;grid-row:1}.ptcPlusSessionCapabilityRow .ptcPlusCapabilitySource{grid-column:1;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityBadge{grid-column:2;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilitySaved{grid-column:1;grid-row:3}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilitySavedDisclosure{grid-column:2;grid-row:3}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityAvailability{grid-column:1/-1;grid-row:4;flex-direction:row;flex-wrap:wrap}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityDisclosure{grid-column:1/-1;grid-row:5;flex-direction:row;flex-wrap:wrap}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityReceipt{grid-column:1/-1;grid-row:6}.ptcPlusSessionCapabilityRow-5 .ptcPlusSessionCapabilitySaved{grid-column:1/-1;grid-row:3}.ptcPlusSessionCapabilityRow-5 .ptcPlusSessionCapabilitySavedDisclosure{grid-column:1/-1;grid-row:4}}
251
+ @media(max-width:900px){.ptcPlusSessionCapabilityToolbar{grid-template-columns:repeat(3,minmax(0,1fr))}.ptcPlusSessionCapabilityToolbar .ptcPlusSearch{grid-column:1/-1}.ptcPlusSessionCapabilityColumns.ptcPlusCapabilityColumns{display:flex;gap:4px 12px;overflow-x:auto;overscroll-behavior-x:contain;padding-block:4px}.ptcPlusSessionCapabilityColumns>span{flex:none}.ptcPlusSessionCapabilityRow.ptcPlusCapabilityItem{grid-template-columns:minmax(0,1fr) auto;gap:4px 12px}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityIdentity{grid-column:1/-1}.ptcPlusSessionCapabilityRow .ptcPlusCapabilitySource{grid-column:1;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityBadge{grid-column:2;grid-row:2}}
252
+ @media(max-width:650px){.ptcPlusSessionCapabilityModal.ptcPlusSessionCapabilityModal{width:calc(100vw - 16px);height:calc(100dvh - 16px);max-height:100%}.ptcPlusSessionCapabilityHead,.ptcPlusSessionCapabilityToolbar,.ptcPlusSessionCapabilityFooter{padding-left:14px;padding-right:14px}.ptcPlusSessionCapabilityHead{padding-top:10px;padding-bottom:10px}.ptcPlusSessionCapabilityToolbar{gap:5px;padding-top:7px;padding-bottom:7px}.ptcPlusSessionCapabilityFooter{flex-wrap:wrap;gap:6px;padding-top:7px;padding-bottom:7px}.ptcPlusSessionCapabilityFooter [role=status]{flex-basis:100%}.ptcPlusSessionCapabilityFooter button{flex:1;min-width:0;width:auto}}
253
+ @media(max-height:480px){.ptcPlusSessionCapabilityModal.ptcPlusSessionCapabilityModal{height:calc(100dvh - 8px);max-height:100%}.ptcPlusSessionCapabilityHead{padding-top:2px;padding-bottom:2px}.ptcPlusSessionCapabilityHead h2{font-size:12px;line-height:16px}.ptcPlusSessionCapabilityHead .ptcPlusDialogClose{width:22px;height:22px}.ptcPlusSessionCapabilityHead p{display:none}.ptcPlusSessionCapabilityToolbar .ptcPlusCapabilityFilter>span{display:none}.ptcPlusSessionCapabilityToolbar{display:flex;gap:6px;overflow-x:auto;overscroll-behavior-x:contain;padding-block:1px}.ptcPlusSessionCapabilityToolbar .ptcPlusSearch{flex:0 0 145px;height:27px}.ptcPlusSessionCapabilityToolbar .ptcPlusCapabilityFilter{flex:0 0 130px}.ptcPlusSessionCapabilityToolbar .ptcPlusSelectTrigger{height:27px}.ptcPlusSessionCapabilityToolbar>.ptcPlusButton{flex:none;min-height:28px;padding:2px 10px;font-size:11px;line-height:14px;white-space:nowrap}.ptcPlusSessionCapabilityColumns.ptcPlusCapabilityColumns{padding-block:0}.ptcPlusSessionCapabilityGroup h3{padding-top:0;padding-bottom:0;line-height:10px}.ptcPlusSessionCapabilityRow.ptcPlusCapabilityItem{grid-template-columns:minmax(0,1.25fr) auto minmax(120px,1fr);min-height:32px;padding-block:3px;gap:0 10px;line-height:16px}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityIdentity{grid-column:1;grid-row:1}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityName{font-size:12px;line-height:16px}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityIdentity code{display:none}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityBadge{grid-column:2;grid-row:1;padding-block:0}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityAvailability{grid-column:3;grid-row:1;flex-direction:row;flex-wrap:nowrap}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityDisclosure{grid-column:3;grid-row:2;flex-direction:row;flex-wrap:nowrap}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityAvailability .ptcPlusSelectTrigger,.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityDisclosure .ptcPlusSelectTrigger{height:24px;padding:0 6px;font-size:11px}.ptcPlusSessionCapabilityRow .ptcPlusCapabilitySource{grid-column:1;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilitySaved{grid-column:2;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilitySavedDisclosure{grid-column:1;grid-row:3}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityReceipt{grid-column:2/-1;grid-row:3}.ptcPlusSessionCapabilityFooter{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:4px;padding:4px 6px}.ptcPlusSessionCapabilityFooter [role=status]{grid-column:1/-1;font-size:10px;line-height:11px;max-height:22px;overflow-y:auto}.ptcPlusSessionCapabilityFooter button{min-width:0;width:100%;min-height:28px;padding:3px 10px;font-size:10px;line-height:14px;white-space:normal}}
254
+ @media(max-height:480px) and (max-width:650px){.ptcPlusSessionCapabilityRow.ptcPlusCapabilityItem{grid-template-columns:minmax(0,1fr) minmax(0,1fr) auto;gap:0 8px;padding-block:4px}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityIdentityText{min-height:0;gap:2px}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityName{line-height:16px}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityIdentity{grid-column:1/3;grid-row:1}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityReceipt{grid-column:3;grid-row:1;justify-self:end;max-width:100%;font-size:10px;line-height:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.ptcPlusSessionCapabilityRow .ptcPlusCapabilitySource{grid-column:1;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilitySaved{grid-column:2;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilitySavedDisclosure{grid-column:3;grid-row:2}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityAvailability{grid-column:1;grid-row:3}.ptcPlusSessionCapabilityRow .ptcPlusSessionCapabilityDisclosure{grid-column:2;grid-row:3}.ptcPlusSessionCapabilityRow .ptcPlusCapabilityBadge{grid-column:3;grid-row:3;justify-self:end}.ptcPlusSessionCapabilityRow-5 .ptcPlusSessionCapabilitySaved{grid-column:1/-1;grid-row:4}.ptcPlusSessionCapabilityRow-5 .ptcPlusSessionCapabilitySavedDisclosure{grid-column:1/-1;grid-row:5}}
211
255
 
212
256
  .ptcPlusCapabilityDialog.ptcPlusCapabilityDialog{box-sizing:border-box;width:min(520px,calc(100vw - 32px));max-height:calc(100dvh - 32px);display:flex;flex-direction:column;padding:0;overflow:hidden;background:var(--dsw-alias-bg-base,#fff);color:var(--dsw-alias-label-primary,#18191c)}
213
- .ptcPlusCapabilityDialog.ptcPlusCapabilityEditorDialog{width:min(640px,calc(100vw - 32px))}
257
+
214
258
  .ptcPlusCapabilityDialogHead{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 18px;border-bottom:1px solid var(--dsw-alias-border-l2)}.ptcPlusCapabilityDialogHead h2{margin:0;font-size:16px;line-height:24px;overflow-wrap:anywhere}
215
- .ptcPlusCapabilityDialogBody{min-height:0;overflow:auto;overscroll-behavior:contain;padding:14px 18px}.ptcPlusCapabilityDialogBody>p{margin:0 0 10px;overflow-wrap:anywhere}.ptcPlusCapabilityDialogBody .ptcPlusCapabilityFilterFields{padding:0;border:0}
259
+ .ptcPlusCapabilityDialogBody{min-height:0;overflow:auto;overscroll-behavior:contain;padding:14px 18px}.ptcPlusCapabilityDialogBody>p{margin:0 0 10px;overflow-wrap:anywhere}
216
260
  .ptcPlusCapabilityDialogFooter{display:flex;align-items:center;justify-content:flex-end;gap:10px;padding:12px 18px;border-top:1px solid var(--dsw-alias-border-l2)}
217
261
  .ptcPlusCapabilityDialogActions{display:flex;flex-direction:column;gap:8px;margin-top:12px}.ptcPlusCapabilityDialogActions>.ptcPlusButton{justify-content:center;width:100%}
218
262
  .ptcPlusConfigurationMore.ptcPlusButton{padding:0 10px;font-size:16px;line-height:1}
263
+ .ptcPlusCapabilitySort{appearance:none;display:inline-flex;align-items:center;gap:4px;min-width:0;max-width:100%;min-height:18px;margin:-3px 0;padding:0;border:0;background:transparent;color:inherit;font:inherit;line-height:18px;text-align:start;cursor:pointer}
264
+ .ptcPlusCapabilitySort:hover{color:var(--dsw-alias-label-primary)}
265
+ .ptcPlusCapabilitySort:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:-2px}
266
+ .ptcPlusCapabilitySortMark{flex:none;font-size:10px;line-height:1;opacity:.55}
267
+ [aria-sort=ascending] .ptcPlusCapabilitySortMark,[aria-sort=descending] .ptcPlusCapabilitySortMark{opacity:1;color:var(--dsw-alias-label-primary)}
219
268
  @media(max-width:420px){.ptcPlusCapabilityDialogFooter{flex-wrap:wrap}.ptcPlusCapabilityDialogFooter button{flex:1;min-width:0}}
220
269
 
221
270
  `
@@ -269,8 +318,7 @@ const REPL_CONSOLE_CSS = `
269
318
  @media(max-width:560px){.ptcPlusConsole{padding:14px 12px}.ptcPlusBindingsModal.ptcPlusBindingsModal{width:calc(100vw - 16px);max-height:calc(100dvh - 16px)}.ptcPlusBindingsDialog{padding:16px;max-height:calc(100dvh - 16px)}.ptcPlusObservationFilters>.ptcPlusSelectTrigger{width:105px}.ptcPlusObservationTable th,.ptcPlusObservationTable td{padding:0 6px}.ptcPlusObservationValue{gap:3px}.ptcPlusObservationState{font-size:10px}.ptcPlusEditorHead{align-items:flex-start}.ptcPlusEditorHead>.ptcPlusBindingLifecycle{margin-left:auto}.ptcPlusSourceBody .cm-editor{height:300px}}
270
319
  .ptcPlusReplIdentity{grid-column:1}.ptcPlusReplReuse{flex:none;padding:0 5px;border-radius:999px;background:var(--dsw-alias-bg-layer-2,rgba(38,49,72,.06));color:var(--dsw-alias-label-tertiary,#74777d);font:500 10px/15px system-ui,sans-serif;white-space:nowrap}
271
320
  .ptcPlusObservationReuseTotal{font-size:13px;color:var(--dsw-alias-label-tertiary)}.ptcPlusObservationReuse{color:var(--dsw-alias-label-tertiary);white-space:nowrap;font-variant-numeric:tabular-nums}
272
- .ptcPlusCapabilityIdentity{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:3px 8px;min-width:0}.ptcPlusCapabilityIdentityText{display:flex;flex-direction:column;gap:3px;min-width:0}.ptcPlusCapabilityPickHead{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:6px}.ptcPlusCapabilityPickHead .ptcPlusCapabilitySort{min-width:0}.ptcPlusPick{appearance:none;position:relative;flex:none;box-sizing:border-box;width:16px;height:16px;margin:0;border:1px solid var(--dsw-alias-border-l4);border-radius:4px;background:var(--dsw-alias-bg-layer-3);cursor:pointer}.ptcPlusPick:checked,.ptcPlusPick:indeterminate{border-color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-brand-primary)}.ptcPlusPick:checked::after{position:absolute;left:4px;top:1px;width:5px;height:9px;border:solid var(--dsw-alias-label-primary-foreground);border-width:0 2px 2px 0;content:'';transform:rotate(45deg)}.ptcPlusPick:indeterminate::after{position:absolute;left:3px;top:6px;width:8px;height:2px;border-radius:1px;background:var(--dsw-alias-label-primary-foreground);content:''}.ptcPlusPick:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:2px}.ptcPlusPick:disabled{cursor:not-allowed;opacity:.4}.ptcPlusCapabilityBatchCount{display:inline-flex;align-items:center;justify-content:center;min-width:16px;height:16px;padding:0 5px;border-radius:999px;background:var(--dsw-alias-state-business-primary,#4d6bfe);color:#fff;font-size:10px;line-height:16px}.ptcPlusCapabilityBlocked{display:flex;gap:8px;align-items:flex-start;margin:10px 24px 0;border:1px solid color-mix(in srgb,var(--dsw-alias-state-warn-primary,#a15c00) 30%,transparent);background:color-mix(in srgb,var(--dsw-alias-state-warn-primary,#a15c00) 8%,var(--dsw-alias-bg-layer-2));color:var(--dsw-alias-label-primary);font-weight:500}.ptcPlusCapabilityBlockedIcon{flex:none;margin-top:2px;color:var(--dsw-alias-state-warn-primary,#a15c00)}.ptcPlusSessionCapabilityDetail .ptcPlusCapabilityImpact{margin:6px 0 14px;font-size:12px;line-height:18px}
273
- @media(max-width:650px){.ptcPlusCapabilityBlocked{margin-inline:14px}}@media(max-width:650px) and (max-height:480px){.ptcPlusCapabilityBlocked{margin:4px 6px 0;font-size:11px}}
321
+ .ptcPlusCapabilityIdentity{display:grid;grid-template-columns:auto minmax(0,1fr);align-items:center;gap:3px 8px;min-width:0}.ptcPlusCapabilityIdentityText{display:flex;flex-direction:column;gap:3px;min-width:0}.ptcPlusPick{appearance:none;position:relative;flex:none;box-sizing:border-box;width:16px;height:16px;margin:0;border:1px solid var(--dsw-alias-border-l4);border-radius:4px;background:var(--dsw-alias-bg-layer-3);cursor:pointer}.ptcPlusPick:checked,.ptcPlusPick:indeterminate{border-color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-brand-primary)}.ptcPlusPick:checked::after{position:absolute;left:4px;top:1px;width:5px;height:9px;border:solid var(--dsw-alias-label-primary-foreground);border-width:0 2px 2px 0;content:'';transform:rotate(45deg)}.ptcPlusPick:indeterminate::after{position:absolute;left:3px;top:6px;width:8px;height:2px;border-radius:1px;background:var(--dsw-alias-label-primary-foreground);content:''}.ptcPlusPick:focus-visible{outline:2px solid var(--dsw-alias-state-business-primary,#4d6bfe);outline-offset:2px}.ptcPlusPick:disabled{cursor:not-allowed;opacity:.4}.ptcPlusCapabilityBatchCount{display:inline-flex;align-items:center;justify-content:center;min-width:16px;height:16px;padding:0 5px;border-radius:999px;background:var(--dsw-alias-state-business-primary,#4d6bfe);color:#fff;font-size:10px;line-height:16px}@media(max-width:650px){.ptcPlusSessionCapabilityMessage{padding-inline:14px}}
274
322
  @media(max-width:650px){.ptcPlusSessionCapabilityFooter button{font-size:11px;line-height:14px}}
275
323
  @media(max-width:650px) and (max-height:480px){.ptcPlusSessionCapabilityFooter{grid-template-columns:repeat(4,minmax(0,1fr));gap:3px;padding:3px 6px}.ptcPlusSessionCapabilityFooter [role=status]{line-height:11px}.ptcPlusSessionCapabilityFooter button{font-size:10px;line-height:12px;padding:1px 10px}}
276
324
  `
package/src/client.js CHANGED
@@ -3,8 +3,9 @@ import { RPC_CONTRACTS } from '../internal/rpc-contract.js'
3
3
  import { CONFIG_DEFAULTS, SETTINGS_NAMESPACE } from '../internal/config-spec.js'
4
4
  import { createPtcToolView } from './client-tool-view.js'
5
5
  import { createPtcSettingsView } from './client-settings-view.js'
6
- import { createCapabilityCommandCard, createCapabilityRefreshView, createSessionCapabilityControlsView } from './client-capabilities-view.js'
6
+ import { createCapabilityCommandCard, createCapabilityRefreshView, createCapabilitySurfaceView } from './client-capabilities-view.js'
7
7
  import { capabilityProfileConfiguration } from '../internal/runtime-config.js'
8
+ import { capabilityPolicyForConfig } from '../internal/capability-policy.js'
8
9
  import { createReplView } from './client-repl-view.js'
9
10
  import { createAuthoringView } from './client-authoring-view.js'
10
11
  import { bindingToggleConversationDefinition } from './client-binding-toggle.js'
@@ -178,18 +179,28 @@ export function createClientPlugin(require) {
178
179
  })
179
180
  const { observeRepl } = createReplObserver({ rpc, ctx })
180
181
  const capabilityCommands = createCommandAccess(ctx, 'capabilities')
182
+ // The panel's binding rows write through the same `/binding` command a human
183
+ // types, so they borrow its availability source instead of a second channel.
184
+ const bindingCommands = createBindingCommandAvailability(ctx)
181
185
  const CapabilityCommandCard = createCapabilityCommandCard(React)
182
186
  const CapabilityRefreshButton = createCapabilityRefreshView(React, capabilityCommands)
183
- const SessionCapabilityControls = createSessionCapabilityControlsView(React, {
184
- commands: capabilityCommands, Modal, Select,
185
- async inspectSessionCatalog(sessionId, signal) {
186
- const result = await rpc.call(RPC_CONTRACTS.capabilities, 'session-catalog', { sessionId }, signal)
187
- if (result?.ok !== true) throw new Error(result?.error?.message ?? 'Session capability catalog unavailable')
188
- return result.value
189
- },
187
+ // One read serves both entrances. A request that names a session states that
188
+ // session's declared face; a request that names none states the Host's own
189
+ // declaration, which is the process-scope object set this entrance can state — a
190
+ // preset's agent-scope entries exist only in a session's declared face.
191
+ async function inspectSessionCatalog(sessionId, signal) {
192
+ const result = await rpc.call(RPC_CONTRACTS.capabilities, 'session-catalog',
193
+ typeof sessionId === 'string' && sessionId ? { sessionId } : {}, signal)
194
+ if (result?.ok !== true) throw new Error(result?.error?.message ?? 'Session capability catalog unavailable')
195
+ return result.value
196
+ }
197
+ // The capability page has one renderer. The session entry and the settings entry
198
+ // both mount it; neither adds a column, a word, a control or a receipt of its own.
199
+ const CapabilitySurface = createCapabilitySurfaceView(React, {
200
+ commands: capabilityCommands, bindingCommands, Modal, Select, inspectSessionCatalog,
190
201
  })
191
202
  const { PTCPlusSettingsCard, PTCPlusSettingsDialog } = createPtcSettingsView(React, {
192
- ActionButton, BindingsDialog, Modal, Select, useWorkbenchController, CapabilityRefreshButton,
203
+ ActionButton, BindingsDialog, Modal, Select, useWorkbenchController, CapabilityRefreshButton, CapabilitySurface,
193
204
  async inspectCapabilityTargets(signal) {
194
205
  const result = await rpc.call(RPC_CONTRACTS.capabilities, 'targets', {}, signal)
195
206
  if (result?.ok !== true) throw new Error(result?.error?.message ?? 'Capability refresh targets unavailable')
@@ -200,17 +211,14 @@ export function createClientPlugin(require) {
200
211
  if (result?.ok !== true) throw new Error(result?.error?.message ?? 'Capability plans unavailable')
201
212
  return result.value
202
213
  },
203
- async inspectCapabilityCatalog(signal) {
204
- const result = await rpc.call(RPC_CONTRACTS.capabilities, 'catalog', {}, signal)
205
- if (result?.ok !== true) throw new Error(result?.error?.message ?? 'Capability catalog unavailable')
206
- return result.value
207
- },
208
214
  async inspectCapabilityAllocation(payload, signal) {
209
215
  const result = await rpc.call(RPC_CONTRACTS.capabilities, 'allocation', payload, signal)
210
216
  if (result?.ok !== true) throw new Error(result?.error?.message ?? 'Capability allocation unavailable')
211
217
  return result.value
212
218
  },
213
- icons: { search: IconSearchOutline16, chevron: IconChevronDownOutline14 },
219
+ // The settings page reads one icon: its navigation chevron. The search icon belonged to
220
+ // the second renderer's toolbar row, which this page no longer has.
221
+ icons: { chevron: IconChevronDownOutline14 },
214
222
  })
215
223
  const { ReplComposer, ReplConsole, ReplMemoryCard, replPopoverIsOpen, placeReplPopover, useObservedReplMemory } = createReplView(React, {
216
224
  CodeBlock, Select, featureEnabled, normalizeReplMemorySnapshot, normalizeReplMemoryView,
@@ -241,9 +249,24 @@ export function createClientPlugin(require) {
241
249
  const before = preferenceScope.getSnapshot()
242
250
  if (before.status !== 'ready' || before.writable !== true || !featureEnabled(before, 'plugin')) throw new Error('Capability settings are not writable')
243
251
  const validated = capabilityProfileConfiguration(configuration)
244
- await preferenceScope.mutate(Object.entries(validated).map(([key, value]) => ({ op: 'set', path: [key], value })))
252
+ const synthesized = JSON.stringify(capabilityPolicyForConfig({ ...validated, capabilityPolicy: undefined }))
253
+ const ops = Object.entries(validated)
254
+ .filter(([key]) => key !== 'capabilityPolicy')
255
+ .map(([key, value]) => ({ op: 'set', path: [key], value }))
256
+ // A policy the rest of this configuration would synthesize belongs to no record: writing it
257
+ // would freeze a synthesized bottom layer into the record and let the management switch
258
+ // reach cells that must read 自动 (capability-surface §8.1c). The record may still hold one
259
+ // from an earlier apply, so remove it with the service's own unset op instead of leaving it.
260
+ const policyWritten = validated.capabilityPolicy !== undefined && validated.capabilityPolicy !== synthesized
261
+ ops.push(policyWritten
262
+ ? { op: 'set', path: ['capabilityPolicy'], value: validated.capabilityPolicy }
263
+ : { op: 'unset', path: ['capabilityPolicy'] })
264
+ await preferenceScope.mutate(ops)
245
265
  const after = preferenceScope.getSnapshot()
246
- if (after.status !== 'ready' || Object.entries(validated).some(([key, value]) => after.value?.[key] !== value)) throw new Error('Capability configuration was not applied')
266
+ const unchanged = Object.entries(validated).every(([key, value]) => key === 'capabilityPolicy'
267
+ ? (policyWritten ? after.value?.capabilityPolicy === value : after.value?.capabilityPolicy === undefined)
268
+ : after.value?.[key] === value)
269
+ if (after.status !== 'ready' || !unchanged) throw new Error('Capability configuration was not applied')
247
270
  return 'status.applied'
248
271
  }
249
272
  // One gated-registration shape for every settings-driven contribution.
@@ -307,7 +330,10 @@ export function createClientPlugin(require) {
307
330
  isEnabled: () => featureEnabled(preferenceScope.getSnapshot(), 'replView')
308
331
  && sessionUsesPtcPreset(preset),
309
332
  register: () => viewScope.slots.register({
310
- name: 'conversation.view', id: 'ptc-plus-repl', label: 'REPL', order: 20,
333
+ // A plugin contribution trails the Host's own tabs: chat is 0 and the
334
+ // experimental statistics tab is 40, and a REPL tab that sorts before them
335
+ // pushes a Host tab to the right of a plugin's.
336
+ name: 'conversation.view', id: 'ptc-plus-repl', label: 'REPL', order: 50,
311
337
  locale: LOCALE_NS, inject: () => ({ ...settingsProps(), hideComposer, observeRepl }),
312
338
  }, props => typeof props.useProjection === 'function' ? h(ReplConsole, props) : null),
313
339
  })
@@ -330,7 +356,7 @@ export function createClientPlugin(require) {
330
356
  const { BindingAuthorButton, BindingReviewDock, BindingCommandCard } = createAuthoringView(React, {
331
357
  ActionButton, IconButton, Menu, MenuFallback, Toast, Tooltip, CodeBlock, Modal, createPortal, BindingsDialog, PTCPlusSettingsDialog,
332
358
  useWorkbenchController, useBindingReview, catalogOwner, callUserBindings, subscribeReset,
333
- settingsCardSeat: settingsCard.seat, updateSetting, updateCapabilityConfiguration, menuChildren, SessionCapabilityControls,
359
+ settingsCardSeat: settingsCard.seat, updateSetting, updateCapabilityConfiguration, menuChildren, SessionCapabilityControls: CapabilitySurface,
334
360
  icons: {
335
361
  sparkle: IconSparkle16, chevron: IconChevronDownOutline14,
336
362
  close: IconCloseOutline16, check: IconCheckOutline14,
@@ -366,7 +392,6 @@ export function createClientPlugin(require) {
366
392
  name: 'conversation.input.dock', id: 'ptc-plus-binding-review', order: -30, locale: LOCALE_NS,
367
393
  }, props => typeof props.useProjection === 'function' && props.sessionId !== undefined
368
394
  ? h(BindingReviewDock, { ...props, key: props.sessionId }) : null)))))
369
- const availability = createBindingCommandAvailability(ctx)
370
395
  // The composer binding entry belongs to the PTC surface, exactly like the
371
396
  // header indicator and the REPL tab. A non-PTC session keeps plugin
372
397
  // settings and `/binding` command cards, but shows no binding shortcut and
@@ -387,7 +412,7 @@ export function createClientPlugin(require) {
387
412
  register: () => ctx.slots.register({
388
413
  name: 'conversation.input.left', id: 'ptc-plus-binding-author', order: 20, locale: LOCALE_NS,
389
414
  inject: sessionId => ({
390
- hooks: { ptcSettings: preferenceScope, bindingCommand: availability.source(sessionId),
415
+ hooks: { ptcSettings: preferenceScope, bindingCommand: bindingCommands.source(sessionId),
391
416
  capabilityCommand: capabilityCommands.source(sessionId) },
392
417
  }),
393
418
  }, props => props.sessionId === undefined ? null : h(BindingAuthorButton, { ...props, key: props.sessionId })),