@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
@@ -1,248 +1,124 @@
1
- import type { OnboardingStep1CapabilityItem, OnboardingSurfaceRecord } from '../runtime/onboarding/index.ts';
2
- import { collectOnboardingSnapshot, deriveStep1Capabilities, deriveStep1CapabilityFlags } from '../runtime/onboarding/index.ts';
1
+ import { join } from 'node:path';
2
+ import { getOrCreateCompanionToken } from '@pellux/goodvibes-sdk/platform/pairing';
3
+ import { GOODVIBES_AGENT_PAIRING_SURFACE } from '../config/surface.ts';
3
4
  import type { CommandContext } from '../input/command-registry.ts';
4
- import { buildProviderAccountSnapshot } from '../panels/provider-account-snapshot.ts';
5
- import { requireLocalUserAuthManager, requirePlatform, requireProvider, requireSecretsManager, requireServiceRegistry, requireShellPaths, requireSubscriptionManager } from '../input/commands/runtime-services.ts';
5
+ import { requireShellPaths } from '../input/commands/runtime-services.ts';
6
+ import { deriveStep1Capabilities, deriveStep1CapabilityFlags } from '../runtime/onboarding/index.ts';
7
+ import { connectedHostOperatorTokenFingerprint, connectedHostOperatorTokenPath, readConnectedHostOperatorToken } from '../runtime/connected-host-auth.ts';
8
+ import { clearSetupWizardCheckpoint, saveSetupWizardCheckpoint } from '../agent/setup-wizard-checkpoint.ts';
9
+ 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 } from '../agent/setup-wizard.ts';
6
10
  import { previewHarnessText } from './agent-harness-text.ts';
11
+ import type { AgentHarnessSetupArgs, SetupResolution } from './agent-harness-setup-posture-types.ts';
12
+ import { buildSetupPlan } from './agent-harness-setup-plan.ts';
13
+ import { buildSetupWizard, describeInstallSmokeCheck, installSmokeNextAction, installSmokeRunResult, installSmokeRunSummary, latestSetupSmokeEvidence, saveSetupSmokeArtifact, setupCompletionMarkerExists, setupSmokeEvidenceFields, setupSmokeEvidenceHistory } from './agent-harness-setup-smoke.ts';
14
+ import { confirmedRepairCandidates, describeCandidate, describeHandoffCard, describeItem, describePlanItem, describeRepairCard, describeRepairDecision, describeServiceLifecycleDecision, nextSetupHandoffSummaries, planSearchText, planSummary, primarySetupRepairDecision, setupRepairTarget } from './agent-harness-setup-describe.ts';
15
+ import { setupHandoffsForItem } from './agent-harness-setup-handoffs.ts';
16
+ import { collectServicePosture, collectSnapshot, itemSearchText, lookupFromArgs, quoteRouteValue, readLimit, readString, safeFileMode, safeIso, summarizeLocalBehavior } from './agent-harness-setup-posture-utils.ts';
7
17
 
