vdelta 0.10.1 → 0.10.2

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.
@@ -3,7 +3,7 @@
3
3
  * claudedocs/2026-07-16-expA-tree-digest.md, ported verbatim):
4
4
  * a git tree object id over tracked+staged+unstaged+untracked files,
5
5
  * excluding committed-gitignore'd paths, computed against a dedicated
6
- * throwaway index seeded from HEAD, with host-dependent git settings pinned.
6
+ * throwaway index, with host-dependent git settings pinned.
7
7
  * Rendered as a bare 40-hex OID (documented deviation from sha256:).
8
8
  *
9
9
  * treeDigest() is read-only with respect to the observed repo: all git
@@ -13,10 +13,51 @@
13
13
  * handles linked worktrees whose objects live in the common dir) are made
14
14
  * available for reads through GIT_ALTERNATE_OBJECT_DIRECTORIES. The
15
15
  * throwaway directory is removed again once the digest has been computed.
16
+ *
17
+ * The throwaway index (GIT_INDEX_FILE) is seeded from a byte copy of the
18
+ * repository's real index file (resolved via `--git-path index`, which
19
+ * yields the per-worktree index for linked worktrees) with its mtime
20
+ * preserved, so git's stat cache is honoured and `add -A` re-hashes only
21
+ * files whose stat data changed, keeping cost proportional to dirty files
22
+ * instead of tracked files. `add -A` + `write-tree` reconcile the index
23
+ * with the working tree so the resulting tree id is independent of the
24
+ * seed (verified for the S1-S17 scenarios of issue #81 and enforced by
25
+ * tests/unit/tree-digest-parity.test.ts).
26
+ *
27
+ * (1) racy-git: correctness of the stat-cache shortcut rests on git's
28
+ * racy-git handling (entries whose mtime is not older than the index
29
+ * file's mtime are re-read rather than trusted, and racily-clean entries
30
+ * are size-smudged at write time); the copy preserves the real index's
31
+ * mtime so these semantics are identical to git's own; the issue's 20/20
32
+ * same-size-same-second sample is evidence, not proof; environments that
33
+ * rewrite file stat data behind git's back (tools that restore mtimes,
34
+ * some sync/backup agents) can break this premise -- when in doubt such
35
+ * environments should be treated as unverified.
36
+ *
37
+ * (2) split-index / extensions: an index with the `link` extension
38
+ * (core.splitIndex) still resolves `sharedindex.*` from the real git dir,
39
+ * so a copied index works (S14 in #81); however core.untrackedCache,
40
+ * core.fsmonitor and index.sparse were all unset in every repo the change
41
+ * was validated against, and behaviour with those enabled is UNVERIFIED.
42
+ * assume-unchanged (CE_VALID) and skip-worktree (sparse-checkout) entries
43
+ * are handled explicitly: `add -A` skips them via ie_match_stat without
44
+ * stat'ing the working tree, so a copied index carrying either flag on a
45
+ * changed file would silently keep the stale HEAD content. After copying,
46
+ * `git ls-files -v` is run against the throwaway index and, if any entry
47
+ * reports a lowercase tag (assume-unchanged) or an `S`/`s` tag
48
+ * (skip-worktree), the copy is discarded and seeding falls back to
49
+ * `read-tree` (note 3) instead, which always re-stats every path via
50
+ * `add -A`. Covered by S16 (assume-unchanged) and S17 (skip-worktree) in
51
+ * tests/unit/tree-digest-parity.test.ts.
52
+ *
53
+ * (3) fallback: when the real index file does not exist (fresh `git
54
+ * init`, checkout from bare, `rm .git/index`) or cannot be copied, the
55
+ * index is seeded with `git read-tree HEAD` (or `read-tree --empty` for
56
+ * an unborn HEAD) exactly as before; this fallback MUST be kept.
16
57
  */
17
58
  import { execFile } from 'node:child_process';
18
59
  import { randomUUID } from 'node:crypto';
19
- import { mkdir, rm } from 'node:fs/promises';
60
+ import { copyFile, mkdir, rm, stat, utimes } from 'node:fs/promises';
20
61
  import { tmpdir } from 'node:os';
21
62
  import { delimiter, join } from 'node:path';
22
63
  import { promisify } from 'node:util';
@@ -38,17 +79,59 @@ async function git(worktree, args, env) {
38
79
  });
39
80
  return stdout.trim();
40
81
  }
