@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.
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveMcpRuntime = resolveMcpRuntime;
4
+ exports.isMcpRuntimeAvailable = isMcpRuntimeAvailable;
5
+ const node_fs_1 = require("node:fs");
6
+ const node_path_1 = require("node:path");
7
+ /** Resolve MCP stdio entrypoint relative to `cli/dist` (index.js directory). */
8
+ function resolveMcpRuntime(cliDistDir) {
9
+ const bundled = (0, node_path_1.resolve)(cliDistDir, "mcp", "agentbridge-mcp.js");
10
+ if ((0, node_fs_1.existsSync)(bundled)) {
11
+ return {
12
+ mode: "bundled",
13
+ path: bundled,
14
+ command: process.execPath,
15
+ args: [bundled],
16
+ };
17
+ }
18
+ const devTs = (0, node_path_1.resolve)(cliDistDir, "..", "..", "mcp", "agentbridge-mcp.ts");
19
+ if ((0, node_fs_1.existsSync)(devTs)) {
20
+ return {
21
+ mode: "dev",
22
+ path: devTs,
23
+ command: "npx",
24
+ args: ["tsx", devTs],
25
+ };
26
+ }
27
+ return null;
28
+ }
29
+ function isMcpRuntimeAvailable(cliDistDir) {
30
+ return resolveMcpRuntime(cliDistDir) !== null;
31
+ }
@@ -1,5 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isPostStartWorkFile = isPostStartWorkFile;
4
+ exports.computeCurrentWorkFiles = computeCurrentWorkFiles;
3
5
  exports.repoDirtySnapshot = repoDirtySnapshot;
4
6
  exports.preflightSyncChangedFiles = preflightSyncChangedFiles;
5
7
  const claimed_paths_1 = require("./claimed-paths");
@@ -7,6 +9,26 @@ const file_fingerprints_1 = require("./file-fingerprints");
7
9
  const git_status_1 = require("./git-status");
8
10
  const session_state_1 = require("./session-state");
9
11
  const server_sync_1 = require("./server-sync");
12
+ /** True when a git-dirty file is genuinely new work within this session (not baseline-only). */
13
+ function isPostStartWorkFile(file, dirtyAtStart, fingerprintsAtStart) {
14
+ if (!dirtyAtStart.has(file))
15
+ return true;
16
+ const fps = (0, file_fingerprints_1.computeFileFingerprints)([file]);
17
+ const current = fps[0];
18
+ if (!current?.exists) {
19
+ return fingerprintsAtStart[file] !== undefined;
20
+ }
21
+ const currentFp = current.sha256 ?? current.mtimeMs?.toString() ?? "";
22
+ const baseFp = fingerprintsAtStart[file];
23
+ return baseFp === undefined || currentFp !== baseFp;
24
+ }
25
+ /** Files dirty now that count as supervised work after session baseline. */
26
+ function computeCurrentWorkFiles(state, dirtyNow) {
27
+ const dirty = normalizeChangedFiles(dirtyNow ?? repoDirtySnapshot());
28
+ const dirtyAtStart = new Set(state.dirtyFilesAtStart ?? []);
29
+ const fingerprintsAtStart = state.fingerprintsAtStart ?? {};
30
+ return dirty.filter((file) => isPostStartWorkFile(file, dirtyAtStart, fingerprintsAtStart));
31
+ }
10
32
  function normalizeChangedFiles(files) {
11
33
  return [...new Set(files.map((file) => file.trim()).filter((file) => file.length > 0))].sort();
12
34
  }
