Conversation
Introduces a plans/ directory with three design documents: a ready-to-implement plan for the two-layer persistence model (immutable profile images plus per-VM overlay disks, with a first-boot setup hook), and two high-level sketches for future optimizations (VM snapshots and a read-only squashfs sidecar) to revisit only if and when their motivating problems materialize. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
📝 WalkthroughWalkthroughThree new planning documents outline proposed future features: read-only squashfs sidecar optimization, VM snapshot restoration for sub-second startup, and a profiles-and-overlay system combining custom initrd images, persistent overlay disks, and first-boot setup hooks. Changes
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~8 minutes Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
plans/future-squashfs-sidecar.md (1)
20-22: Optional wording cleanup for readability.Lines 20–22 start successive bullets with “When…”. Consider varying one opener to reduce repetition.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plans/future-squashfs-sidecar.md` around lines 20 - 22, The three consecutive bullets in plans/future-squashfs-sidecar.md all start with "When…", which is repetitive; edit one bullet (e.g., the second bullet that begins "When a natural use case (ML tooling, JDK-based agents) appears…") to vary the opener — for example change "When" to "If" or rephrase to "A natural use case is…" — keeping the meaning intact and preserving the emphasis that mutable state belongs on the per-VM overlay disk in the third bullet.plans/profiles-and-overlay.md (1)
89-93: Cache key inputs should include builder pipeline/version identity.Current hash inputs (Line 90) omit builder logic/toolchain identity. If packing behavior changes, stale
build.hashmay incorrectly hit cache. Add builder version/salt to the cache key definition.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plans/profiles-and-overlay.md` around lines 89 - 93, Update the image cache key definition to include the builder pipeline/toolchain identity (a builder version or salt) in addition to the existing inputs; specifically, change the "Image cache key = sha256 of `packages` + `build` + base kernel/initrd version" to include a builder identifier (e.g., `builder_version` or `builder_salt`), and ensure this combined value is what is written to and compared in `images/profiles/<name>/build.hash` so that changes in packing logic/toolchain invalidate the cache and trigger rebuilds on the next `pen shell --profile`.plans/future-vm-snapshots.md (1)
21-30: Define a concrete snapshot metadata manifest now (even if feature is deferred).Lines 21–30 list invalidation rules, but without a manifest contract (e.g.,
snapshot.jsonfields), implementation can drift. Add a minimal schema for keys like image hash, overlay fingerprint, env hash, host/vz version, and created-at.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@plans/future-vm-snapshots.md` around lines 21 - 30, Add a concrete snapshot metadata manifest contract (e.g., snapshot.json) that lists minimal required fields and semantics: include imageHash (guest image content hash), overlayFingerprint (overlay disk hash or mtime+size), envHash (hash of injected environment vars), hostVzVersion (host OS + vz library version and CPU generation tag), createdAt (ISO timestamp) and an optional invalidateReasons array; document expected formats and when each field must be checked (restore validation uses imageHash, overlayFingerprint, envHash, hostVzVersion) and when to bump invalidateReasons. Ensure names match this manifest (snapshot.json imageHash, overlayFingerprint, envHash, hostVzVersion, createdAt) so code like snapshot creation, restore validation, and invalidation logic can reliably read/write the same keys.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@plans/profiles-and-overlay.md`:
- Around line 42-59: The markdown has bare triple-backtick fences in
plans/profiles-and-overlay.md around the filesystem tree starting with
"~/.config/pen/" and the numbered init sequence starting "1. Mount proc, sys,
dev, tmp, run, devpts"; update those fences to include language identifiers (use
```text for the filesystem tree block and ```sh or ```text for the init sequence
block as appropriate) so the fenced code blocks satisfy markdownlint MD040 and
avoid lint failures.
---
Nitpick comments:
In `@plans/future-squashfs-sidecar.md`:
- Around line 20-22: The three consecutive bullets in
plans/future-squashfs-sidecar.md all start with "When…", which is repetitive;
edit one bullet (e.g., the second bullet that begins "When a natural use case
(ML tooling, JDK-based agents) appears…") to vary the opener — for example
change "When" to "If" or rephrase to "A natural use case is…" — keeping the
meaning intact and preserving the emphasis that mutable state belongs on the
per-VM overlay disk in the third bullet.
In `@plans/future-vm-snapshots.md`:
- Around line 21-30: Add a concrete snapshot metadata manifest contract (e.g.,
snapshot.json) that lists minimal required fields and semantics: include
imageHash (guest image content hash), overlayFingerprint (overlay disk hash or
mtime+size), envHash (hash of injected environment vars), hostVzVersion (host OS
+ vz library version and CPU generation tag), createdAt (ISO timestamp) and an
optional invalidateReasons array; document expected formats and when each field
must be checked (restore validation uses imageHash, overlayFingerprint, envHash,
hostVzVersion) and when to bump invalidateReasons. Ensure names match this
manifest (snapshot.json imageHash, overlayFingerprint, envHash, hostVzVersion,
createdAt) so code like snapshot creation, restore validation, and invalidation
logic can reliably read/write the same keys.
In `@plans/profiles-and-overlay.md`:
- Around line 89-93: Update the image cache key definition to include the
builder pipeline/toolchain identity (a builder version or salt) in addition to
the existing inputs; specifically, change the "Image cache key = sha256 of
`packages` + `build` + base kernel/initrd version" to include a builder
identifier (e.g., `builder_version` or `builder_salt`), and ensure this combined
value is what is written to and compared in `images/profiles/<name>/build.hash`
so that changes in packing logic/toolchain invalidate the cache and trigger
rebuilds on the next `pen shell --profile`.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: a2969ebf-79b5-422e-8236-45a87669b3b6
📒 Files selected for processing (3)
plans/future-squashfs-sidecar.mdplans/future-vm-snapshots.mdplans/profiles-and-overlay.md
| ``` | ||
| ~/.config/pen/ | ||
| ├── images/ | ||
| │ ├── vmlinuz # base kernel (unchanged location) | ||
| │ ├── initrd # base initrd (unchanged location) | ||
| │ └── profiles/ | ||
| │ └── <profile-name>/ | ||
| │ ├── initrd # custom initrd built from profile | ||
| │ └── build.hash # sha256 of image-affecting profile fields | ||
| ├── profiles/ | ||
| │ └── <profile-name>.toml # user-authored profile config | ||
| └── vms/ | ||
| └── <vm-name>/ | ||
| ├── vm.json # existing | ||
| ├── pen.lock # existing | ||
| ├── pid # existing | ||
| └── overlay.img # new: ext4 sparse file, per-VM persistent disk | ||
| ``` |
There was a problem hiding this comment.
Add language identifiers to fenced code blocks to satisfy markdownlint (MD040).
Line 42 and Line 116 use bare triple-backtick fences. Add explicit languages (text, sh) to avoid lint noise/failures.
Proposed doc-only lint fix
-```
+```text
~/.config/pen/
├── images/
...
-```
+```
-```
+```text
1. Mount proc, sys, dev, tmp, run, devpts (unchanged)
...
9. exec /bin/sh -l (unchanged)
-```
+```Also applies to: 116-142
🧰 Tools
🪛 markdownlint-cli2 (0.22.0)
[warning] 42-42: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@plans/profiles-and-overlay.md` around lines 42 - 59, The markdown has bare
triple-backtick fences in plans/profiles-and-overlay.md around the filesystem
tree starting with "~/.config/pen/" and the numbered init sequence starting "1.
Mount proc, sys, dev, tmp, run, devpts"; update those fences to include language
identifiers (use ```text for the filesystem tree block and ```sh or ```text for
the init sequence block as appropriate) so the fenced code blocks satisfy
markdownlint MD040 and avoid lint failures.
- plans/profiles-and-overlay.md: top-level status now "Phase 1 complete". Phase 1 section annotated DONE with commit hashes and a pointer to TestOverlayPersistence. Open question #2 (disk-not-clean recovery) resolved — ext4 journal replay was observed working during smoke testing, no explicit e2fsck needed. - CLAUDE.md: add a terse "Testing" section stating that `make test-integration` must be run before marking any task complete, since CI cannot run it. Kept to two sentences; details live in ARCHITECTURE.md. - docs/ARCHITECTURE.md: note in the CI/CD section that test-integration is deliberately not wired into CI because GitHub's hosted macOS runners are themselves Anka VMs and Apple VZ refuses nested virt (actions/runner-images#13505, closed "not planned"). Integration tests are local-only. - .gitignore: ignore .claude/settings.local.json (Claude Code harness state). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Adds a
plans/directory with three design documents capturing the path to fast, customizablepen shellstartup:plans/profiles-and-overlay.md— ready-to-implement plan for a two-layer persistence model: immutable profile-built images (bake in stable tools likeclaude, node, git) + per-VM overlay disks via overlayfs (persist runtimeapk add,node_modules, project state). Includes a profile TOML schema, CLI surface, guest init changes (overlayfs + pivot_root + first-boot hook), a builder-VM pipeline for custom images, and a four-phase implementation order.plans/future-vm-snapshots.md— high-level sketch of snapshot/restore as a future startup optimization. Flags the hard problems (stale state, env re-injection, snapshot portability, overlay consistency) and alternatives (backgrounded VMs, kexec).plans/future-squashfs-sidecar.md— high-level sketch of a read-only squashfs sidecar for when initrd bloat eventually becomes an issue from baking heavy content (JDK, model weights, CUDA).The main plan locks in two design decisions from prior discussion: profile
setupscript changes are not re-run against existing VMs (Option 1), and the first-boot-complete marker lives at/var/lib/pen/setup-doneinside the merged rootfs view (chosen over a raw-disk path to keep the pivot_root sequence clean).No code changes — planning only. Implementation lands in follow-up PRs per phase.
Test plan
Summary by CodeRabbit