@pellux/goodvibes-agent 1.2.0 → 1.3.0

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 (77) hide show
  1. package/CHANGELOG.md +159 -0
  2. package/dist/package/main.js +19016 -12684
  3. package/docs/README.md +3 -3
  4. package/docs/connected-host.md +2 -2
  5. package/docs/getting-started.md +11 -9
  6. package/docs/tools-and-commands.md +12 -10
  7. package/docs/voice-and-live-tts.md +2 -2
  8. package/package.json +1 -1
  9. package/release/release-notes.md +17 -5
  10. package/release/release-readiness.json +36 -36
  11. package/src/agent/competitive-feature-inventory.ts +42 -44
  12. package/src/agent/setup-wizard-artifact-receipts.ts +366 -0
  13. package/src/agent/setup-wizard.ts +245 -9
  14. package/src/input/agent-workspace-categories.ts +2 -2
  15. package/src/input/agent-workspace-onboarding-categories.ts +4 -4
  16. package/src/input/agent-workspace-settings.ts +52 -1
  17. package/src/input/agent-workspace-setup-snapshot.ts +20 -1
  18. package/src/input/agent-workspace-setup.ts +32 -5
  19. package/src/input/agent-workspace-snapshot.ts +23 -3
  20. package/src/input/agent-workspace.ts +5 -1
  21. package/src/input/setup-wizard-live-receipts.ts +76 -0
  22. package/src/renderer/agent-workspace-context-lines.ts +21 -6
  23. package/src/renderer/agent-workspace.ts +46 -10
  24. package/src/runtime/tool-permission-safety.ts +1 -1
  25. package/src/tools/agent-harness-agent-orchestration-policy.ts +75 -0
  26. package/src/tools/agent-harness-agent-orchestration.ts +216 -128
  27. package/src/tools/agent-harness-autonomy-live-records.ts +154 -0
  28. package/src/tools/agent-harness-autonomy-queue-types.ts +1 -1
  29. package/src/tools/agent-harness-autonomy-queue.ts +19 -8
  30. package/src/tools/agent-harness-autonomy-watcher-read-models.ts +509 -0
  31. package/src/tools/agent-harness-background-processes.ts +8 -4
  32. package/src/tools/agent-harness-browser-cockpit-route.ts +188 -34
  33. package/src/tools/agent-harness-browser-control.ts +12 -4
  34. package/src/tools/agent-harness-browser-pwa-read-models.ts +622 -0
  35. package/src/tools/agent-harness-device-live-read-models.ts +366 -0
  36. package/src/tools/agent-harness-execution-posture.ts +3 -0
  37. package/src/tools/agent-harness-interactive-runtime-records.ts +421 -0
  38. package/src/tools/agent-harness-local-model-benchmarks.ts +71 -1
  39. package/src/tools/agent-harness-local-model-endpoints.ts +469 -354
  40. package/src/tools/agent-harness-local-model-smoke.ts +277 -0
  41. package/src/tools/agent-harness-local-model-url.ts +78 -0
  42. package/src/tools/agent-harness-media-posture.ts +27 -12
  43. package/src/tools/agent-harness-memory-external-providers.ts +796 -0
  44. package/src/tools/agent-harness-memory-posture.ts +253 -137
  45. package/src/tools/agent-harness-memory-provider-certification.ts +219 -0
  46. package/src/tools/agent-harness-memory-refinement.ts +340 -0
  47. package/src/tools/agent-harness-mode-catalog.ts +4 -2
  48. package/src/tools/agent-harness-model-provider-health.ts +139 -42
  49. package/src/tools/agent-harness-model-readiness.ts +31 -5
  50. package/src/tools/agent-harness-model-routing-types.ts +61 -0
  51. package/src/tools/agent-harness-model-routing.ts +31 -6
  52. package/src/tools/agent-harness-pairing-posture.ts +30 -9
  53. package/src/tools/agent-harness-personal-ops-certification.ts +116 -0
  54. package/src/tools/agent-harness-personal-ops-lanes.ts +81 -15
  55. package/src/tools/agent-harness-personal-ops-operations.ts +225 -0
  56. package/src/tools/agent-harness-personal-ops-provider-records.ts +358 -0
  57. package/src/tools/agent-harness-personal-ops-provider-task-records.ts +321 -0
  58. package/src/tools/agent-harness-personal-ops-records.ts +176 -224
  59. package/src/tools/agent-harness-personal-ops-types.ts +19 -1
  60. package/src/tools/agent-harness-personal-ops.ts +18 -11
  61. package/src/tools/agent-harness-remote-read-models.ts +541 -0
  62. package/src/tools/agent-harness-research-briefing.ts +26 -7
  63. package/src/tools/agent-harness-research-live-read-models.ts +500 -0
  64. package/src/tools/agent-harness-research-runs.ts +15 -3
  65. package/src/tools/agent-harness-research-workflow.ts +92 -19
  66. package/src/tools/agent-harness-setup-model-helpers.ts +1 -0
  67. package/src/tools/agent-harness-setup-smoke.ts +26 -1
  68. package/src/tools/agent-harness-tool-schema.ts +23 -1
  69. package/src/tools/agent-harness-tool-types.ts +5 -0
  70. package/src/tools/agent-harness-tool.ts +9 -1
  71. package/src/tools/agent-harness-workspace-actions.ts +1 -1
  72. package/src/tools/agent-memory-tool.ts +40 -1
  73. package/src/tools/agent-model-compare-run.ts +13 -0
  74. package/src/tools/agent-research-runner.ts +367 -0
  75. package/src/tools/agent-research-tool.ts +7 -179
  76. package/src/tools/agent-route-planner-candidates-surfaces.ts +1 -1
  77. package/src/version.ts +1 -1
