@pellux/goodvibes-agent 1.1.7 → 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 (255) hide show
  1. package/CHANGELOG.md +170 -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 +132577 -91483
  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 +39 -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 +199 -5
  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 +137 -7
  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 +106 -85
  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/version.ts +1 -1
@@ -0,0 +1,557 @@
1
+ import type { OnboardingStep1CapabilityItem } from '../runtime/onboarding/index.ts';
2
+ import type { AgentSetupWizard } from '../agent/setup-wizard.ts';
3
+ import { DEFAULT_AGENT_SETUP_WIZARD_REVIEW_ROUTE } from '../agent/setup-wizard.ts';
4
+ import { previewHarnessText } from './agent-harness-text.ts';
5
+ import { setupHandoffsForItem } from './agent-harness-setup-handoffs.ts';
6
+ import { collectSnapshot, lookupFromArgs, readLimit, safeIso, summarizeLocalBehavior } from './agent-harness-setup-posture-utils.ts';
7
+ import type { AgentHarnessSetupArgs, SetupHandoffCard, SetupPlanItem, SetupRepairCard, SetupRepairDecision, SetupServiceLifecycleDecision } from './agent-harness-setup-posture-types.ts';
8
+
9
+ export function planSearchText(item: SetupPlanItem): string {
10
+ return [
11
+ item.id,
12
+ item.label,
13
+ item.status,
14
+ item.reason,
15
+ item.nextAction,
16
+ item.userRoute,
17
+ item.modelRoute,
18
+ item.relatedSetupItemId ?? '',
19
+ item.signals?.join('\n') ?? '',
20
+ JSON.stringify(item.localModelReadiness ?? {}),
21
+ setupHandoffsForItem(item).map((handoff) => [
22
+ handoff.id,
23
+ handoff.label,
24
+ handoff.kind,
25
+ handoff.effect,
26
+ handoff.modelRoute,
27
+ handoff.userRoute,
28
+ handoff.nextStep,
29
+ handoff.safety,
30
+ handoff.prerequisite ?? '',
31
+ ].join(' ')).join('\n'),
32
+ item.repairCards?.map((card) => [
33
+ card.id,
34
+ card.label,
35
+ card.state,
36
+ card.effect,
37
+ card.methodId ?? '',
38
+ card.modelRoute ?? '',
39
+ card.prerequisite ?? '',
40
+ card.recommendation,
41
+ card.liveEvidence?.probeStatus ?? '',
42
+ card.liveEvidence?.summary ?? '',
43
+ card.recommendedWhen,
44
+ card.safety,
45
+ ].join(' ')).join('\n') ?? '',
46
+ JSON.stringify(item.serviceLifecycleDecision ?? {}),
47
+ JSON.stringify(item.serviceProbe ?? {}),
48
+ JSON.stringify(item.authPosture ?? {}),
49
+ JSON.stringify(item.installSmokePlan ?? {}),
50
+ JSON.stringify(item.sudoPosture ?? {}),
51
+ ].join('\n').toLowerCase();
52
+ }
53
+
54
+ export function describeRepairCard(card: SetupRepairCard): Record<string, unknown> {
55
+ return {
56
+ id: card.id,
57
+ label: card.label,
58
+ state: card.state,
59
+ effect: card.effect,
60
+ recommendation: card.recommendation,
61
+ ...(card.methodId ? { methodId: card.methodId } : {}),
62
+ ...(card.modelRoute ? { modelRoute: card.modelRoute } : {}),
63
+ userRoute: card.userRoute,
64
+ ...(card.prerequisite ? { prerequisite: previewHarnessText(card.prerequisite, 140) } : {}),
65
+ ...(card.liveEvidence ? { liveEvidence: {
66
+ probeStatus: card.liveEvidence.probeStatus,
67
+ summary: previewHarnessText(card.liveEvidence.summary, 160),
68
+ } } : {}),
69
+ ...(card.outcome ? { outcome: {
70
+ target: card.outcome.target,
71
+ successCriteria: card.outcome.successCriteria.map((criterion) => previewHarnessText(criterion, 160)),
72
+ evidenceFields: card.outcome.evidenceFields,
73
+ verificationRoute: previewHarnessText(card.outcome.verificationRoute, 160),
74
+ recoveryRoute: previewHarnessText(card.outcome.recoveryRoute, 160),
75
+ } } : {}),
76
+ recommendedWhen: previewHarnessText(card.recommendedWhen, 160),
77
+ safety: previewHarnessText(card.safety, 160),
78
+ };
79
+ }
80
+
81
+ export function describeServiceLifecycleDecision(decision: SetupServiceLifecycleDecision): Record<string, unknown> {
82
+ return {
83
+ status: decision.status,
84
+ recommendedAction: decision.recommendedAction,
85
+ modelRoute: previewHarnessText(decision.modelRoute, 160),
86
+ reason: previewHarnessText(decision.reason, 180),
87
+ evidence: decision.evidence,
88
+ receiptRules: decision.receiptRules,
89
+ blockedMutations: decision.blockedMutations,
90
+ };
91
+ }
92
+
93
+ export function describeHandoffCard(card: SetupHandoffCard, includeParameters: boolean): Record<string, unknown> {
94
+ return {
95
+ id: card.id,
96
+ label: card.label,
97
+ kind: card.kind,
98
+ effect: card.effect,
99
+ userRoute: previewHarnessText(card.userRoute, includeParameters ? 140 : 96),
100
+ modelRoute: previewHarnessText(card.modelRoute, includeParameters ? 220 : 120),
101
+ nextStep: previewHarnessText(card.nextStep, includeParameters ? 180 : 120),
102
+ safety: previewHarnessText(card.safety, includeParameters ? 180 : 120),
103
+ ...(card.requiresConfirmation ? { requiresConfirmation: true } : {}),
104
+ ...(card.prerequisite ? { prerequisite: previewHarnessText(card.prerequisite, includeParameters ? 160 : 100) } : {}),
105
+ };
106
+ }
107
+
108
+ export function describeRepairDecision(decision: SetupRepairDecision, includeParameters: boolean): Record<string, unknown> {
109
+ return {
110
+ id: decision.id,
111
+ label: decision.label,
112
+ status: decision.status,
113
+ effect: decision.effect,
114
+ modelRoute: previewHarnessText(decision.modelRoute, includeParameters ? 220 : 140),
115
+ userRoute: previewHarnessText(decision.userRoute, includeParameters ? 160 : 120),
116
+ nextStep: previewHarnessText(decision.nextStep, includeParameters ? 220 : 140),
117
+ reason: previewHarnessText(decision.reason, includeParameters ? 220 : 140),
118
+ safety: previewHarnessText(decision.safety, includeParameters ? 220 : 140),
119
+ ...(decision.requiresConfirmation ? { requiresConfirmation: true } : {}),
120
+ ...(decision.prerequisite ? { prerequisite: previewHarnessText(decision.prerequisite, includeParameters ? 180 : 120) } : {}),
121
+ };
122
+ }
123
+
124
+ export function setupRepairDecisionFromCard(
125
+ card: SetupRepairCard,
126
+ status: SetupRepairDecision['status'],
127
+ nextStep: string,
128
+ ): SetupRepairDecision | null {
129
+ if (!card.modelRoute) return null;
130
+ return {
131
+ id: card.id,
132
+ label: card.label,
133
+ status,
134
+ effect: card.effect,
135
+ modelRoute: card.modelRoute,
136
+ userRoute: card.userRoute,
137
+ nextStep,
138
+ reason: card.liveEvidence?.summary ?? card.recommendedWhen,
139
+ safety: card.safety,
140
+ ...(card.effect === 'confirmed-effect' ? { requiresConfirmation: true } : {}),
141
+ ...(card.prerequisite ? { prerequisite: card.prerequisite } : {}),
142
+ };
143
+ }
144
+
145
+ export function setupRepairDecisionFromHandoff(
146
+ handoff: SetupHandoffCard,
147
+ status: SetupRepairDecision['status'],
148
+ reason: string,
149
+ ): SetupRepairDecision {
150
+ return {
151
+ id: handoff.id,
152
+ label: handoff.label,
153
+ status,
154
+ effect: handoff.effect,
155
+ modelRoute: handoff.modelRoute,
156
+ userRoute: handoff.userRoute,
157
+ nextStep: handoff.nextStep,
158
+ reason,
159
+ safety: handoff.safety,
160
+ ...(handoff.requiresConfirmation ? { requiresConfirmation: true } : {}),
161
+ ...(handoff.prerequisite ? { prerequisite: handoff.prerequisite } : {}),
162
+ };
163
+ }
164
+
165
+ export function repairCardById(item: SetupPlanItem, id: string): SetupRepairCard | null {
166
+ return item.repairCards?.find((card) => card.id === id) ?? null;
167
+ }
168
+
169
+ export function confirmedRepairCandidates(item: SetupPlanItem): readonly SetupRepairDecision[] {
170
+ return (item.repairCards ?? [])
171
+ .filter((card) => card.state === 'available' && card.effect === 'confirmed-effect' && card.recommendation !== 'not-needed' && card.modelRoute)
172
+ .map((card) => setupRepairDecisionFromCard(
173
+ card,
174
+ 'confirmed-repair-available',
175
+ 'Run only after read-only status evidence proves this exact service lifecycle mutation is needed.',
176
+ ))
177
+ .filter((decision): decision is SetupRepairDecision => decision !== null);
178
+ }
179
+
180
+ export function primarySetupRepairDecision(item: SetupPlanItem): SetupRepairDecision {
181
+ if (item.id === 'connected-host-auth') {
182
+ const handoff = setupHandoffsForItem(item)[0];
183
+ if (handoff) {
184
+ return setupRepairDecisionFromHandoff(
185
+ handoff,
186
+ handoff.requiresConfirmation ? 'confirmed-repair-available' : 'inspect-first',
187
+ item.authPosture?.operatorToken.usable
188
+ ? 'Connected-host token is usable; verify protected daemon route readiness before relying on automation.'
189
+ : 'Connected-host token is missing or unusable; token provisioning is the narrow confirmed repair.',
190
+ );
191
+ }
192
+ }
193
+
194
+ if (item.id === 'connected-host-readiness') {
195
+ const lifecycle = item.serviceLifecycleDecision;
196
+ if (lifecycle?.status === 'bootstrap-first') {
197
+ return {
198
+ id: 'connected-host-bootstrap',
199
+ label: 'Show host bootstrap checklist',
200
+ status: 'user-run-bootstrap',
201
+ effect: 'user-run',
202
+ modelRoute: 'setup action:"item" setupItemId:"connected-host-readiness" includeParameters:true',
203
+ userRoute: item.userRoute,
204
+ nextStep: 'Show the user-run Bun install, GoodVibes host install/start, binary verification, and reconnect checks for the owning host.',
205
+ reason: lifecycle.reason,
206
+ safety: item.bootstrapPlan?.policy ?? 'Bootstrap remains user-run guidance; Agent does not start or install the owning host implicitly.',
207
+ };
208
+ }
209
+
210
+ if (lifecycle?.status === 'needs-status-receipt') {
211
+ const statusCard = repairCardById(item, 'service-status');
212
+ const decision = statusCard
213
+ ? setupRepairDecisionFromCard(
214
+ statusCard,
215
+ 'inspect-first',
216
+ 'Read services.status first; choose install, start, restart, or no mutation only from that receipt.',
217
+ )
218
+ : null;
219
+ if (decision) return decision;
220
+ }
221
+
222
+ if (lifecycle?.status === 'status-route-unavailable') {
223
+ const posture = repairCardById(item, 'service-posture');
224
+ const decision = posture
225
+ ? setupRepairDecisionFromCard(
226
+ posture,
227
+ 'inspect-first',
228
+ 'Inspect endpoint binding, reachability, and logs because the daemon contract does not publish services.status.',
229
+ )
230
+ : null;
231
+ if (decision) return decision;
232
+ }
233
+
234
+ if (lifecycle?.status === 'no-lifecycle-action') {
235
+ const status = repairCardById(item, 'connected-host-status');
236
+ const decision = status
237
+ ? setupRepairDecisionFromCard(
238
+ status,
239
+ 'ready',
240
+ 'Runtime is reachable; inspect host readiness and avoid install/start/restart unless later diagnostics prove a gap.',
241
+ )
242
+ : null;
243
+ if (decision) return decision;
244
+ }
245
+ }
246
+
247
+ const handoff = setupHandoffsForItem(item)[0];
248
+ if (handoff) {
249
+ return setupRepairDecisionFromHandoff(
250
+ handoff,
251
+ handoff.requiresConfirmation ? 'confirmed-repair-available' : item.status === 'ready' ? 'ready' : 'inspect-first',
252
+ item.reason,
253
+ );
254
+ }
255
+
256
+ return {
257
+ id: `${item.id}-inspect`,
258
+ label: `Inspect ${item.label}`,
259
+ status: item.status === 'ready' ? 'ready' : 'inspect-first',
260
+ effect: 'read-only',
261
+ modelRoute: item.modelRoute,
262
+ userRoute: item.userRoute,
263
+ nextStep: item.nextAction,
264
+ reason: item.reason,
265
+ safety: 'Read-only setup inspection. Mutating routes remain separate and confirmation-gated.',
266
+ };
267
+ }
268
+
269
+ export function setupRepairPlanCandidates(plan: readonly SetupPlanItem[], input: string): readonly SetupPlanItem[] {
270
+ const normalized = input.toLowerCase();
271
+ const tokens = normalized.split(/[^a-z0-9]+/).filter((token) => token.length > 0);
272
+ const scored = plan
273
+ .map((item, index) => {
274
+ const id = item.id.toLowerCase();
275
+ const label = item.label.toLowerCase();
276
+ const text = planSearchText(item);
277
+ let score = 0;
278
+ if (id === normalized || label === normalized) score += 10_000;
279
+ if (id.includes(normalized) || label.includes(normalized)) score += 3_000;
280
+ for (const token of tokens) {
281
+ if (id.includes(token)) score += 1_000;
282
+ if (label.includes(token)) score += 700;
283
+ if (text.includes(token)) score += 120;
284
+ }
285
+ if (item.blocksAutonomy && item.status !== 'ready') score += 200;
286
+ if (item.status === 'blocked') score += 120;
287
+ if (item.status === 'check') score += 60;
288
+ return { item, index, score };
289
+ })
290
+ .filter((entry) => entry.score > 0)
291
+ .sort((left, right) => right.score - left.score || left.item.priority - right.item.priority || left.index - right.index);
292
+ return scored.map((entry) => entry.item);
293
+ }
294
+
295
+ export function defaultSetupRepairItem(plan: readonly SetupPlanItem[], wizard: AgentSetupWizard): SetupPlanItem | null {
296
+ const current = wizard.currentStepId
297
+ ? plan.find((item) => item.id === wizard.currentStepId)
298
+ : null;
299
+ if (current) return current;
300
+ return plan.find((item) => item.blocksAutonomy && item.status !== 'ready')
301
+ ?? plan.find((item) => item.status === 'blocked')
302
+ ?? plan.find((item) => item.status === 'check')
303
+ ?? plan.find((item) => item.status === 'recommended')
304
+ ?? plan[0]
305
+ ?? null;
306
+ }
307
+
308
+ export function setupRepairTarget(
309
+ plan: readonly SetupPlanItem[],
310
+ wizard: AgentSetupWizard,
311
+ args: AgentHarnessSetupArgs,
312
+ ): { readonly item: SetupPlanItem; readonly lookup: Record<string, unknown> } | { readonly error: Record<string, unknown> } {
313
+ const lookup = lookupFromArgs(args);
314
+ if (!lookup) {
315
+ const item = defaultSetupRepairItem(plan, wizard);
316
+ if (!item) {
317
+ return {
318
+ error: {
319
+ status: 'no_setup_items',
320
+ usage: 'No setup repair target is available. Inspect setup action:"status".',
321
+ },
322
+ };
323
+ }
324
+ return {
325
+ item,
326
+ lookup: {
327
+ source: 'setup_wizard',
328
+ resolvedBy: wizard.currentStepId === item.id ? 'current-step' : 'first-actionable-plan-item',
329
+ },
330
+ };
331
+ }
332
+
333
+ const normalized = lookup.input.toLowerCase();
334
+ const exact = plan.find((item) => item.id === lookup.input);
335
+ if (exact) return { item: exact, lookup: { ...lookup, resolvedBy: 'plan-id' } };
336
+ const insensitive = plan.find((item) => item.id.toLowerCase() === normalized);
337
+ if (insensitive) return { item: insensitive, lookup: { ...lookup, resolvedBy: 'case-insensitive-plan-id' } };
338
+ const candidates = setupRepairPlanCandidates(plan, lookup.input);
339
+ if (candidates.length === 1) return { item: candidates[0]!, lookup: { ...lookup, resolvedBy: 'repair-search' } };
340
+ if (candidates.length > 1) {
341
+ const best = candidates[0]!;
342
+ return {
343
+ item: best,
344
+ lookup: {
345
+ ...lookup,
346
+ resolvedBy: 'ranked-repair-search',
347
+ candidates: candidates.slice(0, 6).map((item) => ({
348
+ setupItemId: item.id,
349
+ label: item.label,
350
+ status: item.status,
351
+ modelRoute: item.modelRoute,
352
+ })),
353
+ },
354
+ };
355
+ }
356
+ return {
357
+ error: {
358
+ status: 'missing_lookup',
359
+ usage: `Unknown setup repair target ${lookup.input}. Use setup action:"status" to inspect setup item ids.`,
360
+ },
361
+ };
362
+ }
363
+
364
+ export function describePlanItem(item: SetupPlanItem, includeParameters: boolean): Record<string, unknown> {
365
+ const availableRepairCards = item.repairCards
366
+ ?.filter((card) => card.state === 'available')
367
+ .map((card) => card.id);
368
+ const recommendedRepairCards = item.repairCards
369
+ ?.filter((card) => card.state === 'available' && card.recommendation === 'recommended')
370
+ .map((card) => card.id);
371
+ const handoffs = setupHandoffsForItem(item);
372
+ const primaryHandoff = handoffs[0];
373
+ return {
374
+ setupItemId: item.id,
375
+ label: item.label,
376
+ status: item.status,
377
+ priority: item.priority,
378
+ blocksAutonomy: item.blocksAutonomy,
379
+ summary: previewHarnessText(item.reason, includeParameters ? 180 : 96),
380
+ nextAction: previewHarnessText(item.nextAction, includeParameters ? 180 : 96),
381
+ userRoute: previewHarnessText(item.userRoute, includeParameters ? 140 : 96),
382
+ modelRoute: previewHarnessText(item.modelRoute, includeParameters ? 140 : 96),
383
+ ...(primaryHandoff ? { primaryHandoff: describeHandoffCard(primaryHandoff, includeParameters) } : {}),
384
+ ...(item.relatedSetupItemId ? { relatedSetupItemId: item.relatedSetupItemId } : {}),
385
+ ...(item.signals && item.signals.length > 0 ? { signals: item.signals.slice(0, includeParameters ? 10 : 3) } : {}),
386
+ ...(availableRepairCards && availableRepairCards.length > 0 ? { availableRepairCards } : {}),
387
+ ...(recommendedRepairCards && recommendedRepairCards.length > 0 ? { recommendedRepairCards } : {}),
388
+ ...(item.bootstrapPlan ? { bootstrapRoute: 'setup action:"item" setupItemId:"connected-host-readiness"' } : {}),
389
+ ...(includeParameters && item.serviceProbe ? { serviceProbe: item.serviceProbe } : {}),
390
+ ...(includeParameters && item.serviceLifecycleDecision ? { serviceLifecycleDecision: describeServiceLifecycleDecision(item.serviceLifecycleDecision) } : {}),
391
+ ...(includeParameters && item.authPosture ? { authPosture: item.authPosture } : {}),
392
+ ...(includeParameters && item.installSmokePlan ? { installSmokePlan: item.installSmokePlan } : {}),
393
+ ...(includeParameters && item.localModelReadiness ? { localModelReadiness: item.localModelReadiness } : {}),
394
+ ...(includeParameters && item.vibeHealth ? { vibeHealth: item.vibeHealth } : {}),
395
+ ...(includeParameters && item.sudoPosture ? { sudoPosture: item.sudoPosture } : {}),
396
+ ...(includeParameters && handoffs.length > 0 ? { handoffs: handoffs.map((handoff) => describeHandoffCard(handoff, true)) } : {}),
397
+ ...(includeParameters && item.repairCards && item.repairCards.length > 0 ? { repairCards: item.repairCards.map(describeRepairCard) } : {}),
398
+ ...(includeParameters && item.bootstrapPlan ? { bootstrapPlan: item.bootstrapPlan } : {}),
399
+ ...(includeParameters ? {
400
+ policy: {
401
+ effect: 'read-only',
402
+ mutation: 'Setup plan rows only point to visible setup, status, settings, read-only diagnostics, and confirmed tool routes. Destructive service stop/uninstall actions are intentionally excluded from first-run repair cards.',
403
+ },
404
+ } : {}),
405
+ };
406
+ }
407
+
408
+ export function planSummary(plan: readonly SetupPlanItem[]): Record<string, number> {
409
+ return {
410
+ ready: plan.filter((item) => item.status === 'ready').length,
411
+ blocked: plan.filter((item) => item.status === 'blocked').length,
412
+ recommended: plan.filter((item) => item.status === 'recommended').length,
413
+ optional: plan.filter((item) => item.status === 'optional').length,
414
+ check: plan.filter((item) => item.status === 'check').length,
415
+ blocksAutonomy: plan.filter((item) => item.blocksAutonomy && item.status !== 'ready').length,
416
+ };
417
+ }
418
+
419
+ export function nextSetupHandoffSummaries(plan: readonly SetupPlanItem[], limit: number): readonly Record<string, unknown>[] {
420
+ return plan
421
+ .filter((item) => item.status === 'blocked' || item.status === 'check' || item.status === 'recommended')
422
+ .slice(0, limit)
423
+ .map((item) => {
424
+ const primaryHandoff = setupHandoffsForItem(item)[0];
425
+ return {
426
+ setupItemId: item.id,
427
+ label: item.label,
428
+ status: item.status,
429
+ nextAction: previewHarnessText(item.nextAction, 140),
430
+ modelRoute: previewHarnessText(item.modelRoute, 96),
431
+ ...(primaryHandoff ? {
432
+ handoffLabel: primaryHandoff.label,
433
+ handoffKind: primaryHandoff.kind,
434
+ handoffRoute: previewHarnessText(primaryHandoff.modelRoute, 140),
435
+ handoffUserRoute: previewHarnessText(primaryHandoff.userRoute, 120),
436
+ ...(primaryHandoff.requiresConfirmation ? { requiresConfirmation: true } : {}),
437
+ } : {}),
438
+ };
439
+ });
440
+ }
441
+
442
+ export function signalsForItem(
443
+ item: OnboardingStep1CapabilityItem,
444
+ snapshot: Awaited<ReturnType<typeof collectSnapshot>>,
445
+ ): Record<string, unknown> {
446
+ if (item.id === 'provider-access') {
447
+ return {
448
+ currentRoute: snapshot.providerRouting,
449
+ providerAccounts: {
450
+ providers: snapshot.providerAccounts?.providers.length ?? 0,
451
+ configured: snapshot.providerAccounts?.configuredCount ?? 0,
452
+ issues: snapshot.providerAccounts?.issueCount ?? 0,
453
+ },
454
+ subscriptions: {
455
+ active: snapshot.subscriptions.active.length,
456
+ pending: snapshot.subscriptions.pending.length,
457
+ activeProviderIds: snapshot.subscriptions.activeProviderIds,
458
+ pendingProviderIds: snapshot.subscriptions.pendingProviderIds,
459
+ },
460
+ credentialReferences: snapshot.secrets.records.length,
461
+ };
462
+ }
463
+ if (item.id === 'local-behavior') {
464
+ return summarizeLocalBehavior(snapshot);
465
+ }
466
+ if (item.id === 'communication-channels') {
467
+ return {
468
+ configuredEnabledKinds: snapshot.surfaces.configuredEnabledKinds,
469
+ surfaces: snapshot.surfaces.records.map((surface) => ({
470
+ id: surface.id,
471
+ kind: surface.kind,
472
+ label: surface.label,
473
+ enabled: surface.enabled,
474
+ state: surface.state,
475
+ capabilities: surface.capabilities,
476
+ })),
477
+ };
478
+ }
479
+ if (item.id === 'automation-review') {
480
+ return {
481
+ permissionsMode: snapshot.runtimeDefaults.permissionsMode,
482
+ helperEnabled: snapshot.providerRouting.helperEnabled,
483
+ toolLlmEnabled: snapshot.providerRouting.toolLlmEnabled,
484
+ };
485
+ }
486
+ if (item.id === 'operator-terminal') {
487
+ return {
488
+ display: snapshot.runtimeDefaults.display,
489
+ setupMarker: {
490
+ scope: snapshot.acknowledgements.scope,
491
+ exists: snapshot.acknowledgements.exists,
492
+ updatedAt: safeIso(snapshot.acknowledgements.updatedAt),
493
+ source: snapshot.acknowledgements.source,
494
+ mode: snapshot.acknowledgements.mode ?? null,
495
+ },
496
+ collectionIssues: snapshot.collectionIssues,
497
+ };
498
+ }
499
+ return {
500
+ status: item.selected ? 'covered' : 'available',
501
+ };
502
+ }
503
+
504
+ export function describeItem(
505
+ item: OnboardingStep1CapabilityItem,
506
+ snapshot: Awaited<ReturnType<typeof collectSnapshot>>,
507
+ options: {
508
+ readonly includeParameters?: boolean;
509
+ readonly lookup?: Record<string, unknown>;
510
+ } = {},
511
+ ): Record<string, unknown> {
512
+ return {
513
+ setupItemId: item.id,
514
+ label: item.label,
515
+ selected: item.selected,
516
+ modelRoute: setupItemModelRoute(),
517
+ ...(options.lookup ? { lookup: options.lookup } : {}),
518
+ ...(options.includeParameters
519
+ ? {
520
+ detail: item.detail,
521
+ signals: signalsForItem(item, snapshot),
522
+ policy: {
523
+ effect: 'read-only',
524
+ values: 'Setup posture returns onboarding readiness, counts, safe setting keys, and route metadata only; secret values and raw provider tokens are never returned.',
525
+ mutation: 'Setup apply, provider auth, local behavior import/create, channel delivery, and starter profile changes stay visible workspace, settings, slash-command, or first-class tool flows.',
526
+ },
527
+ modelAccess: {
528
+ inspectSetup: DEFAULT_AGENT_SETUP_WIZARD_REVIEW_ROUTE,
529
+ inspectSetupItem: 'setup action:"item"',
530
+ openOnboarding: 'agent_harness mode:"open_ui_surface" surfaceId:"onboarding" confirm:true explicitUserRequest:"..."',
531
+ setupWorkspace: 'agent_harness mode:"workspace_action" target:"setup"',
532
+ settings: 'settings action:"list|get|set|reset"; compatibility detail remains in agent_harness settings modes',
533
+ providerRouting: 'models action:"status"',
534
+ providerAccounts: 'models action:"providers"',
535
+ channels: 'channels action:"status"',
536
+ media: 'agent_harness mode:"media_posture"',
537
+ security: 'agent_harness mode:"security_posture"',
538
+ },
539
+ }
540
+ : {
541
+ summary: previewHarnessText(item.detail),
542
+ }),
543
+ };
544
+ }
545
+
546
+ export function setupItemModelRoute(): string {
547
+ return 'setup action:"item" or agent_harness mode:"open_ui_surface"';
548
+ }
549
+
550
+ export function describeCandidate(item: OnboardingStep1CapabilityItem): Record<string, unknown> {
551
+ return {
552
+ setupItemId: item.id,
553
+ label: item.label,
554
+ selected: item.selected,
555
+ modelRoute: setupItemModelRoute(),
556
+ };
557
+ }