@agentbridge1/cli 0.0.5 → 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.
@@ -39,9 +39,8 @@ const domain_resolution_1 = require("../domain-resolution");
39
39
  const errors_1 = require("../errors");
40
40
  const error_catalog_1 = require("../error-catalog");
41
41
  const http_1 = require("../http");
42
- const git_status_1 = require("../git-status");
43
42
  const session_1 = require("../session");
44
- const work_contract_1 = require("../work-contract");
43
+ const session_state_1 = require("../session-state");
45
44
  const server_sync_1 = require("../server-sync");
46
45
  const work_context_resolver_1 = require("../work-context-resolver");
47
46
  const PROMOTION_PLAN = {
@@ -567,84 +566,55 @@ async function executeStartWorkSession(opts) {
567
566
  otherSessionIds: [...new Set(otherSessionIds)],
568
567
  };
569
568
  }
570
- async function runSmartStart(opts = {}) {
571
- const cfg = (0, config_1.readConfig)();
572
- await ensureProjectAccess();
573
- const ctx = (0, config_1.contextFromConfig)();
574
- const explicitAgentId = opts.agentId?.trim();
575
- const configuredActiveAgentId = cfg.activeAgentId?.trim();
576
- if (!explicitAgentId && !configuredActiveAgentId) {
577
- throw (0, errors_1.catalogCliError)("START_MISSING_ACTIVE_AGENT");
578
- }
579
- const executionSurfaceId = await resolveExecutionSurfaceIdForStart(ctx, opts, cfg.executionSurfaceId);
580
- if (!executionSurfaceId) {
581
- throw (0, errors_1.catalogCliError)("START_EXECUTION_SURFACE_REQUIRED");
582
- }
583
- const resolution = await (0, work_context_resolver_1.resolveWorkContext)(ctx, {
584
- allowServerCurrentForCr: true,
585
- includeOtherActiveSessions: true,
586
- });
587
- if (resolution.state === "current_session_resolved") {
588
- process.stdout.write("Active work session found - entering watch mode.\n");
589
- if (!opts.skipWatch) {
590
- const { runWatch } = await Promise.resolve().then(() => __importStar(require("./watch")));
591
- await runWatch({ allowDirty: true });
592
- }
593
- return;
594
- }
595
- if (resolution.state === "ambiguous_active_sessions") {
596
- process.stdout.write(`${(0, work_context_resolver_1.renderWorkContextLines)(resolution).join("\n")}\n`);
597
- throw (0, errors_1.catalogCliError)((0, error_catalog_1.workContextStateToCode)(resolution.state));
598
- }
599
- if (resolution.state === "mismatch" || resolution.state === "stale_orphan_session_detected") {
600
- process.stdout.write(`${(0, work_context_resolver_1.renderWorkContextLines)(resolution).join("\n")}\n`);
601
- throw (0, errors_1.catalogCliError)((0, error_catalog_1.workContextStateToCode)(resolution.state));
602
- }
603
- const inferred = (0, work_contract_1.inferWorkContract)({
569
+ function hasActiveLocalRun() {
570
+ const local = (0, session_state_1.readSessionState)();
571
+ if (!local)
572
+ return false;
573
+ if (local.status !== "active" && local.status !== "blocked")
574
+ return false;
575
+ if (!local.id || local.id === "none")
576
+ return false;
577
+ return true;
578
+ }
579
+ async function runDefaultStart(opts = {}) {
580
+ const { runLocalSupervision } = await Promise.resolve().then(() => __importStar(require("../local-supervision")));
581
+ await runLocalSupervision({
604
582
  prompt: opts.prompt,
605
- branchName: (0, git_status_1.getBranchName)(),
606
- dirtyFiles: (0, git_status_1.getDirtyWorkingTreeFiles)(),
607
- activeChangeRequestId: cfg.activeChangeRequestId ?? null,
608
- });
609
- const draft = {
610
- summary: inferred.summary,
611
- scope: opts.scope?.trim() || inferred.scope,
612
- };
613
- const confirmed = await (0, work_contract_1.confirmWorkContract)(draft, {
614
- nonInteractive: !process.stdin.isTTY,
615
- });
616
- if (!confirmed) {
617
- process.stdout.write("Cancelled.\n");
618
- return;
619
- }
620
- await executeStartWorkSession({
621
- ...opts,
622
- summary: confirmed.summary,
623
- scope: confirmed.scope,
583
+ details: opts.details,
584
+ confirmClose: opts.confirmClose,
624
585
  });
625
- process.stdout.write("Work session started. Entering watch mode...\n");
626
- if (!opts.skipWatch) {
627
- const { runWatch } = await Promise.resolve().then(() => __importStar(require("./watch")));
628
- await runWatch({ allowDirty: true });
629
- }
586
+ }
587
+ function isStrictTrackedStartRequest(opts) {
588
+ if (opts.resume === true)
589
+ return true;
590
+ if (opts.changeRequestId?.trim())
591
+ return true;
592
+ const explicitSummaryFlag = opts.summaryFlagProvided === true;
593
+ const explicitScopeFlag = opts.scopeFlagProvided === true;
594
+ const explicitInputProvided = opts.summary !== undefined || opts.scope !== undefined;
595
+ return explicitSummaryFlag || explicitScopeFlag || explicitInputProvided;
630
596
  }
631
597
  async function runStart(opts = {}) {
598
+ const strictTrackedStart = isStrictTrackedStartRequest(opts);
632
599
  const explicitSummaryFlag = opts.summaryFlagProvided === true;
633
600
  const explicitScopeFlag = opts.scopeFlagProvided === true;
634
601
  const explicitInputProvided = opts.summary !== undefined || opts.scope !== undefined;
635
602
  const explicitModeRequested = explicitSummaryFlag || explicitScopeFlag || explicitInputProvided;
636
603
  const explicitSummary = opts.summary?.trim();
637
604
  const explicitScope = opts.scope?.trim();
638
- if (explicitModeRequested && explicitSummary && explicitScope) {
605
+ if (strictTrackedStart && explicitSummary && explicitScope) {
639
606
  await executeStartWorkSession({ ...opts, summary: explicitSummary, scope: explicitScope });
640
607
  if (!opts.skipWatch) {
641
608
  const { runWatch } = await Promise.resolve().then(() => __importStar(require("./watch")));
642
- await runWatch({ allowDirty: true });
609
+ await runWatch({ allowDirty: true, details: opts.details });
643
610
  }
644
611
  return;
645
612
  }
613
+ if (strictTrackedStart) {
614
+ throw (0, errors_1.catalogCliError)("START_EXPLICIT_PAIR_REQUIRED");
615
+ }
646
616
  if (explicitModeRequested) {
647
617
  throw (0, errors_1.catalogCliError)("START_EXPLICIT_PAIR_REQUIRED");
648
618
  }
649
- await runSmartStart(opts);
619
+ await runDefaultStart(opts);
650
620
  }
@@ -4,22 +4,22 @@ exports.runVerify = runVerify;
4
4
  const node_child_process_1 = require("node:child_process");
5
5
  const config_1 = require("../config");
6
6
  const errors_1 = require("../errors");
7
- const error_catalog_1 = require("../error-catalog");
8
- const session_state_1 = require("../session-state");
9
- const server_sync_1 = require("../server-sync");
10
7
  const file_fingerprints_1 = require("../file-fingerprints");
11
8
  const git_status_1 = require("../git-status");
12
9
  const operator_snapshot_1 = require("../operator-snapshot");
10
+ const session_1 = require("../session");
11
+ const session_state_1 = require("../session-state");
12
+ const server_sync_1 = require("../server-sync");
13
13
  const work_context_resolver_1 = require("../work-context-resolver");
14
14
  const verification_conditions_1 = require("../verification-conditions");
15
15
  const MAX_EXCERPT_CHARS = 8000;
16
- function resolveNetworkContext() {
16
+ function tryResolveNetworkContext() {
17
17
  const cfg = (0, config_1.readConfig)();
18
18
  const projectId = process.env.AGENTBRIDGE_PROJECT_ID ?? cfg.projectId;
19
19
  const apiKey = process.env.AGENTBRIDGE_API_KEY ?? cfg.apiKey ?? "";
20
20
  const apiBaseUrl = process.env.AGENTBRIDGE_BASE_URL ?? cfg.apiBaseUrl ?? "https://agentauth-api-production.up.railway.app";
21
21
  if (!projectId || !apiKey) {
22
- throw (0, errors_1.catalogCliError)("CONFIG_INCOMPLETE");
22
+ return null;
23
23
  }
24
24
  return { projectId, apiKey, apiBaseUrl };
25
25
  }
@@ -45,6 +45,29 @@ function normalizeChangedFiles(files) {
45
45
  function repoDirtySnapshot() {
46
46
  return (0, git_status_1.repoDirtySnapshotFromGitStatus)();
47
47
  }
48
+ function ensureWritableSessionState() {
49
+ const cfg = (0, config_1.readConfig)();
50
+ const existing = (0, session_state_1.readSessionState)();
51
+ if (existing && existing.status !== "closed" && existing.id !== "none") {
52
+ return existing;
53
+ }
54
+ return (0, session_1.openLocalSession)({
55
+ agentId: cfg.activeAgentId ?? "CLI Agent",
56
+ laneDomain: null,
57
+ claimedPaths: [],
58
+ domains: cfg.domains ?? [],
59
+ });
60
+ }
61
+ function persistLocalVerificationRun(run) {
62
+ const state = ensureWritableSessionState();
63
+ state.lastLocalVerificationRun = run;
64
+ const scopeFiles = normalizeChangedFiles(run.proofScopeFiles);
65
+ if (scopeFiles.length > 0) {
66
+ state.changedFiles = [...new Set([...(state.changedFiles ?? []), ...scopeFiles])].sort();
67
+ }
68
+ (0, session_state_1.writeSessionState)(state);
69
+ return state;
70
+ }
48
71
  async function preflightSyncLocalChangedFiles(ctx, workSessionId) {
49
72
  const state = (0, session_state_1.readSessionState)();
50
73
  if (!state)
@@ -105,61 +128,38 @@ async function runVerify(commandInput, options = {}) {
105
128
  if (!command) {
106
129
  throw (0, errors_1.catalogCliError)("VERIFY_COMMAND_REQUIRED");
107
130
  }
108
- const ctx = resolveNetworkContext();
109
- const resolution = await (0, work_context_resolver_1.resolveWorkContext)(ctx, {
110
- useConfigActiveChangeRequestId: false,
111
- includeOtherActiveSessions: true,
112
- });
113
- if (resolution.state !== "current_session_resolved" || !resolution.binding) {
114
- const workContextErr = (0, errors_1.catalogCliError)((0, error_catalog_1.workContextStateToCode)(resolution.state));
115
- if (options.json) {
116
- const snapshot = (0, operator_snapshot_1.buildOperatorSnapshot)(resolution);
117
- process.stdout.write(`${JSON.stringify({
118
- snapshot,
119
- verification_recorded: false,
120
- next_action: [
121
- 'run agentbridge start --summary "<work>" --scope "<path>"',
122
- "run agentbridge watch --allow-dirty",
123
- ],
124
- }, null, 2)}\n`);
125
- process.stderr.write(`${(0, errors_1.renderCliError)(workContextErr)}\n`);
126
- process.exitCode = 1;
127
- return;
128
- }
129
- process.stdout.write(`${[
130
- ...(0, work_context_resolver_1.renderWorkContextLines)(resolution),
131
- "",
132
- "Verification was not recorded.",
133
- "",
134
- "Next action:",
135
- '- run agentbridge start --summary "<work>" --scope "<path>"',
136
- "- or run agentbridge watch --allow-dirty",
137
- ].join("\n")}\n`);
138
- process.stderr.write(`${(0, errors_1.renderCliError)(workContextErr)}\n`);
139
- process.exitCode = 1;
140
- return;
141
- }
142
- const { workSessionId } = (0, work_context_resolver_1.requireWorkContextBinding)(resolution, "verify");
131
+ const ctx = tryResolveNetworkContext();
143
132
  const startedAt = new Date().toISOString();
144
133
  const run = await execute(command);
145
134
  const finishedAt = new Date().toISOString();
146
135
  const status = run.exitCode === 0 ? "passed" : "failed";
147
- let localSessionChangedFiles = [];
148
- try {
149
- localSessionChangedFiles = await preflightSyncLocalChangedFiles(ctx, workSessionId);
150
- }
151
- catch {
152
- localSessionChangedFiles = [];
153
- }
136
+ let localSessionChangedFiles = normalizeChangedFiles((0, session_state_1.readSessionState)()?.changedFiles ?? []);
137
+ const dirtySnapshot = repoDirtySnapshot();
154
138
  let acceptanceChangedFiles = [];
155
- try {
156
- const report = await (0, server_sync_1.fetchAcceptanceCheck)(ctx, { workSessionId });
157
- acceptanceChangedFiles = normalizeChangedFiles(report.changed_files ?? []);
158
- }
159
- catch {
160
- acceptanceChangedFiles = [];
139
+ let workSessionId = null;
140
+ let resolution = null;
141
+ if (ctx) {
142
+ resolution = await (0, work_context_resolver_1.resolveWorkContext)(ctx, {
143
+ useConfigActiveChangeRequestId: false,
144
+ includeOtherActiveSessions: true,
145
+ });
146
+ if (resolution.state === "current_session_resolved" && resolution.binding) {
147
+ workSessionId = (0, work_context_resolver_1.requireWorkContextBinding)(resolution, "verify").workSessionId;
148
+ try {
149
+ localSessionChangedFiles = await preflightSyncLocalChangedFiles(ctx, workSessionId);
150
+ }
151
+ catch {
152
+ localSessionChangedFiles = normalizeChangedFiles((0, session_state_1.readSessionState)()?.changedFiles ?? []);
153
+ }
154
+ try {
155
+ const report = await (0, server_sync_1.fetchAcceptanceCheck)(ctx, { workSessionId });
156
+ acceptanceChangedFiles = normalizeChangedFiles(report.changed_files ?? []);
157
+ }
158
+ catch {
159
+ acceptanceChangedFiles = [];
160
+ }
161
+ }
161
162
  }
162
- const dirtySnapshot = repoDirtySnapshot();
163
163
  const proofScopeFiles = acceptanceChangedFiles.length > 0
164
164
  ? acceptanceChangedFiles
165
165
  : localSessionChangedFiles.length > 0
@@ -175,10 +175,10 @@ async function runVerify(commandInput, options = {}) {
175
175
  command,
176
176
  proofScopeFiles,
177
177
  proofScopeSource,
178
- serverBacked: true,
178
+ serverBacked: workSessionId !== null,
179
179
  });
180
180
  const confidence = (0, verification_conditions_1.buildVerificationConfidence)({ status, conditions });
181
- await (0, server_sync_1.postVerificationRun)(ctx, { workSessionId }, {
181
+ const localRun = {
182
182
  command,
183
183
  startedAt,
184
184
  finishedAt,
@@ -186,40 +186,61 @@ async function runVerify(commandInput, options = {}) {
186
186
  stdoutExcerpt: excerpt(run.stdout),
187
187
  stderrExcerpt: excerpt(run.stderr),
188
188
  gitHead: currentGitHead(),
189
- changedFilesSnapshot: proofScopeFiles,
190
- proofScopeFiles,
191
- proofScopeSource,
192
189
  repoDirtySnapshot: dirtySnapshot,
190
+ proofScopeFiles,
193
191
  proofScopeFingerprints,
194
192
  status,
195
- conditions,
196
- confidence,
197
- });
193
+ };
194
+ persistLocalVerificationRun(localRun);
195
+ if (ctx && workSessionId) {
196
+ await (0, server_sync_1.postVerificationRun)(ctx, { workSessionId }, {
197
+ command,
198
+ startedAt,
199
+ finishedAt,
200
+ exitCode: run.exitCode,
201
+ stdoutExcerpt: excerpt(run.stdout),
202
+ stderrExcerpt: excerpt(run.stderr),
203
+ gitHead: currentGitHead(),
204
+ changedFilesSnapshot: proofScopeFiles,
205
+ proofScopeFiles,
206
+ proofScopeSource,
207
+ repoDirtySnapshot: dirtySnapshot,
208
+ proofScopeFingerprints,
209
+ status,
210
+ conditions,
211
+ confidence,
212
+ });
213
+ }
198
214
  let protocolWarnings = [];
199
215
  let latestReport = null;
200
- try {
201
- const report = await (0, server_sync_1.fetchAcceptanceCheck)(ctx, { workSessionId });
202
- latestReport = report;
203
- protocolWarnings = report.protocol_warnings ?? [];
204
- const warnings = renderProtocolWarnings(protocolWarnings);
205
- if (warnings.length > 0) {
206
- process.stdout.write(`${warnings.join("\n")}\n`);
216
+ if (ctx && workSessionId) {
217
+ try {
218
+ const report = await (0, server_sync_1.fetchAcceptanceCheck)(ctx, { workSessionId });
219
+ latestReport = report;
220
+ protocolWarnings = report.protocol_warnings ?? [];
221
+ const warnings = renderProtocolWarnings(protocolWarnings);
222
+ if (warnings.length > 0) {
223
+ process.stdout.write(`${warnings.join("\n")}\n`);
224
+ }
225
+ }
226
+ catch {
227
+ // Verification recording is authoritative; warning fetch is best-effort.
207
228
  }
208
- }
209
- catch {
210
- // Verification recording is authoritative; warning fetch is best-effort.
211
229
  }
212
230
  if (options.json) {
213
- const report = latestReport ?? (await (0, server_sync_1.fetchAcceptanceCheck)(ctx, { workSessionId }));
214
- const snapshot = (0, operator_snapshot_1.buildOperatorSnapshot)({
215
- ...resolution,
216
- binding: {
217
- workSessionId,
218
- changeRequestId: report.change_request_id ?? null,
219
- report,
220
- },
221
- resolvedServerSessionId: report.work_session_id,
222
- resolvedChangeRequestId: report.change_request_id ?? null,
231
+ const report = latestReport ??
232
+ (ctx && workSessionId ? await (0, server_sync_1.fetchAcceptanceCheck)(ctx, { workSessionId }) : null);
233
+ const snapshot = (0, operator_snapshot_1.buildOperatorSnapshot)(resolution ?? {
234
+ state: "no_current_session",
235
+ contextSource: "none",
236
+ requestedChangeRequestId: null,
237
+ binding: null,
238
+ ambiguousSessions: [],
239
+ otherActiveSessions: [],
240
+ localServerSessionId: null,
241
+ resolvedServerSessionId: null,
242
+ resolvedChangeRequestId: null,
243
+ message: "No active tracked work session. Run agentbridge watch for live supervision.",
223
244
  });
224
245
  process.stdout.write(`${JSON.stringify({
225
246
  snapshot,
@@ -233,30 +254,42 @@ async function runVerify(commandInput, options = {}) {
233
254
  confidence,
234
255
  conditions,
235
256
  protocol_warnings: protocolWarnings,
257
+ recorded_locally: true,
236
258
  },
237
259
  }, null, 2)}\n`);
260
+ if (status !== "passed") {
261
+ process.exitCode = 1;
262
+ }
238
263
  return;
239
264
  }
240
265
  if (status === "passed") {
241
266
  const confidenceLines = (0, verification_conditions_1.renderConfidenceSummary)(confidence);
242
267
  const hygieneWarning = (0, verification_conditions_1.renderMockHygieneWarning)(conditions.mock_hygiene);
243
- process.stdout.write([
268
+ const lines = [
244
269
  "Verification passed.",
245
270
  `Command: ${command}`,
246
- `Attached to run: ${workSessionId}`,
247
- ...confidenceLines,
248
- ...(hygieneWarning ? [hygieneWarning] : []),
249
- "Run agentbridge check to review the watch result.",
250
- ].join("\n") + "\n");
271
+ "Proof recorded locally.",
272
+ ];
273
+ if (workSessionId) {
274
+ lines.push(`Attached to run: ${workSessionId}`);
275
+ }
276
+ lines.push(...confidenceLines);
277
+ if (hygieneWarning)
278
+ lines.push(hygieneWarning);
279
+ lines.push("Keep agentbridge watch running beside Cursor to supervise changes.");
280
+ process.stdout.write(`${lines.join("\n")}\n`);
251
281
  return;
252
282
  }
253
283
  process.stdout.write([
254
284
  "Verification failed.",
255
285
  `Command: ${command}`,
256
286
  `Exit code: ${run.exitCode}`,
257
- `Attached to run: ${workSessionId}`,
258
- "Run agentbridge check to review failed proof.",
259
- ].join("\n") + "\n");
287
+ "Proof recorded locally (failed).",
288
+ workSessionId ? `Attached to run: ${workSessionId}` : "",
289
+ "Fix the failure and rerun: agentbridge verify -- <test command>",
290
+ ]
291
+ .filter((line) => line.length > 0)
292
+ .join("\n") + "\n");
260
293
  process.stderr.write(`${(0, errors_1.renderCliError)((0, errors_1.catalogCliError)("VERIFY_COMMAND_FAILED", {
261
294
  what: `Verification command "${command}" failed with exit code ${run.exitCode}.`,
262
295
  }))}\n`);