@pellux/goodvibes-agent 1.2.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/CHANGELOG.md +194 -0
  2. package/dist/package/{ast-grep-napi.linux-x64-gnu-swtppvy9.node → ast-grep-napi.linux-x64-gnu-mkk8xwww.node} +0 -0
  3. package/dist/package/{ast-grep-napi.linux-x64-musl-ttfcdtap.node → ast-grep-napi.linux-x64-musl-ryqtgdv6.node} +0 -0
  4. package/dist/package/main.js +65740 -57156
  5. package/docs/README.md +3 -3
  6. package/docs/connected-host.md +2 -2
  7. package/docs/getting-started.md +11 -9
  8. package/docs/tools-and-commands.md +12 -10
  9. package/docs/voice-and-live-tts.md +2 -2
  10. package/package.json +1 -1
  11. package/release/release-notes.md +15 -144
  12. package/release/release-readiness.json +36 -36
  13. package/src/agent/competitive-feature-inventory.ts +42 -44
  14. package/src/agent/setup-wizard-artifact-receipts.ts +366 -0
  15. package/src/agent/setup-wizard.ts +267 -24
  16. package/src/cli/tui-startup.ts +2 -2
  17. package/src/input/agent-workspace-activation.ts +2 -2
  18. package/src/input/agent-workspace-categories.ts +2 -2
  19. package/src/input/agent-workspace-onboarding-categories.ts +4 -4
  20. package/src/input/agent-workspace-onboarding-finish.ts +21 -0
  21. package/src/input/agent-workspace-settings.ts +47 -1
  22. package/src/input/agent-workspace-setup-snapshot.ts +17 -6
  23. package/src/input/agent-workspace-setup.ts +20 -26
  24. package/src/input/agent-workspace-snapshot.ts +16 -3
  25. package/src/input/agent-workspace-types.ts +5 -2
  26. package/src/input/agent-workspace.ts +21 -6
  27. package/src/input/handler.ts +67 -5
  28. package/src/input/setup-wizard-live-receipts.ts +76 -0
  29. package/src/renderer/agent-workspace-context-lines.ts +17 -33
  30. package/src/renderer/agent-workspace.ts +434 -21
  31. package/src/runtime/tool-permission-safety.ts +1 -1
  32. package/src/tools/agent-harness-agent-orchestration-policy.ts +75 -0
  33. package/src/tools/agent-harness-agent-orchestration.ts +216 -128
  34. package/src/tools/agent-harness-autonomy-live-records.ts +154 -0
  35. package/src/tools/agent-harness-autonomy-queue-types.ts +1 -1
  36. package/src/tools/agent-harness-autonomy-queue.ts +19 -8
  37. package/src/tools/agent-harness-autonomy-watcher-read-models.ts +509 -0
  38. package/src/tools/agent-harness-background-processes.ts +8 -4
  39. package/src/tools/agent-harness-browser-cockpit-route.ts +188 -34
  40. package/src/tools/agent-harness-browser-control.ts +12 -4
  41. package/src/tools/agent-harness-browser-pwa-read-models.ts +622 -0
  42. package/src/tools/agent-harness-device-live-read-models.ts +366 -0
  43. package/src/tools/agent-harness-execution-posture.ts +3 -0
  44. package/src/tools/agent-harness-interactive-runtime-records.ts +421 -0
  45. package/src/tools/agent-harness-local-model-benchmarks.ts +71 -1
  46. package/src/tools/agent-harness-local-model-endpoints.ts +469 -354
  47. package/src/tools/agent-harness-local-model-smoke.ts +277 -0
  48. package/src/tools/agent-harness-local-model-url.ts +78 -0
  49. package/src/tools/agent-harness-media-posture.ts +27 -12
  50. package/src/tools/agent-harness-memory-external-providers.ts +796 -0
  51. package/src/tools/agent-harness-memory-posture.ts +253 -137
  52. package/src/tools/agent-harness-memory-provider-certification.ts +219 -0
  53. package/src/tools/agent-harness-memory-refinement.ts +340 -0
  54. package/src/tools/agent-harness-mode-catalog.ts +4 -2
  55. package/src/tools/agent-harness-model-provider-health.ts +139 -42
  56. package/src/tools/agent-harness-model-readiness.ts +31 -5
  57. package/src/tools/agent-harness-model-routing-types.ts +61 -0
  58. package/src/tools/agent-harness-model-routing.ts +31 -6
  59. package/src/tools/agent-harness-pairing-posture.ts +30 -9
  60. package/src/tools/agent-harness-personal-ops-certification.ts +116 -0
  61. package/src/tools/agent-harness-personal-ops-lanes.ts +81 -15
  62. package/src/tools/agent-harness-personal-ops-operations.ts +225 -0
  63. package/src/tools/agent-harness-personal-ops-provider-records.ts +358 -0
  64. package/src/tools/agent-harness-personal-ops-provider-task-records.ts +321 -0
  65. package/src/tools/agent-harness-personal-ops-records.ts +176 -224
  66. package/src/tools/agent-harness-personal-ops-types.ts +19 -1
  67. package/src/tools/agent-harness-personal-ops.ts +18 -11
  68. package/src/tools/agent-harness-remote-read-models.ts +541 -0
  69. package/src/tools/agent-harness-research-briefing.ts +26 -7
  70. package/src/tools/agent-harness-research-live-read-models.ts +500 -0
  71. package/src/tools/agent-harness-research-runs.ts +15 -3
  72. package/src/tools/agent-harness-research-workflow.ts +92 -19
  73. package/src/tools/agent-harness-setup-model-helpers.ts +1 -0
  74. package/src/tools/agent-harness-setup-posture.ts +7 -7
  75. package/src/tools/agent-harness-setup-smoke.ts +26 -1
  76. package/src/tools/agent-harness-tool-schema.ts +23 -1
  77. package/src/tools/agent-harness-tool-types.ts +5 -0
  78. package/src/tools/agent-harness-tool.ts +9 -1
  79. package/src/tools/agent-harness-workspace-actions.ts +1 -1
  80. package/src/tools/agent-memory-tool.ts +40 -1
  81. package/src/tools/agent-model-compare-run.ts +13 -0
  82. package/src/tools/agent-research-runner.ts +367 -0
  83. package/src/tools/agent-research-tool.ts +7 -179
  84. package/src/tools/agent-route-planner-candidates-surfaces.ts +1 -1
  85. package/src/version.ts +1 -1
