chore: keep agent workspaces out of the tree and make the ignore rules symlink-safe - #2
Merged
Merged
Conversation
…s symlink-safe This repository is public. The agent workspace and local agent config were present in the working tree, excluded only by ignore rules. Their contents are now stored outside any repository and reached through symlinks, so the bytes are not in a public tree at all and a forced add would commit a path rather than the content. Drops the trailing slashes at the same time. A trailing-slash rule matches a directory only, so `.agents/` stopped matching the moment the directory became a symlink, and the path fell out of the ignore set silently. Slashless entries match a directory, a file, or a symlink. No change to tracked content: zero paths under these entries before or after, and no commit in this repository has ever touched them.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes
.gitignoreonly. No source, no data, no site content.Two things, both about the same failure mode.
1. Agent workspaces no longer sit in the working tree. Their contents now
live outside any repository and are reached through symlinks. Previously the
only thing keeping them out of this public repository was an ignore rule. Now
the bytes are not in the tree at all, and a forced add would commit a path
rather than the content behind it.
2. The ignore entries lost their trailing slashes.
.agents/matches adirectory only. The moment that directory became a symlink, git saw a file, the
rule stopped matching, and the path fell out of the ignore set silently.
git add -Awould have staged it. Slashless entries match a directory, a file,or a symlink, so the rule survives the relocation.
The second point was found by running
git check-ignoreafter the changerather than reasoning about it beforehand. The first version of this work
introduced exactly the regression it was meant to prevent.
Verification
git ls-tree -r origin/main: 0 paths under these entries, before and after.git log --all -- <paths>: 0 commits have ever touched them. History is cleanand this change does not alter that.
git check-ignore -v: all three entries match explicit rules after therelocation.
git add -A --dry-run: stages nothing under any of them.Does not cover
CI status at merge
CI NOT MEASURED. No run exists on this head (
ec950dcc). The cause isneither of the two candidates that were considered, and is stated here as
UNKNOWN rather than guessed.
Ruled out: workflow triggers not matching the branch.
.github/workflows/ci.ymldeclares
pull_request: branches: [main], this PR's base ismain, and theworkflow file is present and byte-identical on the head ref (
a286dd27). Thereis no
pathsfilter and no job-level condition. The triggers match.Ruled out: the GitHub Actions outage, as a sufficient explanation. The
pull_requestevent was deliberately re-fired by closing and reopening this PRat 21:29Z, which is after Actions had demonstrably recovered: a sibling
repository executed a full job on a real runner at 20:47Z the same day. Twenty
nine minutes after the re-fire, no run exists. An outage that had recovered
cannot explain a re-fired event producing nothing.
Remaining candidate, UNKNOWN. Repository-level Actions settings are
permissive (
enabled: true,allowed_actions: all). The organization-levelActions policy could not be read: HTTP 403, requires the
admin:orgscope. Anorg policy is the leading explanation, and it is recorded as unknown rather than
asserted, because it was not observed.
Baseline note, so an absence is not overread. This is the first pull request
ever opened in this repository. Every one of the 19 workflow runs in its history
is a
pushevent. The absence of priorpull_requestruns therefore carries noinformation about whether they would fire, and is not offered as evidence.
Merging on that basis:
mainis unprotected with no required status checks,verified through the branches API rather than assumed, so no check is being
overridden. The diff is
.gitignore-only and cannot affect a build.Local verification, named
git status --porcelainclean on the branch at merge time..agents,.claude, orCLAUDE.mdon this head: 0,identical to
main. Enumerated from the head tree via the git trees API andfrom
git ls-tree -r origin/main, two independent means, reconciled.Type-substitution probe
For each ignored agent path, the path was replaced with a different filesystem
type and BOTH assertions were checked:
git check-ignore -vstill matchesgit status --porcelaindoes NOT list itRun in a throwaway clone at
ec950dc, so no working tree was mutated. Typesexercised: directory, regular file, and symlink pointing outside any repository.
Self-verifying input, exercised in the same run. The trailing-slash form of
the same rule (
.agents/,.claude/) against the symlink case, which mustfail:
The control failed as required. That is what makes the pass above meaningful: it
distinguishes a correct rule from a check that did not run.
check-ignorealone is insufficient, and that is the specific defect F-022records. Both assertions are required, which is why both are asserted here.
CORRECTION, added after merge
The CI status section above is wrong, and this correction supersedes it.
That section asserted the outage was ruled out, on the reasoning that Actions had
recovered and that a re-fired event producing nothing could not be explained by a
recovered outage. Both the premise and the conclusion were wrong.
What actually happened. The re-fired
pull_requestevent did produce a run.It arrived at 22:25:05Z, roughly 56 minutes after the close and reopen, and well
after this PR had already been merged. Run
31128983196, eventpull_request,head
ec950dcc, conclusionsuccess.CI IS MEASURED, AND IT IS GREEN on the exact head that was merged.
Why the earlier reasoning failed. Actions was not recovered. It was still in a
major outage at 22:18Z, with webhook triggers deliberately throttled and, in
GitHub's own words, many push and pull request events not yet triggering new
workflow runs. The 20:47Z job in a sibling repository that was read as evidence of
recovery was a queued event draining, not a healthy pipeline. A single successful
job is not evidence that event delivery is healthy, and it was treated as such.
Withdrawn: the organization-level Actions policy hypothesis. It was recorded as
UNKNOWN rather than asserted, which was right, but it is no longer needed. Delivery
latency under the outage explains the observation. The 403 on reading the org policy
remains true and remains unread; it is simply not evidence of anything here.
Retained and still correct: the trigger analysis (
base=main, workflow presentand identical on the head ref, no paths filter, no job guard), the baseline note
that this is the first PR ever opened here so prior
pull_requestabsence carriesno information, and the entire type-substitution probe including its control.
The lesson, stated so it survives this PR. The failure was declaring a negative
from an interval of silence. Twenty nine minutes of no run was treated as a result
when it was only an unfinished wait, and a sibling repository's single green job was
promoted into a systemwide recovery claim it could not support. Absence within an
observation window is UNKNOWN, not a finding, and the authoritative status source
should have been read before any cause was written down.