@agentbridge1/cli 0.0.4 → 0.0.6

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.
@@ -1,6 +1,6 @@
1
1
  {
2
- "builtAt": "2026-06-02T04:55:04.008Z",
3
- "gitHead": "86fed7f",
4
- "sourceLatestMtime": "2026-06-02T04:51:46.614Z",
5
- "sourceLatestFile": "src/commands/connect.ts"
2
+ "builtAt": "2026-06-06T12:05:27.957Z",
3
+ "gitHead": "ec17ba8",
4
+ "sourceLatestMtime": "2026-06-06T11:59:41.649Z",
5
+ "sourceLatestFile": "src/commands/watch.ts"
6
6
  }
@@ -10,6 +10,7 @@ const server_sync_1 = require("../server-sync");
10
10
  const operator_snapshot_1 = require("../operator-snapshot");
11
11
  const work_context_resolver_1 = require("../work-context-resolver");
12
12
  const error_catalog_1 = require("../error-catalog");
13
+ const proof_obligations_1 = require("../proof-obligations");
13
14
  const acceptance_preflight_1 = require("../acceptance-preflight");
14
15
  const acceptance_block_1 = require("../acceptance-block");
15
16
  function resolveNetworkContext() {
@@ -36,10 +37,9 @@ function blockedErrorCode(report) {
36
37
  if ((report.out_of_scope_files ?? []).length > 0 || report.scope_status === "drift") {
37
38
  return "SCOPE_DRIFT_OUT_OF_SCOPE_FILE";
38
39
  }
39
- if (report.decision === "needs_proof")
40
- return "PROOF_MISSING";
41
- if (report.decision === "stale_evidence")
42
- return "PROOF_STALE_AFTER_CHANGE";
40
+ const proofCode = (0, proof_obligations_1.resolveProofBlockingErrorCode)(report);
41
+ if (proofCode)
42
+ return proofCode;
43
43
  return "ACCEPTANCE_BLOCKED";
44
44
  }
45
45
  function buildStructuredBlockedOutput(report) {
@@ -9,6 +9,7 @@ const acceptance_preflight_1 = require("../acceptance-preflight");
9
9
  const work_context_resolver_1 = require("../work-context-resolver");
10
10
  const operator_snapshot_1 = require("../operator-snapshot");
11
11
  const proof_guidance_1 = require("../proof-guidance");
12
+ const proof_obligations_1 = require("../proof-obligations");
12
13
  const memory_context_render_1 = require("../memory-context-render");
13
14
  const acceptance_block_1 = require("../acceptance-block");
14
15
  function resolveNetworkContext() {
@@ -184,8 +185,16 @@ function renderAcceptanceReport(report) {
184
185
  }
185
186
  }
186
187
  }
188
+ const obligationSection = (0, proof_obligations_1.renderProofObligationSection)(report);
189
+ if (obligationSection.length > 0) {
190
+ lines.push(...obligationSection);
191
+ }
187
192
  lines.push(`Decision: ${report.decision}`);
188
- if (report.decision === "needs_proof") {
193
+ const obligationErrorLines = (0, proof_obligations_1.renderProofObligationErrorLines)(report);
194
+ if (obligationErrorLines.length > 0) {
195
+ lines.push(...obligationErrorLines);
196
+ }
197
+ else if (report.decision === "needs_proof") {
189
198
  lines.push("✗ Error code: PROOF_MISSING");
190
199
  lines.push(" What happened: No verification proof exists for this work session.");
191
200
  lines.push(" Why it matters: Unverified work cannot be accepted — proof is required.");
@@ -84,6 +84,113 @@ async function listAgents(projectId, apiKey, apiBaseUrl) {
84
84
  const body = (await res.json());
85
85
  return Array.isArray(body.agents) ? body.agents : [];
86
86
  }
87
+ async function resolveExecutionSurfaceFromHello(projectId, apiKey, apiBaseUrl) {
88
+ const url = `${apiBaseUrl}/v1/dev/projects/${projectId}/hello`;
89
+ try {
90
+ const res = await fetch(url, {
91
+ method: "POST",
92
+ headers: {
93
+ Authorization: `Bearer ${apiKey}`,
94
+ "Content-Type": "application/json",
95
+ },
96
+ body: JSON.stringify({ tool_type: "cli" }),
97
+ });
98
+ if (!res.ok) {
99
+ return {
100
+ executionSurfaceId: null,
101
+ identityModel: "unknown",
102
+ status: `http_${res.status}`,
103
+ };
104
+ }
105
+ const body = (await res.json());
106
+ if (body.identity_model !== "work_identity") {
107
+ if (body.identity_model === "legacy") {
108
+ return {
109
+ executionSurfaceId: null,
110
+ identityModel: "legacy",
111
+ status: "legacy_identity",
112
+ };
113
+ }
114
+ return {
115
+ executionSurfaceId: null,
116
+ identityModel: "unknown",
117
+ status: "unknown_identity_model",
118
+ };
119
+ }
120
+ const surfaceId = body.execution_surface?.id?.trim();
121
+ return {
122
+ executionSurfaceId: surfaceId || null,
123
+ identityModel: "work_identity",
124
+ status: surfaceId ? "ok" : "missing_execution_surface",
125
+ };
126
+ }
127
+ catch {
128
+ return {
129
+ executionSurfaceId: null,
130
+ identityModel: "unknown",
131
+ status: "network_error",
132
+ };
133
+ }
134
+ }
135
+ async function bootstrapDefaultConnection(projectId, apiKey, apiBaseUrl) {
136
+ const url = `${apiBaseUrl}/v1/dev/projects/${projectId}/connections/bootstrap-default`;
137
+ try {
138
+ const res = await fetch(url, {
139
+ method: "POST",
140
+ headers: {
141
+ Authorization: `Bearer ${apiKey}`,
142
+ "Content-Type": "application/json",
143
+ },
144
+ body: JSON.stringify({}),
145
+ });
146
+ if (!res.ok)
147
+ return { ok: false, status: res.status, reason: `http_${res.status}` };
148
+ const body = (await res.json());
149
+ const nextApiKey = body.api_key?.trim();
150
+ const executionSurfaceId = body.execution_surface_id?.trim();
151
+ if (!nextApiKey || !executionSurfaceId) {
152
+ return { ok: false, status: 200, reason: "invalid_payload" };
153
+ }
154
+ return { ok: true, apiKey: nextApiKey, executionSurfaceId };
155
+ }
156
+ catch {
157
+ return { ok: false, status: 0, reason: "network_error" };
158
+ }
159
+ }
160
+ async function rotateActiveConnectionKey(projectId, apiKey, apiBaseUrl) {
161
+ const listUrl = `${apiBaseUrl}/v1/dev/projects/${projectId}/connections`;
162
+ try {
163
+ const listRes = await fetch(listUrl, {
164
+ headers: { Authorization: `Bearer ${apiKey}` },
165
+ });
166
+ if (!listRes.ok)
167
+ return { ok: false, reason: `list_http_${listRes.status}` };
168
+ const listBody = (await listRes.json());
169
+ const activeConnection = (listBody.connections ?? []).find((connection) => connection?.id && connection?.status === "active");
170
+ if (!activeConnection?.id)
171
+ return { ok: false, reason: "no_active_connection" };
172
+ const rotateUrl = `${apiBaseUrl}/v1/dev/projects/${projectId}/connections/${activeConnection.id}/rotate-key`;
173
+ const rotateRes = await fetch(rotateUrl, {
174
+ method: "POST",
175
+ headers: {
176
+ Authorization: `Bearer ${apiKey}`,
177
+ "Content-Type": "application/json",
178
+ },
179
+ body: JSON.stringify({}),
180
+ });
181
+ if (!rotateRes.ok)
182
+ return { ok: false, reason: `rotate_http_${rotateRes.status}` };
183
+ const rotateBody = (await rotateRes.json());
184
+ const rotatedApiKey = rotateBody.api_key?.trim();
185
+ const executionSurfaceId = rotateBody.connection?.execution_surface?.id?.trim();
186
+ if (!rotatedApiKey || !executionSurfaceId)
187
+ return { ok: false, reason: "invalid_payload" };
188
+ return { ok: true, apiKey: rotatedApiKey, executionSurfaceId };
189
+ }
190
+ catch {
191
+ return { ok: false, reason: "network_error" };
192
+ }
193
+ }
87
194
  async function runConnect(options = {}) {
88
195
  process.stdout.write("AgentBridge connect\n");
89
196
  process.stdout.write("─────────────────────────────────────────\n");
@@ -142,13 +249,86 @@ async function runConnect(options = {}) {
142
249
  throw err;
143
250
  }
144
251
  process.stdout.write("OK\n");
252
+ let effectiveApiKey = apiKey;
253
+ const diagnostics = {
254
+ helloIdentityModel: "unknown",
255
+ helloStatus: "not_attempted",
256
+ bootstrapStatus: "not_attempted",
257
+ rotateStatus: "not_attempted",
258
+ };
259
+ const helloResolution = await resolveExecutionSurfaceFromHello(projectId, effectiveApiKey, apiBaseUrl);
260
+ diagnostics.helloIdentityModel = helloResolution.identityModel;
261
+ diagnostics.helloStatus = helloResolution.status;
262
+ let executionSurfaceId = helloResolution.executionSurfaceId;
263
+ let connectionUpgraded = false;
264
+ if (!executionSurfaceId) {
265
+ diagnostics.bootstrapStatus = "attempted";
266
+ const bootstrapAttempt = await bootstrapDefaultConnection(projectId, effectiveApiKey, apiBaseUrl);
267
+ if (bootstrapAttempt.ok) {
268
+ effectiveApiKey = bootstrapAttempt.apiKey;
269
+ executionSurfaceId = bootstrapAttempt.executionSurfaceId;
270
+ diagnostics.bootstrapStatus = "ok";
271
+ diagnostics.rotateStatus = "skipped";
272
+ connectionUpgraded = true;
273
+ }
274
+ else if (bootstrapAttempt.status === 409) {
275
+ diagnostics.bootstrapStatus = "http_409_existing_connection";
276
+ const rotated = await rotateActiveConnectionKey(projectId, effectiveApiKey, apiBaseUrl);
277
+ if (rotated.ok) {
278
+ diagnostics.rotateStatus = "ok";
279
+ effectiveApiKey = rotated.apiKey;
280
+ executionSurfaceId = rotated.executionSurfaceId;
281
+ connectionUpgraded = true;
282
+ }
283
+ else {
284
+ diagnostics.rotateStatus = rotated.reason;
285
+ }
286
+ }
287
+ else {
288
+ diagnostics.bootstrapStatus = bootstrapAttempt.reason;
289
+ diagnostics.rotateStatus = "skipped";
290
+ }
291
+ }
292
+ else {
293
+ diagnostics.bootstrapStatus = "skipped";
294
+ diagnostics.rotateStatus = "skipped";
295
+ }
296
+ if (!executionSurfaceId) {
297
+ (0, config_1.updateConfig)({
298
+ projectId,
299
+ apiKey: effectiveApiKey,
300
+ apiBaseUrl,
301
+ });
302
+ throw new errors_1.SafeCliError([
303
+ "Connection incomplete.",
304
+ "Project access was verified, but AgentBridge could not create or resolve an execution surface.",
305
+ "Tracked work cannot start yet.",
306
+ "",
307
+ `hello identity model: ${diagnostics.helloIdentityModel}`,
308
+ `hello status: ${diagnostics.helloStatus}`,
309
+ `bootstrap-default status: ${diagnostics.bootstrapStatus}`,
310
+ `rotate-key status: ${diagnostics.rotateStatus}`,
311
+ `backend URL: ${apiBaseUrl}`,
312
+ ].join("\n"));
313
+ }
145
314
  // Persist credentials
146
- (0, config_1.updateConfig)({ projectId, apiKey, apiBaseUrl });
315
+ (0, config_1.updateConfig)({
316
+ projectId,
317
+ apiKey: effectiveApiKey,
318
+ apiBaseUrl,
319
+ ...(executionSurfaceId ? { executionSurfaceId } : {}),
320
+ });
147
321
  process.stdout.write("Credentials saved to .agentbridge/config.json\n");
322
+ if (connectionUpgraded) {
323
+ process.stdout.write("Auto-configured an AgentConnection key and execution surface for this project.\n");
324
+ }
325
+ else {
326
+ process.stdout.write(`Execution surface: ${executionSurfaceId}\n`);
327
+ }
148
328
  // Pick or auto-select an agent identity
149
329
  let activeAgentId = options.agentId ?? cfg.activeAgentId;
150
330
  if (!activeAgentId) {
151
- const agents = await listAgents(projectId, apiKey, apiBaseUrl);
331
+ const agents = await listAgents(projectId, effectiveApiKey, apiBaseUrl);
152
332
  if (agents.length === 1 && agents[0]) {
153
333
  activeAgentId = agents[0].id;
154
334
  (0, config_1.updateConfig)({ activeAgentId });
@@ -159,7 +339,7 @@ async function runConnect(options = {}) {
159
339
  for (const a of agents) {
160
340
  process.stdout.write(` ${a.id} ${a.name ?? ""} ${a.role ?? ""}\n`.trimEnd() + "\n");
161
341
  }
162
- process.stdout.write('\nRun `agentbridge use <agent-id>` to select one, then `agentbridge watch` to start.\n');
342
+ process.stdout.write('\nRun `agentbridge use <agent-id>` to select one.\n');
163
343
  }
164
344
  }
165
345
  else {
@@ -169,24 +349,23 @@ async function runConnect(options = {}) {
169
349
  process.stdout.write("\n");
170
350
  process.stdout.write(`Project: ${projectName}\n`);
171
351
  process.stdout.write(`Agents: ${agentCount}\n`);
352
+ process.stdout.write(`Execution surface: ${executionSurfaceId}\n`);
172
353
  process.stdout.write(`Server: ${apiBaseUrl}\n`);
173
354
  process.stdout.write("\n");
174
355
  if (activeAgentId) {
175
- process.stdout.write("✓ Connected. Next steps:\n");
356
+ process.stdout.write("✓ Connected and ready.\n");
176
357
  process.stdout.write([
177
358
  "",
178
- " 1. Start a work session:",
179
- " agentbridge start --summary \"your task\" --scope \"src/\"",
180
- "",
181
- " 2. Run the watcher (keep it running in a terminal):",
182
- " agentbridge watch",
183
- "",
184
- " 3. Code normally — AgentBridge watches in the background.",
185
- " Approvals surface when you cross domain boundaries.",
359
+ "Next:",
360
+ " agentbridge doctor",
361
+ " agentbridge watch",
186
362
  "",
187
363
  ].join("\n"));
188
364
  }
189
365
  else {
190
- process.stdout.write("✓ Connected. Run `agentbridge use <agent-id>` then `agentbridge watch`.\n");
366
+ process.stdout.write("✓ Connected.\n");
367
+ process.stdout.write("Run `agentbridge use <agent-id>` and then:\n");
368
+ process.stdout.write(" agentbridge doctor\n");
369
+ process.stdout.write(" agentbridge watch\n");
191
370
  }
192
371
  }
@@ -10,6 +10,7 @@ const http_1 = require("../http");
10
10
  const dist_freshness_1 = require("./dist-freshness");
11
11
  const session_state_1 = require("../session-state");
12
12
  const server_sync_1 = require("../server-sync");
13
+ const recovery_reconcile_1 = require("../recovery-reconcile");
13
14
  function cliRootFromCommandDir() {
14
15
  return (0, node_path_1.resolve)(__dirname, "..", "..");
15
16
  }
@@ -86,11 +87,27 @@ function extractHttpReason(error) {
86
87
  }
87
88
  return `http_${error.status}`;
88
89
  }
89
- function recoveryRequiredByPacket(packet) {
90
- if (!packet || packet.project_mode !== "recovery")
91
- return false;
92
- const status = packet.recovery_status ?? null;
93
- return status === "baseline_required" || status === "pending" || status === null;
90
+ function detectGovernanceSignals(workspaceRoot) {
91
+ const rulesMdcPath = (0, node_path_1.resolve)(workspaceRoot, ".cursor", "rules", "agentbridge.mdc");
92
+ const rulesMarkdownPath = (0, node_path_1.resolve)(workspaceRoot, "AGENTBRIDGE.md");
93
+ const mcpConfigPath = (0, node_path_1.resolve)(workspaceRoot, ".cursor", "mcp.json");
94
+ const rulesInstalled = (0, node_fs_1.existsSync)(rulesMdcPath) && (0, node_fs_1.existsSync)(rulesMarkdownPath);
95
+ let mcpConfigured = false;
96
+ if ((0, node_fs_1.existsSync)(mcpConfigPath)) {
97
+ try {
98
+ const parsed = JSON.parse((0, node_fs_1.readFileSync)(mcpConfigPath, "utf8"));
99
+ mcpConfigured = Boolean(parsed?.mcpServers &&
100
+ (parsed.mcpServers["agentbridge"] || parsed.mcpServers["agentbridge-mcp"]));
101
+ }
102
+ catch {
103
+ mcpConfigured = false;
104
+ }
105
+ }
106
+ return {
107
+ rulesInstalled,
108
+ mcpConfigured,
109
+ governanceStatus: rulesInstalled && mcpConfigured ? "active" : "inactive",
110
+ };
94
111
  }
95
112
  async function checkProjectAccess(ctx) {
96
113
  if (!ctx.configComplete) {
@@ -146,7 +163,39 @@ async function checkProjectAccess(ctx) {
146
163
  }
147
164
  async function checkIdentityAccess(ctx) {
148
165
  if (!ctx.configComplete) {
149
- return { status: "skipped", reason: "config_incomplete" };
166
+ return {
167
+ status: "skipped",
168
+ reason: "config_incomplete",
169
+ identityModel: "unknown",
170
+ executionSurfaceId: null,
171
+ startCapable: false,
172
+ };
173
+ }
174
+ const helloUrl = `${ctx.apiBaseUrl}/v1/dev/projects/${ctx.projectId}/hello`;
175
+ let identityModel = "unknown";
176
+ let executionSurfaceId = null;
177
+ try {
178
+ const helloRes = await fetch(helloUrl, {
179
+ method: "POST",
180
+ headers: {
181
+ Authorization: `Bearer ${ctx.apiKey}`,
182
+ "Content-Type": "application/json",
183
+ },
184
+ body: JSON.stringify({ tool_type: "cli" }),
185
+ });
186
+ if (helloRes.ok) {
187
+ const hello = (await helloRes.json());
188
+ if (hello.identity_model === "work_identity") {
189
+ identityModel = "work_identity";
190
+ }
191
+ else if (hello.identity_model === "legacy") {
192
+ identityModel = "legacy";
193
+ }
194
+ executionSurfaceId = hello.execution_surface?.id?.trim() || null;
195
+ }
196
+ }
197
+ catch {
198
+ // Keep default unknown/null and continue with identity resolution checks.
150
199
  }
151
200
  try {
152
201
  const syncCtx = {
@@ -160,18 +209,34 @@ async function checkIdentityAccess(ctx) {
160
209
  (0, server_sync_1.listWorkIdentities)(syncCtx),
161
210
  ]);
162
211
  const callerId = callerPacket?.work_identity?.id ?? null;
163
- if (callerId)
164
- return { status: "ok" };
165
- if (identities.length === 1)
166
- return { status: "ok" };
167
- return { status: "failed", reason: "caller_identity_unresolved" };
212
+ const startCapable = Boolean(executionSurfaceId);
213
+ if (callerId) {
214
+ return { status: "ok", identityModel, executionSurfaceId, startCapable };
215
+ }
216
+ if (identities.length === 1) {
217
+ return { status: "ok", identityModel, executionSurfaceId, startCapable };
218
+ }
219
+ return {
220
+ status: "failed",
221
+ reason: "caller_identity_unresolved",
222
+ identityModel,
223
+ executionSurfaceId,
224
+ startCapable,
225
+ };
168
226
  }
169
227
  catch {
170
- return { status: "failed", reason: "caller_identity_unresolved" };
228
+ return {
229
+ status: "failed",
230
+ reason: "caller_identity_unresolved",
231
+ identityModel,
232
+ executionSurfaceId,
233
+ startCapable: Boolean(executionSurfaceId),
234
+ };
171
235
  }
172
236
  }
173
237
  async function runDoctor(cliRootOverride) {
174
238
  const cliRoot = cliRootOverride ?? cliRootFromCommandDir();
239
+ const workspaceRoot = process.cwd();
175
240
  const cfg = (0, config_1.readConfig)();
176
241
  const freshness = (0, dist_freshness_1.getDistFreshnessReport)(cliRoot);
177
242
  const configPath = cliRootOverride
@@ -191,6 +256,7 @@ async function runDoctor(cliRootOverride) {
191
256
  const projectConfigPresent = projectIdPresent && apiKeyPresent && baseUrlPresent;
192
257
  const activeSession = (0, session_state_1.readSessionState)();
193
258
  const hasActiveWork = Boolean(activeSession?.id || activeSession?.serverSessionId);
259
+ const governance = detectGovernanceSignals(workspaceRoot);
194
260
  const envContributed = Boolean(process.env.AGENTBRIDGE_PROJECT_ID) ||
195
261
  Boolean(process.env.AGENTBRIDGE_API_KEY) ||
196
262
  Boolean(process.env.AGENTBRIDGE_BASE_URL) ||
@@ -230,10 +296,10 @@ async function runDoctor(cliRootOverride) {
230
296
  apiBaseUrl: resolvedBaseUrl,
231
297
  configComplete: projectConfigPresent && projectAccess.status === "ok",
232
298
  });
233
- lines.push(`Caller identity access: ${identityAccess.status}`);
234
- if (identityAccess.reason) {
235
- lines.push(`Caller identity reason: ${identityAccess.reason}`);
236
- }
299
+ lines.push(`Rules installed: ${governance.rulesInstalled ? "yes" : "no"}`);
300
+ lines.push(`MCP configured: ${governance.mcpConfigured ? "yes" : "no"}`);
301
+ lines.push(`Agent governance: ${governance.governanceStatus}`);
302
+ lines.push(`Start capable: ${identityAccess.startCapable ? "yes" : "no"}`);
237
303
  if (projectAccess.status === "failed" && projectAccess.reason) {
238
304
  const view = (0, error_catalog_1.catalogViewForDoctorReason)(projectAccess.reason, projectAccess.suggestedNextAction);
239
305
  lines.push("");
@@ -252,54 +318,122 @@ async function runDoctor(cliRootOverride) {
252
318
  lines.push("Suggested next action: run npm run dogfood:check before external dogfood.");
253
319
  }
254
320
  let productStatus = "not_ready";
255
- if (projectAccess.status === "ok" && identityAccess.status === "ok") {
321
+ if (projectAccess.status === "ok" &&
322
+ identityAccess.status === "ok" &&
323
+ identityAccess.startCapable) {
256
324
  if (hasActiveWork) {
257
325
  productStatus = "active_work_found";
258
326
  }
259
327
  else {
260
- productStatus = recoveryRequiredByPacket(projectAccess.packet)
261
- ? "needs_recover"
262
- : "ready";
328
+ if ((0, recovery_reconcile_1.recoveryBaselineRequired)(projectAccess.packet)) {
329
+ productStatus = "needs_recover";
330
+ }
331
+ else if ((0, recovery_reconcile_1.recoveryIsBasicPacket)(projectAccess.packet)) {
332
+ productStatus = "ready_basic_recovery";
333
+ }
334
+ else {
335
+ productStatus = "ready";
336
+ }
263
337
  }
264
338
  }
339
+ const localSupervisionReady = true;
340
+ const cloudSyncReady = projectAccess.status === "ok";
341
+ const strictTrackedReady = projectAccess.status === "ok" && identityAccess.status === "ok" && identityAccess.startCapable;
342
+ lines.push("");
343
+ lines.push("Capability levels:");
344
+ lines.push(`- Local supervision: ${localSupervisionReady ? "ready" : "unavailable"}`);
345
+ lines.push(`- Cloud sync: ${cloudSyncReady ? "ready" : "unavailable"}`);
346
+ lines.push(`- Strict tracked work: ${strictTrackedReady ? "ready" : "unavailable"}`);
347
+ if (!cloudSyncReady && projectAccess.reason) {
348
+ lines.push(` Cloud sync note: ${projectAccess.reason}`);
349
+ }
350
+ if (!strictTrackedReady && identityAccess.reason) {
351
+ lines.push(` Strict tracked note: ${identityAccess.reason}`);
352
+ }
265
353
  lines.push("");
266
354
  lines.push("Product status:");
267
355
  if (productStatus === "ready") {
268
356
  lines.push("- Connection: ready");
357
+ lines.push("- Governance: " + governance.governanceStatus);
269
358
  lines.push("- Recovery: ready");
270
- lines.push("- Next: agentbridge start");
359
+ lines.push(`- Rules: ${governance.rulesInstalled ? "installed" : "missing"}`);
360
+ lines.push(`- MCP: ${governance.mcpConfigured ? "configured" : "missing"}`);
361
+ lines.push("- Next: run `agentbridge watch` beside Cursor for live supervision");
362
+ }
363
+ else if (productStatus === "ready_basic_recovery") {
364
+ lines.push("- Connection: ready");
365
+ lines.push("- Governance: " + governance.governanceStatus);
366
+ lines.push("- Recovery: basic");
367
+ lines.push(`- Rules: ${governance.rulesInstalled ? "installed" : "missing"}`);
368
+ lines.push(`- MCP: ${governance.mcpConfigured ? "configured" : "missing"}`);
369
+ lines.push("- Note: Project context exists, but domains are not fully mapped yet.");
370
+ lines.push("- Next: run `agent recover --force` for a full domain rebuild, or `agentbridge watch` for live supervision");
271
371
  }
272
372
  else if (productStatus === "active_work_found") {
373
+ const recoveryBasic = (0, recovery_reconcile_1.recoveryIsBasicPacket)(projectAccess.packet);
273
374
  lines.push("- Connection: ready");
274
- lines.push("- Recovery: ready");
375
+ lines.push("- Governance: " + governance.governanceStatus);
376
+ lines.push("- Recovery: " + (recoveryBasic ? "basic" : "ready"));
377
+ lines.push(`- Rules: ${governance.rulesInstalled ? "installed" : "missing"}`);
378
+ lines.push(`- MCP: ${governance.mcpConfigured ? "configured" : "missing"}`);
379
+ if (recoveryBasic) {
380
+ lines.push("- Note: Project context exists, but domains are not fully mapped yet.");
381
+ }
275
382
  lines.push("- Active work: found");
276
- lines.push("- Next: agentbridge start");
383
+ lines.push("- Next: run `agentbridge watch` beside Cursor for live supervision");
277
384
  }
278
385
  else if (productStatus === "needs_recover") {
279
386
  lines.push("- Connection: ready");
387
+ lines.push("- Governance: " + governance.governanceStatus);
280
388
  lines.push("- Recovery: required");
389
+ lines.push(`- Rules: ${governance.rulesInstalled ? "installed" : "missing"}`);
390
+ lines.push(`- MCP: ${governance.mcpConfigured ? "configured" : "missing"}`);
281
391
  lines.push("- Next: agentbridge recover");
282
392
  }
283
393
  else {
284
- lines.push("- Connection: required");
394
+ lines.push("- Connection: incomplete");
395
+ lines.push("- Governance: " + governance.governanceStatus);
285
396
  lines.push("- Recovery: pending");
397
+ lines.push(`- Rules: ${governance.rulesInstalled ? "installed" : "missing"}`);
398
+ lines.push(`- MCP: ${governance.mcpConfigured ? "configured" : "missing"}`);
286
399
  if (!projectConfigPresent) {
287
400
  lines.push("- Note: Connection details are missing. Add credentials, then rerun agentbridge doctor.");
288
401
  }
289
- else if (identityAccess.status !== "ok") {
290
- lines.push("- Note: Caller identity is unresolved. Run agentbridge identity list and set a valid active agent.");
402
+ else if (!identityAccess.startCapable) {
403
+ lines.push("- Reason: execution surface missing.");
404
+ lines.push("- Next: agentbridge connect");
291
405
  }
292
406
  else {
293
407
  lines.push("- Note: Connection check failed. Verify credentials/network, then rerun agentbridge doctor.");
294
408
  }
295
- lines.push("- Next: agentbridge doctor");
409
+ if (identityAccess.startCapable) {
410
+ lines.push("- Next: agentbridge doctor");
411
+ }
412
+ }
413
+ lines.push("");
414
+ lines.push("Advanced details:");
415
+ lines.push(`- Caller identity access: ${identityAccess.status}`);
416
+ if (identityAccess.reason) {
417
+ lines.push(`- Caller identity reason: ${identityAccess.reason}`);
418
+ }
419
+ lines.push(`- Caller identity model: ${identityAccess.identityModel}`);
420
+ lines.push(`- Execution surface present: ${identityAccess.executionSurfaceId ? "yes" : "no"}`);
421
+ lines.push(`- Start capable (strict/session modes): ${identityAccess.startCapable ? "yes" : "no"}`);
422
+ if (identityAccess.status !== "ok") {
423
+ lines.push("- Note: internal identity mismatch affects strict/resume flows, not room-level inferred watch startup.");
424
+ }
425
+ if (governance.governanceStatus === "inactive") {
426
+ lines.push("");
427
+ lines.push("Governance note: AgentBridge can review in terminal, but your AI agent may not stop automatically until rules and MCP are both configured.");
428
+ }
429
+ else {
430
+ lines.push("");
431
+ lines.push("Governance note: AgentBridge rules are installed and MCP is configured. The AI agent should stop when AgentBridge flags blocked work.");
296
432
  }
297
433
  process.stdout.write(`${lines.join("\n")}\n`);
298
434
  if (freshness.state === "stale")
299
435
  return 1;
300
436
  if (projectAccess.status === "failed")
301
437
  return 1;
302
- if (identityAccess.status === "failed")
303
- return 1;
304
438
  return 0;
305
439
  }
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runProofGuidance = runProofGuidance;
4
+ const config_1 = require("../config");
5
+ const errors_1 = require("../errors");
6
+ const server_sync_1 = require("../server-sync");
7
+ function resolveNetworkContext() {
8
+ const cfg = (0, config_1.readConfig)();
9
+ const projectId = process.env.AGENTBRIDGE_PROJECT_ID ?? cfg.projectId;
10
+ const apiKey = process.env.AGENTBRIDGE_API_KEY ?? cfg.apiKey ?? "";
11
+ const apiBaseUrl = process.env.AGENTBRIDGE_BASE_URL ?? cfg.apiBaseUrl ?? "https://agentauth-api-production.up.railway.app";
12
+ if (!projectId) {
13
+ throw new errors_1.SafeCliError("Missing AGENTBRIDGE_PROJECT_ID. Set AGENTBRIDGE_PROJECT_ID (or run `agentbridge init --project ...`).");
14
+ }
15
+ if (!apiKey) {
16
+ throw new errors_1.SafeCliError("Missing AGENTBRIDGE_API_KEY. Provide --api-key, set AGENTBRIDGE_API_KEY, or save apiKey in .agentbridge/config.json.");
17
+ }
18
+ return { projectId, apiKey, apiBaseUrl };
19
+ }
20
+ async function runProofGuidance(options = {}) {
21
+ const ctx = resolveNetworkContext();
22
+ const guidance = await (0, server_sync_1.fetchAgentProofGuidance)(ctx, {
23
+ workSessionId: options.workSessionId,
24
+ changeRequestId: options.changeRequestId,
25
+ rolloutProofTooWeak: options.rolloutProofTooWeak,
26
+ rolloutProofNotRelevant: options.rolloutProofNotRelevant,
27
+ rolloutImpactCoverageGap: options.rolloutImpactCoverageGap,
28
+ });
29
+ process.stdout.write(`${JSON.stringify(guidance, null, 2)}\n`);
30
+ }