@@ -11,6 +11,12 @@ import {
11
11
  type AgentResearchSourceRecord,
12
12
  } from '../agent/research-source-registry.ts';
13
13
  import { browserControlPosture } from './agent-harness-browser-control.ts';
14
+ import {
15
+ isCertifiedResearchLiveRecord,
16
+ researchLiveReadModelSnapshot,
17
+ type ResearchBrowserRunnerRecord,
18
+ type ResearchVisualReportRecord,
19
+ } from './agent-harness-research-live-read-models.ts';
14
20
  import { previewHarnessText } from './agent-harness-text.ts';
15
21
 
16
22
  interface AgentHarnessResearchWorkflowArgs {
@@ -91,6 +97,41 @@ function relatedSources(
91
97
  ));
92
98
  }
93
99
 
100
+ function liveRunnerSearchText(record: ResearchBrowserRunnerRecord): string {
101
+ return [
102
+ record.id,
103
+ record.runId ?? '',
104
+ record.status,
105
+ record.phase ?? '',
106
+ record.question ?? '',
107
+ record.currentUrl ?? '',
108
+ record.reportDraftId ?? '',
109
+ record.reportArtifactId ?? '',
110
+ ...record.sourceReceiptIds,
111
+ ].join('\n').toLowerCase();
112
+ }
113
+
114
+ function matchingLiveRunners(
115
+ records: readonly ResearchBrowserRunnerRecord[],
116
+ run: AgentResearchRunRecord | null,
117
+ question: string,
118
+ ): readonly ResearchBrowserRunnerRecord[] {
119
+ const normalized = question.toLowerCase();
120
+ return records.filter((record) => (
121
+ (!!run && record.runId === run.id)
122
+ || (!!run?.reportArtifactId && record.reportArtifactId === run.reportArtifactId)
123
+ || (!!normalized && liveRunnerSearchText(record).includes(normalized))
124
+ ));
125
+ }
126
+
127
+ function matchingVisualReports(
128
+ records: readonly ResearchVisualReportRecord[],
129
+ run: AgentResearchRunRecord | null,
130
+ ): readonly ResearchVisualReportRecord[] {
131
+ if (!run?.reportArtifactId) return records;
132
+ return records.filter((record) => record.reportArtifactId === run.reportArtifactId);
133
+ }
134
+
94
135
  function runSummary(run: AgentResearchRunRecord, includeParameters: boolean): Record<string, unknown> {
95
136
  return {
96
137
  runId: run.id,
@@ -128,14 +169,21 @@ function sourceSummary(source: AgentResearchSourceRecord): Record<string, unknow
128
169
  };
129
170
  }
130
171
 
