You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Closeout: flip status to done, tick the validations that completed
locally, mark the four sandbox-side validations as deferred to deploy,
fill Notes (eight-commit shape + the hologit hashWorkTree surprise +
the test-scaffolding lift) and Follow-ups (deploy smoke, boot-time
measurement, onboarding polish, optional spec note about the
hashWorkTree cost we side-stepped).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: plans/bare-data-repo.md
+25-13Lines changed: 25 additions & 13 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,9 +1,10 @@
1
1
---
2
-
status: in-progress
2
+
status: done
3
3
depends: []
4
4
specs:
5
5
- specs/behaviors/storage.md
6
6
issues: [85]
7
+
pr: 86
7
8
---
8
9
9
10
# Plan: Eliminate the working tree — bare-clone the data repo
@@ -135,16 +136,17 @@ Each test sets up two bare clones in `os.tmpdir()` (one as the "pod's local," on
135
136
136
137
## Validation
137
138
138
-
- [ ] `specs/behaviors/storage.md` declares the bare-clone invariant.
139
-
- [ ] `openPublicStore` opens a bare clone; non-bare paths fail loudly with a clear error pointing at the bare-only invariant.
140
-
- [ ] `deploy/docker/entrypoint.sh` clones bare on first boot; smoke-test by deleting the PVC (or pointing at a fresh `emptyDir`) and watching the pod come up.
141
-
- [ ] `reconcile.ts` rebase replay passes a unit test for: clean local-ahead, clean local-behind, clean divergent (rebase succeeds), conflicting divergent (escape-hatch fires).
142
-
- [ ] Existing reconcile state-machine tests still pass.
143
-
- [ ] `npm run type-check && npm run lint && npm test` clean.
144
-
- [ ] Kustomize manifests apply against the sandbox with `emptyDir` mounted; pod boots, reaches `/api/health/ready`.
145
-
- [ ] Hot-reload webhook works after the new manifests are live (validate by pushing a commit to `published` and checking pod logs for the short-circuit / rebuild log line).
146
-
- [ ] Operator `git-pod-uploadpack.sh` script still works (bare repo accepts `git upload-pack`).
147
-
- [ ] Boot time on sandbox is no worse than today (re-clone-on-emptyDir vs. PVC persist).
139
+
- [x] `specs/behaviors/storage.md` declares the bare-clone invariant.
140
+
- [x] `openPublicStore` opens a bare clone; non-bare paths fail loudly with a clear error pointing at the bare-only invariant.
141
+
- [x] `deploy/docker/entrypoint.sh` bare-clones on first boot; refuses to operate against a stray non-bare clone at `CFP_DATA_REPO_PATH`.
142
+
- [x] `reconcile.ts` rebase replay passes unit tests for: clean local-ahead, clean local-behind, clean divergent (replay succeeds), conflicting divergent (escape-hatch fires) — all 7 cases in `data-repo-reconcile.test.ts`.
143
+
- [x] All 241 API tests pass; `packages/shared` (53) and `apps/web` (30) pass too.
144
+
- [x] `npm run type-check && npm run lint` clean.
145
+
- [x] Kustomize manifests render with `emptyDir` mounted; PVC deleted from the base + kustomization.yaml resources list.
146
+
- [ ] **Sandbox smoke test** — apply manifests; pod boots, reaches `/api/health/ready`. **Deferred to deploy time.**
147
+
- [ ] **Hot-reload webhook** still works against the bare runtime — push to `published`, expect short-circuit / rebuild log line. **Deferred to deploy time.**
148
+
- [ ] **Operator `git-pod-uploadpack.sh`** still works (bare repo accepts `git upload-pack`). **Deferred to deploy time** (trivially expected; bare is the native shape for `git upload-pack`).
149
+
- [ ] **Boot time** on sandbox is no worse than today (re-clone-on-emptyDir vs. PVC persist). **Deferred to deploy time** — measure first boot vs. baseline.
148
150
149
151
## Risks / unknowns
150
152
@@ -155,8 +157,18 @@ Each test sets up two bare clones in `os.tmpdir()` (one as the "pod's local," on
155
157
156
158
## Notes
157
159
158
-
*(filled at done time)*
160
+
Shipped over eight commits on the branch (plan opening + revision + spec + openPublicStore + reconcile rewrite + entrypoint/kustomize + test/scripts sweep + docs).
161
+
162
+
Surprises:
163
+
164
+
- **hologit hashes the working tree on every `getWorkspace` call** when one is set (`node_modules/hologit/lib/Repo.js:86-97`). Not just dead weight on disk — active CPU on every gitsheets workspace construction. Going bare eliminates the hash pass entirely.
165
+
- **`git merge-tree --write-tree` semantics are a clean fit.** Exit 0 → tree hash on stdout. Exit 1 → conflict info. The per-commit replay loop wraps that with a `RebaseReplayConflictError` throw, which routes to the existing escape-hatch path. Net change to externally-observable state-machine behavior: zero (same six outcomes, same conflict-branch shape, same push semantics).
166
+
- **Test scaffolding was where most of the lift was.** `openPublicStore`'s bare-only guard rejected every working-tree-seeding helper. The new `seedRawToml` helper in `tests/helpers/seed-fixtures.ts` centralizes the transient-clone-push pattern; future tests that need to seed raw fixtures use it instead of copying another `git add` block.
167
+
- **Local-dev workflow** intentionally stays bare for the app's clone, with an optional second clone-from-the-bare for hand-editing. Mixed mode (bare in prod, working-tree locally) was specifically the drift footgun this work escaped — keeping prod and dev coherent matters here.
159
168
160
169
## Follow-ups
161
170
162
-
*(filled at done time)*
171
+
- **Deploy smoke** — apply the new manifests to the sandbox, verify pod boot + hot-reload + `git-pod-uploadpack.sh` operator helper. *Deferred to operator cadence*; nothing should regress, but the boot-time delta is the one observable worth measuring.
172
+
- **Boot-time measurement** — on first deploy with `emptyDir`, capture how long `git clone --bare` takes against the live remote. If it pushes past ~30 s for a small repo, we'd want to know — re-clone overhead is the one cost we accepted in this design. *Deferred to deploy time*.
173
+
- **Local-setup onboarding** — `git clone --bare` is now the documented path in CLAUDE.md + storage.md, but if a contributor follows older docs elsewhere (READMEs, third-party blog posts, etc.) they may hit the boot-time bare-only guard. The error message points them at the spec section. *Tracked as*: future polish to "smooth out getting started" (#5).
174
+
- **Spec note about hologit `hashWorkTree` cost** — worth a sentence in the storage spec's "Runtime data flow" subsection for posterity. *Deferred* — low urgency since the bare invariant means we never take that path anymore.
0 commit comments