@miraland-labs/conduit-bridge 0.16.6 → 0.16.7
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/driver.js
CHANGED
|
@@ -99,6 +99,16 @@ export function buildAssignmentPrompt(context) {
|
|
|
99
99
|
}
|
|
100
100
|
if (changeScope?.length)
|
|
101
101
|
lines.push("", `CHANGE SCOPE — only modify paths under\n${changeScope.map((item) => `- ${item}`).join("\n")}`);
|
|
102
|
+
const integrationObligations = spec.integration_obligations ?? [];
|
|
103
|
+
if (integrationObligations.length) {
|
|
104
|
+
lines.push("", "INTEGRATION OBLIGATIONS — finalize fails unless these hold");
|
|
105
|
+
for (const obligation of integrationObligations) {
|
|
106
|
+
if (obligation.kind !== "symbol_referenced_from")
|
|
107
|
+
continue;
|
|
108
|
+
const globs = obligation.from_globs?.length ? obligation.from_globs.join(", ") : "runtime entrypoints";
|
|
109
|
+
lines.push(`- symbol "${obligation.symbol}" must be referenced from ${globs}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
102
112
|
if (context.normativeRefs?.length) {
|
|
103
113
|
lines.push("", "NORMATIVE REFERENCES — read-only contract files; your implementation must align. Do not edit anything under .conduit/normative/.");
|
|
104
114
|
for (const ref of context.normativeRefs) {
|
|
@@ -22,8 +22,14 @@ export async function ensureChangeEvidence(input) {
|
|
|
22
22
|
return input.report;
|
|
23
23
|
const paths = input.changedPaths
|
|
24
24
|
?? (input.baseCommit ? await changedPathsSince(input.workspace, input.baseCommit) : null);
|
|
25
|
-
if (
|
|
25
|
+
if (paths === null)
|
|
26
26
|
return input.report;
|
|
27
|
+
if (!paths.length) {
|
|
28
|
+
return {
|
|
29
|
+
...input.report,
|
|
30
|
+
evidence: input.report.evidence.filter((item) => item.kind !== "change"),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
27
33
|
const stat = input.baseCommit ? await diffStatSince(input.workspace, input.baseCommit) : null;
|
|
28
34
|
const baseLabel = input.baseCommit?.slice(0, 12) ?? "base";
|
|
29
35
|
const details = [
|
package/dist/execution.js
CHANGED
|
@@ -1209,10 +1209,9 @@ async function runClaimedAssignment(client, config, driver, workspace, brief, ta
|
|
|
1209
1209
|
repositoryFingerprint: executionContract.repository_fingerprint,
|
|
1210
1210
|
});
|
|
1211
1211
|
// Ask git what changed before trusting what the report says changed.
|
|
1212
|
-
const
|
|
1213
|
-
? await
|
|
1212
|
+
const actualPaths = /^[0-9a-f]{7,40}$/i.test(worktreeStart)
|
|
1213
|
+
? await changedPathsSince(attemptWorkspace, worktreeStart)
|
|
1214
1214
|
: null;
|
|
1215
|
-
const actualPaths = startCommit ? await changedPathsSince(attemptWorkspace, startCommit) : null;
|
|
1216
1215
|
// Mechanical test path: agent often forgets verbatim make test / npm test output.
|
|
1217
1216
|
report = await ensureTestEvidence({
|
|
1218
1217
|
workspace: attemptWorkspace,
|
|
@@ -1223,7 +1222,7 @@ async function runClaimedAssignment(client, config, driver, workspace, brief, ta
|
|
|
1223
1222
|
});
|
|
1224
1223
|
report = await ensureChangeEvidence({
|
|
1225
1224
|
workspace: attemptWorkspace,
|
|
1226
|
-
baseCommit: startCommit,
|
|
1225
|
+
baseCommit: /^[0-9a-f]{7,40}$/i.test(worktreeStart) ? worktreeStart : startCommit,
|
|
1227
1226
|
report,
|
|
1228
1227
|
spec,
|
|
1229
1228
|
grants,
|
|
@@ -41,7 +41,7 @@ export function parseIntegrationObligations(value) {
|
|
|
41
41
|
async function symbolReferencedFrom(workspace, symbol, globs) {
|
|
42
42
|
const pathspecs = globs.map((glob) => `:(glob)${glob}`);
|
|
43
43
|
try {
|
|
44
|
-
const { stdout } = await execFileAsync("git", ["-C", workspace, "grep", "-l", "-F", symbol, "--", ...pathspecs], { timeout: 30_000, maxBuffer: 4_000_000 });
|
|
44
|
+
const { stdout } = await execFileAsync("git", ["-C", workspace, "grep", "-l", "-F", "--untracked", symbol, "--", ...pathspecs], { timeout: 30_000, maxBuffer: 4_000_000 });
|
|
45
45
|
return stdout.trim().length > 0;
|
|
46
46
|
}
|
|
47
47
|
catch (error) {
|
package/dist/land-git-reality.js
CHANGED
|
@@ -84,7 +84,7 @@ export function agentClaimsRepositoryWork(text) {
|
|
|
84
84
|
}
|
|
85
85
|
if (NO_CHANGE_OUTCOME.test(text))
|
|
86
86
|
return false;
|
|
87
|
-
return /\b(rewrote|replaced|implemented|fetcher\.rs|head_commit|"changes"\s*:\s*\[)/i.test(text);
|
|
87
|
+
return /\b(rewrote|replaced|implemented|fetcher\.rs|head_commit|"changes"\s*:\s*\[\s*")/i.test(text);
|
|
88
88
|
}
|
|
89
89
|
/** Parsed Delivery claims repository work (stricter than free text). */
|
|
90
90
|
export function reportClaimsRepositoryWork(report) {
|
package/dist/normative-refs.js
CHANGED
|
@@ -48,9 +48,17 @@ function validateNormativePath(path) {
|
|
|
48
48
|
function cacheDir(sourceWorkspace, repository) {
|
|
49
49
|
return join(sourceWorkspace, ".conduit", "normative-cache", fingerprint(repository).replaceAll("/", "__"));
|
|
50
50
|
}
|
|
51
|
+
const GIT_NO_PROMPT = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
|
|
51
52
|
function cloneUrl(repository) {
|
|
52
53
|
return `https://${fingerprint(repository)}.git`;
|
|
53
54
|
}
|
|
55
|
+
function assertPublicGitHost(repository) {
|
|
56
|
+
const host = fingerprint(repository).split("/")[0] ?? "";
|
|
57
|
+
if (!host || !host.includes(".") || host === "localhost" || host.endsWith(".localhost")
|
|
58
|
+
|| host.endsWith(".internal") || /^\d/.test(host) || host.includes(":")) {
|
|
59
|
+
throw new Error(`${NORMATIVE_REF_PREFIX}: repository host is not a public git host`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
54
62
|
async function pathExists(path) {
|
|
55
63
|
try {
|
|
56
64
|
await access(path, constants.F_OK);
|
|
@@ -72,7 +80,11 @@ async function readPinnedRevision(repoDir) {
|
|
|
72
80
|
return null;
|
|
73
81
|
}
|
|
74
82
|
}
|
|
83
|
+
async function gitNoPrompt(args, timeout, maxBuffer) {
|
|
84
|
+
await execFileAsync("git", args, { timeout, maxBuffer, env: GIT_NO_PROMPT });
|
|
85
|
+
}
|
|
75
86
|
async function ensureRepoCache(sourceWorkspace, ref) {
|
|
87
|
+
assertPublicGitHost(ref.repository);
|
|
76
88
|
const dir = cacheDir(sourceWorkspace, ref.repository);
|
|
77
89
|
const wantedRevision = ref.revision ?? "HEAD";
|
|
78
90
|
const marker = join(dir, ".conduit-normative-revision");
|
|
@@ -89,7 +101,7 @@ async function ensureRepoCache(sourceWorkspace, ref) {
|
|
|
89
101
|
}
|
|
90
102
|
cloneArgs.push(cloneUrl(ref.repository), dir);
|
|
91
103
|
try {
|
|
92
|
-
await
|
|
104
|
+
await gitNoPrompt(cloneArgs, 180_000, 4_000_000);
|
|
93
105
|
}
|
|
94
106
|
catch (error) {
|
|
95
107
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -98,32 +110,23 @@ async function ensureRepoCache(sourceWorkspace, ref) {
|
|
|
98
110
|
}
|
|
99
111
|
else if (ref.revision && cachedRevision !== wantedRevision) {
|
|
100
112
|
try {
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
timeout: 120_000,
|
|
104
|
-
maxBuffer: 4_000_000,
|
|
105
|
-
});
|
|
106
|
-
await execFileAsync("git", ["-C", dir, "checkout", "--detach", "FETCH_HEAD"], {
|
|
107
|
-
timeout: 60_000,
|
|
108
|
-
maxBuffer: 1_000_000,
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
else {
|
|
112
|
-
await execFileAsync("git", ["-C", dir, "fetch", "--depth", "1", "origin", ref.revision], {
|
|
113
|
-
timeout: 120_000,
|
|
114
|
-
maxBuffer: 4_000_000,
|
|
115
|
-
});
|
|
116
|
-
await execFileAsync("git", ["-C", dir, "checkout", "--detach", "FETCH_HEAD"], {
|
|
117
|
-
timeout: 60_000,
|
|
118
|
-
maxBuffer: 1_000_000,
|
|
119
|
-
});
|
|
120
|
-
}
|
|
113
|
+
await gitNoPrompt(["-C", dir, "fetch", "--depth", "1", "origin", ref.revision], 120_000, 4_000_000);
|
|
114
|
+
await gitNoPrompt(["-C", dir, "checkout", "--detach", "FETCH_HEAD"], 60_000, 1_000_000);
|
|
121
115
|
}
|
|
122
116
|
catch (error) {
|
|
123
117
|
const message = error instanceof Error ? error.message : String(error);
|
|
124
118
|
throw new Error(`${NORMATIVE_REF_PREFIX}: could not checkout ${ref.revision} in ${fingerprint(ref.repository)} (${message})`);
|
|
125
119
|
}
|
|
126
120
|
}
|
|
121
|
+
else if (!ref.revision) {
|
|
122
|
+
try {
|
|
123
|
+
await gitNoPrompt(["-C", dir, "fetch", "--depth", "1", "origin", "HEAD"], 120_000, 4_000_000);
|
|
124
|
+
await gitNoPrompt(["-C", dir, "checkout", "--detach", "FETCH_HEAD"], 60_000, 1_000_000);
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
// Keep the last successful cache when origin is unreachable (offline tests, private host already rejected).
|
|
128
|
+
}
|
|
129
|
+
}
|
|
127
130
|
const revision = (await readPinnedRevision(dir)) ?? wantedRevision;
|
|
128
131
|
await writeFile(marker, `${revision}\n`, "utf8");
|
|
129
132
|
return { dir, revision };
|
|
@@ -170,10 +173,12 @@ export function assertNormativeRefsMaterialized(refs, materialized) {
|
|
|
170
173
|
}
|
|
171
174
|
}
|
|
172
175
|
}
|
|
176
|
+
function isConduitPath(path) {
|
|
177
|
+
const normalized = path.replaceAll("\\", "/");
|
|
178
|
+
return normalized === ".conduit" || normalized.startsWith(".conduit/");
|
|
179
|
+
}
|
|
173
180
|
async function markerPresent(workspace, marker, paths) {
|
|
174
|
-
const args = ["-C", workspace, "grep", "-l", "-F", marker];
|
|
175
|
-
if (paths?.length)
|
|
176
|
-
args.push("--", ...paths);
|
|
181
|
+
const args = ["-C", workspace, "grep", "-l", "-F", "--untracked", marker, "--", ...paths];
|
|
177
182
|
try {
|
|
178
183
|
const { stdout } = await execFileAsync("git", args, {
|
|
179
184
|
timeout: 30_000,
|
|
@@ -192,14 +197,19 @@ export async function checkNormativeMarkers(workspace, refs, changedPaths) {
|
|
|
192
197
|
const scoped = refs.filter((ref) => ref.markers?.length);
|
|
193
198
|
if (!scoped.length)
|
|
194
199
|
return { ok: true };
|
|
195
|
-
|
|
200
|
+
if (changedPaths === null) {
|
|
201
|
+
return { ok: false, failures: ["changed files are unknown; required markers cannot be verified"] };
|
|
202
|
+
}
|
|
203
|
+
const searchPaths = changedPaths.filter((path) => path && !isConduitPath(path));
|
|
204
|
+
if (!searchPaths.length) {
|
|
205
|
+
return { ok: false, failures: ["no changed files to search for required markers"] };
|
|
206
|
+
}
|
|
196
207
|
const failures = [];
|
|
197
208
|
for (const ref of scoped) {
|
|
198
209
|
for (const marker of ref.markers ?? []) {
|
|
199
210
|
const found = await markerPresent(workspace, marker, searchPaths);
|
|
200
211
|
if (!found) {
|
|
201
|
-
|
|
202
|
-
failures.push(`marker "${marker}" from ${ref.label} not found in ${scope}`);
|
|
212
|
+
failures.push(`marker "${marker}" from ${ref.label} not found in changed files`);
|
|
203
213
|
}
|
|
204
214
|
}
|
|
205
215
|
}
|
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.7",
|
|
4
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",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|