8
- export interface AgentHarnessSetupArgs {
9
- readonly setupItemId?: unknown;
10
- readonly target?: unknown;
11
- readonly query?: unknown;
12
- readonly includeParameters?: unknown;
13
- readonly limit?: unknown;
14
- }
15
-
16
- type SetupResolution =
17
- | { readonly status: 'found'; readonly item: Record<string, unknown> }
18
- | { readonly status: 'ambiguous'; readonly input: string; readonly candidates: readonly Record<string, unknown>[] }
19
- | { readonly status: 'missing_lookup'; readonly usage: string };
20
-
21
- type SetupLookupSource = 'setupItemId' | 'target' | 'query';
22
-
23
- interface SurfaceRegistryLike {
24
- syncConfiguredSurfaces(): readonly OnboardingSurfaceRecord[];
25
- }
26
-
27
- function readString(value: unknown): string {
28
- return typeof value === 'string' ? value.trim() : '';
29
- }
30
-
31
- function readLimit(value: unknown, fallback: number): number {
32
- const parsed = typeof value === 'string' && value.trim() ? Number(value) : value;
33
- if (typeof parsed !== 'number' || !Number.isFinite(parsed)) return fallback;
34
- return Math.max(1, Math.min(500, Math.trunc(parsed)));
35
- }
36
-
37
- function safeIso(value: number | null | undefined): string | null {
38
- if (typeof value !== 'number' || !Number.isFinite(value)) return null;
39
- return new Date(value).toISOString();
40
- }
41
-
42
- function surfaceRegistry(context: CommandContext): SurfaceRegistryLike | undefined {
43
- const candidate = (context.platform as { readonly surfaceRegistry?: unknown }).surfaceRegistry;
44
- if (candidate && typeof candidate === 'object' && 'syncConfiguredSurfaces' in candidate) {
45
- return candidate as SurfaceRegistryLike;
46
- }
47
- return undefined;
48
- }
49
-
50
- async function collectSnapshot(context: CommandContext) {
51
- const registry = surfaceRegistry(context);
52
- return await collectOnboardingSnapshot({
53
- config: requirePlatform(context).configManager,
54
- shellPaths: requireShellPaths(context),
55
- acknowledgementScope: 'project',
56
- subscriptions: requireSubscriptionManager(context),
57
- secrets: requireSecretsManager(context),
58
- auth: requireLocalUserAuthManager(context),
59
- services: requireServiceRegistry(context),
60
- ...(registry ? {
61
- surfaces: {
62
- list: () => registry.syncConfiguredSurfaces(),
63
- },
64
- } : {}),
65
- providerAccounts: {
66
- loadSnapshot: () => buildProviderAccountSnapshot({
67
- providerModels: requireProvider(context).providerRegistry,
68
- services: requireServiceRegistry(context),
69
- subscriptions: requireSubscriptionManager(context),
70
- environment: {
71
- hasEnvironmentVariable: (name: string) => Boolean(process.env[name]),
72
- },
73
- }),
74
- },
75
- });
76
- }
77
-
78
- function lookupFromArgs(args: AgentHarnessSetupArgs): { readonly source: SetupLookupSource; readonly input: string } | null {
79
- const setupItemId = readString(args.setupItemId);
80
- if (setupItemId) return { source: 'setupItemId', input: setupItemId };
81
- const target = readString(args.target);
82
- if (target) return { source: 'target', input: target };
83
- const query = readString(args.query);
84
- return query ? { source: 'query', input: query } : null;
85
- }
86
-
87
- function itemSearchText(item: OnboardingStep1CapabilityItem): string {
88
- return [
89
- item.id,
90
- item.label,
91
- item.detail,
92
- item.selected ? 'selected ready configured enabled' : 'optional attention unselected',
93
- ].join('\n').toLowerCase();
94
- }
95
-
96
- function summarizeLocalBehavior(snapshot: Awaited<ReturnType<typeof collectSnapshot>>): Record<string, unknown> {
97
- const discovery = snapshot.localBehaviorDiscovery;
98
- return {
99
- personas: discovery.personas,
100
- skills: discovery.skills,
101
- routines: discovery.routines,
102
- };
103
- }
104
-
105
- function signalsForItem(
106
- item: OnboardingStep1CapabilityItem,
107
- snapshot: Awaited<ReturnType<typeof collectSnapshot>>,
108
- ): Record<string, unknown> {
109
- if (item.id === 'provider-access') {
110
- return {
111
- currentRoute: snapshot.providerRouting,
112
- providerAccounts: {
113
- providers: snapshot.providerAccounts?.providers.length ?? 0,
114
- configured: snapshot.providerAccounts?.configuredCount ?? 0,
115
- issues: snapshot.providerAccounts?.issueCount ?? 0,
116
- },
117
- subscriptions: {
118
- active: snapshot.subscriptions.active.length,
119
- pending: snapshot.subscriptions.pending.length,
120
- activeProviderIds: snapshot.subscriptions.activeProviderIds,
121
- pendingProviderIds: snapshot.subscriptions.pendingProviderIds,
122
- },
123
- credentialReferences: snapshot.secrets.records.length,
124
- };
125
- }
126
- if (item.id === 'local-behavior') {
127
- return summarizeLocalBehavior(snapshot);
128
- }
129
- if (item.id === 'communication-channels') {
130
- return {
131
- configuredEnabledKinds: snapshot.surfaces.configuredEnabledKinds,
132
- surfaces: snapshot.surfaces.records.map((surface) => ({
133
- id: surface.id,
134
- kind: surface.kind,
135
- label: surface.label,
136
- enabled: surface.enabled,
137
- state: surface.state,
138
- capabilities: surface.capabilities,
139
- })),
140
- };
141
- }
142
- if (item.id === 'automation-review') {
143
- return {
144
- permissionsMode: snapshot.runtimeDefaults.permissionsMode,
145
- helperEnabled: snapshot.providerRouting.helperEnabled,
146
- toolLlmEnabled: snapshot.providerRouting.toolLlmEnabled,
147
- };
148
- }
149
- if (item.id === 'operator-terminal') {
150
- return {
151
- display: snapshot.runtimeDefaults.display,
152
- setupMarker: {
153
- scope: snapshot.acknowledgements.scope,
154
- exists: snapshot.acknowledgements.exists,
155
- updatedAt: safeIso(snapshot.acknowledgements.updatedAt),
156
- source: snapshot.acknowledgements.source,
157
- mode: snapshot.acknowledgements.mode ?? null,
158
- },
159
- collectionIssues: snapshot.collectionIssues,
160
- };
161
- }
162
- return {
163
- status: item.selected ? 'covered' : 'available',
164
- };
165
- }
166
-
167
- function describeItem(
168
- item: OnboardingStep1CapabilityItem,
169
- snapshot: Awaited<ReturnType<typeof collectSnapshot>>,
170
- options: {
171
- readonly includeParameters?: boolean;
172
- readonly lookup?: Record<string, unknown>;
173
- } = {},
174
- ): Record<string, unknown> {
18
+ export async function setupPostureCatalogStatus(context: CommandContext): Promise<Record<string, unknown>> {
19
+ const snapshot = await collectSnapshot(context);
20
+ const servicePosture = await collectServicePosture(context);
21
+ const plan = buildSetupPlan(context, snapshot, deriveStep1Capabilities(snapshot), servicePosture);
22
+ const setupSmokeEvidence = latestSetupSmokeEvidence(context);
23
+ const setupSmokeHistory = setupSmokeEvidenceHistory(context);
24
+ const setupWizard = buildSetupWizard(plan, context);
175
25
  return {
176
- setupItemId: item.id,
177
- label: item.label,
178
- selected: item.selected,
179
- modelRoute: setupItemModelRoute(),
180
- ...(options.lookup ? { lookup: options.lookup } : {}),
181
- ...(options.includeParameters
182
- ? {
183
- detail: item.detail,
184
- signals: signalsForItem(item, snapshot),
185
- policy: {
186
- effect: 'read-only',
187
- values: 'Setup posture returns onboarding readiness, counts, safe setting keys, and route metadata only; secret values and raw provider tokens are never returned.',
188
- 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.',
189
- },
190
- modelAccess: {
191
- inspectSetup: 'agent_harness mode:"setup_posture"',
192
- inspectSetupItem: 'agent_harness mode:"setup_item"',
193
- openOnboarding: 'agent_harness mode:"open_ui_surface" surfaceId:"onboarding" confirm:true explicitUserRequest:"..."',
194
- setupWorkspace: 'agent_harness mode:"workspace_action" target:"setup"',
195
- settings: 'agent_harness mode:"settings"; inspect or mutate with get_setting, set_setting, or reset_setting',
196
- providerRouting: 'agent_harness mode:"model_routing"',
197
- providerAccounts: 'agent_harness mode:"provider_accounts"',
198
- channels: 'agent_harness mode:"channels"',
199
- media: 'agent_harness mode:"media_posture"',
200
- security: 'agent_harness mode:"security_posture"',
201
- },
202
- }
203
- : {
204
- summary: previewHarnessText(item.detail),
205
- }),
26
+ modes: ['setup_posture', 'setup_item', 'setup_repair', 'setup_checkpoint', 'mark_setup_checkpoint', 'clear_setup_checkpoint', 'provision_connected_host_token', 'run_setup_smoke'],
27
+ capabilities: deriveStep1Capabilities(snapshot).length,
28
+ planItems: plan.length,
29
+ blockedPlanItems: plan.filter((item) => item.status === 'blocked').length,
30
+ autonomyBlockers: plan.filter((item) => item.blocksAutonomy && item.status !== 'ready').length,
31
+ nextSetupHandoffs: nextSetupHandoffSummaries(plan, 5),
32
+ setupWizard,
33
+ setupCloseout: setupWizard.closeout,
34
+ collectionIssues: snapshot.collectionIssues.length,
35
+ setupMarkerExists: setupCompletionMarkerExists(context),
36
+ setupSmokeEvidence,
37
+ setupSmokeHistory,
38
+ readOnly: true,
206
39
  };
207
40
  }
208
41
 
209
- function setupItemModelRoute(): string {
210
- return 'agent_harness mode:"setup_item" or mode:"open_ui_surface"';
211
- }
42
+ export async function setupRepairSummary(context: CommandContext, args: AgentHarnessSetupArgs): Promise<Record<string, unknown>> {
43
+ const snapshot = await collectSnapshot(context);
44
+ const servicePosture = await collectServicePosture(context);
45
+ const plan = buildSetupPlan(context, snapshot, deriveStep1Capabilities(snapshot), servicePosture);
46
+ const setupWizard = buildSetupWizard(plan, context);
47
+ const includeParameters = args.includeParameters === true;
48
+ const target = setupRepairTarget(plan, setupWizard, args);
49
+ if ('error' in target) return target.error;
212
50
 
213
- function describeCandidate(item: OnboardingStep1CapabilityItem): Record<string, unknown> {
51
+ const item = target.item;
52
+ const decision = primarySetupRepairDecision(item);
53
+ const handoffs = setupHandoffsForItem(item);
54
+ const alternatives = handoffs
55
+ .filter((handoff) => handoff.id !== decision.id)
56
+ .slice(0, includeParameters ? 8 : 3)
57
+ .map((handoff) => describeHandoffCard(handoff, includeParameters));
58
+ const confirmedCandidates = confirmedRepairCandidates(item);
214
59
  return {
60
+ mode: 'setup_repair',
61
+ capturedAt: new Date(snapshot.capturedAt).toISOString(),
215
62
  setupItemId: item.id,
216
63
  label: item.label,
217
- selected: item.selected,
218
- modelRoute: setupItemModelRoute(),
219
- };
220
- }
221
-
222
- export async function setupPostureCatalogStatus(context: CommandContext): Promise<Record<string, unknown>> {
223
- const snapshot = await collectSnapshot(context);
224
- return {
225
- modes: ['setup_posture', 'setup_item'],
226
- capabilities: deriveStep1Capabilities(snapshot).length,
227
- collectionIssues: snapshot.collectionIssues.length,
228
- setupMarkerExists: snapshot.acknowledgements.exists,
229
- readOnly: true,
64
+ status: item.status,
65
+ blocksAutonomy: item.blocksAutonomy,
66
+ lookup: target.lookup,
67
+ decision: describeRepairDecision(decision, includeParameters),
68
+ nextAction: previewHarnessText(item.nextAction, includeParameters ? 220 : 140),
69
+ userRoute: previewHarnessText(item.userRoute, includeParameters ? 160 : 120),
70
+ modelRoute: previewHarnessText(item.modelRoute, includeParameters ? 160 : 120),
71
+ alternatives,
72
+ ...(confirmedCandidates.length > 0 ? {
73
+ possibleConfirmedRepairs: confirmedCandidates.map((candidate) => describeRepairDecision(candidate, includeParameters)),
74
+ } : {}),
75
+ ...(item.serviceProbe ? { serviceProbe: item.serviceProbe } : {}),
76
+ ...(item.serviceLifecycleDecision ? { serviceLifecycleDecision: describeServiceLifecycleDecision(item.serviceLifecycleDecision) } : {}),
77
+ ...(includeParameters && item.repairCards ? { repairCards: item.repairCards.map(describeRepairCard) } : {}),
78
+ ...(includeParameters && item.bootstrapPlan ? { bootstrapPlan: item.bootstrapPlan } : {}),
79
+ ...(includeParameters && item.authPosture ? { authPosture: item.authPosture } : {}),
80
+ setupWizard: {
81
+ status: setupWizard.status,
82
+ currentStepId: setupWizard.currentStepId,
83
+ currentStepLabel: setupWizard.currentStepLabel,
84
+ closeout: setupWizard.closeout,
85
+ },
86
+ routes: {
87
+ inspectSetup: DEFAULT_AGENT_SETUP_WIZARD_REVIEW_ROUTE,
88
+ inspectItem: `setup action:"item" setupItemId:"${quoteRouteValue(item.id)}" includeParameters:true`,
89
+ rerunRepair: `setup action:"repair" setupItemId:"${quoteRouteValue(item.id)}" includeParameters:true`,
90
+ },
91
+ policy: {
92
+ effect: 'read-only-repair-decision',
93
+ boundary: 'This route chooses the safest next setup repair route only. It never starts, installs, restarts, writes tokens, imports settings, or opens UI by itself.',
94
+ confirmation: 'Any returned confirmed-effect route still requires confirm:true and explicitUserRequest tied to the user request.',
95
+ hostOwnership: 'GoodVibes Agent does not take ambient ownership of the GoodVibes host lifecycle; disconnected hosts use user-run bootstrap guidance, and reachable hosts use daemon receipts before lifecycle mutation.',
96
+ },
230
97
  };
231
98
  }
232
99
 
233
100
  export async function setupPostureSummary(context: CommandContext, args: AgentHarnessSetupArgs): Promise<Record<string, unknown>> {
234
101
  const snapshot = await collectSnapshot(context);
102
+ const servicePosture = await collectServicePosture(context);
235
103
  const query = readString(args.query).toLowerCase();
236
104
  const includeParameters = args.includeParameters === true;
237
105
  const all = deriveStep1Capabilities(snapshot);
106
+ const plan = buildSetupPlan(context, snapshot, all, servicePosture);
107
+ const setupSmokeEvidence = latestSetupSmokeEvidence(context);
108
+ const setupSmokeHistory = setupSmokeEvidenceHistory(context);
109
+ const setupWizard = buildSetupWizard(plan, context);
238
110
  const filtered = all
239
111
  .filter((item) => !query || itemSearchText(item).includes(query))
240
112
  .slice(0, readLimit(args.limit, 100));
113
+ const filteredPlan = plan
114
+ .filter((item) => !query || planSearchText(item).includes(query))
115
+ .slice(0, readLimit(args.limit, 100));
241
116
  return {
242
117
  capturedAt: new Date(snapshot.capturedAt).toISOString(),
243
118
  setupMarker: {
244
119
  scope: snapshot.acknowledgements.scope,
245
120
  exists: snapshot.acknowledgements.exists,
121
+ completionExists: setupCompletionMarkerExists(context),
246
122
  updatedAt: safeIso(snapshot.acknowledgements.updatedAt),
247
123
  source: snapshot.acknowledgements.source,
248
124
  mode: snapshot.acknowledgements.mode ?? null,
@@ -265,9 +141,26 @@ export async function setupPostureSummary(context: CommandContext, args: AgentHa
265
141
  enabledSurfaceKinds: snapshot.surfaces.configuredEnabledKinds.length,
266
142
  localBehavior: summarizeLocalBehavior(snapshot),
267
143
  capabilityFlags: deriveStep1CapabilityFlags(snapshot),
144
+ readinessPlan: planSummary(plan),
145
+ setupSmokeEvidence,
146
+ setupSmokeHistory,
147
+ setupWizard: {
148
+ status: setupWizard.status,
149
+ progressLabel: setupWizard.progressLabel,
150
+ currentStepId: setupWizard.currentStepId,
151
+ currentStepLabel: setupWizard.currentStepLabel,
152
+ repeatedBlocker: setupWizard.repeatedBlocker,
153
+ },
154
+ setupCloseout: setupWizard.closeout,
268
155
  },
156
+ setupSmokeEvidence,
157
+ setupSmokeHistory,
158
+ setupWizard,
159
+ setupCloseout: setupWizard.closeout,
269
160
  currentRoute: snapshot.providerRouting,
270
161
  issues: snapshot.collectionIssues,
162
+ readinessPlan: filteredPlan.map((item) => describePlanItem(item, includeParameters)),
163
+ nextSetupActions: nextSetupHandoffSummaries(plan, 5),
271
164
  capabilities: filtered.map((item) => describeItem(item, snapshot, { includeParameters })),
272
165
  returned: filtered.length,
273
166
  total: all.length,
@@ -275,6 +168,330 @@ export async function setupPostureSummary(context: CommandContext, args: AgentHa
275
168
  };
276
169
  }
277
170
 
171
+ export async function setupCheckpointSummary(context: CommandContext): Promise<Record<string, unknown>> {
172
+ const snapshot = await collectSnapshot(context);
173
+ const servicePosture = await collectServicePosture(context);
174
+ const plan = buildSetupPlan(context, snapshot, deriveStep1Capabilities(snapshot), servicePosture);
175
+ const setupWizard = buildSetupWizard(plan, context);
176
+ return {
177
+ mode: 'setup_checkpoint',
178
+ checkpoint: setupWizard.checkpoint,
179
+ currentStep: setupWizard.currentStepId
180
+ ? setupWizard.steps.find((step) => step.id === setupWizard.currentStepId) ?? null
181
+ : null,
182
+ setupWizard: {
183
+ status: setupWizard.status,
184
+ progressLabel: setupWizard.progressLabel,
185
+ currentStepId: setupWizard.currentStepId,
186
+ currentStepLabel: setupWizard.currentStepLabel,
187
+ next: setupWizard.next,
188
+ },
189
+ routes: {
190
+ inspectSetup: DEFAULT_AGENT_SETUP_WIZARD_REVIEW_ROUTE,
191
+ markCurrent: DEFAULT_AGENT_SETUP_WIZARD_MARK_CHECKPOINT_ROUTE,
192
+ clear: DEFAULT_AGENT_SETUP_WIZARD_CLEAR_CHECKPOINT_ROUTE,
193
+ },
194
+ policy: 'Read-only checkpoint inspection. Saving or clearing the setup wizard checkpoint requires a confirmed route with explicit user request.',
195
+ };
196
+ }
197
+
198
+ export async function markSetupCheckpoint(context: CommandContext, args: AgentHarnessSetupArgs): Promise<Record<string, unknown>> {
199
+ const snapshot = await collectSnapshot(context);
200
+ const servicePosture = await collectServicePosture(context);
201
+ const plan = buildSetupPlan(context, snapshot, deriveStep1Capabilities(snapshot), servicePosture);
202
+ const setupWizard = buildSetupWizard(plan, context);
203
+ const requestedStepId = readString(args.setupItemId);
204
+ const step = requestedStepId
205
+ ? setupWizard.steps.find((candidate) => candidate.id === requestedStepId)
206
+ : setupWizard.currentStepId
207
+ ? setupWizard.steps.find((candidate) => candidate.id === setupWizard.currentStepId)
208
+ : null;
209
+ if (!step) {
210
+ return {
211
+ status: 'no_checkpoint_written',
212
+ mode: 'mark_setup_checkpoint',
213
+ reason: requestedStepId
214
+ ? `Unknown setup wizard step ${requestedStepId}.`
215
+ : 'Setup wizard has no current step to checkpoint.',
216
+ setupWizard: {
217
+ status: setupWizard.status,
218
+ currentStepId: setupWizard.currentStepId,
219
+ currentStepLabel: setupWizard.currentStepLabel,
220
+ },
221
+ routes: {
222
+ inspectSetup: DEFAULT_AGENT_SETUP_WIZARD_REVIEW_ROUTE,
223
+ },
224
+ };
225
+ }
226
+ if (step.sourceStatus === 'ready') {
227
+ return {
228
+ status: 'no_checkpoint_written',
229
+ mode: 'mark_setup_checkpoint',
230
+ reason: `Setup wizard step ${step.label} is already ready.`,
231
+ step,
232
+ routes: {
233
+ inspectSetup: DEFAULT_AGENT_SETUP_WIZARD_REVIEW_ROUTE,
234
+ clear: DEFAULT_AGENT_SETUP_WIZARD_CLEAR_CHECKPOINT_ROUTE,
235
+ },
236
+ };
237
+ }
238
+ const shellPaths = requireShellPaths(context);
239
+ const checkpoint = saveSetupWizardCheckpoint(shellPaths, {
240
+ currentStepId: step.id,
241
+ currentStepLabel: step.label,
242
+ source: 'harness',
243
+ note: 'User-confirmed setup wizard checkpoint.',
244
+ });
245
+ const updatedWizard = buildSetupWizard(plan, context);
246
+ return {
247
+ status: 'checkpoint_saved',
248
+ mode: 'mark_setup_checkpoint',
249
+ explicitUserRequest: previewHarnessText(readString(args.explicitUserRequest), 160),
250
+ step,
251
+ checkpoint,
252
+ setupWizard: {
253
+ status: updatedWizard.status,
254
+ progressLabel: updatedWizard.progressLabel,
255
+ currentStepId: updatedWizard.currentStepId,
256
+ currentStepLabel: updatedWizard.currentStepLabel,
257
+ checkpoint: updatedWizard.checkpoint,
258
+ },
259
+ routes: {
260
+ inspectCheckpoint: DEFAULT_AGENT_SETUP_WIZARD_INSPECT_CHECKPOINT_ROUTE,
261
+ inspectSetup: DEFAULT_AGENT_SETUP_WIZARD_REVIEW_ROUTE,
262
+ clear: DEFAULT_AGENT_SETUP_WIZARD_CLEAR_CHECKPOINT_ROUTE,
263
+ },
264
+ policy: {
265
+ effect: 'confirmed-setup-checkpoint-save',
266
+ boundary: 'Only the current setup wizard step id, label, source, timestamp, and generic note were saved in Agent-owned setup state.',
267
+ },
268
+ };
269
+ }
270
+
271
+ export function clearSetupCheckpoint(context: CommandContext, args: AgentHarnessSetupArgs): Record<string, unknown> {
272
+ const shellPaths = requireShellPaths(context);
273
+ const checkpoint = clearSetupWizardCheckpoint(shellPaths);
274
+ return {
275
+ status: 'checkpoint_cleared',
276
+ mode: 'clear_setup_checkpoint',
277
+ explicitUserRequest: previewHarnessText(readString(args.explicitUserRequest), 160),
278
+ checkpoint,
279
+ routes: {
280
+ inspectCheckpoint: DEFAULT_AGENT_SETUP_WIZARD_INSPECT_CHECKPOINT_ROUTE,
281
+ inspectSetup: DEFAULT_AGENT_SETUP_WIZARD_REVIEW_ROUTE,
282
+ markCurrent: DEFAULT_AGENT_SETUP_WIZARD_MARK_CHECKPOINT_ROUTE,
283
+ },
284
+ policy: {
285
+ effect: 'confirmed-setup-checkpoint-clear',
286
+ boundary: 'Removed only the Agent-owned setup wizard checkpoint file.',
287
+ },
288
+ };
289
+ }
290
+
291
+ export function provisionConnectedHostOperatorToken(context: CommandContext, args: AgentHarnessSetupArgs): Record<string, unknown> {
292
+ const setupItemId = readString(args.setupItemId);
293
+ if (setupItemId && setupItemId !== 'connected-host-auth') {
294
+ return {
295
+ status: 'unsupported_setup_item',
296
+ usage: 'provision_connected_host_token supports setupItemId:"connected-host-auth" only.',
297
+ };
298
+ }
299
+
300
+ const shellPaths = requireShellPaths(context);
301
+ const before = readConnectedHostOperatorToken(shellPaths.homeDirectory);
302
+ const explicitUserRequest = readString(args.explicitUserRequest);
303
+ const beforeFingerprint = before.token ? connectedHostOperatorTokenFingerprint(before.token) : null;
304
+ if (before.token && before.path.startsWith('env:')) {
305
+ return {
306
+ status: 'already_usable_env_token',
307
+ mode: 'provision_connected_host_token',
308
+ setupItemId: 'connected-host-auth',
309
+ explicitUserRequest: previewHarnessText(explicitUserRequest, 160),
310
+ token: {
311
+ path: before.path,
312
+ present: true,
313
+ usable: true,
314
+ fingerprint: beforeFingerprint,
315
+ rawValueReturned: false,
316
+ },
317
+ mutation: {
318
+ performed: false,
319
+ reason: 'Environment-provided connected-host token is already effective; no local token file was written.',
320
+ },
321
+ routes: {
322
+ inspectAuth: 'setup action:"item" setupItemId:"connected-host-auth"',
323
+ inspectStatus: 'host action:"status" includeParameters:true',
324
+ pairingPosture: 'agent_harness mode:"pairing_posture" includeParameters:true',
325
+ },
326
+ policy: {
327
+ effect: 'confirmed-local-token-provisioning',
328
+ secrets: 'Raw connected-host tokens are never returned.',
329
+ boundary: 'Environment-provided tokens take precedence and are not modified by this route.',
330
+ },
331
+ };
332
+ }
333
+
334
+ const daemonHomeDir = join(shellPaths.homeDirectory, '.goodvibes', 'daemon');
335
+ const canonicalPath = connectedHostOperatorTokenPath(shellPaths.homeDirectory);
336
+ try {
337
+ const record = getOrCreateCompanionToken(GOODVIBES_AGENT_PAIRING_SURFACE, { daemonHomeDir });
338
+ const after = readConnectedHostOperatorToken(shellPaths.homeDirectory);
339
+ if (!after.token) {
340
+ return {
341
+ status: 'failed',
342
+ mode: 'provision_connected_host_token',
343
+ setupItemId: 'connected-host-auth',
344
+ explicitUserRequest: previewHarnessText(explicitUserRequest, 160),
345
+ error: after.error ? previewHarnessText(after.error, 160) : 'SDK token provisioning completed but no usable connected-host token was readable.',
346
+ token: {
347
+ path: after.path,
348
+ present: after.present,
349
+ usable: false,
350
+ rawValueReturned: false,
351
+ },
352
+ routes: {
353
+ inspectAuth: 'setup action:"item" setupItemId:"connected-host-auth"',
354
+ inspectStatus: 'host action:"status" includeParameters:true',
355
+ },
356
+ };
357
+ }
358
+ const afterFingerprint = connectedHostOperatorTokenFingerprint(after.token);
359
+ const changed = beforeFingerprint !== afterFingerprint;
360
+ const result = before.token
361
+ ? changed ? 'repaired' : 'already_usable'
362
+ : before.present ? 'repaired' : 'created';
363
+ return {
364
+ status: result,
365
+ mode: 'provision_connected_host_token',
366
+ setupItemId: 'connected-host-auth',
367
+ explicitUserRequest: previewHarnessText(explicitUserRequest, 160),
368
+ token: {
369
+ path: after.path,
370
+ canonicalPath,
371
+ present: true,
372
+ usable: true,
373
+ fingerprint: afterFingerprint,
374
+ rawValueReturned: false,
375
+ fileMode: safeFileMode(canonicalPath),
376
+ },
377
+ companionRecord: {
378
+ surface: GOODVIBES_AGENT_PAIRING_SURFACE,
379
+ peerId: record.peerId,
380
+ createdAt: safeIso(record.createdAt),
381
+ },
382
+ mutation: {
383
+ performed: result === 'created' || result === 'repaired',
384
+ result,
385
+ existingTokenPreserved: result === 'already_usable',
386
+ source: 'getOrCreateCompanionToken',
387
+ },
388
+ routes: {
389
+ inspectAuth: 'setup action:"item" setupItemId:"connected-host-auth"',
390
+ inspectStatus: 'host action:"status" includeParameters:true',
391
+ pairingPosture: 'agent_harness mode:"pairing_posture" includeParameters:true',
392
+ runSetupSmoke: DEFAULT_AGENT_SETUP_WIZARD_RERUN_SMOKE_ROUTE,
393
+ },
394
+ policy: {
395
+ effect: 'confirmed-local-token-provisioning',
396
+ source: 'SDK platform pairing helper writes the canonical connected-host operator token file with owner-only permissions.',
397
+ secrets: 'Only path, fingerprint, peer id, and timestamps are returned; the raw token is not returned.',
398
+ rotation: 'This route preserves a valid existing token and only creates or repairs the local canonical file.',
399
+ },
400
+ };
401
+ } catch (error) {
402
+ return {
403
+ status: 'failed',
404
+ mode: 'provision_connected_host_token',
405
+ setupItemId: 'connected-host-auth',
406
+ explicitUserRequest: previewHarnessText(explicitUserRequest, 160),
407
+ error: previewHarnessText(error instanceof Error ? error.message : String(error), 160),
408
+ token: {
409
+ path: canonicalPath,
410
+ present: before.present,
411
+ usable: false,
412
+ rawValueReturned: false,
413
+ },
414
+ routes: {
415
+ inspectAuth: 'setup action:"item" setupItemId:"connected-host-auth"',
416
+ inspectStatus: 'host action:"status" includeParameters:true',
417
+ },
418
+ policy: {
419
+ effect: 'confirmed-local-token-provisioning',
420
+ secrets: 'Raw connected-host tokens are never returned.',
421
+ },
422
+ };
423
+ }
424
+ }
425
+
426
+ export async function runSetupInstallSmoke(context: CommandContext, args: AgentHarnessSetupArgs): Promise<Record<string, unknown>> {
427
+ const setupItemId = readString(args.setupItemId);
428
+ if (setupItemId && setupItemId !== 'install-smoke') {
429
+ return {
430
+ status: 'unsupported_setup_item',
431
+ usage: 'run_setup_smoke currently supports setupItemId:"install-smoke" only.',
432
+ };
433
+ }
434
+
435
+ const snapshot = await collectSnapshot(context);
436
+ const servicePosture = await collectServicePosture(context);
437
+ const plan = buildSetupPlan(context, snapshot, deriveStep1Capabilities(snapshot), servicePosture);
438
+ const installSmoke = plan.find((item) => item.id === 'install-smoke');
439
+ const smokePlan = installSmoke?.installSmokePlan;
440
+ if (!smokePlan) {
441
+ return {
442
+ status: 'missing_smoke_plan',
443
+ usage: 'Install smoke plan is not available. Inspect mode:"setup_posture" for setup readiness.',
444
+ };
445
+ }
446
+
447
+ const includeParameters = args.includeParameters === true;
448
+ const summary = installSmokeRunSummary(smokePlan);
449
+ const blockedChecks = smokePlan.checks.filter((check) => check.status === 'blocked').map((check) => check.id);
450
+ const userRunChecks = smokePlan.checks.filter((check) => check.status === 'user-run').map((check) => check.id);
451
+ const capturedAt = new Date(snapshot.capturedAt).toISOString();
452
+ const explicitUserRequest = readString(args.explicitUserRequest);
453
+ const evidenceFields = setupSmokeEvidenceFields(args.fields);
454
+ const artifact = await saveSetupSmokeArtifact({
455
+ context,
456
+ capturedAt,
457
+ explicitUserRequest,
458
+ smokePlan,
459
+ summary,
460
+ blockedChecks,
461
+ userRunChecks,
462
+ evidenceFields,
463
+ });
464
+ return {
465
+ status: 'executed',
466
+ mode: 'run_setup_smoke',
467
+ setupItemId: 'install-smoke',
468
+ capturedAt,
469
+ smokeStatus: smokePlan.status,
470
+ result: installSmokeRunResult(smokePlan),
471
+ explicitUserRequest: previewHarnessText(explicitUserRequest, 160),
472
+ summary,
473
+ blockedChecks,
474
+ userRunChecks,
475
+ checks: smokePlan.checks.map((check) => describeInstallSmokeCheck(check, includeParameters)),
476
+ artifact,
477
+ successCriteria: includeParameters ? smokePlan.successCriteria : smokePlan.successCriteria.map((entry) => previewHarnessText(entry, 120)),
478
+ nextAction: installSmokeNextAction(smokePlan),
479
+ routes: {
480
+ inspectSetup: DEFAULT_AGENT_SETUP_WIZARD_REVIEW_ROUTE,
481
+ inspectSmoke: 'setup action:"item" setupItemId:"install-smoke"',
482
+ rerunSmoke: DEFAULT_AGENT_SETUP_WIZARD_RERUN_SMOKE_ROUTE,
483
+ saveEvidence: DEFAULT_AGENT_SETUP_WIZARD_SAVE_SMOKE_ROUTE,
484
+ },
485
+ policy: {
486
+ effect: 'confirmed-redacted-setup-smoke',
487
+ shell: 'No package, host, or shell commands were executed implicitly.',
488
+ secrets: 'Secrets and connected-host tokens are never returned; token evidence remains presence, path, and fingerprint only.',
489
+ source: smokePlan.policy,
490
+ },
491
+ source: smokePlan.source,
492
+ };
493
+ }
494
+
278
495
  export async function describeHarnessSetupItem(context: CommandContext, args: AgentHarnessSetupArgs): Promise<SetupResolution> {
279
496
  const lookup = lookupFromArgs(args);
280
497
  if (!lookup) {
@@ -284,19 +501,30 @@ export async function describeHarnessSetupItem(context: CommandContext, args: Ag
284
501
  };
285
502
  }
286
503
  const snapshot = await collectSnapshot(context);
504
+ const servicePosture = await collectServicePosture(context);
287
505
  const items = deriveStep1Capabilities(snapshot);
506
+ const plan = buildSetupPlan(context, snapshot, items, servicePosture);
288
507
  const normalized = lookup.input.toLowerCase();
289
508
  const exact = items.find((item) => item.id === lookup.input);
290
509
  if (exact) return { status: 'found', item: describeItem(exact, snapshot, { includeParameters: true, lookup: { ...lookup, resolvedBy: 'id' } }) };
510
+ const exactPlan = plan.find((item) => item.id === lookup.input);
511
+ if (exactPlan) return { status: 'found', item: { ...describePlanItem(exactPlan, true), lookup: { ...lookup, resolvedBy: 'plan-id' } } };
291
512
  const insensitive = items.find((item) => item.id.toLowerCase() === normalized);
292
513
  if (insensitive) return { status: 'found', item: describeItem(insensitive, snapshot, { includeParameters: true, lookup: { ...lookup, resolvedBy: 'case-insensitive-id' } }) };
514
+ const insensitivePlan = plan.find((item) => item.id.toLowerCase() === normalized);
515
+ if (insensitivePlan) return { status: 'found', item: { ...describePlanItem(insensitivePlan, true), lookup: { ...lookup, resolvedBy: 'case-insensitive-plan-id' } } };
293
516
  const searched = items.filter((item) => itemSearchText(item).includes(normalized));
294
- if (searched.length === 1) return { status: 'found', item: describeItem(searched[0]!, snapshot, { includeParameters: true, lookup: { ...lookup, resolvedBy: 'search' } }) };
295
- if (searched.length > 1) {
517
+ const searchedPlan = plan.filter((item) => planSearchText(item).includes(normalized));
518
+ if (searched.length === 1 && searchedPlan.length === 0) return { status: 'found', item: describeItem(searched[0]!, snapshot, { includeParameters: true, lookup: { ...lookup, resolvedBy: 'search' } }) };
519
+ if (searched.length === 0 && searchedPlan.length === 1) return { status: 'found', item: { ...describePlanItem(searchedPlan[0]!, true), lookup: { ...lookup, resolvedBy: 'plan-search' } } };
520
+ if (searched.length > 0 || searchedPlan.length > 0) {
296
521
  return {
297
522
  status: 'ambiguous',
298
523
  input: lookup.input,
299
- candidates: searched.slice(0, 8).map(describeCandidate),
524
+ candidates: [
525
+ ...searched.map(describeCandidate),
526
+ ...searchedPlan.map((item) => describePlanItem(item, false)),
527
+ ].slice(0, 8),
300
528
  };
301
529
  }
302
530
  return {