@@ -49,21 +71,6 @@ async function preflightSyncChangedFiles(ctx) {
49
71
  // acquire new content within the session.
50
72
  const dirtyAtStart = new Set(state.dirtyFilesAtStart ?? []);
51
73
  const startFingerprints = state.fingerprintsAtStart ?? {};
52
- /** True when a git-dirty file is genuinely new work within this session. */
53
- function isNewWorkFile(file) {
54
- if (!dirtyAtStart.has(file))
55
- return true; // wasn't dirty at start → always new work
56
- // Was dirty at start – only include if content changed since start
57
- const fps = (0, file_fingerprints_1.computeFileFingerprints)([file]);
58
- const current = fps[0];
59
- if (!current?.exists) {
60
- // File now missing. Treat as new work only when it previously existed at start.
61
- return startFingerprints[file] !== undefined;
62
- }
63
- const currentFp = current.sha256 ?? current.mtimeMs?.toString() ?? "";
64
- const baseFp = startFingerprints[file];
65
- return baseFp === undefined || currentFp !== baseFp;
66
- }
67
74
  const watchOnlyFiles = watchFiles.filter((file) => !gitFileSet.has(file));
68
75
  const watchOnlyFingerprints = (0, file_fingerprints_1.computeFileFingerprints)(watchOnlyFiles);
69
76
  const activeWatchOnlyFiles = watchOnlyFingerprints
@@ -72,9 +79,9 @@ async function preflightSyncChangedFiles(ctx) {
72
79
  const merged = normalizeChangedFiles([
73
80
  ...watchFiles.filter((file) => gitFileSet.has(file)),
74
81
  ...activeWatchOnlyFiles,
75
- ...gitFiles.filter((file) => isNewWorkFile(file) &&
82
+ ...gitFiles.filter((file) => isPostStartWorkFile(file, dirtyAtStart, startFingerprints) &&
76
83
  (claimedPaths.length === 0 || (0, claimed_paths_1.fileWithinClaimedPaths)(file, claimedPaths))),
77
- ...gitFiles.filter((file) => isNewWorkFile(file) &&
84
+ ...gitFiles.filter((file) => isPostStartWorkFile(file, dirtyAtStart, startFingerprints) &&
78
85
  claimedPaths.length > 0 &&
79
86
  !(0, claimed_paths_1.fileWithinClaimedPaths)(file, claimedPaths)),
80
87
  ]);
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.obligationBlocksAtRollout = obligationBlocksAtRollout;
4
+ exports.getBlockingObligations = getBlockingObligations;
5
+ exports.primaryBlockingObligation = primaryBlockingObligation;
6
+ exports.resolveProofBlockingErrorCode = resolveProofBlockingErrorCode;
7
+ exports.minimumCommandsForReport = minimumCommandsForReport;
8
+ exports.buildObligationSuggestedPrompt = buildObligationSuggestedPrompt;
9
+ exports.renderProofObligationSection = renderProofObligationSection;
10
+ exports.renderProofObligationErrorLines = renderProofObligationErrorLines;
11
+ exports.buildWatchBlockingIssueFromObligation = buildWatchBlockingIssueFromObligation;
12
+ const error_catalog_1 = require("./error-catalog");
13
+ const OBLIGATION_CODE_PRIORITY = [
14
+ "PROOF_TOO_WEAK",
15
+ "PROOF_NOT_RELEVANT",
16
+ "PROOF_IMPACT_COVERAGE_GAP",
17
+ ];
18
+ function obligationBlocksAtRollout(obligation) {
19
+ return (obligation.status === "unsatisfied" &&
20
+ obligation.rollout_stage !== undefined &&
21
+ obligation.rollout_stage !== "warn_only");
22
+ }
23
+ function getBlockingObligations(report) {
24
+ return (report.obligation_set ?? []).filter(obligationBlocksAtRollout);
25
+ }
26
+ function primaryBlockingObligation(report) {
27
+ const blocking = getBlockingObligations(report);
28
+ if (blocking.length === 0)
29
+ return null;
30
+ for (const code of OBLIGATION_CODE_PRIORITY) {
31
+ const match = blocking.find((obligation) => obligation.code === code);
32
+ if (match)
33
+ return match;
34
+ }
35
+ return blocking[0] ?? null;
36
+ }
37
+ function resolveProofBlockingErrorCode(report) {
38
+ const primary = primaryBlockingObligation(report);
39
+ if (primary?.code)
40
+ return primary.code;
41
+ if (report.decision === "needs_proof")
42
+ return "PROOF_MISSING";
43
+ if (report.decision === "stale_evidence")
44
+ return "PROOF_STALE_AFTER_CHANGE";
45
+ return null;
46
+ }
47
+ function uniqueCommands(values) {
48
+ return [...new Set(values.map((value) => value.trim()).filter((value) => value.length > 0))];
49
+ }
50
+ function minimumCommandsForReport(report, obligation) {
51
+ const fromObligation = obligation?.recommended_commands ?? [];
52
+ const fromGuidance = report.proof_guidance?.minimum_commands ?? [];
53
+ const fromBlocking = getBlockingObligations(report).flatMap((item) => item.recommended_commands ?? []);
54
+ return uniqueCommands([...fromObligation, ...fromGuidance, ...fromBlocking]);
55
+ }
56
+ function buildObligationSuggestedPrompt(input) {
57
+ const { obligation, report } = input;
58
+ const files = obligation.applies_to_files.length > 0 ? obligation.applies_to_files : report.changed_files;
59
+ const commands = minimumCommandsForReport(report, obligation);
60
+ const unacceptable = report.proof_guidance?.unacceptable_commands ?? [];
61
+ const lines = [
62
+ obligation.requirement ??
63
+ `Proof obligation ${obligation.code ?? obligation.source} is unsatisfied.`,
64
+ obligation.code === "PROOF_TOO_WEAK" && unacceptable.length > 0
65
+ ? `These commands are too weak for this change: ${unacceptable.join(", ")}`
66
+ : "",
67
+ commands.length > 0
68
+ ? `Run one of these minimum commands:\n${commands.map((command) => `- ${command}`).join("\n")}`
69
+ : "Run a stronger verification command that covers the changed files.",
70
+ files.length > 0 ? `Files: ${files.join(", ")}` : "",
71
+ ].filter((line) => line.length > 0);
72
+ return lines.join("\n");
73
+ }
74
+ function renderProofObligationSection(report) {
75
+ const obligations = report.obligation_set ?? [];
76
+ if (obligations.length === 0 && !report.proof_guidance)
77
+ return [];
78
+ const lines = ["Proof obligations:"];
79
+ if (obligations.length === 0) {
80
+ lines.push(" - none");
81
+ }
82
+ else {
83
+ for (const obligation of obligations) {
84
+ const label = obligation.code ?? obligation.source;
85
+ const rollout = obligation.rollout_stage ? ` (${obligation.rollout_stage})` : "";
86
+ lines.push(` - [${obligation.status}] ${label}${rollout}`);
87
+ if (obligation.requirement) {
88
+ lines.push(` requirement: ${obligation.requirement}`);
89
+ }
90
+ if (obligation.recommended_commands && obligation.recommended_commands.length > 0) {
91
+ for (const command of obligation.recommended_commands) {
92
+ lines.push(` run: ${command}`);
93
+ }
94
+ }
95
+ }
96
+ }
97
+ if (report.proof_guidance) {
98
+ lines.push(`Proof guidance: ${report.proof_guidance.reason}`);
99
+ if (report.proof_guidance.minimum_commands.length > 0) {
100
+ lines.push("Minimum commands:");
101
+ for (const command of report.proof_guidance.minimum_commands) {
102
+ lines.push(` - ${command}`);
103
+ }
104
+ }
105
+ if (report.proof_guidance.unacceptable_commands.length > 0) {
106
+ lines.push("Unacceptable (too weak):");
107
+ for (const command of report.proof_guidance.unacceptable_commands) {
108
+ lines.push(` - ${command}`);
109
+ }
110
+ }
111
+ }
112
+ return lines;
113
+ }
114
+ function renderProofObligationErrorLines(report) {
115
+ const code = resolveProofBlockingErrorCode(report);
116
+ if (!code || code === "PROOF_MISSING" || code === "PROOF_STALE_AFTER_CHANGE") {
117
+ return [];
118
+ }
119
+ const obligation = primaryBlockingObligation(report);
120
+ const entry = (0, error_catalog_1.catalogEntryForCode)(code);
121
+ const commands = minimumCommandsForReport(report, obligation);
122
+ const lines = [`✗ Error code: ${code}`];
123
+ lines.push(` What happened: ${entry?.what ?? "A proof obligation is unsatisfied."}`);
124
+ lines.push(` Why it matters: ${entry?.why ?? "Acceptance requires proof that matches this risk profile."}`);
125
+ if (obligation?.requirement) {
126
+ lines.push(` Obligation: ${obligation.requirement}`);
127
+ }
128
+ if (commands.length > 0) {
129
+ lines.push(" Minimum commands:");
130
+ for (const command of commands) {
131
+ lines.push(` - ${command}`);
132
+ }
133
+ }
134
+ else if (entry?.next) {
135
+ lines.push(` Next action: ${entry.next}`);
136
+ }
137
+ return lines;
138
+ }
139
+ function buildWatchBlockingIssueFromObligation(report, obligation) {
140
+ const code = obligation.code ?? "PROOF_MISSING";
141
+ const entry = (0, error_catalog_1.catalogEntryForCode)(code);
142
+ const files = [
143
+ ...new Set(obligation.applies_to_files.length > 0 ? obligation.applies_to_files : report.changed_files),
144
+ ];
145
+ const commands = minimumCommandsForReport(report, obligation);
146
+ const nextAction = commands[0] ?? entry?.next ?? "Run a stronger verification command for the changed files.";
147
+ return {
148
+ errorCode: code,
149
+ whatHappened: entry?.what ?? obligation.requirement ?? "A proof obligation is unsatisfied.",
150
+ whyItMatters: entry?.why ?? "Acceptance requires proof that matches this change profile.",
151
+ files,
152
+ suggestedPrompt: buildObligationSuggestedPrompt({ obligation, report }),
153
+ nextAction,
154
+ };
155
+ }
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeDomainKey = normalizeDomainKey;
4
+ exports.isGenericGeneralDomain = isGenericGeneralDomain;
5
+ exports.activeDomainsFromPacket = activeDomainsFromPacket;
6
+ exports.packetDomainsToRefs = packetDomainsToRefs;
7
+ exports.isLoneGenericGeneral = isLoneGenericGeneral;
8
+ exports.hasMeaningfulDomainMap = hasMeaningfulDomainMap;
9
+ exports.assessRecoveryQuality = assessRecoveryQuality;
10
+ exports.buildReconcilePlan = buildReconcilePlan;
11
+ exports.mergeBootstrapDomainEntries = mergeBootstrapDomainEntries;
12
+ exports.recoveryQualityLabel = recoveryQualityLabel;
13
+ exports.recoveryBaselineRequired = recoveryBaselineRequired;
14
+ exports.recoveryIsBasicPacket = recoveryIsBasicPacket;
15
+ function normalizeDomainKey(name) {
16
+ return name
17
+ .trim()
18
+ .toLowerCase()
19
+ .replace(/[\s-]+/g, "_")
20
+ .replace(/[^a-z0-9_]/g, "");
21
+ }
22
+ function isGenericGeneralDomain(name) {
23
+ const key = normalizeDomainKey(name);
24
+ return key === "general" || key === "misc";
25
+ }
26
+ function activeDomainsFromPacket(packet) {
27
+ return (packet?.domains_summary ?? []).filter((d) => d.state !== "retired");
28
+ }
29
+ function packetDomainsToRefs(packet, configDomains = []) {
30
+ const active = activeDomainsFromPacket(packet);
31
+ const configByKey = new Map(configDomains.map((d) => [normalizeDomainKey(d.domain), d.pathPatterns]));
32
+ return active.map((d) => ({
33
+ name: d.domain_name,
34
+ pathPatterns: configByKey.get(normalizeDomainKey(d.domain_name)) ?? [],
35
+ }));
36
+ }
37
+ function isLoneGenericGeneral(domains) {
38
+ if (domains.length !== 1)
39
+ return false;
40
+ return isGenericGeneralDomain(domains[0]?.name ?? "");
41
+ }
42
+ function hasMeaningfulDomainMap(domains) {
43
+ const nonGeneric = domains.filter((d) => !isGenericGeneralDomain(d.name));
44
+ return nonGeneric.length >= 2 || (nonGeneric.length === 1 && domains.length >= 1 && !isLoneGenericGeneral(domains));
45
+ }
46
+ function domainMapsEqual(a, b) {
47
+ const keysA = new Set(a.map((d) => normalizeDomainKey(d.name)));
48
+ const keysB = new Set(b.map((d) => normalizeDomainKey(d.name)));
49
+ if (keysA.size !== keysB.size)
50
+ return false;
51
+ for (const key of keysA) {
52
+ if (!keysB.has(key))
53
+ return false;
54
+ }
55
+ return true;
56
+ }
57
+ function assessRecoveryQuality(input) {
58
+ const { packet, existingActive, candidates, rulesInstalled } = input;
59
+ const status = packet?.recovery_status ?? null;
60
+ if (!packet ||
61
+ status === "baseline_required" ||
62
+ status === "pending" ||
63
+ status === null ||
64
+ existingActive.length === 0) {
65
+ return "missing";
66
+ }
67
+ if (isLoneGenericGeneral(existingActive)) {
68
+ const scanHasSpecific = candidates.some((d) => !isGenericGeneralDomain(d.name));
69
+ if (scanHasSpecific) {
70
+ return "stale";
71
+ }
72
+ return "basic";
73
+ }
74
+ const candidateNonGeneric = candidates.filter((d) => !isGenericGeneralDomain(d.name));
75
+ const existingNonGeneric = existingActive.filter((d) => !isGenericGeneralDomain(d.name));
76
+ if (existingNonGeneric.length === 0 && candidateNonGeneric.length > 0) {
77
+ return "stale";
78
+ }
79
+ const candidateKeys = new Set(candidates.map((d) => normalizeDomainKey(d.name)));
80
+ const existingKeys = new Set(existingActive.map((d) => normalizeDomainKey(d.name)));
81
+ const missingFromStored = candidateNonGeneric.filter((c) => !existingKeys.has(normalizeDomainKey(c.name)));
82
+ const orphanStored = existingNonGeneric.filter((e) => !candidateKeys.has(normalizeDomainKey(e.name)));
83
+ if (missingFromStored.length > 0 && existingNonGeneric.length > 0) {
84
+ return orphanStored.length > 0 ? "mismatch" : "stale";
85
+ }
86
+ if (!hasMeaningfulDomainMap(existingActive)) {
87
+ return "basic";
88
+ }
89
+ const hasCharter = Boolean(packet.charter_summary?.purpose?.trim());
90
+ if (!hasCharter || rulesInstalled === false) {
91
+ return "needs_review";
92
+ }
93
+ if (domainMapsEqual(existingActive, candidates)) {
94
+ return "complete";
95
+ }
96
+ if (missingFromStored.length > 0) {
97
+ return "stale";
98
+ }
99
+ return "complete";
100
+ }
101
+ function buildReconcilePlan(input) {
102
+ const { existingActive, candidates, mode, packet, rulesInstalled } = input;
103
+ const existingByKey = new Map(existingActive.map((d) => [normalizeDomainKey(d.name), d]));
104
+ const candidateByKey = new Map(candidates.map((d) => [normalizeDomainKey(d.name), d]));
105
+ const toAdd = candidates.filter((c) => !existingByKey.has(normalizeDomainKey(c.name)));
106
+ const unchanged = existingActive.filter((e) => candidateByKey.has(normalizeDomainKey(e.name)));
107
+ let toRetire = [];
108
+ let toPreserve = [];
109
+ if (mode === "force") {
110
+ toRetire = existingActive.filter((e) => !candidateByKey.has(normalizeDomainKey(e.name)));
111
+ toPreserve = [];
112
+ }
113
+ else {
114
+ const upgradingFromGeneral = isLoneGenericGeneral(existingActive) &&
115
+ candidates.some((c) => !isGenericGeneralDomain(c.name));
116
+ if (upgradingFromGeneral) {
117
+ toRetire = existingActive.filter((e) => isGenericGeneralDomain(e.name));
118
+ toPreserve = existingActive.filter((e) => !isGenericGeneralDomain(e.name));
119
+ }
120
+ else {
121
+ toPreserve = existingActive.filter((e) => !toAdd.some((a) => normalizeDomainKey(a.name) === normalizeDomainKey(e.name)));
122
+ }
123
+ }
124
+ const hasChanges = toAdd.length > 0 ||
125
+ toRetire.length > 0 ||
126
+ (mode === "force" && !domainMapsEqual(existingActive, candidates));
127
+ const quality = assessRecoveryQuality({
128
+ packet,
129
+ existingActive,
130
+ candidates,
131
+ rulesInstalled,
132
+ });
133
+ return {
134
+ mode,
135
+ candidates,
136
+ existingActive,
137
+ toAdd,
138
+ toPreserve,
139
+ toRetire,
140
+ unchanged,
141
+ hasChanges,
142
+ quality,
143
+ };
144
+ }
145
+ function mergeBootstrapDomainEntries(plan, candidateEntries, existingEntries) {
146
+ const byKey = new Map();
147
+ const addEntry = (entry) => {
148
+ const name = typeof entry.name === "string" ? entry.name : "";
149
+ if (!name)
150
+ return;
151
+ byKey.set(normalizeDomainKey(name), entry);
152
+ };
153
+ if (plan.mode === "force") {
154
+ for (const entry of candidateEntries)
155
+ addEntry(entry);
156
+ return Array.from(byKey.values());
157
+ }
158
+ for (const entry of existingEntries)
159
+ addEntry(entry);
160
+ for (const entry of candidateEntries)
161
+ addEntry(entry);
162
+ if (plan.toRetire.some((d) => isGenericGeneralDomain(d.name)) &&
163
+ plan.toAdd.some((d) => !isGenericGeneralDomain(d.name))) {
164
+ byKey.delete("general");
165
+ byKey.delete("misc");
166
+ }
167
+ return Array.from(byKey.values());
168
+ }
169
+ function recoveryQualityLabel(quality) {
170
+ return quality;
171
+ }
172
+ function recoveryBaselineRequired(packet) {
173
+ if (!packet || packet.project_mode !== "recovery")
174
+ return false;
175
+ const status = packet.recovery_status ?? null;
176
+ return status === "baseline_required" || status === "pending" || status === null;
177
+ }
178
+ function recoveryIsBasicPacket(packet) {
179
+ const active = packetDomainsToRefs(packet);
180
+ if (active.length === 0)
181
+ return false;
182
+ return isLoneGenericGeneral(active) || !hasMeaningfulDomainMap(active);
183
+ }
@@ -12,6 +12,7 @@ exports.postObservedDiff = postObservedDiff;
12
12
  exports.postScopedApproval = postScopedApproval;
13
13
  exports.closeServerSession = closeServerSession;
14
14
  exports.fetchAcceptanceCheck = fetchAcceptanceCheck;
15
+ exports.fetchAgentProofGuidance = fetchAgentProofGuidance;
15
16
  exports.reviewOnceForWatch = reviewOnceForWatch;
16
17
  exports.isWatchFastPathUnavailable = isWatchFastPathUnavailable;
17
18
  exports.fetchMemorySuggestion = fetchMemorySuggestion;
@@ -132,6 +133,17 @@ async function fetchCallerIdentityPacket(ctx) {
132
133
  typeof domainCandidate.name === "string"
133
134
  ? { id: domainCandidate.id, name: domainCandidate.name }
134
135
  : null;
136
+ const executionSurfaceCandidate = typeof response.execution_surface === "object" && response.execution_surface !== null
137
+ ? response.execution_surface
138
+ : null;
139
+ const executionSurface = executionSurfaceCandidate && typeof executionSurfaceCandidate.id === "string"
140
+ ? {
141
+ id: executionSurfaceCandidate.id,
142
+ ...(typeof executionSurfaceCandidate.display_name === "string"
143
+ ? { display_name: executionSurfaceCandidate.display_name }
144
+ : {}),
145
+ }
146
+ : null;
135
147
  return {
136
148
  identity_model: "work_identity",
137
149
  work_identity: {
@@ -139,6 +151,7 @@ async function fetchCallerIdentityPacket(ctx) {
139
151
  name: workIdentity.name,
140
152
  domain,
141
153
  },
154
+ execution_surface: executionSurface,
142
155
  };
143
156
  }
144
157
  async function postObservedDiff(ctx, binding, payload) {
@@ -240,6 +253,29 @@ async function fetchAcceptanceCheck(ctx, options) {
240
253
  const query = queryParams.toString();
241
254
  return (0, http_1.getJson)(ctx, `/v1/dev/projects/${encodeURIComponent(ctx.projectId)}/work-sessions/current/acceptance-check${query ? `?${query}` : ""}`);
242
255
  }
256
+ async function fetchAgentProofGuidance(ctx, options) {
257
+ const rolloutParams = new URLSearchParams();
258
+ if (options?.rolloutProofTooWeak) {
259
+ rolloutParams.set("rollout_proof_too_weak", options.rolloutProofTooWeak);
260
+ }
261
+ if (options?.rolloutProofNotRelevant) {
262
+ rolloutParams.set("rollout_proof_not_relevant", options.rolloutProofNotRelevant);
263
+ }
264
+ if (options?.rolloutImpactCoverageGap) {
265
+ rolloutParams.set("rollout_impact_coverage_gap", options.rolloutImpactCoverageGap);
266
+ }
267
+ const rolloutSuffix = rolloutParams.toString();
268
+ if (options?.workSessionId) {
269
+ const qs = rolloutSuffix ? `?${rolloutSuffix}` : "";
270
+ return (0, http_1.getJson)(ctx, `/v1/dev/projects/${encodeURIComponent(ctx.projectId)}/work-sessions/${encodeURIComponent(options.workSessionId)}/proof-guidance${qs}`);
271
+ }
272
+ const queryParams = new URLSearchParams(rolloutParams);
273
+ if (options?.changeRequestId && options.changeRequestId.trim().length > 0) {
274
+ queryParams.set("change_request_id", options.changeRequestId);
275
+ }
276
+ const query = queryParams.toString();
277
+ return (0, http_1.getJson)(ctx, `/v1/dev/projects/${encodeURIComponent(ctx.projectId)}/work-sessions/current/proof-guidance${query ? `?${query}` : ""}`);
278
+ }
243
279
  /**
244
280
  * One-shot Agent Watch review fast path. Collapses cold-create / resume +
245
281
  * observed-diff sync + acceptance check into a single bounded server call.