@pellux/goodvibes-agent 0.1.66 → 0.1.67

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  All notable changes to GoodVibes Agent will be recorded here.
4
4
 
5
+ ## 0.1.67 - 2026-05-31
6
+
7
+ - Reworked remote bridge and remote review language from copied runner/control-room wording to Agent-facing worker/review wording.
8
+ - Made bridge worker assignment read-only in Agent and removed hidden contract creation from remote show/contract paths.
9
+ - Added regressions around the remote worker review panel and bridge command wording.
10
+
5
11
  ## 0.1.66 - 2026-05-31
6
12
 
7
13
  - Removed remote-runner and node/device posture wording from first-run Agent setup surfaces.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pellux/goodvibes-agent",
3
- "version": "0.1.66",
3
+ "version": "0.1.67",
4
4
  "private": false,
5
5
  "description": "GoodVibes personal operator assistant TUI with a proactive Agent product brain, isolated Agent Knowledge, local profiles, routines, skills, personas, and explicit build delegation.",
6
6
  "type": "module",
@@ -148,7 +148,7 @@ export function registerExperienceRuntimeCommands(registry: CommandRegistry): vo
148
148
  name: 'worker-pool',
149
149
  aliases: ['pool'],
150
150
  description: 'Dedicated front-door for remote worker pool review flows',
