@pellux/goodvibes-agent 1.1.6 → 1.2.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 (256) hide show
  1. package/CHANGELOG.md +176 -0
  2. package/README.md +46 -30
  3. package/dist/package/{ast-grep-napi.linux-x64-gnu-mkk8xwww.node → ast-grep-napi.linux-x64-gnu-swtppvy9.node} +0 -0
  4. package/dist/package/{ast-grep-napi.linux-x64-musl-ryqtgdv6.node → ast-grep-napi.linux-x64-musl-ttfcdtap.node} +0 -0
  5. package/dist/package/main.js +132662 -91399
  6. package/docs/README.md +14 -7
  7. package/docs/channels-remote-and-api.md +8 -5
  8. package/docs/connected-host.md +14 -12
  9. package/docs/getting-started.md +56 -30
  10. package/docs/knowledge-artifacts-and-multimodal.md +7 -5
  11. package/docs/project-planning.md +2 -2
  12. package/docs/providers-and-routing.md +11 -3
  13. package/docs/tools-and-commands.md +114 -45
  14. package/docs/voice-and-live-tts.md +3 -1
  15. package/package.json +3 -2
  16. package/release/release-notes.md +130 -5
  17. package/release/release-readiness.json +120 -90
  18. package/src/agent/assistant-cockpit.ts +247 -0
  19. package/src/agent/autonomy-schedule-format.ts +96 -0
  20. package/src/agent/autonomy-schedule.ts +514 -0
  21. package/src/agent/channel-delivery-receipts.ts +292 -0
  22. package/src/agent/competitive-feature-inventory.ts +296 -0
  23. package/src/agent/document-registry-types.ts +106 -0
  24. package/src/agent/document-registry.ts +734 -0
  25. package/src/agent/harness-control.ts +2 -2
  26. package/src/agent/memory-prompt.ts +2 -2
  27. package/src/agent/operator-actions.ts +50 -6
  28. package/src/agent/persona-registry.ts +8 -0
  29. package/src/agent/project-context-files.ts +273 -0
  30. package/src/agent/prompt-context-receipts.ts +502 -0
  31. package/src/agent/reminder-schedule-format.ts +16 -2
  32. package/src/agent/research-run-registry.ts +582 -0
  33. package/src/agent/research-source-registry.ts +441 -0
  34. package/src/agent/routine-registry.ts +19 -3
  35. package/src/agent/routine-schedule-format.ts +27 -2
  36. package/src/agent/runtime-profile-starters.ts +7 -0
  37. package/src/agent/runtime-profile.ts +106 -4
  38. package/src/agent/schedule-edit-format.ts +129 -0
  39. package/src/agent/schedule-edit.ts +496 -0
  40. package/src/agent/schedule-next-routes.ts +42 -0
  41. package/src/agent/setup-wizard-checkpoint.ts +140 -0
  42. package/src/agent/setup-wizard.ts +447 -0
  43. package/src/agent/skill-registry-types.ts +102 -0
  44. package/src/agent/skill-registry.ts +81 -107
  45. package/src/agent/vibe-confirmation-routes.ts +62 -0
  46. package/src/agent/vibe-file.ts +285 -0
  47. package/src/cli/agent-knowledge-command.ts +45 -2
  48. package/src/cli/help.ts +3 -0
  49. package/src/cli/profiles-command.ts +25 -11
  50. package/src/config/agent-settings-policy.ts +1 -18
  51. package/src/input/agent-workspace-activation.ts +53 -0
  52. package/src/input/agent-workspace-artifact-browser-editor.ts +494 -0
  53. package/src/input/agent-workspace-artifact-metadata.ts +17 -0
  54. package/src/input/agent-workspace-basic-command-editors.ts +5 -1
  55. package/src/input/agent-workspace-categories.ts +153 -155
  56. package/src/input/agent-workspace-channel-triage.ts +481 -0
  57. package/src/input/agent-workspace-channels.ts +263 -0
  58. package/src/input/agent-workspace-command-editor.ts +152 -0
  59. package/src/input/agent-workspace-context-snapshot.ts +349 -0
  60. package/src/input/agent-workspace-delegation-editor-submission.ts +8 -0
  61. package/src/input/agent-workspace-document-editor.ts +502 -0
  62. package/src/input/agent-workspace-document-ops-editor.ts +523 -0
  63. package/src/input/agent-workspace-host-category.ts +1 -1
  64. package/src/input/agent-workspace-local-library-snapshot.ts +167 -0
  65. package/src/input/agent-workspace-model-compare-editor.ts +376 -0
  66. package/src/input/agent-workspace-model-compare-prompt-submission.ts +552 -0
  67. package/src/input/agent-workspace-model-compare-types.ts +82 -0
  68. package/src/input/agent-workspace-model-compare-utils.ts +35 -0
  69. package/src/input/agent-workspace-onboarding-categories.ts +141 -0
  70. package/src/input/agent-workspace-operations-command-editor-submission.ts +53 -0
  71. package/src/input/agent-workspace-operations-command-editors.ts +22 -0
  72. package/src/input/agent-workspace-research-report-editor.ts +212 -0
  73. package/src/input/agent-workspace-research-run-editor.ts +144 -0
  74. package/src/input/agent-workspace-research-source-editor.ts +167 -0
  75. package/src/input/agent-workspace-review-packet-snapshot.ts +593 -0
  76. package/src/input/agent-workspace-review-packet-utils.ts +265 -0
  77. package/src/input/agent-workspace-settings.ts +262 -30
  78. package/src/input/agent-workspace-setup-checkpoint-action.ts +127 -0
  79. package/src/input/agent-workspace-setup-snapshot.ts +198 -0
  80. package/src/input/agent-workspace-setup.ts +34 -1
  81. package/src/input/agent-workspace-snapshot.ts +162 -147
  82. package/src/input/agent-workspace-types.ts +287 -2
  83. package/src/input/agent-workspace.ts +18 -0
  84. package/src/input/command-registry.ts +9 -2
  85. package/src/input/commands/agent-runtime-profile-runtime.ts +28 -13
  86. package/src/input/commands/channels-runtime.ts +102 -114
  87. package/src/input/commands/delegation-runtime.ts +87 -24
  88. package/src/input/commands/knowledge-browser-flags.ts +12 -0
  89. package/src/input/commands/knowledge.ts +28 -14
  90. package/src/input/commands/operator-actions-runtime.ts +6 -3
  91. package/src/input/commands/schedule-runtime.ts +71 -14
  92. package/src/input/commands/session-content.ts +2 -2
  93. package/src/input/commands/shell-core.ts +2 -0
  94. package/src/input/commands/vibe-runtime.ts +140 -0
  95. package/src/input/commands.ts +2 -0
  96. package/src/input/connected-host-routes.ts +123 -0
  97. package/src/input/settings-modal-types.ts +14 -0
  98. package/src/main.ts +15 -15
  99. package/src/panels/qr-panel.ts +2 -2
  100. package/src/renderer/agent-workspace-context-lines.ts +686 -0
  101. package/src/renderer/agent-workspace.ts +30 -419
  102. package/src/renderer/settings-modal-helpers.ts +12 -0
  103. package/src/renderer/settings-modal.ts +12 -0
  104. package/src/runtime/bootstrap-command-context.ts +11 -1
  105. package/src/runtime/bootstrap-command-parts.ts +14 -3
  106. package/src/runtime/bootstrap-core.ts +43 -1
  107. package/src/runtime/bootstrap-shell.ts +6 -0
  108. package/src/runtime/bootstrap.ts +113 -30
  109. package/src/runtime/connected-host-auth.ts +3 -2
  110. package/src/runtime/execution-ledger.ts +231 -0
  111. package/src/runtime/services.ts +88 -10
  112. package/src/runtime/tool-permission-safety.ts +287 -0
  113. package/src/shell/session-continuity-hints.ts +39 -0
  114. package/src/tools/agent-artifacts-tool.ts +606 -0
  115. package/src/tools/agent-audit-tool.ts +155 -0
  116. package/src/tools/agent-autonomy-schedule-tool.ts +238 -0
  117. package/src/tools/agent-autonomy-tool.ts +140 -0
  118. package/src/tools/agent-channel-send-tool.ts +24 -2
  119. package/src/tools/agent-channels-tool.ts +140 -0
  120. package/src/tools/agent-computer-tool.ts +168 -0
  121. package/src/tools/agent-context-policy.ts +267 -10
  122. package/src/tools/agent-context-tool.ts +143 -0
  123. package/src/tools/agent-delegation-tool.ts +128 -0
  124. package/src/tools/agent-device-tool.ts +240 -0
  125. package/src/tools/agent-documents-tool.ts +684 -0
  126. package/src/tools/agent-execution-tool.ts +230 -0
  127. package/src/tools/agent-harness-agent-orchestration.ts +703 -0
  128. package/src/tools/agent-harness-autonomy-intake.ts +785 -0
  129. package/src/tools/agent-harness-autonomy-live-records.ts +588 -0
  130. package/src/tools/agent-harness-autonomy-queue-types.ts +88 -0
  131. package/src/tools/agent-harness-autonomy-queue.ts +560 -0
  132. package/src/tools/agent-harness-background-processes-types.ts +35 -0
  133. package/src/tools/agent-harness-background-processes.ts +794 -0
  134. package/src/tools/agent-harness-browser-cockpit-route.ts +219 -0
  135. package/src/tools/agent-harness-browser-control.ts +338 -0
  136. package/src/tools/agent-harness-channel-metadata.ts +168 -10
  137. package/src/tools/agent-harness-cli-command-policy.ts +110 -0
  138. package/src/tools/agent-harness-command-catalog.ts +4 -2
  139. package/src/tools/agent-harness-command-runner.ts +42 -0
  140. package/src/tools/agent-harness-connected-host-status.ts +7 -4
  141. package/src/tools/agent-harness-delegation-posture.ts +234 -19
  142. package/src/tools/agent-harness-document-ops-reviewer-readiness.ts +234 -0
  143. package/src/tools/agent-harness-document-ops-types.ts +72 -0
  144. package/src/tools/agent-harness-document-ops.ts +671 -0
  145. package/src/tools/agent-harness-execution-history.ts +489 -0
  146. package/src/tools/agent-harness-execution-posture.ts +382 -0
  147. package/src/tools/agent-harness-file-recovery.ts +135 -0
  148. package/src/tools/agent-harness-keybinding-metadata.ts +16 -12
  149. package/src/tools/agent-harness-learning-curator-common.ts +102 -0
  150. package/src/tools/agent-harness-learning-curator-consolidation.ts +295 -0
  151. package/src/tools/agent-harness-learning-curator-proposals.ts +606 -0
  152. package/src/tools/agent-harness-learning-curator-types.ts +151 -0
  153. package/src/tools/agent-harness-learning-curator.ts +417 -0
  154. package/src/tools/agent-harness-local-model-benchmarks.ts +199 -0
  155. package/src/tools/agent-harness-local-model-cookbook.ts +238 -0
  156. package/src/tools/agent-harness-local-model-endpoints.ts +673 -0
  157. package/src/tools/agent-harness-media-posture.ts +208 -2
  158. package/src/tools/agent-harness-memory-posture.ts +556 -0
  159. package/src/tools/agent-harness-metadata.ts +100 -168
  160. package/src/tools/agent-harness-mode-catalog.ts +84 -33
  161. package/src/tools/agent-harness-model-catalog.ts +162 -0
  162. package/src/tools/agent-harness-model-provider-health.ts +186 -0
  163. package/src/tools/agent-harness-model-readiness.ts +406 -0
  164. package/src/tools/agent-harness-model-routing-types.ts +266 -0
  165. package/src/tools/agent-harness-model-routing-utils.ts +30 -0
  166. package/src/tools/agent-harness-model-routing.ts +137 -190
  167. package/src/tools/agent-harness-operator-methods.ts +115 -133
  168. package/src/tools/agent-harness-pairing-posture.ts +431 -18
  169. package/src/tools/agent-harness-personal-ops-discovery.ts +533 -0
  170. package/src/tools/agent-harness-personal-ops-intake.ts +385 -0
  171. package/src/tools/agent-harness-personal-ops-lanes.ts +204 -0
  172. package/src/tools/agent-harness-personal-ops-records.ts +732 -0
  173. package/src/tools/agent-harness-personal-ops-runner.ts +637 -0
  174. package/src/tools/agent-harness-personal-ops-types.ts +222 -0
  175. package/src/tools/agent-harness-personal-ops.ts +606 -0
  176. package/src/tools/agent-harness-project-context.ts +144 -0
  177. package/src/tools/agent-harness-prompt-context.ts +589 -0
  178. package/src/tools/agent-harness-provider-account-metadata.ts +2 -2
  179. package/src/tools/agent-harness-release-evidence.ts +9 -7
  180. package/src/tools/agent-harness-release-readiness.ts +9 -7
  181. package/src/tools/agent-harness-research-briefing.ts +427 -0
  182. package/src/tools/agent-harness-research-queue.ts +250 -0
  183. package/src/tools/agent-harness-research-runs.ts +295 -0
  184. package/src/tools/agent-harness-research-workflow.ts +322 -0
  185. package/src/tools/agent-harness-security-posture.ts +2 -2
  186. package/src/tools/agent-harness-service-posture.ts +9 -9
  187. package/src/tools/agent-harness-session-metadata.ts +3 -3
  188. package/src/tools/agent-harness-setup-connected-host.ts +501 -0
  189. package/src/tools/agent-harness-setup-describe.ts +557 -0
  190. package/src/tools/agent-harness-setup-handoffs.ts +502 -0
  191. package/src/tools/agent-harness-setup-model-helpers.ts +101 -0
  192. package/src/tools/agent-harness-setup-plan.ts +253 -0
  193. package/src/tools/agent-harness-setup-posture-types.ts +218 -0
  194. package/src/tools/agent-harness-setup-posture-utils.ts +173 -0
  195. package/src/tools/agent-harness-setup-posture.ts +449 -221
  196. package/src/tools/agent-harness-setup-smoke.ts +508 -0
  197. package/src/tools/agent-harness-sudo-posture.ts +114 -0
  198. package/src/tools/agent-harness-tool-schema.ts +120 -7
  199. package/src/tools/agent-harness-tool-types.ts +78 -0
  200. package/src/tools/agent-harness-tool-utils.ts +43 -0
  201. package/src/tools/agent-harness-tool.ts +311 -370
  202. package/src/tools/agent-harness-ui-surface-metadata.ts +76 -69
  203. package/src/tools/agent-harness-ui-surface-types.ts +46 -0
  204. package/src/tools/agent-harness-vibe-health.ts +105 -0
  205. package/src/tools/agent-harness-workspace-action-runner.ts +149 -0
  206. package/src/tools/agent-harness-workspace-actions.ts +114 -8
  207. package/src/tools/agent-harness-workspace-editor-execution.ts +214 -0
  208. package/src/tools/agent-harness-workspace-editor-runner.ts +755 -0
  209. package/src/tools/agent-host-tool.ts +159 -0
  210. package/src/tools/agent-knowledge-ingest-tool.ts +34 -1
  211. package/src/tools/agent-learning-consolidation-core.ts +327 -0
  212. package/src/tools/agent-learning-consolidation-tool.ts +758 -0
  213. package/src/tools/agent-memory-tool.ts +214 -0
  214. package/src/tools/agent-model-compare-export.ts +315 -0
  215. package/src/tools/agent-model-compare-handoff.ts +592 -0
  216. package/src/tools/agent-model-compare-judgment.ts +633 -0
  217. package/src/tools/agent-model-compare-run.ts +722 -0
  218. package/src/tools/agent-model-compare-tool.ts +698 -0
  219. package/src/tools/agent-model-compare-types.ts +191 -0
  220. package/src/tools/agent-model-compare-utils.ts +93 -0
  221. package/src/tools/agent-models-tool.ts +208 -0
  222. package/src/tools/agent-operator-action-tool.ts +1 -1
  223. package/src/tools/agent-operator-method-tool.ts +643 -0
  224. package/src/tools/agent-personal-ops-tool.ts +197 -0
  225. package/src/tools/agent-policy-explanation.ts +415 -0
  226. package/src/tools/agent-research-report-tool.ts +608 -0
  227. package/src/tools/agent-research-runs-tool.ts +434 -0
  228. package/src/tools/agent-research-sources-tool.ts +443 -0
  229. package/src/tools/agent-research-tool.ts +687 -0
  230. package/src/tools/agent-review-packet-presets-core.ts +757 -0
  231. package/src/tools/agent-review-packet-presets-tool.ts +466 -0
  232. package/src/tools/agent-review-packet-share-tool.ts +305 -0
  233. package/src/tools/agent-route-planner-candidates-setup.ts +411 -0
  234. package/src/tools/agent-route-planner-candidates-surfaces.ts +432 -0
  235. package/src/tools/agent-route-planner-candidates-work.ts +251 -0
  236. package/src/tools/agent-route-planner-helpers.ts +667 -0
  237. package/src/tools/agent-route-planner.ts +185 -0
  238. package/src/tools/agent-route-tool.ts +105 -0
  239. package/src/tools/agent-schedule-edit-tool.ts +210 -0
  240. package/src/tools/agent-schedule-tool.ts +282 -0
  241. package/src/tools/agent-security-tool.ts +145 -0
  242. package/src/tools/agent-sessions-tool.ts +122 -0
  243. package/src/tools/agent-settings-import-tool.ts +104 -0
  244. package/src/tools/agent-settings-tool.ts +176 -0
  245. package/src/tools/agent-setup-tool.ts +226 -0
  246. package/src/tools/agent-support-tool.ts +122 -0
  247. package/src/tools/agent-terminal-process-tools.ts +167 -0
  248. package/src/tools/agent-tool-policy-guard-types.ts +77 -0
  249. package/src/tools/agent-tool-policy-guard.ts +110 -89
  250. package/src/tools/agent-vibe-tool.ts +297 -0
  251. package/src/tools/agent-work-plan-tool.ts +265 -6
  252. package/src/tools/agent-workspace-tool.ts +305 -0
  253. package/src/tools/artifact-archive.ts +169 -0
  254. package/src/tools/tool-definition-compaction.ts +36 -0
  255. package/src/tools/tool-execution-safety.ts +41 -0
  256. package/src/version.ts +1 -1