131
- function browserRunnerContract(browser: ReturnType<typeof browserControlPosture>): Record<string, unknown> {
172
+ function browserRunnerContract(
173
+ browser: ReturnType<typeof browserControlPosture>,
174
+ liveRecords: readonly ResearchBrowserRunnerRecord[],
175
+ ): Record<string, unknown> {
176
+ const certified = liveRecords.filter(isCertifiedResearchLiveRecord);
132
177
  return {
133
- status: browser.configured ? 'ready-with-confirmation' : 'setup-contract-needed',
178
+ status: certified.length > 0 ? 'certified-live-runner' : browser.configured ? 'ready-with-confirmation' : 'setup-contract-needed',
134
179
  userOutcome: 'Run browser-backed research only when live browser state, authenticated pages, or interactive source discovery are necessary.',
135
- currentState: browser.configured
180
+ currentState: certified.length > 0
181
+ ? 'The SDK/daemon published certified browser-backed research run records with visible controls, source/page receipts, bounded logs, and exact inspect routes.'
182
+ : browser.configured
136
183
  ? 'A reviewed browser/desktop route is configured; use it only after the user accepts the browser-backed research scope.'
137
184
  : 'No reviewed browser-backed research runner is configured, so public web_search/fetch stays the current safe route.',
138
185
  requiredContracts: [
186
+ 'Certified schema/version/publication/publisher/provenance/freshness-cursor/receipt metadata for every live browser-backed research run.',
139
187
  'Trusted browser or desktop-control route with setup posture status ready.',
140
188
  'Visible run id, phase/progress, current URL/task scope, checkpoint route, and pause/resume/cancel controls for every browser-backed research run.',
141
189
  'Source-capture receipt for each accepted source with URL/title/publisher/summary/provenance.',
@@ -144,14 +192,17 @@ function browserRunnerContract(browser: ReturnType<typeof browserControlPosture>
144
192
  'No credential or page-content leakage outside bounded redacted source summaries.',
145
193
  ],
146
194
  setupRoutes: [
195
+ ...certified.slice(0, 3).map((record) => record.modelRoute),
147
196
  'computer action:"control" includeParameters:true',
148
197
  'computer action:"setup" includeParameters:true',
149
198
  browser.setupRoute,
150
199
  ...browser.fallbackRoutes,
151
200
  ],
152
- recommendedRoute: browser.recommendedRoute,
201
+ recommendedRoute: certified[0]?.modelRoute ?? browser.recommendedRoute,
153
202
  fallbackRoutes: browser.fallbackRoutes,
154
- policy: 'Browser-backed research is not started by this workflow plan. Use bounded public web/fetch routes until the browser runner contract is ready and the user explicitly confirms the scope.',
203
+ liveRecords: liveRecords.slice(0, 5),
204
+ certifiedLiveRecords: certified.slice(0, 5),
205
+ policy: 'Browser-backed research is not started by this workflow plan. Use certified live SDK/daemon records only as read-only evidence, and use returned confirmed routes before any browser/PWA, source-save, report-save, or Knowledge-ingest effect.',
155
206
  };
156
207
  }
157
208
 
@@ -160,12 +211,16 @@ function visualReportContract(options: {
160
211
  readonly reportRoute: string;
161
212
  readonly bundleRoute: string;
162
213
  readonly question: string;
214
+ readonly liveRecords: readonly ResearchVisualReportRecord[];
163
215
  }): Record<string, unknown> {
216
+ const certified = options.liveRecords.filter(isCertifiedResearchLiveRecord);
164
217
  return {
165
- status: options.reviewedSources > 0 ? 'visual-report-packet-ready' : 'waiting-for-reviewed-sources',
218
+ status: certified.length > 0 ? 'certified-live-renderer' : options.reviewedSources > 0 ? 'visual-report-packet-ready' : 'waiting-for-reviewed-sources',
166
219
  userOutcome: 'Produce an inspectable research report with source-backed findings, citations, caveats, and handoff/export routes.',
167
- currentRoute: options.reviewedSources > 0 ? options.reportRoute : options.bundleRoute,
168
- currentState: options.reviewedSources > 0
220
+ currentRoute: certified[0]?.modelRoute ?? (options.reviewedSources > 0 ? options.reportRoute : options.bundleRoute),
221
+ currentState: certified.length > 0
222
+ ? 'The SDK/daemon published a certified browser/PWA visual report render over the same reviewed report artifact, with source-map and citation-coverage evidence.'
223
+ : options.reviewedSources > 0
169
224
  ? 'Agent can save a citation-covered markdown report artifact with a visual report packet now; browser/PWA rendering remains an optional view over the same artifact.'
170
225
  : 'Review at least one source before saving a report or visual packet.',
171
226
  requiredSections: [
@@ -184,12 +239,14 @@ function visualReportContract(options: {
184
239
  'Every material claim maps to a reviewed source line or an explicit caveat.',
185
240
  'The report artifact includes citation coverage metadata and repair hints.',
186
241
  'The visual report packet is generated by research action:"report" visualReport:true over the same saved report/source artifacts, not a separate uncited answer.',
242
+ 'Connected-host visual rendering counts only when the SDK/daemon publishes certified render route, source-map, citation coverage, section, publication, and receipt evidence.',
187
243
  'Knowledge ingest remains a separate confirmed action after report review.',
188
244
  ],
189
245
  routes: {
190
246
  reviewedSourceBundle: options.bundleRoute,
191
247
  saveVisualReport: options.reportRoute,
192
248
  saveMarkdownReport: options.reportRoute,
249
+ ...(certified[0] ? { openRenderedReport: certified[0].renderRoute } : {}),
193
250
  reviewPacketWizard: 'agent_harness mode:"document_ops_lane" laneId:"review_packet_wizard"',
194
251
  archiveArtifacts: 'agent_artifacts mode:"archive" artifactIds:["..."] destinationPath:"exports/research-report.zip" confirm:true explicitUserRequest:"..."',
195
252
  },
@@ -199,6 +256,8 @@ function visualReportContract(options: {
199
256
  'agent_harness mode:"document_ops_lane" laneId:"review_packet_wizard"',
200
257
  'agent_artifacts mode:"archive" artifactIds:["..."] destinationPath:"exports/research-report.zip" confirm:true explicitUserRequest:"..."',
201
258
  ],
259
+ liveRecords: options.liveRecords.slice(0, 5),
260
+ certifiedRendererRecords: certified.slice(0, 5),
202
261
  policy: `This contract is read-only planning for ${previewHarnessText(options.question, 96)}; saving reports, exports, packages, shares, or Knowledge ingest stay on separate confirmed routes.`,
203
262
  };
204
263
  }
@@ -216,6 +275,11 @@ export function researchWorkflowSummary(context: CommandContext, args: AgentHarn
216
275
  const reviewedSources = matchedSources.filter((source) => source.status === 'reviewed' || source.status === 'used');
217
276
  const candidateSources = matchedSources.filter((source) => source.status === 'candidate');
218
277
  const browser = browserControlPosture(context);
278
+ const liveResearch = researchLiveReadModelSnapshot(context);
279
+ const liveRunnerRecords = matchingLiveRunners(liveResearch.browserRunnerRecords, run, question);
280
+ const certifiedRunnerRecords = liveRunnerRecords.filter(isCertifiedResearchLiveRecord);
281
+ const liveVisualRecords = matchingVisualReports(liveResearch.visualReportRecords, run);
282
+ const certifiedVisualRecords = liveVisualRecords.filter(isCertifiedResearchLiveRecord);
219
283
  const status = !shellPaths
220
284
  ? 'unavailable'
221
285
  : run?.status === 'completed'
@@ -251,20 +315,25 @@ export function researchWorkflowSummary(context: CommandContext, args: AgentHarn
251
315
  candidateSources: candidateSources.slice(0, includeParameters ? 8 : 3).map(sourceSummary),
252
316
  },
253
317
  browserBackedResearch: {
254
- status: browser.status,
255
- configured: browser.configured,
256
- recommendedRoute: browser.recommendedRoute,
318
+ status: certifiedRunnerRecords.length > 0 ? 'certified-live-runner' : browser.status,
319
+ configured: browser.configured || certifiedRunnerRecords.length > 0,
320
+ recommendedRoute: certifiedRunnerRecords[0]?.modelRoute ?? browser.recommendedRoute,
257
321
  fallbackRoutes: browser.fallbackRoutes,
258
322
  next: browser.configured
259
323
  ? 'Use reviewed browser/desktop tooling only when live browser state or authenticated pages are necessary.'
260
- : 'Use bounded public web_search/fetch routes now; inspect setup before browser-backed execution.',
324
+ : certifiedRunnerRecords.length > 0
325
+ ? 'Inspect the certified live research runner record, then use confirmed routes for follow-up source, report, or browser effects.'
326
+ : 'Use bounded public web_search/fetch routes now; inspect setup before browser-backed execution.',
327
+ liveRunnerRecords: liveRunnerRecords.slice(0, includeParameters ? 8 : 3),
328
+ certifiedLiveRunnerCount: certifiedRunnerRecords.length,
261
329
  },
262
- browserRunnerContract: browserRunnerContract(browser),
330
+ browserRunnerContract: browserRunnerContract(browser, liveRunnerRecords),
263
331
  visualReportContract: visualReportContract({
264
332
  reviewedSources: reviewedSources.length,
265
333
  reportRoute,
266
334
  bundleRoute,
267
335
  question,
336
+ liveRecords: liveVisualRecords,
268
337
  }),
269
338
  workflow: [
270
339
  {
@@ -276,11 +345,13 @@ export function researchWorkflowSummary(context: CommandContext, args: AgentHarn
276
345
  },
277
346
  {
278
347
  id: 'collect-sources',
279
- status: reviewedSources.length > 0 || candidateSources.length > 0 ? 'started' : 'needed',
280
- next: browser.configured
348
+ status: certifiedRunnerRecords.length > 0 ? 'ready' : reviewedSources.length > 0 || candidateSources.length > 0 ? 'started' : 'needed',
349
+ next: certifiedRunnerRecords.length > 0
350
+ ? 'Use the certified live runner record to inspect source receipts, then review captured sources before report generation.'
351
+ : browser.configured
281
352
  ? 'Collect bounded sources, preferring primary/current sources, then capture each useful source in the queue.'
282
353
  : 'Use web_search/fetch for public sources and capture each useful source in the queue.',
283
- route: 'web_search query:"..." verbosity:"evidence" maxResults:10 evidenceTopN:3 or fetch urls:[...]',
354
+ route: certifiedRunnerRecords[0]?.modelRoute ?? 'web_search query:"..." verbosity:"evidence" maxResults:10 evidenceTopN:3 or fetch urls:[...]',
284
355
  captureRoute: `research action:"add_source" question:${quote(question)} title:"..." url:"..." summary:"..." credibility:"unreviewed" tags:["research"] confirm:true explicitUserRequest:"..."`,
285
356
  },
286
357
  {
@@ -292,9 +363,9 @@ export function researchWorkflowSummary(context: CommandContext, args: AgentHarn
292
363
  },
293
364
  {
294
365
  id: 'save-report',
295
- status: reviewedSources.length > 0 ? 'ready' : 'waiting',
296
- next: reviewedSources.length > 0 ? 'Use the reviewed-source bundle and save a citation-covered visual report packet artifact.' : 'Save the report only after reviewed or used sources exist.',
297
- route: reviewedSources.length > 0 ? bundleRoute : `research action:"sources" query:${quote(sourceQuery)}`,
366
+ status: certifiedVisualRecords.length > 0 || reviewedSources.length > 0 ? 'ready' : 'waiting',
367
+ next: certifiedVisualRecords.length > 0 ? 'Inspect the certified browser/PWA report render, then export, archive, or promote only after review.' : reviewedSources.length > 0 ? 'Use the reviewed-source bundle and save a citation-covered visual report packet artifact.' : 'Save the report only after reviewed or used sources exist.',
368
+ route: certifiedVisualRecords[0]?.modelRoute ?? (reviewedSources.length > 0 ? bundleRoute : `research action:"sources" query:${quote(sourceQuery)}`),
298
369
  reportRoute,
299
370
  },
300
371
  {
@@ -312,6 +383,8 @@ export function researchWorkflowSummary(context: CommandContext, args: AgentHarn
312
383
  inspectSources: `research action:"sources" query:${quote(sourceQuery)}`,
313
384
  bundleSources: bundleRoute,
314
385
  saveReport: reportRoute,
386
+ ...(certifiedRunnerRecords[0] ? { liveRunner: certifiedRunnerRecords[0].modelRoute } : {}),
387
+ ...(certifiedVisualRecords[0] ? { liveVisualReport: certifiedVisualRecords[0].modelRoute } : {}),
315
388
  ...(run ? {
316
389
  checkpointRun: `research action:"checkpoint" id:${quote(run.id)} phase:"reading" progress:${Math.max(run.progress, 25)} note:"..." sourceIds:["..."] confirm:true explicitUserRequest:"..."`,
317
390
  completeRun: `research action:"complete" id:${quote(run.id)} reportArtifactId:"..." confirm:true explicitUserRequest:"..."`,
@@ -11,6 +11,7 @@ export function browserControlSignals(posture: BrowserControlPosture): readonly
11
11
  `mcp:${server.name} ${server.connected ? 'connected' : 'disconnected'} ${server.readiness} role=${server.role} trust=${server.trustMode} schema=${server.schemaFreshness}`
12
12
  )));
13
13
  }
14
+ if (posture.certifiedRuntimeRecords.length > 0) signals.push(`certified runtime receipts: ${posture.certifiedRuntimeRecords.length}`);
14
15
  if (signals.length === 0) signals.push('No browser, desktop, computer-use, screenshot, or screen-recording tool is configured.');
15
16
  return signals;
16
17
  }
@@ -30,7 +30,7 @@ export async function setupPostureCatalogStatus(context: CommandContext): Promis
30
30
  autonomyBlockers: plan.filter((item) => item.blocksAutonomy && item.status !== 'ready').length,
31
31
  nextSetupHandoffs: nextSetupHandoffSummaries(plan, 5),
32
32
  setupWizard,
33
- setupCloseout: setupWizard.closeout,
33
+ setupCloseout: setupWizard._diagnostic.closeout,
34
34
  collectionIssues: snapshot.collectionIssues.length,
35
35
  setupMarkerExists: setupCompletionMarkerExists(context),
36
36
  setupSmokeEvidence,
@@ -81,7 +81,7 @@ export async function setupRepairSummary(context: CommandContext, args: AgentHar
81
81
  status: setupWizard.status,
82
82
  currentStepId: setupWizard.currentStepId,
83
83
  currentStepLabel: setupWizard.currentStepLabel,
84
- closeout: setupWizard.closeout,
84
+ closeout: setupWizard._diagnostic.closeout,
85
85
  },
86
86
  routes: {
87
87
  inspectSetup: DEFAULT_AGENT_SETUP_WIZARD_REVIEW_ROUTE,
@@ -149,14 +149,14 @@ export async function setupPostureSummary(context: CommandContext, args: AgentHa
149
149
  progressLabel: setupWizard.progressLabel,
150
150
  currentStepId: setupWizard.currentStepId,
151
151
  currentStepLabel: setupWizard.currentStepLabel,
152
- repeatedBlocker: setupWizard.repeatedBlocker,
152
+ repeatedBlocker: setupWizard._diagnostic.repeatedBlocker,
153
153
  },
154
- setupCloseout: setupWizard.closeout,
154
+ setupCloseout: setupWizard._diagnostic.closeout,
155
155
  },
156
156
  setupSmokeEvidence,
157
157
  setupSmokeHistory,
158
158
  setupWizard,
159
- setupCloseout: setupWizard.closeout,
159
+ setupCloseout: setupWizard._diagnostic.closeout,
160
160
  currentRoute: snapshot.providerRouting,
161
161
  issues: snapshot.collectionIssues,
162
162
  readinessPlan: filteredPlan.map((item) => describePlanItem(item, includeParameters)),
@@ -175,7 +175,7 @@ export async function setupCheckpointSummary(context: CommandContext): Promise<R
175
175
  const setupWizard = buildSetupWizard(plan, context);
176
176
  return {
177
177
  mode: 'setup_checkpoint',
178
- checkpoint: setupWizard.checkpoint,
178
+ checkpoint: setupWizard._diagnostic.checkpoint,
179
179
  currentStep: setupWizard.currentStepId
180
180
  ? setupWizard.steps.find((step) => step.id === setupWizard.currentStepId) ?? null
181
181
  : null,
@@ -254,7 +254,7 @@ export async function markSetupCheckpoint(context: CommandContext, args: AgentHa
254
254
  progressLabel: updatedWizard.progressLabel,
255
255
  currentStepId: updatedWizard.currentStepId,
256
256
  currentStepLabel: updatedWizard.currentStepLabel,
257
- checkpoint: updatedWizard.checkpoint,
257
+ checkpoint: updatedWizard._diagnostic.checkpoint,
258
258
  },
259
259
  routes: {
260
260
  inspectCheckpoint: DEFAULT_AGENT_SETUP_WIZARD_INSPECT_CHECKPOINT_ROUTE,
@@ -2,8 +2,10 @@ import type { ArtifactDescriptor } from '@pellux/goodvibes-sdk/platform/artifact
2
2
  import type { CommandContext } from '../input/command-registry.ts';
3
3
  import { requireShellPaths } from '../input/commands/runtime-services.ts';
4
4
  import { readOnboardingCompletionMarker } from '../runtime/onboarding/index.ts';
5
+ import { buildSetupWizardDurableReceipts } from '../agent/setup-wizard-artifact-receipts.ts';
6
+ import { mergeSetupWizardDurableReceipts, setupWizardLiveDurableReceipts } from '../input/setup-wizard-live-receipts.ts';
5
7
  import { clearSetupWizardCheckpoint, readSetupWizardCheckpoint, saveSetupWizardCheckpoint } from '../agent/setup-wizard-checkpoint.ts';
6
- import { DEFAULT_AGENT_SETUP_WIZARD_CLEAR_CHECKPOINT_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_INSPECT_CHECKPOINT_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_MARK_CHECKPOINT_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_REVIEW_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_RERUN_SMOKE_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_SAVE_SMOKE_ROUTE, buildAgentSetupWizard, emptyAgentSetupSmokeHistory, emptyAgentSetupWizardCheckpoint, type AgentSetupWizard, type AgentSetupWizardCheckpoint, type AgentSetupWizardSmokeHistory, type AgentSetupWizardSourceItem } from '../agent/setup-wizard.ts';
8
+ import { DEFAULT_AGENT_SETUP_WIZARD_CLEAR_CHECKPOINT_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_INSPECT_CHECKPOINT_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_MARK_CHECKPOINT_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_REVIEW_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_RERUN_SMOKE_ROUTE, DEFAULT_AGENT_SETUP_WIZARD_SAVE_SMOKE_ROUTE, buildAgentSetupWizard, emptyAgentSetupSmokeHistory, emptyAgentSetupWizardCheckpoint, type AgentSetupWizard, type AgentSetupWizardCheckpoint, type AgentSetupWizardDurableReceipt, type AgentSetupWizardSmokeHistory, type AgentSetupWizardSourceItem } from '../agent/setup-wizard.ts';
7
9
  import { previewHarnessText } from './agent-harness-text.ts';
8
10
  import { readFieldMap, readString, safeIso, setupSmokeArtifactStore } from './agent-harness-setup-posture-utils.ts';
9
11
  import { setupHandoffsForItem } from './agent-harness-setup-handoffs.ts';
@@ -273,6 +275,12 @@ export function setupSmokeEvidenceTrend(artifacts: readonly ArtifactDescriptor[]
273
275
  return 'unchanged';
274
276
  }
275
277
 
278
+ function artifactCreatedAtIso(artifact: ArtifactDescriptor): string | null {
279
+ const createdAt = artifact.createdAt;
280
+ if (typeof createdAt !== 'number' || !Number.isFinite(createdAt)) return null;
281
+ return new Date(createdAt).toISOString();
282
+ }
283
+
276
284
  export function setupSmokeBlockedCheckFrequency(artifacts: readonly ArtifactDescriptor[]): readonly Record<string, unknown>[] {
277
285
  const counts = new Map<string, number>();
278
286
  for (const artifact of artifacts) {
@@ -343,6 +351,8 @@ export function setupSmokeEvidenceHistory(context: CommandContext): Record<strin
343
351
  trend: setupSmokeEvidenceTrend(artifacts),
344
352
  latestResult: readArtifactMetadataString(artifacts[0]!, 'result') || 'unknown',
345
353
  previousResult: artifacts[1] ? readArtifactMetadataString(artifacts[1], 'result') || 'unknown' : null,
354
+ latestEvidenceId: artifacts[0]!.id,
355
+ latestEvidenceAt: artifactCreatedAtIso(artifacts[0]!),
346
356
  resultCounts,
347
357
  blockedCheckFrequency: setupSmokeBlockedCheckFrequency(artifacts),
348
358
  recent: artifacts.slice(0, 5).map(describeSetupSmokeEvidenceArtifact),
@@ -373,6 +383,8 @@ export function setupWizardSmokeHistory(context: CommandContext): AgentSetupWiza
373
383
  trend: setupSmokeEvidenceTrend(artifacts),
374
384
  latestResult: readArtifactMetadataString(artifacts[0]!, 'result') || 'unknown',
375
385
  previousResult: artifacts[1] ? readArtifactMetadataString(artifacts[1], 'result') || 'unknown' : null,
386
+ latestEvidenceId: artifacts[0]!.id,
387
+ latestEvidenceAt: artifactCreatedAtIso(artifacts[0]!),
376
388
  resultCounts,
377
389
  blockedCheckFrequency: setupSmokeBlockedCheckFrequency(artifacts).map((entry) => ({
378
390
  checkId: readString(entry.checkId),
@@ -430,6 +442,17 @@ export function setupWizardCheckpoint(context: CommandContext): AgentSetupWizard
430
442
  }
431
443
  }
432
444
 
445
+ export function setupWizardDurableReceipts(context: CommandContext): readonly AgentSetupWizardDurableReceipt[] {
446
+ const artifactStore = setupSmokeArtifactStore(context);
447
+ const liveReceipts = setupWizardLiveDurableReceipts(context);
448
+ if (!artifactStore?.list) return liveReceipts;
449
+ try {
450
+ return mergeSetupWizardDurableReceipts(buildSetupWizardDurableReceipts(artifactStore.list(100)), liveReceipts);
451
+ } catch {
452
+ return liveReceipts;
453
+ }
454
+ }
455
+
433
456
  export function setupCompletionMarkerExists(context: CommandContext): boolean {
434
457
  try {
435
458
  return readOnboardingCompletionMarker(requireShellPaths(context), 'user').exists;
@@ -467,6 +490,8 @@ export function buildSetupWizard(plan: readonly SetupPlanItem[], context: Comman
467
490
  smokeHistory: setupWizardSmokeHistory(context),
468
491
  checkpoint: setupWizardCheckpoint(context),
469
492
  closeoutCriticalStepIds: plan.filter((item) => item.blocksAutonomy).map((item) => item.id),
493
+ receiptRequiredStepIds: ['connected-host-readiness', 'connected-host-auth', 'install-smoke'],
494
+ durableReceipts: setupWizardDurableReceipts(context),
470
495
  setupMarkerExists: markerItem?.status === 'ready' || setupCompletionMarkerExists(context),
471
496
  repeatedBlockerAliases: SETUP_WIZARD_PLAN_BLOCKER_ALIASES,
472
497
  });
@@ -13,7 +13,7 @@ export const AGENT_HARNESS_MODES = [
13
13
  'execution_history', 'execution_history_item',
14
14
  'file_recovery', 'run_file_recovery',
15
15
  'personal_ops_briefing', 'personal_ops', 'personal_ops_queue', 'personal_ops_intake', 'personal_ops_lane', 'run_personal_ops_read',
16
- 'memory_posture', 'memory_provider',
16
+ 'memory_posture', 'memory_provider', 'memory_refinement', 'run_memory_refinement',
17
17
  'autonomy_intake', 'autonomy_queue', 'autonomy_queue_item',
18
18
  'learning_curator', 'learning_candidate',
19
19
  'research_briefing', 'research_workflow', 'research_runs', 'research_run',
@@ -242,6 +242,28 @@ export const AGENT_HARNESS_PARAMETER_PROPERTIES = {
242
242
  type: 'string',
243
243
  description: 'Selected Agent-local record id.',
244
244
  },
245
+ knowledgeSpaceId: {
246
+ type: 'string',
247
+ description: 'Agent Knowledge space id for memory_refinement or run_memory_refinement.',
248
+ },
249
+ sourceIds: {
250
+ type: 'array',
251
+ items: { type: 'string' },
252
+ description: 'Agent Knowledge source ids for scoped semantic refinement.',
253
+ },
254
+ gapIds: {
255
+ type: 'array',
256
+ items: { type: 'string' },
257
+ description: 'Agent Knowledge semantic gap ids for scoped refinement.',
258
+ },
259
+ maxRunMs: {
260
+ type: 'number',
261
+ description: 'Maximum semantic refinement run budget in milliseconds.',
262
+ },
263
+ force: {
264
+ type: 'boolean',
265
+ description: 'Force semantic refinement reprocessing where supported.',
266
+ },
245
267
  key: {
246
268
  type: 'string',
247
269
  description: 'Agent setting key.',
@@ -41,6 +41,11 @@ export interface AgentHarnessToolArgs {
41
41
  readonly panelId?: unknown;
42
42
  readonly actionId?: unknown;
43
43
  readonly recordId?: unknown;
44
+ readonly knowledgeSpaceId?: unknown;
45
+ readonly sourceIds?: unknown;
46
+ readonly gapIds?: unknown;
47
+ readonly maxRunMs?: unknown;
48
+ readonly force?: unknown;
44
49
  readonly fields?: unknown;
45
50
  readonly combo?: unknown;
46
51
  readonly combos?: unknown;
@@ -24,6 +24,7 @@ import { describeHarnessMcpServer, mcpServerCatalogStatus, mcpServerSummary } fr
24
24
  import { describeHarnessModelRoute, modelRoutingCatalogStatus, modelRoutingSummary, runLocalModelServerSmoke } from './agent-harness-model-routing.ts';
25
25
  import { describeHarnessModelTool, listHarnessModelTools } from './agent-harness-model-tool-catalog.ts';
26
26
  import { describeMemoryProvider, memoryPostureCatalogStatus, memoryPostureSummary } from './agent-harness-memory-posture.ts';
27
+ import { memoryRefinementCatalogStatus, memoryRefinementSummary, runMemoryRefinement } from './agent-harness-memory-refinement.ts';
27
28
  import { describeHarnessOperatorMethod, operatorMethodCatalogStatus, operatorMethodSummary } from './agent-harness-operator-methods.ts';
28
29
  import { describePersonalOpsLane, personalOpsBriefingSummary, personalOpsCatalogStatus, personalOpsIntakeSummary, personalOpsQueueSummary, personalOpsSummary, runPersonalOpsRead } from './agent-harness-personal-ops.ts';
29
30
  import { describeHarnessPairingRoute, pairingPostureCatalogStatus, pairingPostureSummary } from './agent-harness-pairing-posture.ts';
@@ -99,7 +100,7 @@ function detailedHarnessModelAccessGuide(): Record<string, string> {
99
100
  executionHistory: 'Prefer execution action:"history|record" for activity cards and records; use returned verification, supervision, and recovery routes.',
100
101
  fileRecovery: 'Prefer execution action:"recovery"; apply local file undo/redo snapshots with mode:"run_file_recovery" and confirmation.',
101
102
  personalOps: 'Prefer personal_ops action:"briefing|status|queue|intake|lane|read"; lower-level modes personal_ops_briefing/personal_ops/personal_ops_queue/personal_ops_intake/personal_ops_lane/run_personal_ops_read remain available for harness inspection.',
102
- memoryPosture: 'Prefer memory action:"status|provider|curator|candidate|list|search|get"; memory writes, vector rebuilds, and embedding-provider changes stay on confirmed existing routes.',
103
+ memoryPosture: 'Prefer memory action:"status|provider|refinement|run_refinement|curator|candidate|list|search|get"; run_refinement, memory writes, vector rebuilds, and embedding-provider changes stay on confirmed existing routes.',
103
104
  autonomyQueue: 'Prefer autonomy action:"intake|queue|item" for ongoing work and visible autonomous work; lower-level autonomy_* modes remain available for detail. Effects stay confirmed on the owning route.',
104
105
  learningCurator: 'Prefer memory action:"curator|candidate"; writes stay on reviewed Agent-local routes.',
105
106
  researchWorkflow: 'Prefer research action:"briefing" for the current next-action queue, action:"plan" for deep-research route planning, action:"search" for bounded public source candidates, and action:"runner" for browser-runner readiness; lower-level mode:"research_workflow" sequences visible run, web/fetch or browser posture, source queue, report, and Knowledge promotion routes.',
@@ -176,6 +177,7 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
176
177
  status: 'unavailable',
177
178
  error: formatHarnessError(err),
178
179
  }));
180
+ const memoryRefinement = memoryRefinementCatalogStatus(deps.commandContext);
179
181
  const autonomyQueue = autonomyQueueCatalogStatus(deps.commandContext);
180
182
  const learningCurator = learningCuratorCatalogStatus(deps.commandContext);
181
183
  const researchBriefing = researchBriefingCatalogStatus(deps.commandContext);
@@ -232,6 +234,7 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
232
234
  fileRecovery,
233
235
  personalOps,
234
236
  memoryPosture,
237
+ memoryRefinement,
235
238
  autonomyQueue,
236
239
  learningCurator,
237
240
  researchBriefing,
@@ -483,6 +486,11 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
483
486
  if (resolved.status === 'ambiguous') return error(`Ambiguous memory provider ${resolved.input}. Candidates: ${JSON.stringify(resolved.candidates)}`);
484
487
  return error(resolved.usage);
485
488
  }
489
+ if (args.mode === 'memory_refinement') return output(memoryRefinementSummary(deps.commandContext, args));
490
+ if (args.mode === 'run_memory_refinement') {
491
+ const confirmationError = requireConfirmedAction(args, 'Agent Knowledge semantic refinement');
492
+ return confirmationError ? error(confirmationError) : output(await runMemoryRefinement(deps.commandContext, args));
493
+ }
486
494
  if (args.mode === 'autonomy_intake') return output(autonomyIntakeSummary(deps.commandContext, args));
487
495
  if (args.mode === 'autonomy_queue') return output(autonomyQueueSummary(deps.commandContext, args));
488
496
  if (args.mode === 'autonomy_queue_item') {
@@ -322,7 +322,7 @@ export function describeWorkspaceAction(
322
322
  confirmation: 'required',
323
323
  readinessRoute: 'agent_harness mode:"ui_surface" surfaceId:"connected-browser-cockpit" includeParameters:true',
324
324
  fallback: 'Inspect host action:"service" endpointId:"web" or host action:"services" when the web cockpit is not enabled.',
325
- note: 'Opens the connected-host browser/PWA cockpit through the configured web route; readiness inspection also reports workspace category coverage, mobile/PWA controls, and first-run receipt gaps without creating a separate Agent-hosted web app.',
325
+ note: 'Opens the connected-host browser/PWA cockpit through the configured web route; readiness inspection also reports certified workspace category coverage, mobile/PWA controls, and first-run receipt evidence without creating a separate Agent-hosted web app.',
326
326
  },
327
327
  } : {}),
328
328
  ...(action.kind === 'local-selection' || action.kind === 'local-operation' ? {
@@ -6,6 +6,8 @@ import { createAgentHarnessTool } from './agent-harness-tool.ts';
6
6
  type AgentMemoryAction =
7
7
  | 'status'
8
8
  | 'provider'
9
+ | 'refinement'
10
+ | 'run_refinement'
9
11
  | 'curator'
10
12
  | 'candidate'
11
13
  | 'list'
@@ -24,6 +26,9 @@ interface AgentMemoryToolArgs {
24
26
  readonly recordId?: unknown;
25
27
  readonly providerId?: unknown;
26
28
  readonly candidateId?: unknown;
29
+ readonly knowledgeSpaceId?: unknown;
30
+ readonly sourceIds?: unknown;
31
+ readonly gapIds?: unknown;
27
32
  readonly target?: unknown;
28
33
  readonly query?: unknown;
29
34
  readonly includeParameters?: unknown;
@@ -36,6 +41,8 @@ interface AgentMemoryToolArgs {
36
41
  readonly confidence?: unknown;
37
42
  readonly tags?: unknown;
38
43
  readonly reason?: unknown;
44
+ readonly maxRunMs?: unknown;
45
+ readonly force?: unknown;
39
46
  readonly confirm?: unknown;
40
47
  readonly explicitUserRequest?: unknown;
41
48
  }
@@ -61,6 +68,8 @@ function normalizeMemoryAction(value: unknown): AgentMemoryAction | null {
61
68
  if (!action) return null;
62
69
  if (action === 'status' || action === 'summary' || action === 'posture' || action === 'memory_posture' || action === 'recall' || action === 'providers') return 'status';
63
70
  if (action === 'provider' || action === 'memory_provider' || action === 'embedding' || action === 'external' || action === 'external_provider') return 'provider';
71
+ if (action === 'refinement' || action === 'refinement_tasks' || action === 'semantic_refinement' || action === 'self_improvement' || action === 'semantic_self_improvement' || action === 'learning_loop') return 'refinement';
72
+ if (action === 'run_refinement' || action === 'refine' || action === 'run_semantic_refinement' || action === 'run_self_improvement' || action === 'self_improve') return 'run_refinement';
64
73
  if (action === 'curator' || action === 'learning' || action === 'learning_curator' || action === 'queue' || action === 'review_queue' || action === 'plan') return 'curator';
65
74
  if (action === 'candidate' || action === 'learning_candidate' || action === 'card' || action === 'inspect_candidate') return 'candidate';
66
75
  if (action === 'list' || action === 'records' || action === 'memories') return 'list';
@@ -131,7 +140,7 @@ export function createAgentMemoryTool(deps: AgentMemoryToolDeps): Tool {
131
140
  properties: {
132
141
  action: {
133
142
  type: 'string',
134
- enum: ['status', 'provider', 'curator', 'candidate', 'list', 'search', 'get', 'create', 'update', 'review', 'stale', 'delete'],
143
+ enum: ['status', 'provider', 'refinement', 'run_refinement', 'curator', 'candidate', 'list', 'search', 'get', 'create', 'update', 'review', 'stale', 'delete'],
135
144
  description: 'Read memory posture/providers/curator or operate records.',
136
145
  },
137
146
  mode: { type: 'string', description: 'Alias for action.' },
@@ -139,6 +148,9 @@ export function createAgentMemoryTool(deps: AgentMemoryToolDeps): Tool {
139
148
  recordId: { type: 'string', description: 'Alias for id.' },
140
149
  providerId: { type: 'string', description: 'Embedding or external-memory provider id.' },
141
150
  candidateId: { type: 'string', description: 'Learning curator candidate id.' },
151
+ knowledgeSpaceId: { type: 'string', description: 'Agent Knowledge space id for semantic refinement.' },
152
+ sourceIds: { type: 'array', items: { type: 'string' }, description: 'Agent Knowledge source ids for scoped semantic refinement.' },
153
+ gapIds: { type: 'array', items: { type: 'string' }, description: 'Agent Knowledge semantic gap ids for scoped refinement.' },
142
154
  target: { type: 'string', description: 'Lookup target or search text.' },
143
155
  query: { type: 'string', description: 'Search text.' },
144
156
  includeParameters: { type: 'boolean', description: 'Include provider setup contracts or candidate details.' },
@@ -151,6 +163,8 @@ export function createAgentMemoryTool(deps: AgentMemoryToolDeps): Tool {
151
163
  confidence: { type: 'number', description: 'Review confidence, 0-100.' },
152
164
  tags: { type: 'array', items: { type: 'string' }, description: 'Memory tags.' },
153
165
  reason: { type: 'string', description: 'Reason for stale/delete decisions.' },
166
+ maxRunMs: { type: 'number', description: 'Maximum semantic refinement run budget in milliseconds.' },
167
+ force: { type: 'boolean', description: 'Force semantic refinement reprocessing where supported.' },
154
168
  confirm: { type: 'boolean', description: 'Required for deletion and other confirmed memory effects.' },
155
169
  explicitUserRequest: { type: 'string', description: 'User request authorizing confirmed memory effects.' },
156
170
  },
@@ -180,6 +194,31 @@ export function createAgentMemoryTool(deps: AgentMemoryToolDeps): Tool {
180
194
  includeParameters: args.includeParameters,
181
195
  }));
182
196
  }
197
+ if (action === 'refinement') {
198
+ return harnessTool.execute(compactArgs({
199
+ mode: 'memory_refinement',
200
+ target: args.target,
201
+ query: args.query,
202
+ knowledgeSpaceId: args.knowledgeSpaceId,
203
+ sourceIds: args.sourceIds,
204
+ gapIds: args.gapIds,
205
+ limit: args.limit,
206
+ includeParameters: args.includeParameters,
207
+ }));
208
+ }
209
+ if (action === 'run_refinement') {
210
+ return harnessTool.execute(compactArgs({
211
+ mode: 'run_memory_refinement',
212
+ knowledgeSpaceId: args.knowledgeSpaceId,
213
+ sourceIds: args.sourceIds,
214
+ gapIds: args.gapIds,
215
+ limit: args.limit,
216
+ maxRunMs: args.maxRunMs,
217
+ force: args.force,
218
+ confirm: args.confirm,
219
+ explicitUserRequest: args.explicitUserRequest,
220
+ }));
221
+ }
183
222
  if (action === 'curator') {
184
223
  return harnessTool.execute(compactArgs({
185
224
  mode: 'learning_curator',
@@ -461,6 +461,18 @@ export function toArtifactCandidate(candidate: CompareCandidateResult): Record<s
461
461
  };
462
462
  }
463
463
 
464
+ export function toArtifactCandidateLatencyMetadata(candidate: CompareCandidateResult): Record<string, unknown> {
465
+ return {
466
+ blindId: candidate.blindId,
467
+ status: candidate.status,
468
+ latencyMs: candidate.latencyMs,
469
+ registryKey: candidate.model.registryKey,
470
+ providerId: candidate.model.providerId,
471
+ modelId: candidate.model.modelId,
472
+ displayName: candidate.model.displayName,
473
+ };
474
+ }
475
+
464
476
  export function comparisonArtifactText(input: {
465
477
  readonly comparison: StoredComparison;
466
478
  readonly prompt: string;
@@ -580,6 +592,7 @@ export async function saveComparisonArtifact(input: {
580
592
  ...(input.comparison.documentId ? { documentId: input.comparison.documentId } : {}),
581
593
  candidateCount: input.comparison.candidates.length,
582
594
  completedCandidates: input.comparison.candidates.filter((candidate) => candidate.status === 'completed').length,
595
+ candidateLatencyEvidence: input.comparison.candidates.map(toArtifactCandidateLatencyMetadata),
583
596
  ...(input.benchmarkKind ? { benchmarkKind: input.benchmarkKind } : {}),
584
597
  ...(input.comparison.taskType ? { taskType: input.comparison.taskType } : {}),
585
598
  revealStored: true,