151
- usage: '[list|show <id>|create <id> <label...>|assign <pool> <runner>|unassign <pool> <runner>]',
151
+ usage: '[list|show <id>]',
152
152
  async handler(args, ctx) {
153
153
  const sub = (args[0] ?? 'list').toLowerCase();
154
154
  if (!ctx.executeCommand) {
@@ -164,11 +164,11 @@ export function registerExperienceRuntimeCommands(registry: CommandRegistry): vo
164
164
  return;
165
165
  }
166
166
  if (sub === 'create' && args[1] && args.length >= 3) {
167
- await ctx.executeCommand('remote', ['pool', 'create', args[1], ...args.slice(2)]);
167
+ ctx.print('Remote worker pool mutation is blocked in GoodVibes Agent. Use /worker-pool list or /worker-pool show <id>.');
168
168
  return;
169
169
  }
170
170
  if ((sub === 'assign' || sub === 'unassign') && args[1] && args[2]) {
171
- await ctx.executeCommand('remote', ['pool', sub, args[1], args[2]]);
171
+ ctx.print('Remote worker pool mutation is blocked in GoodVibes Agent. Use /worker-pool list or /worker-pool show <id>.');
172
172
  return;
173
173
  }
174
174
  ctx.print('Usage: /worker-pool [list|show <id>]');
@@ -132,7 +132,7 @@ export function registerProductRuntimeCommands(registry: CommandRegistry): void
132
132
  registry.register({
133
133
  name: 'bridge',
134
134
  description: 'Review self-hosted bridge and remote worker flows',
135
- usage: '[status|pools|assign <pool> <runner> --yes|runner <id>|review <artifactId>|export <artifactId> [path] --yes|import <path> --yes]',
135
+ usage: '[status|pools|worker <id>|review <artifactId>|export <artifactId> [path] --yes|import <path> --yes]',
136
136
  async handler(args, ctx) {
137
137
  const parsed = stripYesFlag(args);
138
138
  const commandArgs = [...parsed.rest];
@@ -156,7 +156,7 @@ export function registerProductRuntimeCommands(registry: CommandRegistry): void
156
156
  if (sub === 'pools') {
157
157
  const pools = remoteRegistry.listPools();
158
158
  ctx.print(pools.length > 0
159
- ? ['Bridge Pools', ...pools.map((pool) => ` ${pool.id} runners=${pool.runnerIds.length} trust=${pool.trustClass}`)].join('\n')
159
+ ? ['Bridge Pools', ...pools.map((pool) => ` ${pool.id} workers=${pool.runnerIds.length} trust=${pool.trustClass}`)].join('\n')
160
160
  : 'Bridge Pools\n No worker pools registered yet.');
161
161
  return;
162
162
  }
@@ -164,34 +164,30 @@ export function registerProductRuntimeCommands(registry: CommandRegistry): void
164
164
  const poolId = commandArgs[1];
165
165
  const runnerId = commandArgs[2];
166
166
  if (!poolId || !runnerId) {
167
- ctx.print('Usage: /bridge assign <pool> <runner> --yes');
167
+ ctx.print('Usage: /bridge assign <pool> <worker> --yes');
168
168
  return;
169
169
  }
170
- if (!parsed.yes) {
171
- requireYesFlag(ctx, `assign bridge runner ${runnerId} to pool ${poolId}`, '/bridge assign <pool> <runner> --yes');
172
- return;
173
- }
174
- const pool = remoteRegistry.assignRunnerToPool(poolId, runnerId);
175
- if (!pool) {
176
- ctx.print(`Unable to assign runner ${runnerId} to pool ${poolId}.`);
177
- return;
178
- }
179
- ctx.print(`Assigned runner ${runnerId} to bridge pool ${poolId}.`);
170
+ ctx.print([
171
+ 'Bridge worker assignment is read-only in GoodVibes Agent.',
172
+ ` requested: /bridge assign ${poolId} ${runnerId}`,
173
+ ' policy: Agent reviews remote bridge state but does not mutate worker topology',
174
+ ' next: inspect /bridge pools or delegate explicit build/fix/review work to GoodVibes TUI',
175
+ ].join('\n'));
180
176
  return;
181
177
  }
182
- if (sub === 'runner') {
178
+ if (sub === 'runner' || sub === 'worker') {
183
179
  const runnerId = commandArgs[1];
184
180
  if (!runnerId) {
185
- ctx.print('Usage: /bridge runner <id>');
181
+ ctx.print('Usage: /bridge worker <id>');
186
182
  return;
187
183
  }
188
184
  const contract = remoteRegistry.getContract(runnerId);
189
185
  if (!contract) {
190
- ctx.print(`Unknown runner contract: ${runnerId}`);
186
+ ctx.print(`Unknown worker contract: ${runnerId}`);
191
187
  return;
192
188
  }
193
189
  ctx.print([
194
- `Bridge Runner ${runnerId}`,
190
+ `Bridge Worker ${runnerId}`,
195
191
  ` template: ${contract.template}`,
196
192
  ` trustClass: ${contract.trustClass}`,
197
193
  ` transport: ${contract.sourceTransport}/${contract.transport.state}`,
@@ -242,10 +238,10 @@ export function registerProductRuntimeCommands(registry: CommandRegistry): void
242
238
  return;
243
239
  }
244
240
  const artifact = await remoteRegistry.importArtifact(shellPaths.resolveWorkspacePath(pathArg));
245
- ctx.print(`Imported remote bridge artifact ${artifact.id} for runner ${artifact.runnerId}.`);
241
+ ctx.print(`Imported remote bridge artifact ${artifact.id} for worker ${artifact.runnerId}.`);
246
242
  return;
247
243
  }
248
- ctx.print('Usage: /bridge [status|pools|assign <pool> <runner> --yes|runner <id>|review <artifactId>|export <artifactId> [path] --yes|import <path> --yes]');
244
+ ctx.print('Usage: /bridge [status|pools|worker <id>|review <artifactId>|export <artifactId> [path] --yes|import <path> --yes]');
249
245
  },
250
246
  });
251
247
 
@@ -36,7 +36,7 @@ export function handleRemoteCancelCommand(
36
36
  ctx.print([
37
37
  'GoodVibes Agent remote control is read-only.',
38
38
  ` requested: /remote cancel ${agentId}`,
39
- ' policy: Agent does not cancel local ACP/runner processes from this surface',
39
+ ' policy: Agent does not cancel local remote-worker processes from this surface',
40
40
  ' next: inspect with /remote show or delegate explicit build/fix/review work to GoodVibes TUI',
41
41
  ].join('\n'));
42
42
  }
@@ -46,7 +46,7 @@ export function registerRemoteRuntimeCommands(registry: CommandRegistry): void {
46
46
  name: 'remote',
47
47
  aliases: [],
48
48
  description: 'Inspect remote workers, delegated work receipts, and review artifacts',
49
- usage: '[list | show [agentId] | supervisor [workerId] | support [workerId] | recover [workerId] | setup [export <path> --yes] | env [export <path> --yes] | tunnel [review|export <path> --yes] | bootstrap [export <path> --yes|inspect <path>] | session <export|inspect|import> <path> [--yes] | pool <list|show> ... | dispatch [template] <description> | dispatch-pool <pool> [template] <description> | contract [agentId] | cancel <agentId> | export <agentId> [path] --yes | artifact list | artifact show <id> | artifact export <id> [path] --yes | review <id> | rerun-local <id> | import <path> --yes]',
49
+ usage: '[list | show [agentId] | supervisor [workerId] | support [workerId] | recover [workerId] | setup [export <path> --yes] | env [export <path> --yes] | tunnel [review|export <path> --yes] | bootstrap [export <path> --yes|inspect <path>] | session <export|inspect|import> <path> [--yes] | pool <list|show> ... | dispatch [template] <description> | dispatch-pool <pool> [template] <description> | contract [workerId] | cancel <agentId> | export <agentId> [path] --yes | artifact list | artifact show <id> | artifact export <id> [path] --yes | review <id> | rerun-local <id> | import <path> --yes]',
50
50
  async handler(args, ctx) {
51
51
  if (args.length === 0) {
52
52
  if (ctx.openRemotePanel) {
@@ -210,7 +210,7 @@ export function registerRemoteRuntimeCommands(registry: CommandRegistry): void {
210
210
  ctx.print(agentId ? `Unknown remote connection: ${agentId}` : 'No active remote connections.');
211
211
  return;
212
212
  }
213
- const contract = remoteRunners.upsertContractForAgent(connection.agentId);
213
+ const contract = remoteRunners.getContract(connection.agentId);
214
214
  ctx.print([
215
215
  `Remote connection ${connection.agentId}`,
216
216
  ` label: ${connection.label}`,
@@ -278,14 +278,14 @@ export function registerRemoteRuntimeCommands(registry: CommandRegistry): void {
278
278
  ctx.print('No remote worker contracts are available yet.');
279
279
  return;
280
280
  }
281
- const contract = remoteRunners.upsertContractForAgent(agentId);
281
+ const contract = remoteRunners.getContract(agentId);
282
282
  if (!contract) {
283
283
  ctx.print(`Unknown remote worker: ${agentId}`);
284
284
  return;
285
285
  }
286
286
  ctx.print([
287
287
  `Remote worker contract ${contract.id}`,
288
- ` runnerId: ${contract.runnerId}`,
288
+ ` workerId: ${contract.runnerId}`,
289
289
  ` label: ${contract.label}`,
290
290
  ` pool: ${contract.poolId ?? '(none)'}`,
291
291
  ` trustClass: ${contract.trustClass}`,
@@ -422,7 +422,7 @@ export function registerRemoteRuntimeCommands(registry: CommandRegistry): void {
422
422
  return;
423
423
  }
424
424
  const artifact = await remoteRunners.importArtifact(path);
425
- ctx.print(`Imported remote review artifact ${artifact.id} for runner ${artifact.runnerId}.`);
425
+ ctx.print(`Imported remote review artifact ${artifact.id} for worker ${artifact.runnerId}.`);
426
426
  return;
427
427
  }
428
428
 
@@ -85,7 +85,7 @@ export function buildProviderHealthDomainSummaries(
85
85
  summary: remote.supervisor.sessions.length === 0
86
86
  ? 'no remote sessions tracked'
87
87
  : `${remote.supervisor.sessions.length} sessions / ${remote.supervisor.degradedConnections} degraded`,
88
- next: remote.supervisor.degradedConnections > 0 ? '/remote recover <runnerId>' : '/remote supervisor',
88
+ next: remote.supervisor.degradedConnections > 0 ? '/remote recover <workerId>' : '/remote supervisor',
89
89
  details: remote.supervisor.sessions.length === 0
90
90
  ? ['no remote sessions have been attached yet']
91
91
  : remote.supervisor.sessions
@@ -98,7 +98,7 @@ export function buildProviderHealthDomainSummaries(
98
98
  .slice(0, 3)
99
99
  .map((entry) => `${entry.runnerId}: transport=${entry.transportState} heartbeat=${entry.heartbeat.status}${entry.lastError ? ` error=${entry.lastError}` : ''}`),
100
100
  nextSteps: remote.supervisor.degradedConnections > 0
101
- ? ['/remote supervisor', '/remote recover <runnerId>', '/remote support']
101
+ ? ['/remote supervisor', '/remote recover <workerId>', '/remote support']
102
102
  : ['/remote supervisor'],
103
103
  });
104
104
 
@@ -111,13 +111,13 @@ export class RemotePanel extends BasePanel {
111
111
 
112
112
  public render(width: number, height: number): Line[] {
113
113
  this.needsRender = false;
114
- const intro = 'Bridge, ACP, runner-contract, and artifact posture for self-hosted remote work.';
114
+ const intro = 'Remote worker, bridge, and review-artifact posture for delegated work.';
115
115
 
116
116
  if (!this.readModel) {
117
117
  const sectionLines = buildEmptyState(
118
118
  width,
119
119
  ' Runtime store not wired into this panel yet.',
120
- 'The remote control room needs the shell read model so it can display ACP state, runner contracts, and replay artifacts.',
120
+ 'The remote review workspace needs the shell read model so it can display worker state and review artifacts.',
121
121
  [
122
122
  { command: '/remote setup', summary: 'review bootstrap, env, tunnel, and bridge guidance' },
123
123
  { command: '/remote panel', summary: 'reopen the panel from the shell-owned runtime' },
@@ -125,7 +125,7 @@ export class RemotePanel extends BasePanel {
125
125
  C,
126
126
  );
127
127
  const lines = buildPanelWorkspace(width, height, {
128
- title: 'Remote Control Room',
128
+ title: 'Remote Work Review',
129
129
  intro,
130
130
  sections: [{ lines: sectionLines }],
131
131
  palette: C,
@@ -176,7 +176,7 @@ export class RemotePanel extends BasePanel {
176
176
  [String(acp.totalMessages), acp.totalMessages > 0 ? C.value : C.dim],
177
177
  ]),
178
178
  buildPanelLine(width, [
179
- [' runner contracts ', C.label],
179
+ [' worker contracts ', C.label],
180
180
  [String(contracts.length), C.info],
181
181
  [' pools ', C.label],
182
182
  [String(pools.length), pools.length > 0 ? C.info : C.dim],
@@ -204,7 +204,7 @@ export class RemotePanel extends BasePanel {
204
204
  ]));
205
205
  }
206
206
  postureLines.push(
207
- buildGuidanceLine(width, '/remote recover', 'resume remote state with runner support and disconnect recovery hints', C),
207
+ buildGuidanceLine(width, '/remote recover', 'inspect remote state with worker support and disconnect recovery hints', C),
208
208
  buildGuidanceLine(width, '/remote support', 'inspect transport support before routing remote work or reattaching a session', C),
209
209
  );
210
210
 
@@ -219,17 +219,17 @@ export class RemotePanel extends BasePanel {
219
219
  ...buildEmptyState(
220
220
  width,
221
221
  ' No active ACP or remote subagent connections.',
222
- 'The remote control room is healthy but idle. Runner contracts, session bundles, and bridge pools will appear here once remote work starts.',
222
+ 'Remote review is healthy but idle. Worker contracts, session bundles, and bridge pools will appear here once delegated work exists.',
223
223
  [
224
224
  { command: '/remote setup', summary: 'review remote bootstrap and environment export' },
225
225
  { command: '/remote env', summary: 'emit a reusable remote shell snippet' },
226
- { command: '/bridge status', summary: 'inspect runner pools and existing remote artifacts' },
226
+ { command: '/bridge status', summary: 'inspect worker pools and existing remote artifacts' },
227
227
  ],
228
228
  C,
229
229
  ),
230
230
  ];
231
231
  const lines = buildPanelWorkspace(width, height, {
232
- title: 'Remote Control Room',
232
+ title: 'Remote Work Review',
233
233
  intro,
234
234
  sections: [{ lines: buildSummaryBlock(width, 'Remote posture', idleLines, C) }],
235
235
  footerLines,
@@ -341,7 +341,7 @@ export class RemotePanel extends BasePanel {
341
341
  ]));
342
342
  } else if (selectedContract) {
343
343
  detailRows.push(buildPanelLine(width, [
344
- [' Runner: ', C.label],
344
+ [' Worker: ', C.label],
345
345
  [selectedContract.runnerId, C.value],
346
346
  [' Template: ', C.label],
347
347
  [selectedContract.template, C.info],
@@ -392,7 +392,7 @@ export class RemotePanel extends BasePanel {
392
392
  const detailSection: PanelWorkspaceSection = {
393
393
  lines: buildDetailBlock(width, selected ? 'Selected connection' : 'Selected contract', detailRows, C),
394
394
  };
395
- const browseTitle = viewingConnections ? 'Active Connections' : 'Registered Remote Runner Contracts';
395
+ const browseTitle = viewingConnections ? 'Active Connections' : 'Registered Remote Worker Contracts';
396
396
  const rawBrowseLines: Line[] = viewingConnections
397
397
  ? activeConnections.map((connection, absolute) => {
398
398
  return buildPanelListRow(width, [
@@ -437,7 +437,7 @@ export class RemotePanel extends BasePanel {
437
437
  detailSection,
438
438
  ];
439
439
  const lines = buildPanelWorkspace(width, height, {
440
- title: 'Remote Control Room',
440
+ title: 'Remote Work Review',
441
441
  intro,
442
442
  sections,
443
443
  footerLines,
@@ -66,7 +66,7 @@ function formatReturnContextLines(returnContext: SessionInfo['returnContext']):
66
66
  lines.push(`tasks: active=${returnContext.activeTasks ?? 0} blocked=${returnContext.blockedTasks ?? 0} approvals=${returnContext.pendingApprovals ?? 0}`);
67
67
  }
68
68
  if (returnContext.remoteRunners?.length) {
69
- lines.push(`remote runners: ${returnContext.remoteRunners.join(', ')}`);
69
+ lines.push(`remote workers: ${returnContext.remoteRunners.join(', ')}`);
70
70
  }
71
71
  if (returnContext.openPanels?.length) {
72
72
  lines.push(`open panels: ${returnContext.openPanels.join(', ')}`);
package/src/version.ts CHANGED
@@ -6,7 +6,7 @@ import { join } from 'node:path';
6
6
  // The prebuild script updates the fallback value before compilation.
7
7
  // Uses import.meta.dir (Bun) to locate package.json relative to this file,
8
8
  // which is correct regardless of the process working directory.
9
- let _version = '0.1.66';
9
+ let _version = '0.1.67';
10
10
  let _sdkVersion = '0.33.35';
11
11
  try {
12
12
  const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', 'package.json'), 'utf-8')) as {