From 6b6cf25862b3f60f9a2c271f096d369c0a040dfc Mon Sep 17 00:00:00 2001 From: Dai Ha Date: Sat, 15 Aug 2026 10:17:26 +0200 Subject: [PATCH] CB-581: neutralise the parityOverlay false-preserve risk, and record the rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue #57 criterion 5 asked for an explicit decision on this rather than silence. It is closer to live than the issue assumed. The DEFAULT parityOverlay is List.of(".env", ".envrc"), so it applies to every profile, and neither path was gitignored. Since CB-576 a release preserves any worktree that git status --porcelain calls dirty, and that deliberately counts untracked files — the work lost in CB-576 was a file nobody had added. So one .env at the repo root would make every COMPLETED release preserve its worktree, and worktrees would accumulate with no error to notice. Inert today only because neither file exists here. Both are now gitignored, which they deserve on their own as environment files. The javadoc carries the rule for the next overlay path: it must be gitignored, or tracked and skip-worktree'd. --- .gitignore | 8 ++++++++ .../dev/ltms/bridged/config/BridgedConfig.java | 16 +++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5a0e8dd..d8308c4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,14 @@ # Settings backups inherit the env block — and secrets with it. .claude/settings.local.json.bak* +# The default profile parityOverlay copies these primary→worktree, so they appear in EVERY worker +# worktree. Two reasons they must be ignored. They hold environment values, which is reason enough. +# And since CB-576 a release preserves any worktree that `git status --porcelain` calls dirty — +# untracked files included, deliberately. An untracked overlay file would therefore make every +# COMPLETED release preserve its worktree, and worktrees would pile up with no error to notice. +.env +.envrc + # Daemon runtime artefacts. bridged appends its log wherever it is launched from, so both the # repo root and bridged/ collect one; neither belongs in git. bridged.out diff --git a/bridged/src/main/java/dev/ltms/bridged/config/BridgedConfig.java b/bridged/src/main/java/dev/ltms/bridged/config/BridgedConfig.java index 4d257a9..78b2901 100644 --- a/bridged/src/main/java/dev/ltms/bridged/config/BridgedConfig.java +++ b/bridged/src/main/java/dev/ltms/bridged/config/BridgedConfig.java @@ -151,7 +151,21 @@ public record BridgedConfig( * @param cwd fixed working directory for this profile's workers (CB-112 "told otherwise"); * {@code null}/blank → inherit the primary's cwd, else the daemon's * @param parityOverlay repo-relative paths copied primary→worktree for config parity; null/empty - * defaults to a sensible set of local config files + * defaults to a sensible set of local config files. + *

Every overlay path must be gitignored or tracked-and-skipped. + * CB-576 made {@code release()} preserve a worktree that {@code git status + * --porcelain} reports as dirty, and it deliberately counts untracked files — + * the work lost in CB-576 was a new file nobody had added. So an overlay path + * that is neither gitignored nor tracked lands in every worktree as an + * untracked file, makes every {@code COMPLETED} release preserve, and + * worktrees then accumulate with no error anywhere. + *

Checked on 2026-08-15 (CB-581): inert as configured. Tracked overlay + * files carry {@code --skip-worktree} so {@code --porcelain} cannot see them, + * {@code bridged.yaml} is gitignored, and the default pair {@code .env} / + * {@code .envrc} does not exist in this repo. Note the default applies to + * every profile, so creating either file at the repo root is enough + * to make it live. Add a new overlay path to {@code .gitignore} in the same + * change that adds it here. * @param gitTokenEnv name of the host env var holding the git-forge API token; when set, its * value is injected as {@code GITEA_TOKEN} so the worker can open its own PR * at checkpoint (CB-302). {@code null}/blank ⇒ no token is injected