Part of #2
D3 — Persistence & volume strategy
Labels: wayfinder:grilling status:closed
Blocks: D6, D8
Resolution
chartr already has a two-root model in internal/server/server.go: DataDir (runtime, per-session payload archives) and ConfigDir (operator config — agent registry, sources, prompt contract). ConfigRoot (server.go:298-309) resolves XDG_CONFIG_HOME first, then falls back to $fallback/config. The Docker spec mirrors this split.
State map:
| Kind |
In-container path |
Volume? |
Notes |
Runtime / session payload archives (DataDir) |
/data |
Yes |
Set via CHARTR_DATA_DIR=/data env (per D1). Declared as VOLUME /data in the Dockerfile. |
Operator config, agent registry, sources, prompt contract (ConfigDir) |
/config |
Yes |
Set via XDG_CONFIG_HOME=/config in image ENV — no new Go env needed (ConfigRoot already honors it). Declared as VOLUME /config. |
/tmp — spawned PTY child scratch |
container-local (default) |
No |
Explicit non-goal: do NOT VOLUME /tmp and do NOT document a /tmp bind-mount. Left to the container's own writable layer or an operator-supplied tmpfs. |
| Repo working trees |
operator-chosen (/workspace, etc.) |
No — not chartr's volume |
Comes from the operator's bind-mounts per D5's contract. Chartr's own volumes hold zero repo bytes. |
| Ephemeral caches (Go module, npm, etc.) |
build-time only |
n/a |
Live in build stages only; final image ships no cache dirs to volume. |
Env/config surface the operator can relocate with:
CHARTR_DATA_DIR — overrides -data-dir default (per D1).
XDG_CONFIG_HOME — overrides ConfigDir derivation. Chartr's existing behavior; no new env.
Rationale for two volumes over one:
- Backup semantics:
/config alone is a small, meaningful snapshot; /data is regenerable-ish runtime.
- Symmetric with the codebase's own split — no in-container path convention that fights the existing model.
Downstream impact:
- D6 (Dockerfile) — declare
VOLUME ["/data", "/config"]; add ENV XDG_CONFIG_HOME=/config alongside D1's other envs.
- D8 (compose + docs) — the compose example maps both volumes; docs note
/tmp is intentionally not a mount and repo trees come from D5's bind-mounts.
Question
Enumerate every piece of state chartr writes today (config, registered spaces, maps under repo working trees, agent registration, logs, caches) and decide, for the container:
- Which paths need to survive container recreation → declared
VOLUMEs or documented bind-mount targets.
- Canonical in-container paths (e.g.
/config, /state) and how they map to chartr's usual XDG dirs. Do we override XDG_CONFIG_HOME/XDG_STATE_HOME, or teach chartr an in-container path convention?
- Which paths are ephemeral (caches, tmp) and must NOT be volumes.
- Compose-example implication: what volume declarations the getting-started example needs.
Deliverable: a table of state kind → in-container path → volume? → notes, plus the env/config surface (if any) that lets an operator relocate them.
Part of #2
D3 — Persistence & volume strategy
Labels:
wayfinder:grillingstatus:closedBlocks: D6, D8
Resolution
chartr already has a two-root model in
internal/server/server.go:DataDir(runtime, per-session payload archives) andConfigDir(operator config — agent registry, sources, prompt contract).ConfigRoot(server.go:298-309) resolvesXDG_CONFIG_HOMEfirst, then falls back to$fallback/config. The Docker spec mirrors this split.State map:
DataDir)/dataCHARTR_DATA_DIR=/dataenv (per D1). Declared asVOLUME /datain the Dockerfile.ConfigDir)/configXDG_CONFIG_HOME=/configin imageENV— no new Go env needed (ConfigRootalready honors it). Declared asVOLUME /config./tmp— spawned PTY child scratchVOLUME /tmpand do NOT document a/tmpbind-mount. Left to the container's own writable layer or an operator-supplied tmpfs./workspace, etc.)Env/config surface the operator can relocate with:
CHARTR_DATA_DIR— overrides-data-dirdefault (per D1).XDG_CONFIG_HOME— overridesConfigDirderivation. Chartr's existing behavior; no new env.Rationale for two volumes over one:
/configalone is a small, meaningful snapshot;/datais regenerable-ish runtime.Downstream impact:
VOLUME ["/data", "/config"]; addENV XDG_CONFIG_HOME=/configalongside D1's other envs./tmpis intentionally not a mount and repo trees come from D5's bind-mounts.Question
Enumerate every piece of state chartr writes today (config, registered spaces, maps under repo working trees, agent registration, logs, caches) and decide, for the container:
VOLUMEs or documented bind-mount targets./config,/state) and how they map to chartr's usual XDG dirs. Do we overrideXDG_CONFIG_HOME/XDG_STATE_HOME, or teach chartr an in-container path convention?Deliverable: a table of
state kind → in-container path → volume? → notes, plus the env/config surface (if any) that lets an operator relocate them.