@miraland-labs/conduit-bridge 0.16.27 → 0.16.28

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.
@@ -97,6 +97,48 @@ export async function captureVerificationFailure(input) {
97
97
  // Every bounded command passed (or none could start): agent failed for another reason.
98
98
  return null;
99
99
  }
100
+ /** Longest failure detail Bridge will attach. Enough to diagnose; short enough to store and read. */
101
+ export const FAILURE_DETAIL_MAX_CHARS = 4_000;
102
+ /** Leading lines kept for orientation before the elision. */
103
+ const FAILURE_DETAIL_HEAD_LINES = 3;
104
+ /**
105
+ * A failure detail that keeps the part which explains the failure.
106
+ *
107
+ * This used to keep the first 100 lines and then the first 2,000 characters of the join. A failing
108
+ * command explains itself at the **end** — the assertion, the stack, the summary line, and the exit
109
+ * code — so head-truncation discarded exactly the evidence and kept a screen of `... ok`. A real
110
+ * incident cost three attempts on one task because every report looked like a passing test run cut
111
+ * short, and nobody could see the actual error.
112
+ *
113
+ * So: the command line for orientation, a few opening lines, then the **tail**, and the exit code
114
+ * always. What was dropped is stated rather than silently vanishing, because a reader must be able
115
+ * to tell a short failure from a truncated one.
116
+ */
117
+ export function boundedFailureDetail(command, stdoutLines, stderrLines, code, maxChars = FAILURE_DETAIL_MAX_CHARS) {
118
+ const cap = (line) => (line.length > 500 ? `${line.slice(0, 500)}…` : line);
119
+ const body = [...stdoutLines, ...stderrLines].map(cap);
120
+ const first = `$ ${command}`;
121
+ const last = `exit ${code}`;
122
+ // The exit code is never a candidate for elision: it is the one line that always carries meaning.
123
+ const fixed = `${first}\n${last}`.length;
124
+ const budget = Math.max(0, maxChars - fixed - 1);
125
+ const head = body.slice(0, FAILURE_DETAIL_HEAD_LINES);
126
+ const rest = body.slice(FAILURE_DETAIL_HEAD_LINES);
127
+ const tail = [];
128
+ let used = head.join("\n").length;
129
+ for (let index = rest.length - 1; index >= 0; index -= 1) {
130
+ const line = rest[index];
131
+ if (used + line.length + 1 > budget)
132
+ break;
133
+ tail.unshift(line);
134
+ used += line.length + 1;
135
+ }
136
+ const dropped = rest.length - tail.length;
137
+ const middle = dropped > 0
138
+ ? [...head, `… ${dropped} line${dropped === 1 ? "" : "s"} omitted …`, ...tail]
139
+ : [...head, ...tail];
140
+ return [first, ...middle, last].join("\n");
141
+ }
100
142
  async function defaultRunCommand(command, workspace) {
101
143
  const argv = argvForBoundedCommand(command);
102
144
  const bin = argv[0];
@@ -175,13 +217,7 @@ export async function ensureTestEvidence(input) {
175
217
  const stderrLines = result.stderr.trim() ? result.stderr.trim().split("\n") : [];
176
218
  if (result.code !== 0) {
177
219
  // Prefix must match FINALIZE_CONTRACT_PATTERN ("Agent report") — not Bridge-fault laundering.
178
- const failedDetails = [
179
- `$ ${command}`,
180
- ...stdoutLines,
181
- ...stderrLines,
182
- `exit ${result.code}`,
183
- ].map((line) => line.slice(0, 4_000)).slice(0, 100);
184
- throw new Error(`Agent report: Verification failed (${command}): ${failedDetails.join("\n").slice(0, 2_000)}`);
220
+ throw new Error(`Agent report: Verification failed (${command}): ${boundedFailureDetail(command, stdoutLines, stderrLines, result.code)}`);
185
221
  }
186
222
  // Empty exit-0 is not proof — a no-op recipe (`@true`) must not clear required_evidence: test.
187
223
  if (stdoutLines.length === 0 && stderrLines.length === 0) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@miraland-labs/conduit-bridge",
3
- "version": "0.16.27",
4
- "description": "Conduit Bridge CLI join, connect, disconnect, multi-driver lanes, and run Claude Code / Codex / Cursor / OpenCode / Pi / Kiro / Antigravity / Grok Build agents for a Conduit organization",
3
+ "version": "0.16.28",
4
+ "description": "Conduit Bridge CLI \u2014 join, connect, disconnect, multi-driver lanes, and run Claude Code / Codex / Cursor / OpenCode / Pi / Kiro / Antigravity / Grok Build agents for a Conduit organization",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "conduit": "dist/cli.js"