@miraland-labs/conduit-bridge 0.16.105 → 0.16.107
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/dist/execution.js +39 -13
- package/dist/failure-signal.js +35 -0
- package/package.json +1 -1
package/dist/execution.js
CHANGED
|
@@ -13,7 +13,7 @@ import { execFile } from "node:child_process";
|
|
|
13
13
|
import { promisify } from "node:util";
|
|
14
14
|
import { buildWorkspaceBrief, ensureCommitAvailable, fetchOrigin, normalizeRepositoryUrl, resolveAttemptStartCommit } from "./brief.js";
|
|
15
15
|
import { buildSovereignExecutionFacts, bootstrapResultForWorkspace, changedExecutionFact, resumeExecutionFacts, workspaceIsClean } from "./execution-facts.js";
|
|
16
|
-
import { executionFactChangedSignal, verificationRedBaseSignal, verificationScopeConflictSignal } from "./failure-signal.js";
|
|
16
|
+
import { bridgeCause, executionFactChangedSignal, verificationRedBaseSignal, verificationScopeConflictSignal } from "./failure-signal.js";
|
|
17
17
|
import { forgeTransportFailure } from "./transport-fault.js";
|
|
18
18
|
import { managedWorkspacePath, switchManagedWorkspace } from "./on-shift-apply.js";
|
|
19
19
|
import { formatResetMinute, parseQuotaResetAt } from "./quota-reset.js";
|
|
@@ -22,7 +22,7 @@ import { BRIDGE_PROTOCOL_VERSION } from "./preflight.js";
|
|
|
22
22
|
import { bridgeVersion } from "./version.js";
|
|
23
23
|
import { PULL_REQUEST_OPEN_FAILURE_PREFIX, ensureDeliveryPullRequest } from "./ensure-pull-request.js";
|
|
24
24
|
import { ensureLandCommit } from "./ensure-land-commit.js";
|
|
25
|
-
import { AgentNoLandCommitError, agentNoLandCommitMessage, requiresLandCommit } from "./land-contract.js";
|
|
25
|
+
import { AGENT_NO_LAND_COMMIT_PREFIX, AgentNoLandCommitError, agentNoLandCommitMessage, requiresLandCommit } from "./land-contract.js";
|
|
26
26
|
import { agentClaimsRepositoryWork, claimsVsGitMismatch, isLandTreeEmpty, reportClaimsRepositoryWork, } from "./land-git-reality.js";
|
|
27
27
|
const execFileAsync = promisify(execFile);
|
|
28
28
|
import { captureVerificationFailure, detectGateRanNothing, ensureTestEvidence, needsTestEvidence, runBoundedVerificationCommand, verificationEvidenceCommands, VerificationGateRanNothingError } from "./ensure-test-evidence.js";
|
|
@@ -185,6 +185,9 @@ class AgentTurnTimeoutError extends Error {
|
|
|
185
185
|
/** Environment faults that must Hold — mirror CP ENVIRONMENT_FAILURES message patterns. */
|
|
186
186
|
const FINALIZE_ENVIRONMENT_PATTERN = /base[_ ]not[_ ]ancestor|required base commit is not available|source[_ ]workspace[_ ]dirty|uncommitted changes|dirty workspace|workspace[_ ]head[_ ]changed|workspace[_ ]repository|workspace[_ ]unavailable|driver[_ ]not[_ ]authenticated|not logged in|no login|not authenticated|login required|no[_ ]online[_ ]driver|bridge[_ ]preflight|stale bridge|bridge version/i;
|
|
187
187
|
/** Delivery-report / grant / evidence contract defects (non-retryable rework). */
|
|
188
|
+
/** Two contract messages the control plane reads with builders of its own; they carry no code from here. */
|
|
189
|
+
const CONTRACT_SCOPE_CONFLICT_MESSAGE = /Agent reported changes outside the approved scope:/i;
|
|
190
|
+
const VERIFICATION_UNWITNESSABLE_MESSAGE = /verification produced (?:no|insufficient) output/i;
|
|
188
191
|
const FINALIZE_CONTRACT_PATTERN = /missing required evidence|without the repo_write grant|pull_request_url|Artifact delivery requires|outside the approved scope|head commit|test evidence must include|Met acceptance criteria|Agent report|Agent reported|Agent did not land repository changes|Delivery report|Integration obligation not met|Normative reference unavailable|Normative marker not found/i;
|
|
189
192
|
/**
|
|
190
193
|
* Classify throws from ensureDeliveryPullRequest + validateDeliveryReport.
|
|
@@ -192,7 +195,7 @@ const FINALIZE_CONTRACT_PATTERN = /missing required evidence|without the repo_wr
|
|
|
192
195
|
*/
|
|
193
196
|
export function classifyFinalizeFailure(message) {
|
|
194
197
|
if (forgeTransportFailure(message))
|
|
195
|
-
return { retryable: true, error: message };
|
|
198
|
+
return { retryable: true, error: message, failure: bridgeCause("forge_unreachable", message) };
|
|
196
199
|
// The control plane refused to open the change request — no forge connection resolves for this
|
|
197
200
|
// organization or project, or the task's repository is not one that connection can open a change
|
|
198
201
|
// request on. No retry and no rework can supply a connection, and the owner must read the control
|
|
@@ -201,8 +204,19 @@ export function classifyFinalizeFailure(message) {
|
|
|
201
204
|
return { retryable: false, error: message };
|
|
202
205
|
if (FINALIZE_ENVIRONMENT_PATTERN.test(message))
|
|
203
206
|
return { retryable: false, error: message };
|
|
204
|
-
|
|
205
|
-
|
|
207
|
+
// Bridge names the contract defect it found (K3). A scope conflict keeps its own builder on the
|
|
208
|
+
// control plane, which quotes the paths; an unknown throw below stays prose until its own site
|
|
209
|
+
// names a code.
|
|
210
|
+
if (FINALIZE_CONTRACT_PATTERN.test(message)) {
|
|
211
|
+
const failure = CONTRACT_SCOPE_CONFLICT_MESSAGE.test(message)
|
|
212
|
+
? undefined
|
|
213
|
+
: VERIFICATION_UNWITNESSABLE_MESSAGE.test(message)
|
|
214
|
+
? bridgeCause("verification_unwitnessable", message)
|
|
215
|
+
: message.startsWith(AGENT_NO_LAND_COMMIT_PREFIX)
|
|
216
|
+
? bridgeCause("agent_no_land_commit", message)
|
|
217
|
+
: bridgeCause("execution_contract_failed", message);
|
|
218
|
+
return { retryable: false, error: message, ...(failure ? { failure } : {}) };
|
|
219
|
+
}
|
|
206
220
|
// Unknown finalize faults fail closed once — retrying burns the attempt budget (Invariant 22).
|
|
207
221
|
// Distinct from execution_contract_failed so owners see a Bridge fault, not a contract lie.
|
|
208
222
|
return { retryable: false, error: `Bridge finalize interrupted: ${message}` };
|
|
@@ -1060,7 +1074,7 @@ async function runAttempt(client, config, driver, workspace, brief, taskId, watc
|
|
|
1060
1074
|
const liveBrief = await buildWorkspaceBrief(workspace).catch(() => brief);
|
|
1061
1075
|
const liveRepository = liveBrief?.repository ? normalizeRepositoryUrl(liveBrief.repository) : null;
|
|
1062
1076
|
if (executionContract.repository_fingerprint && liveRepository !== executionContract.repository_fingerprint) {
|
|
1063
|
-
await queueTerminal(client, taskId, { action: "fail", body: { error: "Workspace repository changed after dispatch", retryable: true, idempotency_key: `bridge:workspace-mismatch:${active.attemptId}` } });
|
|
1077
|
+
await queueTerminal(client, taskId, { action: "fail", body: { error: "Workspace repository changed after dispatch", retryable: true, failure: bridgeCause("workspace_repository_mismatch", "Workspace repository changed after dispatch"), idempotency_key: `bridge:workspace-mismatch:${active.attemptId}` } });
|
|
1064
1078
|
console.error(`Assignment ${taskId} preflight failed: Workspace repository changed after dispatch`);
|
|
1065
1079
|
return;
|
|
1066
1080
|
}
|
|
@@ -1122,13 +1136,13 @@ async function runAttempt(client, config, driver, workspace, brief, taskId, watc
|
|
|
1122
1136
|
}
|
|
1123
1137
|
else {
|
|
1124
1138
|
if (!startCommit) {
|
|
1125
|
-
await queueTerminal(client, taskId, { action: "fail", body: { error: "No start commit for attempt worktree", retryable: true, idempotency_key: `bridge:no-start-commit:${active.attemptId}` } });
|
|
1139
|
+
await queueTerminal(client, taskId, { action: "fail", body: { error: "No start commit for attempt worktree", retryable: true, failure: bridgeCause("agent_execution_failed", "No start commit for attempt worktree"), idempotency_key: `bridge:no-start-commit:${active.attemptId}` } });
|
|
1126
1140
|
return;
|
|
1127
1141
|
}
|
|
1128
1142
|
if (executionContract.requested_base_commit) {
|
|
1129
1143
|
const resolved = await resolveAttemptStartCommit(workspace, executionContract.requested_base_commit, startCommit);
|
|
1130
1144
|
if (!resolved) {
|
|
1131
|
-
await queueTerminal(client, taskId, { action: "fail", body: { error: "Required base commit is not available in this workspace", retryable: true, idempotency_key: `bridge:base-not-ancestor:${active.attemptId}` } });
|
|
1145
|
+
await queueTerminal(client, taskId, { action: "fail", body: { error: "Required base commit is not available in this workspace", retryable: true, failure: bridgeCause("base_not_ancestor", "Required base commit is not available in this workspace"), idempotency_key: `bridge:base-not-ancestor:${active.attemptId}` } });
|
|
1132
1146
|
return;
|
|
1133
1147
|
}
|
|
1134
1148
|
worktreeStart = resolved;
|
|
@@ -1136,7 +1150,7 @@ async function runAttempt(client, config, driver, workspace, brief, taskId, watc
|
|
|
1136
1150
|
else if (liveBrief?.base_commit && liveBrief.base_commit !== startCommit) {
|
|
1137
1151
|
const reachable = await ensureCommitAvailable(workspace, startCommit).catch(() => false);
|
|
1138
1152
|
if (!reachable) {
|
|
1139
|
-
await queueTerminal(client, taskId, { action: "fail", body: { error: "Delivered head is not available in this workspace", retryable: true, idempotency_key: `bridge:workspace-mismatch:${active.attemptId}` } });
|
|
1153
|
+
await queueTerminal(client, taskId, { action: "fail", body: { error: "Delivered head is not available in this workspace", retryable: true, failure: bridgeCause("agent_execution_failed", "Delivered head is not available in this workspace"), idempotency_key: `bridge:workspace-mismatch:${active.attemptId}` } });
|
|
1140
1154
|
console.error(`Assignment ${taskId} preflight failed: Delivered head is not available in this workspace`);
|
|
1141
1155
|
return;
|
|
1142
1156
|
}
|
|
@@ -1153,7 +1167,7 @@ async function runAttempt(client, config, driver, workspace, brief, taskId, watc
|
|
|
1153
1167
|
const message = code === "source_workspace_dirty"
|
|
1154
1168
|
? "Source workspace has uncommitted changes; refuse to start an isolated attempt"
|
|
1155
1169
|
: `Unable to create attempt worktree: ${code}`;
|
|
1156
|
-
await queueTerminal(client, taskId, { action: "fail", body: { error: message, retryable: true, idempotency_key: `bridge:worktree:${active.attemptId}:${code}` } });
|
|
1170
|
+
await queueTerminal(client, taskId, { action: "fail", body: { error: message, retryable: true, ...(code === "source_workspace_dirty" ? { failure: bridgeCause("workspace_dirty", message) } : {}), idempotency_key: `bridge:worktree:${active.attemptId}:${code}` } });
|
|
1157
1171
|
console.error(`Assignment ${taskId} worktree create failed: ${redactSecrets(message)}`);
|
|
1158
1172
|
return;
|
|
1159
1173
|
}
|
|
@@ -1190,6 +1204,9 @@ async function runAttempt(client, config, driver, workspace, brief, taskId, watc
|
|
|
1190
1204
|
body: {
|
|
1191
1205
|
error: message,
|
|
1192
1206
|
retryable,
|
|
1207
|
+
failure: retryable
|
|
1208
|
+
? bridgeCause(forgeTransportFailure(message) ? "forge_unreachable" : "agent_execution_failed", message)
|
|
1209
|
+
: bridgeCause(message.startsWith(NORMATIVE_REF_PREFIX) ? "execution_contract_failed" : "execution_unclassified", message),
|
|
1193
1210
|
idempotency_key: `bridge:normative-ref:${active.attemptId}`,
|
|
1194
1211
|
},
|
|
1195
1212
|
});
|
|
@@ -1221,7 +1238,7 @@ async function runAttempt(client, config, driver, workspace, brief, taskId, watc
|
|
|
1221
1238
|
// attempt budget when a pre-inversion task row still lacked the stamp.
|
|
1222
1239
|
const response = await queueTerminal(client, taskId, {
|
|
1223
1240
|
action: "fail",
|
|
1224
|
-
body: { error: detail, retryable: false, idempotency_key: `bridge:fail:${active.attemptId}:missing-class` },
|
|
1241
|
+
body: { error: detail, retryable: false, failure: bridgeCause("execution_unclassified", detail), idempotency_key: `bridge:fail:${active.attemptId}:missing-class` },
|
|
1225
1242
|
});
|
|
1226
1243
|
await removeReleasedDiagnosticWorktree(response);
|
|
1227
1244
|
return;
|
|
@@ -1232,7 +1249,7 @@ async function runAttempt(client, config, driver, workspace, brief, taskId, watc
|
|
|
1232
1249
|
console.error(`Assignment ${taskId}: ${detail}`);
|
|
1233
1250
|
await queueTerminal(client, taskId, {
|
|
1234
1251
|
action: "fail",
|
|
1235
|
-
body: { error: detail, retryable: false, idempotency_key: `bridge:fail:${active.attemptId}:artifact-class` },
|
|
1252
|
+
body: { error: detail, retryable: false, failure: bridgeCause("execution_unclassified", detail), idempotency_key: `bridge:fail:${active.attemptId}:artifact-class` },
|
|
1236
1253
|
});
|
|
1237
1254
|
return;
|
|
1238
1255
|
}
|
|
@@ -1243,7 +1260,7 @@ async function runAttempt(client, config, driver, workspace, brief, taskId, watc
|
|
|
1243
1260
|
console.error(`Assignment ${taskId}: ${detail}`);
|
|
1244
1261
|
const response = await queueTerminal(client, taskId, {
|
|
1245
1262
|
action: "fail",
|
|
1246
|
-
body: { error: detail, retryable: false, idempotency_key: `bridge:fail:${active.attemptId}:class-floor` },
|
|
1263
|
+
body: { error: detail, retryable: false, failure: bridgeCause("execution_unclassified", detail), idempotency_key: `bridge:fail:${active.attemptId}:class-floor` },
|
|
1247
1264
|
});
|
|
1248
1265
|
await removeReleasedDiagnosticWorktree(response);
|
|
1249
1266
|
return;
|
|
@@ -1279,6 +1296,7 @@ async function runAttempt(client, config, driver, workspace, brief, taskId, watc
|
|
|
1279
1296
|
body: {
|
|
1280
1297
|
error: "Diagnostic assignment is missing witnessed failure output",
|
|
1281
1298
|
retryable: true,
|
|
1299
|
+
failure: bridgeCause("agent_execution_failed", "Diagnostic assignment is missing witnessed failure output"),
|
|
1282
1300
|
idempotency_key: `bridge:diagnosis-context-missing:${active.attemptId}`,
|
|
1283
1301
|
},
|
|
1284
1302
|
});
|
|
@@ -1298,6 +1316,7 @@ async function runAttempt(client, config, driver, workspace, brief, taskId, watc
|
|
|
1298
1316
|
body: {
|
|
1299
1317
|
error: detail,
|
|
1300
1318
|
retryable: false,
|
|
1319
|
+
failure: bridgeCause("missing_verification", detail),
|
|
1301
1320
|
idempotency_key: `bridge:missing-verification:${active.attemptId}`,
|
|
1302
1321
|
},
|
|
1303
1322
|
});
|
|
@@ -1762,6 +1781,9 @@ async function runAttempt(client, config, driver, workspace, brief, taskId, watc
|
|
|
1762
1781
|
const response = await queueTerminal(client, taskId, { action: "fail", body: {
|
|
1763
1782
|
error: message,
|
|
1764
1783
|
retryable: bindingRequired ? false : retryableAgentFailure(agentMessage),
|
|
1784
|
+
// The abort is Bridge's own reading of the vendor's words, so Bridge names the cause; a spent
|
|
1785
|
+
// allowance, read the same way, wins over it as it always has.
|
|
1786
|
+
...(modelAborted && !bindingRequired && !verificationDetail ? { failure: bridgeCause("agent_model_abort", message) } : {}),
|
|
1765
1787
|
...(providerQuotaRefusal(agentMessage) ? { failure: providerQuotaFailure(agentMessage) } : {}),
|
|
1766
1788
|
...(signal ? { signal } : {}),
|
|
1767
1789
|
idempotency_key: `bridge:fail:${active.attemptId}`,
|
|
@@ -1871,6 +1893,7 @@ async function runAttempt(client, config, driver, workspace, brief, taskId, watc
|
|
|
1871
1893
|
body: {
|
|
1872
1894
|
error: classified.error,
|
|
1873
1895
|
retryable: classified.retryable,
|
|
1896
|
+
...(classified.failure ? { failure: classified.failure } : {}),
|
|
1874
1897
|
idempotency_key: `bridge:claims-git-gate:${active.attemptId}`,
|
|
1875
1898
|
},
|
|
1876
1899
|
});
|
|
@@ -1887,6 +1910,7 @@ async function runAttempt(client, config, driver, workspace, brief, taskId, watc
|
|
|
1887
1910
|
body: {
|
|
1888
1911
|
error: classified.error,
|
|
1889
1912
|
retryable: classified.retryable,
|
|
1913
|
+
...(classified.failure ? { failure: classified.failure } : {}),
|
|
1890
1914
|
idempotency_key: `bridge:claims-git-gate:${active.attemptId}`,
|
|
1891
1915
|
},
|
|
1892
1916
|
});
|
|
@@ -2066,6 +2090,7 @@ async function runAttempt(client, config, driver, workspace, brief, taskId, watc
|
|
|
2066
2090
|
body: {
|
|
2067
2091
|
error: classified.error,
|
|
2068
2092
|
retryable: classified.retryable,
|
|
2093
|
+
...(classified.failure ? { failure: classified.failure } : {}),
|
|
2069
2094
|
idempotency_key: `bridge:claims-git-gate-report:${active.attemptId}`,
|
|
2070
2095
|
},
|
|
2071
2096
|
});
|
|
@@ -2202,6 +2227,7 @@ async function runAttempt(client, config, driver, workspace, brief, taskId, watc
|
|
|
2202
2227
|
body: {
|
|
2203
2228
|
error: classified.error,
|
|
2204
2229
|
retryable: classified.retryable,
|
|
2230
|
+
...(!verificationFailed && classified.failure ? { failure: classified.failure } : {}),
|
|
2205
2231
|
...(verificationFailed ? { signal: {
|
|
2206
2232
|
phase: "verification",
|
|
2207
2233
|
witness: "bridge",
|
package/dist/failure-signal.js
CHANGED
|
@@ -75,6 +75,41 @@ export const failureSignalSchema = z.object({
|
|
|
75
75
|
*/
|
|
76
76
|
model: z.string().max(200).optional(),
|
|
77
77
|
});
|
|
78
|
+
/**
|
|
79
|
+
* The causes Bridge names itself — before the agent starts, or while finishing its report — as one
|
|
80
|
+
* table keyed by code, so Bridge sends the envelope and the control plane validates it (K3).
|
|
81
|
+
*
|
|
82
|
+
* Until 2026-09-15 Bridge wrote these causes as sentences chosen so the control plane's regex
|
|
83
|
+
* tables would recognise them; every wording change on either side was a silent reclassification.
|
|
84
|
+
* The texts here are those tables' texts, moved: one definition, read by both twins.
|
|
85
|
+
*/
|
|
86
|
+
export const BRIDGE_CAUSES = {
|
|
87
|
+
workspace_repository_mismatch: { class: "environment", disposition: "hold", responsible_party: "computer_operator", message: "This checkout does not match the work package repository.", next_action: "Run Bridge from the matching repository checkout, then recheck readiness." },
|
|
88
|
+
workspace_unavailable: { class: "environment", disposition: "hold", responsible_party: "computer_operator", message: "Bridge cannot read the configured workspace.", next_action: "Restore access to the workspace, then recheck readiness." },
|
|
89
|
+
workspace_head_changed: { class: "environment", disposition: "hold", responsible_party: "computer_operator", message: "The checkout changed after Conduit prepared the assignment.", next_action: "Let the checkout settle, then recheck readiness." },
|
|
90
|
+
base_not_ancestor: { class: "environment", disposition: "hold", responsible_party: "computer_operator", message: "Conduit could not prepare the required project version on this computer.", next_action: "No Git work is required from the product owner. Keep the computer and Bridge online, then try again so Bridge can refresh the project. If the hold returns, the computer operator should check Bridge's repository access." },
|
|
91
|
+
workspace_dirty: { class: "environment", disposition: "hold", responsible_party: "computer_operator", message: "The source workspace has uncommitted changes.", next_action: "Commit, stash, or discard the local changes, then recheck readiness." },
|
|
92
|
+
missing_verification: { class: "environment", disposition: "hold", responsible_party: "computer_operator", message: "This checkout has no verification commands Conduit can run for this package.", next_action: "Conductor will adjust how this package is verified. Open Connect only if the computer itself is unhealthy — you do not need to author test commands." },
|
|
93
|
+
verification_unwitnessable: { class: "environment", disposition: "hold", responsible_party: "computer_operator", message: "The project's verification command runs but prints nothing, so test evidence cannot be witnessed.", next_action: "Fix the verification recipe in the checkout so it prints real output, then recheck readiness. You do not need to author test commands for the agent." },
|
|
94
|
+
execution_contract_failed: { class: "contract", disposition: "rework", responsible_party: "conduit", message: "The agent could not satisfy the approved execution contract.", next_action: "Review the last run and rework the same contract; change the plan only if its authority or outcome is wrong." },
|
|
95
|
+
agent_no_land_commit: { class: "contract", disposition: "rework", responsible_party: "conduit", message: "The agent finished without committing the repository changes this package requires.", next_action: "Retry implement. Conductor will brief a land-focused recovery attempt — you do not need to edit technical constraints." },
|
|
96
|
+
execution_unclassified: { class: "platform", disposition: "stop", responsible_party: "conduit", message: "Conduit could not classify this failure.", next_action: "Ask Conductor to diagnose the stopped run, then retry the same plan or open a revision. You do not need to translate the technical detail into agent constraints." },
|
|
97
|
+
forge_unreachable: { class: "transient", disposition: "retry", responsible_party: "conduit", message: "The connection to the code host failed mid-run.", next_action: "Nothing to repair here — the run stopped on a network fault, not on the work. Retry the same plan." },
|
|
98
|
+
agent_model_abort: { class: "transient", disposition: "retry", responsible_party: "conduit", message: "The agent CLI stopped its own run: it detected a loop, asked for a different model, or the prompt did not fit the context window.", next_action: "Conduit retries on another model of the same intelligence tier. The product owner does not need to author technical constraints." },
|
|
99
|
+
agent_execution_failed: { class: "transient", disposition: "retry", responsible_party: "conduit", message: "The agent run failed before delivery.", next_action: "Conduit will retry with bounded backoff while the authoring budget remains. No technical constraints are required from the owner." },
|
|
100
|
+
};
|
|
101
|
+
/** Is this string a code Bridge may name as a cause? Narrows a caller-supplied reason. */
|
|
102
|
+
export function isBridgeCauseCode(value) {
|
|
103
|
+
return Object.prototype.hasOwnProperty.call(BRIDGE_CAUSES, value);
|
|
104
|
+
}
|
|
105
|
+
/** The envelope for a cause Bridge names by code, with the run's own words as the detail. */
|
|
106
|
+
export function bridgeCause(code, detail) {
|
|
107
|
+
const cause = BRIDGE_CAUSES[code];
|
|
108
|
+
// The control plane's envelope schema bounds the detail at 20,000 characters and refuses the
|
|
109
|
+
// whole terminal report otherwise; the run's words are cut there, never the report.
|
|
110
|
+
const text = detail?.trim() ?? "";
|
|
111
|
+
return { code, ...cause, ...(text ? { diagnostic_detail: text.length > 20_000 ? `${text.slice(0, 19_999)}…` : text } : {}) };
|
|
112
|
+
}
|
|
78
113
|
/** A reset time as a person reads it: "2026-09-10 09:36 UTC". Every reset is stored ISO in UTC. */
|
|
79
114
|
function resetClock(resetsAt) {
|
|
80
115
|
return `${resetsAt.slice(0, 16).replace("T", " ")} UTC`;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@miraland-labs/conduit-bridge",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.107",
|
|
4
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": {
|