@@ -0,0 +1,671 @@
1
+ import type { CommandContext } from '../input/command-registry.ts';
2
+ import { AGENT_WORKSPACE_CATEGORIES } from '../input/agent-workspace-categories.ts';
3
+ import { buildAgentWorkspaceRuntimeSnapshot } from '../input/agent-workspace-snapshot.ts';
4
+ import type { AgentWorkspaceReviewPacketWizard, AgentWorkspaceReviewPacketWizardStep } from '../input/agent-workspace-types.ts';
5
+ import { previewHarnessText } from './agent-harness-text.ts';
6
+ import { buildReviewerReadinessChecklist } from './agent-harness-document-ops-reviewer-readiness.ts';
7
+ import type {
8
+ AgentHarnessDocumentOpsArgs,
9
+ DocumentOpsLane,
10
+ DocumentOpsLaneId,
11
+ DocumentOpsLaneResolution,
12
+ DocumentOpsStatus,
13
+ ReviewerReadinessCheck,
14
+ ReviewerReadinessChecklist,
15
+ } from './agent-harness-document-ops-types.ts';
16
+ export type {
17
+ DocumentOpsLaneId,
18
+ DocumentOpsLaneResolution,
19
+ } from './agent-harness-document-ops-types.ts';
20
+
21
+ const LANE_IDS: readonly DocumentOpsLaneId[] = [
22
+ 'documents',
23
+ 'uploads',
24
+ 'exports',
25
+ 'reviewer_readiness',
26
+ 'review_packet_timeline',
27
+ 'review_packet_wizard',
28
+ 'source_library',
29
+ 'media_artifacts',
30
+ 'artifact_browser',
31
+ 'model_compare',
32
+ ];
33
+
34
+ function readString(value: unknown): string {
35
+ return typeof value === 'string' ? value.trim() : '';
36
+ }
37
+
38
+ function workspaceActionIds(): ReadonlySet<string> {
39
+ return new Set(AGENT_WORKSPACE_CATEGORIES.flatMap((category) => category.actions.map((action) => action.id)));
40
+ }
41
+
42
+ function existingActions(ids: readonly string[], available: ReadonlySet<string>): readonly string[] {
43
+ return ids.filter((id) => available.has(id));
44
+ }
45
+
46
+ function hasTool(context: CommandContext, toolName: string): boolean {
47
+ return context.extensions.toolRegistry.has(toolName);
48
+ }
49
+
50
+ function statusRank(status: DocumentOpsStatus): number {
51
+ if (status === 'attention') return 5;
52
+ if (status === 'ready') return 4;
53
+ if (status === 'partial') return 3;
54
+ if (status === 'needs-setup') return 2;
55
+ return 1;
56
+ }
57
+
58
+ function searchText(lane: DocumentOpsLane): string {
59
+ return [
60
+ lane.id,
61
+ lane.label,
62
+ lane.status,
63
+ lane.outcome,
64
+ lane.current,
65
+ lane.next,
66
+ lane.userRoute,
67
+ lane.modelRoute,
68
+ lane.signals.join('\n'),
69
+ lane.actionIds.join('\n'),
70
+ lane.reviewPacketWizard ? [
71
+ lane.reviewPacketWizard.status,
72
+ lane.reviewPacketWizard.next,
73
+ lane.reviewPacketWizard.finalReview,
74
+ lane.reviewPacketWizard.steps.map((step) => [
75
+ step.id,
76
+ step.label,
77
+ step.status,
78
+ step.detail,
79
+ step.userRoute,
80
+ step.modelRoute,
81
+ step.backtrackRoute ?? '',
82
+ ].join(' ')).join('\n'),
83
+ ].join('\n') : '',
84
+ lane.reviewerReadiness ? [
85
+ lane.reviewerReadiness.status,
86
+ lane.reviewerReadiness.next,
87
+ lane.reviewerReadiness.policy,
88
+ lane.reviewerReadiness.checks.map((check) => [
89
+ check.id,
90
+ check.label,
91
+ check.status,
92
+ check.detail,
93
+ check.inspectRoute,
94
+ check.repairRoute ?? '',
95
+ ].join(' ')).join('\n'),
96
+ ].join('\n') : '',
97
+ ].join('\n').toLowerCase();
98
+ }
99
+
100
+ function describeReviewerReadinessCheck(check: ReviewerReadinessCheck, includeParameters: boolean): Record<string, unknown> {
101
+ return {
102
+ id: check.id,
103
+ label: check.label,
104
+ status: check.status,
105
+ count: check.count,
106
+ detail: previewHarnessText(check.detail, includeParameters ? 180 : 96),
107
+ inspectRoute: previewHarnessText(check.inspectRoute, includeParameters ? 180 : 96),
108
+ ...(check.repairRoute ? { repairRoute: previewHarnessText(check.repairRoute, includeParameters ? 240 : 120) } : {}),
109
+ };
110
+ }
111
+
112
+ function describeReviewerReadiness(checklist: ReviewerReadinessChecklist, includeParameters: boolean): Record<string, unknown> {
113
+ return {
114
+ status: checklist.status,
115
+ next: previewHarnessText(checklist.next, includeParameters ? 220 : 120),
116
+ summary: checklist.summary,
117
+ checks: checklist.checks
118
+ .slice(0, includeParameters ? checklist.checks.length : 4)
119
+ .map((check) => describeReviewerReadinessCheck(check, includeParameters)),
120
+ policy: previewHarnessText(checklist.policy, includeParameters ? 220 : 120),
121
+ };
122
+ }
123
+
124
+ function describeReviewPacketWizardStep(step: AgentWorkspaceReviewPacketWizardStep, includeParameters: boolean): Record<string, unknown> {
125
+ return {
126
+ id: step.id,
127
+ label: step.label,
128
+ status: step.status,
129
+ detail: previewHarnessText(step.detail, includeParameters ? 180 : 96),
130
+ userRoute: previewHarnessText(step.userRoute, includeParameters ? 180 : 96),
131
+ modelRoute: previewHarnessText(step.modelRoute, includeParameters ? 220 : 120),
132
+ actionId: step.actionId,
133
+ ...(step.backtrackRoute ? { backtrackRoute: previewHarnessText(step.backtrackRoute, includeParameters ? 220 : 120) } : {}),
134
+ };
135
+ }
136
+
137
+ function describeReviewPacketPresetLineage(
138
+ lineage: AgentWorkspaceReviewPacketWizard['presetLineage'],
139
+ includeParameters: boolean,
140
+ ): Record<string, unknown> | null {
141
+ if (!lineage) return null;
142
+ return {
143
+ artifactId: lineage.artifactId,
144
+ presetId: lineage.presetId,
145
+ name: lineage.name,
146
+ refreshed: lineage.refreshed,
147
+ refreshedFromArtifactId: lineage.refreshedFromArtifactId,
148
+ refreshedFromPresetId: lineage.refreshedFromPresetId,
149
+ freshnessMissingCount: lineage.freshnessMissingCount,
150
+ freshnessSupersededCount: lineage.freshnessSupersededCount,
151
+ freshnessUnresolvedCount: lineage.freshnessUnresolvedCount,
152
+ summary: previewHarnessText(lineage.summary, includeParameters ? 220 : 120),
153
+ inspectRoute: previewHarnessText(lineage.inspectRoute, includeParameters ? 220 : 120),
154
+ };
155
+ }
156
+
157
+ function describeReviewPacketWizard(wizard: AgentWorkspaceReviewPacketWizard, includeParameters: boolean): Record<string, unknown> {
158
+ const presetLineage = describeReviewPacketPresetLineage(wizard.presetLineage, includeParameters);
159
+ return {
160
+ status: wizard.status,
161
+ progress: `${wizard.completedSteps}/${wizard.totalSteps}`,
162
+ completedSteps: wizard.completedSteps,
163
+ totalSteps: wizard.totalSteps,
164
+ currentStepId: wizard.currentStepId,
165
+ currentStepLabel: wizard.currentStepLabel,
166
+ next: previewHarnessText(wizard.next, includeParameters ? 240 : 120),
167
+ finalReview: previewHarnessText(wizard.finalReview, includeParameters ? 220 : 120),
168
+ ...(presetLineage ? { presetLineage } : {}),
169
+ steps: wizard.steps
170
+ .slice(0, includeParameters ? wizard.steps.length : 4)
171
+ .map((step) => describeReviewPacketWizardStep(step, includeParameters)),
172
+ policy: 'The review packet wizard is read-only. It guides the user through existing document, comparison, handoff, route-decision, archive, and share routes; every write or external delivery still requires the owning confirmed action.',
173
+ };
174
+ }
175
+
176
+ function describeLane(lane: DocumentOpsLane, includeParameters: boolean): Record<string, unknown> {
177
+ return {
178
+ id: lane.id,
179
+ label: lane.label,
180
+ status: lane.status,
181
+ outcome: lane.outcome,
182
+ current: lane.current,
183
+ next: lane.next,
184
+ userRoute: previewHarnessText(lane.userRoute, 96),
185
+ modelRoute: previewHarnessText(lane.modelRoute, 96),
186
+ signals: lane.signals,
187
+ ...(lane.reviewerReadiness ? { reviewerReadiness: describeReviewerReadiness(lane.reviewerReadiness, includeParameters) } : {}),
188
+ ...(lane.reviewPacketWizard ? { reviewPacketWizard: describeReviewPacketWizard(lane.reviewPacketWizard, includeParameters) } : {}),
189
+ ...(includeParameters ? {
190
+ routes: {
191
+ user: lane.userRoute,
192
+ model: lane.modelRoute,
193
+ },
194
+ actionIds: lane.actionIds,
195
+ safety: 'Document writes, file ingest, export, media generation, model comparison, and model changes stay explicit user-visible actions. Blind model comparison spends tokens only through confirmed agent_model_compare runs.',
196
+ } : {}),
197
+ };
198
+ }
199
+
200
+ function buildLanes(context: CommandContext): readonly DocumentOpsLane[] {
201
+ const snapshot = buildAgentWorkspaceRuntimeSnapshot(context);
202
+ const available = workspaceActionIds();
203
+ const documentActions = existingActions([
204
+ 'document-browse-drafts',
205
+ 'document-show-draft',
206
+ 'document-create-draft',
207
+ 'document-revise-draft',
208
+ 'document-review-draft',
209
+ 'document-comment-draft',
210
+ 'document-resolve-comment',
211
+ 'document-suggest-draft',
212
+ 'document-accept-suggestion',
213
+ 'document-reject-suggestion',
214
+ 'document-insert-artifact',
215
+ 'document-attach-artifact',
216
+ 'document-review-packet-timeline',
217
+ 'document-review-packet-wizard',
218
+ 'document-save-review-packet-preset',
219
+ 'document-refresh-review-packet-preset',
220
+ 'document-reviewer-readiness',
221
+ 'document-export-draft',
222
+ 'document-draft-chat',
223
+ ], available);
224
+ const uploadActions = existingActions([
225
+ 'artifact-attach-image',
226
+ 'artifact-paste',
227
+ 'artifact-ingest-file',
228
+ 'artifact-ingest-url-list',
229
+ 'artifact-import-bookmarks',
230
+ 'artifact-browser-history',
231
+ 'document-attach-image',
232
+ 'document-paste',
233
+ 'document-ingest-file',
234
+ ], available);
235
+ const exportActions = existingActions([
236
+ 'artifact-export-conversation',
237
+ 'artifact-session-export',
238
+ 'conversation-export-current',
239
+ 'conversation-session-export',
240
+ 'document-export-draft',
241
+ 'document-export-artifact-file',
242
+ 'document-export-artifact-package',
243
+ 'document-export-conversation',
244
+ 'document-export-session',
245
+ 'artifact-export-file',
246
+ 'artifact-export-package',
247
+ ], available);
248
+ const sourceActions = existingActions([
249
+ 'artifact-source-library',
250
+ 'artifact-show-source',
251
+ 'research-knowledge-search',
252
+ 'research-knowledge-ask',
253
+ 'document-sources',
254
+ 'document-show-source',
255
+ ], available);
256
+ const mediaActions = existingActions([
257
+ 'artifact-media-providers',
258
+ 'artifact-generate-media',
259
+ 'media-providers',
260
+ 'media-generate',
261
+ 'document-media-providers',
262
+ 'document-generate-media',
263
+ ], available);
264
+ const artifactBrowserActions = existingActions([
265
+ 'document-browse-artifacts',
266
+ 'document-show-artifact',
267
+ 'document-export-artifact-file',
268
+ 'document-export-artifact-package',
269
+ 'document-promote-artifact',
270
+ 'artifact-browse',
271
+ 'artifact-show',
272
+ 'artifact-export-file',
273
+ 'artifact-export-package',
274
+ 'artifact-promote-knowledge',
275
+ 'artifact-insert-document',
276
+ 'artifact-attach-document',
277
+ 'document-artifacts',
278
+ 'artifact-flow',
279
+ 'artifact-show-source',
280
+ ], available);
281
+ const modelCompareActions = existingActions([
282
+ 'document-run-compare',
283
+ 'document-review-compare',
284
+ 'document-diff-handoffs',
285
+ 'document-judge-compare',
286
+ 'document-compare-analytics',
287
+ 'document-apply-compare',
288
+ 'document-record-route-decision',
289
+ 'document-export-compare',
290
+ 'artifact-review-compare',
291
+ 'artifact-diff-handoffs',
292
+ 'artifact-judge-compare',
293
+ 'artifact-compare-analytics',
294
+ 'artifact-apply-compare',
295
+ 'artifact-export-compare',
296
+ 'document-model-routing',
297
+ 'account-main-model',
298
+ ], available);
299
+ const modelCompareReady = hasTool(context, 'agent_model_compare') && modelCompareActions.includes('document-run-compare');
300
+ const documentsReady = hasTool(context, 'agent_documents')
301
+ && documentActions.includes('document-browse-drafts')
302
+ && documentActions.includes('document-show-draft')
303
+ && documentActions.includes('document-create-draft')
304
+ && documentActions.includes('document-revise-draft')
305
+ && documentActions.includes('document-comment-draft')
306
+ && documentActions.includes('document-resolve-comment')
307
+ && documentActions.includes('document-suggest-draft')
308
+ && documentActions.includes('document-accept-suggestion')
309
+ && documentActions.includes('document-reject-suggestion')
310
+ && documentActions.includes('document-insert-artifact')
311
+ && documentActions.includes('document-attach-artifact')
312
+ && documentActions.includes('document-export-draft');
313
+ const artifactBrowserReady = hasTool(context, 'agent_artifacts')
314
+ && hasTool(context, 'agent_knowledge_ingest')
315
+ && Boolean(context.platform.artifactStore?.list)
316
+ && Boolean(context.platform.artifactStore?.readContent)
317
+ && artifactBrowserActions.includes('artifact-browse')
318
+ && artifactBrowserActions.includes('artifact-show')
319
+ && artifactBrowserActions.includes('artifact-export-file')
320
+ && artifactBrowserActions.includes('artifact-export-package')
321
+ && artifactBrowserActions.includes('artifact-promote-knowledge');
322
+ const reviewerReadiness = buildReviewerReadinessChecklist(context, {
323
+ documentsReady,
324
+ modelCompareReady,
325
+ artifactBrowserReady,
326
+ });
327
+
328
+ return [
329
+ {
330
+ id: 'documents',
331
+ label: 'Documents',
332
+ status: documentsReady ? 'ready' : 'partial',
333
+ outcome: 'Draft, revise, and export user-facing documents without leaving the Agent conversation.',
334
+ current: documentsReady
335
+ ? 'Agent has project-scoped markdown document drafts with version history, review status, review comments, AI suggestion review, read-only inspection, confirmed artifact attachment, confirmed artifact insertion, and confirmed artifact export with reviewer-ready comment and suggestion appendices.'
336
+ : 'Agent can draft and revise documents in the main conversation and export transcript/session artifacts, but the dedicated markdown draft tool is not fully wired.',
337
+ next: documentsReady
338
+ ? 'Use versioned drafts, comments, suggestions, artifact reuse, artifact packages or ZIP archives, and artifact-backed comparison as one document workflow.'
339
+ : 'Wire agent_documents plus browse/show/create/revise/review/export workspace actions.',
340
+ userRoute: 'Agent Workspace -> Documents & Compare -> Create document draft',
341
+ modelRoute: documentsReady ? 'agent_documents' : 'agent_harness mode:"workspace_actions" categoryId:"documents"',
342
+ signals: [
343
+ `Chat route ${snapshot.provider} / ${snapshot.modelDisplayName}`,
344
+ `Document draft tool: ${hasTool(context, 'agent_documents') ? 'available' : 'gap'}`,
345
+ `${documentActions.length} document draft action(s)`,
346
+ `${exportActions.length} export action(s) available`,
347
+ documentsReady ? 'Versioned markdown drafts: available' : 'Versioned markdown drafts: gap',
348
+ documentActions.includes('document-comment-draft') ? 'Review comments: available' : 'Review comments: gap',
349
+ documentActions.includes('document-suggest-draft') ? 'AI suggestion review: available' : 'AI suggestion review: not wired',
350
+ documentActions.includes('document-attach-artifact') ? 'Artifact-to-document attachment: available' : 'Artifact-to-document attachment: gap',
351
+ documentActions.includes('document-insert-artifact') ? 'Artifact-to-document insert: available' : 'Artifact-to-document insert: gap',
352
+ documentActions.includes('document-save-review-packet-preset') ? 'Review packet presets: available' : 'Review packet presets: gap',
353
+ documentActions.includes('document-refresh-review-packet-preset') ? 'Preset refresh: available' : 'Preset refresh: gap',
354
+ ],
355
+ actionIds: documentActions,
356
+ },
357
+ {
358
+ id: 'uploads',
359
+ label: 'Uploads',
360
+ status: uploadActions.length >= 4 ? 'ready' : uploadActions.length > 0 ? 'partial' : 'gap',
361
+ outcome: 'Attach, paste, or ingest files and URLs through explicit user-visible routes.',
362
+ current: `${uploadActions.length} upload/ingest action(s) are reachable from the workspace.`,
363
+ next: uploadActions.length > 0
364
+ ? 'Use attach, paste, or reviewed source ingest depending on whether the file is prompt context or durable Agent Knowledge.'
365
+ : 'Wire upload, paste, and file ingest actions before exposing this as ready.',
366
+ userRoute: 'Agent Workspace -> Documents & Compare -> Attach or ingest',
367
+ modelRoute: 'agent_harness mode:"workspace_actions" query:"upload file ingest"',
368
+ signals: [
369
+ `${uploadActions.length} upload/ingest action(s)`,
370
+ `Artifact max ${Math.round(snapshot.artifactMaxBytes / (1024 * 1024))} MB`,
371
+ ],
372
+ actionIds: uploadActions,
373
+ },
374
+ {
375
+ id: 'exports',
376
+ label: 'Exports',
377
+ status: exportActions.length >= 2 ? 'ready' : exportActions.length > 0 ? 'partial' : 'gap',
378
+ outcome: 'Turn conversations, sessions, documents, and saved artifacts into local files the user can keep or reuse.',
379
+ current: `${exportActions.length} export action(s) are reachable for conversation, session, document, comparison, and saved artifact output.`,
380
+ next: 'Keep transcript, session, document, comparison, and artifact exports visible, explicit, and reusable from one place.',
381
+ userRoute: 'Agent Workspace -> Documents & Compare -> Export',
382
+ modelRoute: 'agent_harness mode:"workspace_actions" query:"export artifact"',
383
+ signals: [
384
+ `${exportActions.length} export action(s)`,
385
+ `Session ${snapshot.sessionId}`,
386
+ ],
387
+ actionIds: exportActions,
388
+ },
389
+ {
390
+ id: 'reviewer_readiness',
391
+ label: 'Reviewer Readiness',
392
+ status: reviewerReadiness.status === 'ready' ? 'ready' : reviewerReadiness.status === 'attention' ? 'attention' : 'needs-setup',
393
+ outcome: 'Know what must be resolved before exporting, handing off, archiving, or applying comparison-backed route changes.',
394
+ current: `${reviewerReadiness.summary.documents} document draft(s), ${reviewerReadiness.summary.openComments} open comment(s), ${reviewerReadiness.summary.proposedSuggestions} proposed suggestion(s), ${reviewerReadiness.summary.savedComparisons} saved comparison(s), ${reviewerReadiness.summary.revealedJudgments} revealed judgment(s).`,
395
+ next: reviewerReadiness.next,
396
+ userRoute: 'Agent Workspace -> Documents & Compare -> Review readiness preflight',
397
+ modelRoute: 'agent_harness mode:"document_ops_lane" laneId:"reviewer_readiness"',
398
+ signals: [
399
+ `Reviewer readiness ${reviewerReadiness.status}`,
400
+ `Open comments ${reviewerReadiness.summary.openComments}`,
401
+ `Proposed suggestions ${reviewerReadiness.summary.proposedSuggestions}`,
402
+ `Missing source artifacts ${reviewerReadiness.summary.documentsMissingSourceArtifacts}`,
403
+ `Unrevealed comparisons ${reviewerReadiness.summary.unrevealedComparisons}`,
404
+ `Hidden judgments ${reviewerReadiness.summary.hiddenJudgments}`,
405
+ `Route decisions ${reviewerReadiness.summary.revealedJudgments}`,
406
+ `Handoffs missing related evidence ${reviewerReadiness.summary.handoffsMissingRelatedArtifacts}`,
407
+ ],
408
+ actionIds: [
409
+ ...documentActions.filter((id) => [
410
+ 'document-show-draft',
411
+ 'document-reviewer-readiness',
412
+ 'document-resolve-comment',
413
+ 'document-accept-suggestion',
414
+ 'document-reject-suggestion',
415
+ 'document-attach-artifact',
416
+ 'document-export-draft',
417
+ ].includes(id)),
418
+ ...modelCompareActions.filter((id) => [
419
+ 'document-review-compare',
420
+ 'document-diff-handoffs',
421
+ 'document-judge-compare',
422
+ 'document-apply-compare',
423
+ 'document-export-compare',
424
+ ].includes(id)),
425
+ ...artifactBrowserActions.filter((id) => [
426
+ 'artifact-browse',
427
+ 'artifact-show',
428
+ 'artifact-export-package',
429
+ ].includes(id)),
430
+ ],
431
+ reviewerReadiness,
432
+ },
433
+ {
434
+ id: 'review_packet_timeline',
435
+ label: 'Review Packet Timeline',
436
+ status: !snapshot.reviewPacketTimeline.available
437
+ ? 'needs-setup'
438
+ : snapshot.reviewPacketTimeline.items.some((event) => event.status === 'attention')
439
+ ? 'attention'
440
+ : snapshot.reviewPacketTimeline.count > 0
441
+ ? 'ready'
442
+ : 'partial',
443
+ outcome: 'Scan one chronological packet history across document review, source evidence, blind comparisons, judgments, handoffs, archives, and route decisions.',
444
+ current: snapshot.reviewPacketTimeline.items[0]
445
+ ? `${snapshot.reviewPacketTimeline.count} packet event(s); latest ${snapshot.reviewPacketTimeline.items[0].label}.`
446
+ : 'No document, artifact, comparison, judgment, handoff, archive, or route-decision packet events are available yet.',
447
+ next: snapshot.reviewPacketTimeline.next,
448
+ userRoute: 'Agent Workspace -> Documents & Compare -> Review packet timeline',
449
+ modelRoute: 'agent_harness mode:"document_ops_lane" laneId:"review_packet_timeline"',
450
+ signals: [
451
+ `Timeline available ${snapshot.reviewPacketTimeline.available ? 'yes' : 'no'}`,
452
+ `Timeline events ${snapshot.reviewPacketTimeline.count}`,
453
+ ...snapshot.reviewPacketTimeline.items.slice(0, 5).map((event) => `${event.status}: ${event.kind} ${event.label} -> ${event.route}`),
454
+ ],
455
+ actionIds: [
456
+ ...documentActions.filter((id) => [
457
+ 'document-review-packet-timeline',
458
+ 'document-show-draft',
459
+ 'document-reviewer-readiness',
460
+ 'document-resolve-comment',
461
+ 'document-accept-suggestion',
462
+ 'document-reject-suggestion',
463
+ 'document-attach-artifact',
464
+ 'document-export-draft',
465
+ ].includes(id)),
466
+ ...modelCompareActions.filter((id) => [
467
+ 'document-review-compare',
468
+ 'document-diff-handoffs',
469
+ 'document-judge-compare',
470
+ 'document-apply-compare',
471
+ 'document-export-compare',
472
+ ].includes(id)),
473
+ ...artifactBrowserActions.filter((id) => [
474
+ 'artifact-browse',
475
+ 'artifact-show',
476
+ 'artifact-export-package',
477
+ ].includes(id)),
478
+ ],
479
+ },
480
+ {
481
+ id: 'review_packet_wizard',
482
+ label: 'Review Packet Wizard',
483
+ status: snapshot.reviewPacketWizard.status === 'complete'
484
+ ? 'ready'
485
+ : snapshot.reviewPacketWizard.status === 'blocked'
486
+ ? 'needs-setup'
487
+ : snapshot.reviewPacketWizard.status === 'empty'
488
+ ? 'partial'
489
+ : 'attention',
490
+ outcome: 'Carry one reviewer packet through draft review, document export, comparison judgment, reviewer handoff, route decision, and final archive review without re-entering ids.',
491
+ current: snapshot.reviewPacketWizard.currentStepLabel
492
+ ? `${snapshot.reviewPacketWizard.completedSteps}/${snapshot.reviewPacketWizard.totalSteps} step(s) complete; current ${snapshot.reviewPacketWizard.currentStepLabel}.`
493
+ : `${snapshot.reviewPacketWizard.completedSteps}/${snapshot.reviewPacketWizard.totalSteps} step(s) complete.`,
494
+ next: snapshot.reviewPacketWizard.next,
495
+ userRoute: 'Agent Workspace -> Documents & Compare -> Review packet wizard',
496
+ modelRoute: 'agent_harness mode:"document_ops_lane" laneId:"review_packet_wizard"',
497
+ signals: [
498
+ `Wizard status ${snapshot.reviewPacketWizard.status}`,
499
+ `Wizard progress ${snapshot.reviewPacketWizard.completedSteps}/${snapshot.reviewPacketWizard.totalSteps}`,
500
+ `Current step ${snapshot.reviewPacketWizard.currentStepLabel ?? 'none'}`,
501
+ `Final review ${snapshot.reviewPacketWizard.finalReview}`,
502
+ ...snapshot.reviewPacketWizard.steps.map((step) => `${step.status}: ${step.label} -> ${step.modelRoute}`),
503
+ ],
504
+ actionIds: existingActions([
505
+ 'document-review-packet-wizard',
506
+ 'document-share-review-packet',
507
+ 'document-record-route-decision',
508
+ ...snapshot.reviewPacketWizard.steps.map((step) => step.actionId),
509
+ ], available),
510
+ reviewPacketWizard: snapshot.reviewPacketWizard,
511
+ },
512
+ {
513
+ id: 'source_library',
514
+ label: 'Sources',
515
+ status: sourceActions.length >= 2 ? 'ready' : sourceActions.length > 0 ? 'partial' : 'gap',
516
+ outcome: 'Inspect source-backed records before citing, summarizing, or promoting knowledge.',
517
+ current: `${sourceActions.length} source lookup/search action(s) are reachable through isolated Agent Knowledge.`,
518
+ next: 'Use source search/show for citation checks; ingest reviewed files or URLs only through explicit source actions.',
519
+ userRoute: 'Agent Workspace -> Documents & Compare -> Sources',
520
+ modelRoute: 'agent_harness mode:"workspace_actions" query:"Agent Knowledge sources"',
521
+ signals: [
522
+ `Knowledge route ${snapshot.knowledgeRoute}`,
523
+ `Knowledge isolation ${snapshot.knowledgeIsolation}`,
524
+ ],
525
+ actionIds: sourceActions,
526
+ },
527
+ {
528
+ id: 'media_artifacts',
529
+ label: 'Media Artifacts',
530
+ status: snapshot.mediaGenerationProviderCount > 0 ? 'ready' : mediaActions.length > 0 ? 'needs-setup' : 'gap',
531
+ outcome: 'Generate image or video artifacts through configured providers and keep generated bytes out of the transcript.',
532
+ current: `${snapshot.voiceMediaReadiness.readyMediaProviderCount}/${snapshot.mediaProviderCount} media provider(s) ready; ${snapshot.mediaGenerationProviderCount} generation provider(s).`,
533
+ next: snapshot.mediaGenerationProviderCount > 0
534
+ ? 'Use confirmed media generation when the user asks for a concrete artifact.'
535
+ : 'Configure a media generation provider before claiming generated media is ready.',
536
+ userRoute: 'Agent Workspace -> Documents & Compare -> Generate media',
537
+ modelRoute: 'agent_media_generate',
538
+ signals: [
539
+ `${mediaActions.length} media action(s)`,
540
+ `${snapshot.mediaGenerationProviderCount} generation provider(s)`,
541
+ ],
542
+ actionIds: mediaActions,
543
+ },
544
+ {
545
+ id: 'artifact_browser',
546
+ label: 'Artifact Browser',
547
+ status: artifactBrowserReady ? 'ready' : artifactBrowserActions.length > 0 ? 'partial' : 'gap',
548
+ outcome: 'Find and reuse uploaded, exported, generated, and source-backed artifacts from one place.',
549
+ current: artifactBrowserReady
550
+ ? 'Agent has a unified artifact browser with filters, redacted metadata, bounded text previews, confirmed artifact export-to-file, confirmed multi-artifact package export and ZIP archive export, confirmed artifact-to-Knowledge promotion, confirmed artifact-to-document attachment, and confirmed artifact-to-document insertion over the SDK artifact store.'
551
+ : 'Artifacts are real and visible in transcript, source, session, and media routes, but the unified browser is not fully wired in this runtime.',
552
+ next: artifactBrowserReady
553
+ ? 'Use package or ZIP archive exports across document, upload, generated media, session, comparison, and Knowledge artifacts.'
554
+ : 'Wire agent_artifacts and browse/show workspace actions over the SDK artifact store.',
555
+ userRoute: 'Agent Workspace -> Artifacts -> Browse artifacts, Export package, or Promote to Knowledge',
556
+ modelRoute: artifactBrowserReady ? 'agent_artifacts + agent_knowledge_ingest' : 'agent_harness mode:"workspace_actions" categoryId:"artifacts"',
557
+ signals: [
558
+ `${uploadActions.length + exportActions.length + mediaActions.length} related artifact action(s)`,
559
+ `Artifact browser tool: ${hasTool(context, 'agent_artifacts') ? 'available' : 'gap'}`,
560
+ `Knowledge ingest tool: ${hasTool(context, 'agent_knowledge_ingest') ? 'available' : 'gap'}`,
561
+ `Artifact list/read store: ${context.platform.artifactStore?.list && context.platform.artifactStore?.readContent ? 'available' : 'gap'}`,
562
+ `Artifact export action: ${artifactBrowserActions.includes('artifact-export-file') ? 'available' : 'gap'}`,
563
+ `Artifact package export action: ${artifactBrowserActions.includes('artifact-export-package') ? 'available' : 'gap'}`,
564
+ `Knowledge promotion action: ${artifactBrowserActions.includes('artifact-promote-knowledge') ? 'available' : 'gap'}`,
565
+ `Document attachment action: ${artifactBrowserActions.includes('artifact-attach-document') ? 'available' : 'gap'}`,
566
+ `Document insertion action: ${artifactBrowserActions.includes('artifact-insert-document') ? 'available' : 'gap'}`,
567
+ ],
568
+ actionIds: artifactBrowserActions,
569
+ },
570
+ {
571
+ id: 'model_compare',
572
+ label: 'Blind Model Compare',
573
+ status: modelCompareReady ? 'partial' : 'gap',
574
+ outcome: 'Run the same prompt across multiple models, hide model identities while judging, save a judgment, then apply the revealed winner or record leave-unchanged evidence only after confirmation.',
575
+ current: modelCompareReady
576
+ ? 'Agent has a confirmed blind comparison runner with selectable or auto-selected candidates, identical prompt or saved text artifact delivery, rubric capture, delayed reveal, durable JSON comparison artifacts, read-only saved review boards, side-by-side reviewer views, visual reviewer handoff diffs, confirmed saved judgment artifacts, task/document/benchmark-filtered preference analytics/synthesis, markdown report export, reviewer handoff artifacts, one-click reviewer handoff ZIP archives with source and matching route-decision receipt evidence, separate confirmed winner route updates, and leave-unchanged route-decision receipts.'
577
+ : 'Model routing and model catalog inspection exist, but Agent does not have a blind side-by-side comparison runner or saved comparison artifacts.',
578
+ next: modelCompareReady
579
+ ? 'Use cross-session synthesis and reviewer handoff ZIP archives around saved comparison, judgment, export, route-update, route-decision receipt, and source-artifact reuse artifacts.'
580
+ : 'Implement a blind compare runner with selectable candidate models, identical prompt/context, rubric capture, delayed reveal, export, and route update handoff.',
581
+ userRoute: 'Agent Workspace -> Documents & Compare -> Run blind compare',
582
+ modelRoute: modelCompareReady ? 'agent_model_compare' : 'models action:"status"',
583
+ signals: [
584
+ `Current model ${snapshot.provider} / ${snapshot.modelDisplayName}`,
585
+ `Blind compare runner: ${modelCompareReady ? 'available' : 'gap'}`,
586
+ `Saved comparison artifact: ${modelCompareReady && context.platform.artifactStore ? 'available' : 'gap'}`,
587
+ `Artifact-to-compare reuse: ${modelCompareActions.includes('document-run-compare') ? 'available' : 'gap'}`,
588
+ `Saved review board/side-by-side/handoff diff view: ${modelCompareActions.includes('document-review-compare') && modelCompareActions.includes('document-diff-handoffs') ? 'available' : 'gap'}`,
589
+ `Saved judgment artifact: ${modelCompareActions.includes('document-judge-compare') ? 'available' : 'gap'}`,
590
+ `Saved preference analytics/synthesis with task/document/benchmark filters: ${modelCompareActions.includes('document-compare-analytics') ? 'available' : 'gap'}`,
591
+ `Winner route update: ${modelCompareActions.includes('document-apply-compare') ? 'available' : 'gap'}`,
592
+ `Leave-unchanged route receipt: ${modelCompareActions.includes('document-record-route-decision') ? 'available' : 'gap'}`,
593
+ `Markdown export/handoff/archive: ${modelCompareActions.includes('document-export-compare') ? 'available' : 'gap'}`,
594
+ ],
595
+ actionIds: modelCompareActions,
596
+ },
597
+ ];
598
+ }
599
+
600
+ function nextActions(lanes: readonly DocumentOpsLane[]): readonly string[] {
601
+ const urgent = lanes
602
+ .filter((lane) => lane.status === 'gap' || lane.status === 'needs-setup' || lane.status === 'attention')
603
+ .map((lane) => `${lane.label}: ${lane.next}`);
604
+ const partial = lanes
605
+ .filter((lane) => lane.status === 'partial')
606
+ .map((lane) => `${lane.label}: ${lane.next}`);
607
+ return [...urgent, ...partial].slice(0, 5);
608
+ }
609
+
610
+ export function documentOpsCatalogStatus(context: CommandContext): Record<string, unknown> {
611
+ const lanes = buildLanes(context);
612
+ const counts = lanes.reduce<Record<DocumentOpsStatus, number>>((acc, lane) => {
613
+ acc[lane.status] += 1;
614
+ return acc;
615
+ }, { ready: 0, attention: 0, partial: 0, 'needs-setup': 0, gap: 0 });
616
+ return {
617
+ modes: ['document_ops', 'document_ops_lane'],
618
+ lanes: lanes.length,
619
+ ...counts,
620
+ bestReadyStatus: lanes.reduce((best, lane) => Math.max(best, statusRank(lane.status)), 0),
621
+ };
622
+ }
623
+
624
+ export function documentOpsSummary(context: CommandContext, args: AgentHarnessDocumentOpsArgs): Record<string, unknown> {
625
+ const includeParameters = args.includeParameters === true;
626
+ const lanes = buildLanes(context);
627
+ const reviewerReadiness = lanes.find((lane) => lane.id === 'reviewer_readiness')?.reviewerReadiness;
628
+ return {
629
+ lanes: lanes.map((lane) => describeLane(lane, includeParameters)),
630
+ returned: lanes.length,
631
+ total: lanes.length,
632
+ ...(reviewerReadiness ? { reviewerReadiness: describeReviewerReadiness(reviewerReadiness, includeParameters) } : {}),
633
+ policy: 'Document Ops unifies versioned document drafts, chronological review packet timelines, guided review packet wizard progress, reviewer-readiness checks, review comments, AI suggestion review, uploads, exports, sources, media artifacts, artifact browsing, artifact-to-Knowledge promotion, and model comparison.',
634
+ nextActions: nextActions(lanes),
635
+ };
636
+ }
637
+
638
+ export function describeDocumentOpsLane(context: CommandContext, args: AgentHarnessDocumentOpsArgs): DocumentOpsLaneResolution {
639
+ const laneId = readString(args.laneId);
640
+ const target = readString(args.target);
641
+ const query = readString(args.query);
642
+ const input = laneId || target || query;
643
+ if (!input) {
644
+ return {
645
+ status: 'missing_lookup',
646
+ usage: `document_ops_lane requires laneId, target, or query. Lane ids: ${LANE_IDS.join(', ')}.`,
647
+ };
648
+ }
649
+ const normalized = input.toLowerCase();
650
+ const lanes = buildLanes(context);
651
+ const exact = lanes.find((lane) => lane.id === normalized);
652
+ if (exact) return { status: 'found', lane: describeLane(exact, true) };
653
+ const matches = lanes.filter((lane) => searchText(lane).includes(normalized));
654
+ if (matches.length === 1) return { status: 'found', lane: describeLane(matches[0]!, true) };
655
+ if (matches.length > 1) {
656
+ return {
657
+ status: 'ambiguous',
658
+ input,
659
+ candidates: matches.map((lane) => ({
660
+ laneId: lane.id,
661
+ label: lane.label,
662
+ status: lane.status,
663
+ modelRoute: lane.modelRoute,
664
+ })),
665
+ };
666
+ }
667
+ return {
668
+ status: 'missing_lookup',
669
+ usage: `Unknown Document Ops lane ${input}. Lane ids: ${LANE_IDS.join(', ')}.`,
670
+ };
671
+ }