82
+ /**
83
+ * Seed the throwaway index by copying the repository's real index file
84
+ * byte-for-byte, preserving its mtime (see header note 1: preserving
85
+ * mtime keeps racy-git behaviour identical to git's own handling of the
86
+ * real index). Returns false when the real index does not exist or the
87
+ * copy cannot be completed, in which case any partial copy is removed and
88
+ * the caller MUST fall back to `read-tree` (header note 3).
89
+ */
90
+ async function seedFromRealIndex(realIndex, idx) {
91
+ try {
92
+ const st = await stat(realIndex);
93
+ if (!st.isFile())
94
+ return false;
95
+ await copyFile(realIndex, idx);
96
+ await utimes(idx, st.atime, st.mtime);
97
+ return true;
98
+ }
99
+ catch {
100
+ await rm(idx, { force: true });
101
+ return false;
102
+ }
103
+ }
104
+ /**
105
+ * `git ls-files -v` tags each entry H (cached), S (skip-worktree), M
106
+ * (unmerged), R (removed), C (modified/changed) or K (to be killed); the
107
+ * tag is lowercased when the entry also has the assume-unchanged
108
+ * (CE_VALID) bit set. `add -A` reconciles the index against the working
109
+ * tree via ie_match_stat, which treats both assume-unchanged and
110
+ * skip-worktree entries as trusted and skips re-stat'ing them -- so a
111
+ * copied real index carrying either flag on a changed file would leave the
112
+ * throwaway index (and therefore the resulting tree) pinned to the stale
113
+ * content. Detect that here so the caller can fall back to a `read-tree`
114
+ * seed, which re-stats every path.
115
+ */
116
+ function hasUntrustworthyIndexFlags(lsFilesOutput) {
117
+ return lsFilesOutput
118
+ .split('\n')
119
+ .some((line) => line !== '' && /^[a-z]|^[Ss]/.test(line));
120
+ }
41
121
  export async function treeDigest(worktree) {
42
122
  const idx = join(tmpdir(), `vd-idx-${randomUUID()}`);
43
123
  const objDir = join(tmpdir(), `vd-obj-${randomUUID()}`);
44
124
  try {
45
125
  await mkdir(objDir, { recursive: true });
46
- const realObjects = await git(worktree, [
126
+ const paths = await git(worktree, [
47
127
  'rev-parse',
48
128
  '--path-format=absolute',
49
129
  '--git-path',
50
130
  'objects',
131
+ '--git-path',
132
+ 'index',
51
133
  ]);
134
+ const [realObjects = '', realIndex = ''] = paths.split(/\r?\n/);
52
135
  const existingAlternates = process.env.GIT_ALTERNATE_OBJECT_DIRECTORIES;
53
136
  const alternates = existingAlternates
54
137
  ? `${realObjects}${delimiter}${existingAlternates}`
@@ -58,18 +141,20 @@ export async function treeDigest(worktree) {
58
141
  GIT_OBJECT_DIRECTORY: objDir,
59
142
  GIT_ALTERNATE_OBJECT_DIRECTORIES: alternates,
60
143
  };
61
- let hasHead = true;
62
- try {
63
- await git(worktree, ['rev-parse', '--verify', '-q', 'HEAD']);
64
- }
65
- catch {
66
- hasHead = false;
67
- }
68
- if (hasHead) {
69
- await git(worktree, ['read-tree', 'HEAD'], env);
144
+ let seeded = await seedFromRealIndex(realIndex, idx);
145
+ if (seeded &&
146
+ hasUntrustworthyIndexFlags(await git(worktree, ['ls-files', '-v'], env))) {
147
+ seeded = false;
70
148
  }
71
- else {
72
- await git(worktree, ['read-tree', '--empty'], env);
149
+ if (!seeded) {
150
+ let hasHead = true;
151
+ try {
152
+ await git(worktree, ['rev-parse', '--verify', '-q', 'HEAD']);
153
+ }
154
+ catch {
155
+ hasHead = false;
156
+ }
157
+ await git(worktree, ['read-tree', hasHead ? 'HEAD' : '--empty'], env);
73
158
  }
74
159
  await git(worktree, ['add', '-A'], env);
75
160
  return await git(worktree, ['write-tree'], env);
@@ -1 +1 @@
1
- {"version":3,"file":"tree-digest.js","sourceRoot":"","sources":["../src/tree-digest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tree-digest.js","sourceRoot":"","sources":["../src/tree-digest.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vdelta",
3
- "version": "0.10.1",
3
+ "version": "0.10.2",
4
4
  "description": "Reference implementation of veridelta/1 — proof-carrying verification deltas for coding-agent development loops",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -199,12 +199,19 @@ full digest.
199
199
  git tree object id over the union of tracked, staged, unstaged, and untracked
200
200
  files, excluding paths ignored by committed `.gitignore`/`.gitattributes`
201
201
  rules. Implementations MUST compute it against a dedicated, throwaway index
202
- (`GIT_INDEX_FILE`) seeded from `HEAD` (`git read-tree HEAD`, or `read-tree
203
- --empty` for an unborn `HEAD`), followed by `git add -A` and `git write-tree`,
204
- so that the operation never mutates the repository's real index or working
205
- tree. To keep the digest deterministic and independent of host and time, the
206
- computation MUST pin `core.autocrlf=false`, `core.eol=lf`, and
207
- `core.excludesFile=/dev/null`, and MUST NOT depend on file mtimes. For a clean
202
+ (`GIT_INDEX_FILE`), followed by `git add -A` and `git write-tree`, so that the
203
+ operation never mutates the repository's real index or working tree. The
204
+ throwaway index MAY be seeded from `HEAD` (`git read-tree HEAD`, or
205
+ `read-tree --empty` for an unborn `HEAD`) or from a byte copy of the
206
+ repository's real index file (which carries git's stat cache and avoids
207
+ re-hashing unchanged tracked files); because `git add -A` reconciles the
208
+ index with the working tree before `write-tree`, the resulting id MUST NOT
209
+ depend on which seed was used. To keep the digest deterministic and
210
+ independent of host and time, the computation MUST pin
211
+ `core.autocrlf=false`, `core.eol=lf`, and `core.excludesFile=/dev/null`, and
212
+ MUST NOT depend on file mtimes (an implementation MAY consult git's stat
213
+ cache to skip re-hashing, relying on git's racy-git detection, provided the
214
+ resulting id equals that of a full re-hash). For a clean
208
215
  checkout the resulting id is identical to `git rev-parse HEAD^{tree}`, which a
209
216
  verifier MAY use directly as the canonical form (subject to the conditions of
210
217
  §11.3). The digest records submodules solely by their gitlink commit id; it