@agent-delivery-harness/cli 0.8.0 → 0.8.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-delivery-harness/cli",
3
- "version": "0.8.0",
3
+ "version": "0.8.1",
4
4
  "type": "module",
5
5
  "description": "Delivery harness CLI: admit, prepare, review-context, submit-evidence, gate, record, verify, check",
6
6
  "license": "FSL-1.1-ALv2",
@@ -13,7 +13,7 @@
13
13
  "node": ">=22.6.0"
14
14
  },
15
15
  "dependencies": {
16
- "@agent-delivery-harness/kernel": "0.8.0"
16
+ "@agent-delivery-harness/kernel": "0.8.1"
17
17
  },
18
18
  "exports": {
19
19
  ".": "./src/index.ts"
@@ -159,6 +159,29 @@ function selfReferences(...created: (string | undefined)[]): string[] {
159
159
  export function executionPath(root: string, value: string): string {
160
160
  return value.split(path.delimiter).filter(p => p && path.isAbsolute(p) && !inside(root, p) && !p.split(path.sep).includes("node_modules")).join(path.delimiter) || "/usr/bin:/bin";
161
161
  }
162
+ /** The commit depth a materialization fetch needs, or undefined for the source's whole history.
163
+ * A tip lies at most `merge-base..tip` commits plus one above the merge-base on any path, so
164
+ * that depth from both tips keeps every commit a merge-base, ancestry or three-dot read walks.
165
+ * That holds only while the merge-base is the sole commit those ranges stand on: a side branch
166
+ * forked below it would arrive cut off from it and read as a second merge-base. */
167
+ async function materializationDepth(input: SnapshotRequest, git: (...args: string[]) => Promise<string>): Promise<number | undefined> {
168
+ if (input.gitContext === "none") return 1;
169
+ const { headSha, base } = input.candidate;
170
+ try {
171
+ // Reading the author's repository only; the fetch below still transfers object bytes.
172
+ // A tip above the merge-base stands on it alone exactly when it is the range's one boundary
173
+ // commit, which also makes it an ancestor of that tip and so fetched through it.
174
+ for (const tip of [headSha, base.tipSha]) {
175
+ const boundary = (await git("-C", input.rootDir, "rev-list", "--boundary", `${base.mergeBaseSha}..${tip}`))
176
+ .split("\n").filter(line => line.startsWith("-"));
177
+ if (tip !== base.mergeBaseSha && boundary.join("\n") !== `-${base.mergeBaseSha}`) return undefined;
178
+ }
179
+ const counts = await Promise.all([headSha, base.tipSha].map(tip => git("-C", input.rootDir, "rev-list", "--count", `${base.mergeBaseSha}..${tip}`)));
180
+ const longest = Math.max(...counts.map(Number));
181
+ return Number.isSafeInteger(longest) && longest >= 0 ? longest + 1 : undefined;
182
+ } catch { return undefined; }
183
+ }
184
+
162
185
  export async function createCheckSnapshot(input: SnapshotRequest): Promise<CheckSnapshot> {
163
186
  if (input.physicalSource !== undefined) return createFiniteCheckSnapshot(input);
164
187
  const report = (phase: SnapshotPhase, started: number) => {
@@ -193,7 +216,16 @@ export async function createCheckSnapshot(input: SnapshotRequest): Promise<Check
193
216
  // cannot create writable links back to the author's Git metadata.
194
217
  // Accept the source's shallow boundary in this private repository. Without
195
218
  // it, fetch can reject objects or succeed while dropping required grafts.
196
- await git("fetch", "--update-shallow", "--no-tags", "--no-write-fetch-head", input.rootDir, input.candidate.headSha, input.candidate.base.tipSha, input.candidate.treeSha);
219
+ // Fetch only the history a check can read (V26-3284): none past the pinned
220
+ // commits without Git, and with Git the commits from the merge-base to each
221
+ // tip, which merge-base, ancestry and three-dot diffs need. A distance the
222
+ // source cannot measure keeps today's whole-history fetch.
223
+ const depth = await materializationDepth(input, git);
224
+ // Within a bounded full history the merge-base is already fetched from both
225
+ // tips; asked for by itself it would deepen past itself by the same depth.
226
+ const mergeBase = input.gitContext !== "none" && depth !== undefined ? [] : [input.candidate.base.mergeBaseSha];
227
+ await git("fetch", "--update-shallow", ...(depth === undefined ? [] : ["--depth", String(depth)]), "--no-tags", "--no-write-fetch-head", input.rootDir,
228
+ input.candidate.headSha, input.candidate.base.tipSha, ...mergeBase, input.candidate.treeSha);
197
229
  await git("update-ref", "HEAD", input.candidate.headSha);
198
230
  await git("read-tree", input.candidate.treeSha);
199
231
  await git("checkout-index", "--all", "--force");