@@ -0,0 +1,366 @@
1
+ import type { CommandContext } from '../input/command-registry.ts';
2
+ import { previewHarnessText } from './agent-harness-text.ts';
3
+
4
+ export interface DeviceLiveRecordCertification {
5
+ readonly schemaStatus: 'certified' | 'legacy';
6
+ readonly schemaVersion?: string;
7
+ readonly publicationGuarantee?: string;
8
+ readonly publisher?: string;
9
+ readonly provenance?: readonly string[];
10
+ readonly receiptId?: string;
11
+ readonly cursor?: string;
12
+ readonly missingSignals: readonly string[];
13
+ readonly policy: string;
14
+ }
15
+
16
+ export interface DeviceLiveCapabilityRecord {
17
+ readonly id: string;
18
+ readonly capabilityId: string;
19
+ readonly label: string | null;
20
+ readonly domain: string;
21
+ readonly status: string;
22
+ readonly summary: string | null;
23
+ readonly capabilities: readonly string[];
24
+ readonly permissionScope: string | null;
25
+ readonly route: string | null;
26
+ readonly modelRoute: string;
27
+ readonly controlRoutes: Readonly<Record<string, string>>;
28
+ readonly sourcePath: string;
29
+ readonly source: 'daemon-read-model' | 'sdk-read-model';
30
+ readonly certification: DeviceLiveRecordCertification;
31
+ }
32
+
33
+ export interface DeviceLiveReadModelSnapshot {
34
+ readonly capabilities: readonly DeviceLiveCapabilityRecord[];
35
+ readonly sourceCounts: Readonly<Record<string, number>>;
36
+ }
37
+
38
+ interface SourceCandidate {
39
+ readonly path: string;
40
+ readonly source: unknown;
41
+ readonly kind: 'daemon-read-model' | 'sdk-read-model';
42
+ }
43
+
44
+ interface CollectedRecord {
45
+ readonly path: string;
46
+ readonly kind: 'daemon-read-model' | 'sdk-read-model';
47
+ readonly record: Record<string, unknown>;
48
+ }
49
+
50
+ const WRAPPER_KEYS = [
51
+ 'records',
52
+ 'items',
53
+ 'capabilities',
54
+ 'deviceCapabilities',
55
+ 'mobileCapabilities',
56
+ 'voiceWorkflows',
57
+ 'workflows',
58
+ 'sensors',
59
+ 'sensorRoutes',
60
+ ] as const;
61
+
62
+ const SNAPSHOT_METHODS = ['getSnapshot', 'snapshot', 'toJSON'] as const;
63
+ const LIST_METHODS = ['listCapabilities', 'listDeviceCapabilities', 'listSensors', 'listVoiceWorkflows', 'list'] as const;
64
+
65
+ function readObject(value: unknown): Record<string, unknown> {
66
+ return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : {};
67
+ }
68
+
69
+ function readString(value: unknown): string {
70
+ return typeof value === 'string' ? value.trim() : '';
71
+ }
72
+
73
+ function readMetadata(record: Record<string, unknown>): Record<string, unknown> {
74
+ return readObject(record.metadata);
75
+ }
76
+
77
+ function nestedString(record: Record<string, unknown>, key: string): string {
78
+ return readString(record[key])
79
+ || readString(readMetadata(record)[key])
80
+ || readString(readObject(record.capability)[key])
81
+ || readString(readObject(record.device)[key])
82
+ || readString(readObject(record.permission)[key])
83
+ || readString(readObject(record.evidence)[key])
84
+ || readString(readObject(record.route)[key]);
85
+ }
86
+
87
+ function certificationRecords(record: Record<string, unknown>): readonly Record<string, unknown>[] {
88
+ return [
89
+ record,
90
+ readMetadata(record),
91
+ readObject(record.schema),
92
+ readObject(record.contract),
93
+ readObject(record.publication),
94
+ readObject(record.receipt),
95
+ readObject(record.certification),
96
+ ];
97
+ }
98
+
99
+ function firstAcross(records: readonly Record<string, unknown>[], keys: readonly string[]): string {
100
+ for (const record of records) {
101
+ for (const key of keys) {
102
+ const value = readString(record[key]);
103
+ if (value) return value;
104
+ }
105
+ }
106
+ return '';
107
+ }
108
+
109
+ function stringArray(value: unknown): readonly string[] {
110
+ if (Array.isArray(value)) return [...new Set(value.map((entry) => readString(entry)).filter(Boolean))].slice(0, 16);
111
+ const text = readString(value);
112
+ return text ? text.split(',').map((entry) => entry.trim()).filter(Boolean).slice(0, 16) : [];
113
+ }
114
+
115
+ function redactText(value: string): string {
116
+ return value
117
+ .replace(/\b(bearer)\s+[a-z0-9._~+/=-]+/gi, '$1 <redacted>')
118
+ .replace(/\b(token|secret|password|api[_-]?key|authorization)\s*[:=]\s*[^,\s;/]+/gi, '$1=<redacted>');
119
+ }
120
+
121
+ function safePreview(value: string, limit: number): string {
122
+ return previewHarnessText(redactText(value), limit);
123
+ }
124
+
125
+ function safeNullablePreview(value: string, limit: number): string | null {
126
+ return value ? safePreview(value, limit) : null;
127
+ }
128
+
129
+ function schemaStatus(records: readonly Record<string, unknown>[]): DeviceLiveRecordCertification['schemaStatus'] {
130
+ const explicit = firstAcross(records, ['schemaStatus', 'receiptSchemaStatus', 'certificationStatus']).toLowerCase().replace(/[_\s]+/g, '-');
131
+ if (['certified', 'valid', 'verified', 'schema-certified'].includes(explicit)) return 'certified';
132
+ return firstAcross(records, ['schemaVersion', 'receiptSchemaVersion', 'contractVersion'])
133
+ && firstAcross(records, ['publicationGuarantee', 'hostPublicationGuarantee', 'devicePublicationGuarantee'])
134
+ && firstAcross(records, ['publisher', 'publisherId', 'daemonId', 'hostId'])
135
+ ? 'certified'
136
+ : 'legacy';
137
+ }
138
+
139
+ function routeMap(record: Record<string, unknown>): Readonly<Record<string, string>> {
140
+ const routes = { ...readObject(record.routes), ...readObject(record.controls) };
141
+ const output: Record<string, string> = {};
142
+ for (const key of ['inspect', 'open', 'run', 'capture', 'repairPermission', 'grantPermission', 'revokePermission', 'test']) {
143
+ const value = readString(routes[key]) || nestedString(record, `${key}Route`);
144
+ if (value) output[key] = safePreview(value, 180);
145
+ }
146
+ return output;
147
+ }
148
+
149
+ function certification(input: {
150
+ readonly record: Record<string, unknown>;
151
+ readonly sourcePath: string;
152
+ readonly id: string;
153
+ readonly capabilityId: string;
154
+ readonly status: string;
155
+ readonly permissionScope: string;
156
+ readonly modelRoute: string;
157
+ readonly hasRoutes: boolean;
158
+ }): DeviceLiveRecordCertification {
159
+ const records = certificationRecords(input.record);
160
+ const currentSchemaStatus = schemaStatus(records);
161
+ const schemaVersion = firstAcross(records, ['schemaVersion', 'receiptSchemaVersion', 'contractVersion']);
162
+ const publicationGuarantee = firstAcross(records, ['publicationGuarantee', 'hostPublicationGuarantee', 'devicePublicationGuarantee']);
163
+ const publisher = firstAcross(records, ['publisher', 'publisherId', 'daemonId', 'hostId']);
164
+ const receiptId = firstAcross(records, ['receiptId', 'capabilityReceiptId', 'permissionReceiptId', 'routeReceiptId']);
165
+ const cursor = firstAcross(records, ['cursor', 'freshnessCursor', 'sequence', 'checkpoint']);
166
+ const provenance = [...new Set([
167
+ ...stringArray(input.record.provenance),
168
+ input.sourcePath ? `source ${input.sourcePath}` : '',
169
+ firstAcross(records, ['methodId']) ? `method ${firstAcross(records, ['methodId'])}` : '',
170
+ firstAcross(records, ['sourceTool']) ? `sourceTool ${firstAcross(records, ['sourceTool'])}` : '',
171
+ ].map((entry) => safePreview(entry, 180)).filter(Boolean))].slice(0, 8);
172
+ const missingSignals = [
173
+ ...(currentSchemaStatus === 'certified' ? [] : ['Certified device capability schema is not published.']),
174
+ ...(input.id ? [] : ['Durable device capability record id is not published.']),
175
+ ...(input.capabilityId ? [] : ['Device capability id is not published.']),
176
+ ...(input.status ? [] : ['Device capability status is not published.']),
177
+ ...(publicationGuarantee ? [] : ['Device capability publication guarantee is not published.']),
178
+ ...(publisher ? [] : ['Device capability publisher is not published.']),
179
+ ...(provenance.length > 0 ? [] : ['Device capability provenance is not published.']),
180
+ ...(cursor ? [] : ['Device capability freshness cursor is not published.']),
181
+ ...(input.permissionScope ? [] : ['Permission scope is not published.']),
182
+ ...(input.modelRoute && input.hasRoutes ? [] : ['Exact inspect/control route is not published.']),
183
+ ];
184
+ return {
185
+ schemaStatus: currentSchemaStatus,
186
+ ...(schemaVersion ? { schemaVersion: safePreview(schemaVersion, 80) } : {}),
187
+ ...(publicationGuarantee ? { publicationGuarantee: safePreview(publicationGuarantee, 220) } : {}),
188
+ ...(publisher ? { publisher: safePreview(publisher, 80) } : {}),
189
+ ...(provenance.length > 0 ? { provenance } : {}),
190
+ ...(receiptId ? { receiptId: safePreview(receiptId, 96) } : {}),
191
+ ...(cursor ? { cursor: safePreview(cursor, 96) } : {}),
192
+ missingSignals,
193
+ policy: 'Device capability read models certify release readiness only when the SDK or daemon publishes schema, durable capability ids, permission scope, publication guarantee, publisher/provenance, freshness cursor, exact inspect/control routes, and redacted receipt evidence.',
194
+ };
195
+ }
196
+
197
+ function callMethod(source: Record<string, unknown>, method: string): unknown {
198
+ const fn = source[method];
199
+ if (typeof fn !== 'function') return undefined;
200
+ try {
201
+ return (fn as () => unknown).call(source);
202
+ } catch {
203
+ return undefined;
204
+ }
205
+ }
206
+
207
+ function collectFromSource(
208
+ source: unknown,
209
+ path: string,
210
+ kind: 'daemon-read-model' | 'sdk-read-model',
211
+ visited = new WeakSet<object>(),
212
+ ): readonly CollectedRecord[] {
213
+ if (!source) return [];
214
+ if (Array.isArray(source)) return source.flatMap((entry, index) => collectFromSource(entry, `${path}[${index}]`, kind, visited));
215
+ if (source instanceof Map) return Array.from(source.entries()).flatMap(([key, value]) => collectFromSource(value, `${path}.${String(key)}`, kind, visited));
216
+ if (typeof source !== 'object') return [];
217
+ if (visited.has(source)) return [];
218
+ visited.add(source);
219
+ const record = source as Record<string, unknown>;
220
+ const fromSnapshots = SNAPSHOT_METHODS.flatMap((method) => {
221
+ const snapshot = callMethod(record, method);
222
+ return snapshot === undefined ? [] : collectFromSource(snapshot, `${path}.${method}()`, kind, visited);
223
+ });
224
+ const fromMethods = LIST_METHODS.flatMap((method) => {
225
+ const snapshot = callMethod(record, method);
226
+ return snapshot === undefined ? [] : collectFromSource(snapshot, `${path}.${method}()`, kind, visited);
227
+ });
228
+ const fromWrappers = WRAPPER_KEYS.flatMap((key) => {
229
+ if (!(key in record)) return [];
230
+ return collectFromSource(record[key], `${path}.${key}`, kind, visited);
231
+ });
232
+ if (fromSnapshots.length > 0 || fromMethods.length > 0 || fromWrappers.length > 0) {
233
+ return [...fromSnapshots, ...fromMethods, ...fromWrappers];
234
+ }
235
+ return [{ path, kind, record }];
236
+ }
237
+
238
+ function modelRoute(record: Record<string, unknown>, capabilityId: string): string {
239
+ const routes = readObject(record.routes);
240
+ return nestedString(record, 'modelRoute')
241
+ || nestedString(record, 'inspectRoute')
242
+ || nestedString(record, 'route')
243
+ || readString(routes.inspect)
244
+ || readString(routes.open)
245
+ || readString(routes.run)
246
+ || `device action:"capability" capabilityId:"${capabilityId}" includeParameters:true`;
247
+ }
248
+
249
+ function capabilityId(record: Record<string, unknown>, index: number): string {
250
+ return nestedString(record, 'capabilityId')
251
+ || nestedString(record, 'id')
252
+ || nestedString(record, 'kind')
253
+ || `device-capability-${index}`;
254
+ }
255
+
256
+ function normalizeCapability(entry: CollectedRecord, index: number): DeviceLiveCapabilityRecord | null {
257
+ const capId = capabilityId(entry.record, index);
258
+ if (!capId) return null;
259
+ const id = nestedString(entry.record, 'id') || nestedString(entry.record, 'receiptId') || `device-live:${capId}:${index}`;
260
+ const routes = routeMap(entry.record);
261
+ const route = nestedString(entry.record, 'route') || nestedString(entry.record, 'openRoute') || routes.open || routes.run || routes.inspect || null;
262
+ const routeForModel = modelRoute(entry.record, capId);
263
+ const permissionScope = nestedString(entry.record, 'permissionScope') || nestedString(entry.record, 'scope') || nestedString(entry.record, 'permission');
264
+ const status = nestedString(entry.record, 'status') || nestedString(entry.record, 'state') || 'unknown';
265
+ return {
266
+ id,
267
+ capabilityId: capId,
268
+ label: safeNullablePreview(nestedString(entry.record, 'label') || nestedString(entry.record, 'title'), 120),
269
+ domain: nestedString(entry.record, 'domain') || nestedString(entry.record, 'surface') || 'device',
270
+ status,
271
+ summary: safeNullablePreview(nestedString(entry.record, 'summary') || nestedString(entry.record, 'detail'), 220),
272
+ capabilities: [...new Set([
273
+ ...stringArray(entry.record.capabilities),
274
+ ...stringArray(entry.record.features),
275
+ ...stringArray(readObject(entry.record.capability).capabilities),
276
+ capId,
277
+ ].map((value) => safePreview(value, 80)).filter(Boolean))].slice(0, 16),
278
+ permissionScope: safeNullablePreview(permissionScope, 120),
279
+ route: route ? safePreview(route, 180) : null,
280
+ modelRoute: routeForModel,
281
+ controlRoutes: routes,
282
+ sourcePath: entry.path,
283
+ source: entry.kind,
284
+ certification: certification({
285
+ record: entry.record,
286
+ sourcePath: entry.path,
287
+ id,
288
+ capabilityId: capId,
289
+ status,
290
+ permissionScope,
291
+ modelRoute: routeForModel,
292
+ hasRoutes: Boolean(route || Object.keys(routes).length > 0),
293
+ }),
294
+ };
295
+ }
296
+
297
+ function sourceCounts(entries: readonly CollectedRecord[]): Readonly<Record<string, number>> {
298
+ const counts: Record<string, number> = {};
299
+ for (const entry of entries) counts[entry.path] = (counts[entry.path] ?? 0) + 1;
300
+ return counts;
301
+ }
302
+
303
+ function sources(context: CommandContext): readonly SourceCandidate[] {
304
+ const platform = readObject(context.platform);
305
+ const readModels = readObject(platform.readModels);
306
+ const device = readObject(readModels.device);
307
+ const companion = readObject(readModels.companion);
308
+ const voice = readObject(readModels.voice);
309
+ const opsDevice = readObject(readObject(context.ops).device);
310
+ const clients = readObject(context.clients);
311
+ const operator = readObject(clients.operator);
312
+ const operatorSdk = readObject(clients.operatorSdk);
313
+ return [
314
+ { path: 'context.platform.readModels.device.capabilities', source: device.capabilities, kind: 'daemon-read-model' },
315
+ { path: 'context.platform.readModels.device.sensors', source: device.sensors, kind: 'daemon-read-model' },
316
+ { path: 'context.platform.readModels.companion.capabilities', source: companion.capabilities, kind: 'daemon-read-model' },
317
+ { path: 'context.platform.readModels.voice.workflows', source: voice.workflows, kind: 'daemon-read-model' },
318
+ { path: 'context.platform.readModels.deviceCapabilities', source: readModels.deviceCapabilities, kind: 'daemon-read-model' },
319
+ { path: 'context.platform.readModels.companionCapabilities', source: readModels.companionCapabilities, kind: 'daemon-read-model' },
320
+ { path: 'context.ops.device.capabilities', source: opsDevice.capabilities, kind: 'sdk-read-model' },
321
+ { path: 'context.clients.operator.device.capabilities', source: readObject(operator.device).capabilities, kind: 'sdk-read-model' },
322
+ { path: 'context.clients.operatorSdk.device.capabilities', source: readObject(operatorSdk.device).capabilities, kind: 'sdk-read-model' },
323
+ ];
324
+ }
325
+
326
+ export function isCertifiedDeviceLiveRecord(record: DeviceLiveCapabilityRecord): boolean {
327
+ return record.certification.schemaStatus === 'certified' && record.certification.missingSignals.length === 0;
328
+ }
329
+
330
+ export function certifiedDeviceLiveRecords(
331
+ snapshot: DeviceLiveReadModelSnapshot,
332
+ capabilityId: string,
333
+ terms: readonly string[] = [],
334
+ ): readonly DeviceLiveCapabilityRecord[] {
335
+ const expected = [capabilityId, ...terms].map((term) => term.toLowerCase());
336
+ return snapshot.capabilities.filter((record) => {
337
+ if (!isCertifiedDeviceLiveRecord(record)) return false;
338
+ const text = [
339
+ record.id,
340
+ record.capabilityId,
341
+ record.label ?? '',
342
+ record.domain,
343
+ record.status,
344
+ record.summary ?? '',
345
+ record.permissionScope ?? '',
346
+ ...record.capabilities,
347
+ ].join('\n').toLowerCase();
348
+ return expected.some((term) => text.includes(term));
349
+ });
350
+ }
351
+
352
+ export function deviceLiveReadModelSnapshot(context: CommandContext): DeviceLiveReadModelSnapshot {
353
+ const entries = sources(context).flatMap((candidate) => collectFromSource(candidate.source, candidate.path, candidate.kind));
354
+ const seen = new Set<string>();
355
+ const capabilities: DeviceLiveCapabilityRecord[] = [];
356
+ for (const record of entries.map(normalizeCapability).filter((entry): entry is DeviceLiveCapabilityRecord => entry !== null)) {
357
+ const key = `${record.capabilityId}:${record.id}`;
358
+ if (seen.has(key)) continue;
359
+ seen.add(key);
360
+ capabilities.push(record);
361
+ }
362
+ return {
363
+ capabilities,
364
+ sourceCounts: sourceCounts(entries),
365
+ };
366
+ }
@@ -3,6 +3,7 @@ import type { CommandContext } from '../input/command-registry.ts';
3
3
  import { browserControlPosture } from './agent-harness-browser-control.ts';
4
4
  import { delegationDecisionCards } from './agent-harness-delegation-posture.ts';
5
5
  import { fileRecoveryCatalogStatus } from './agent-harness-file-recovery.ts';
6
+ import { interactiveRuntimeCapabilitySummary } from './agent-harness-interactive-runtime-records.ts';
6
7
  import { sudoExecutionPosture } from './agent-harness-sudo-posture.ts';
7
8
  import { previewHarnessText } from './agent-harness-text.ts';
8
9
 
@@ -333,6 +334,7 @@ export function executionPostureSummary(context: CommandContext, toolRegistry: T
333
334
  browserControlSetup: browserControl,
334
335
  delegationDecisionCards: delegationCards,
335
336
  sudoPosture: sudoExecutionPosture(context),
337
+ interactiveRuntime: interactiveRuntimeCapabilitySummary(context),
336
338
  executionHistory: 'execution action:"history"',
337
339
  backgroundProcesses: 'execution action:"processes"',
338
340
  fileRecovery: fileRecoveryCatalogStatus(context),
@@ -343,6 +345,7 @@ export function executionPostureSummary(context: CommandContext, toolRegistry: T
343
345
  'Do not delegate ordinary local implementation, fix, review, or verification work when local tools and permissions are sufficient.',
344
346
  'Do delegate when isolation, parallelism, remote execution, a separate worktree, or a requested delegated review improves the user outcome.',
345
347
  'Report setup gaps directly for browser/desktop control instead of pretending browser automation exists.',
348
+ 'Treat PTY, sudo, live output, and browser/desktop command execution as ready only when certified SDK/daemon runtime records publish exact visible routes and receipts.',
346
349
  'Use tracked background processes for approved long-running local commands instead of hidden exec background mode.',
347
350
  ],
348
351
  routes: routes.map((route) => describeRoute(route, context, toolRegistry, { includeParameters })),