Skip to content

Move project agent context into the repository - #2772

Open
cameronraysmith wants to merge 2 commits into
mainfrom
fm/vx-plan-migrate-pilot
Open

Move project agent context into the repository#2772
cameronraysmith wants to merge 2 commits into
mainfrom
fm/vx-plan-migrate-pilot

Conversation

@cameronraysmith

Copy link
Copy Markdown
Owner

Project-level agent context now lives in this repository as committed files.

Until now it lived outside the tree: a file in a separate private repository, reached through a CLAUDE.md symlink installed by hand in one checkout and hidden from git through .git/info/exclude. That arrangement has three costs. Nothing ties the description to the tree, so it drifts silently — the text landing here claimed 115 skills across 17 packages, and the tree holds 132 across 18. Any clone or worktree made anywhere else contains no project context at all, which matters now that most work happens in short-lived checkouts. And because the description lived in a different repository, a change to the code and the correction to its description could never be reviewed together.

Committing the file fixes all three. AGENTS.md holds the content, CLAUDE.md is a one-line @AGENTS.md pointer so there is no second copy to drift, and both are reviewed like any other file. docs/development/architecture/adrs/0022-committed-per-repository-agent-context has the longer argument, including the alternatives that were rejected.

The two commits are separable on purpose. The first is the scrub and nothing else; the second adds the wiki generator's brief and its schedule.

What was removed, and why

The source text was written for a private location and assumed a private reader. Each removal below is a category, not a line count.

Who uses which machine. The source carried a fleet table mapping every workstation to the person who uses it, by given name. None of it is needed to work on this repository and it is not ours to publish. The machine directory names under machines/ were already public and stay; the mapping to people is gone. What replaces it is the part that is actually load-bearing for someone editing a module: the repository carries two admin-username conventions, and which one applies is a property of the machine.

Which servers are up. The source named the always-on coordinator and listed which cloud machines were provisioned and which were configured but torn down. That is the state of an account on a particular afternoon, not a fact about this repository, and it is wrong as soon as it is written. The durable mechanism is kept instead: the per-machine enabled toggle in modules/terranix/, what flipping it does, and the standing rule that a machine present in machines/ may not be reachable.

Pointers a reader here cannot follow. Several sections referenced private repositories, one of them explicitly marked as internal-only and not to be cited from project materials, plus local checkouts of book companion code. The upstream references that a reader can actually resolve are kept. For the domain-modeling sources the attribution is kept — author, title, year, and what each contributes to the vocabulary the preference skills use — while the paths to personal copies are dropped, since the attribution is the part that helps and the path is the part that only worked on one machine.

Whatever migration happened to be in flight. Roughly a third of the source described a build-infrastructure epic and a Kubernetes prototype: the tracker ID, the cost problem motivating it, the network model of one new server, a dependency pinned to an unreleased upstream branch, and a roadmap of providers to adopt later. Current strategy is what dates a context file fastest, and none of it survives contact with the next quarter. The tools that strategy actually uses are kept as reference pointers; the plan around them is not.

A generated metrics block sizing this working tree, and a section instructing agents never to commit this file.

Everything else is kept: the architecture, the layout, the build and check commands, the conventions, and the vocabulary.

Correcting what was stale

Claims were re-derived from the tree rather than carried across. The skill inventory is 132 skills in 18 packages. The note that .claude/ is absent and unignored is now the opposite of what it said, because the directory exists and holds a settings file excluded per checkout. The tracker section described a database that is not present in this repository and is dropped. The merge description is now split, because human and bot pull requests are handled differently in .github/mergify.yml.

The provenance section is rewritten rather than deleted. It previously told agents not to commit this file, which would have contradicted the file's own status the moment it landed.

The wiki generator

openwiki/INSTRUCTIONS.md is the brief the generator reads for scope and priorities and never rewrites, so it is where the wiki is steered. It repeats the exclusions above as standing instructions, so the generator does not reintroduce by inference what was removed by hand.

.github/workflows/openwiki-update.yml runs the refresh weekly and opens a pull request when the generated pages move. Weekly rather than the generator's daily default: the wiki describes architecture rather than individual commits, and a daily run mostly spends model budget confirming nothing changed. It is guarded to this repository so scheduled runs do not fire on forks, and it does not list its own file among the paths the bot may commit.

Two things it needs before the first run: an OPENWIKI_ANTHROPIC_API_KEY repository secret, and a decision about whether the resulting bot pull requests should be batched by the merge queue like the other automated ones. Until the secret exists the scheduled run fails on credentials, which is visible rather than silent.

The file is named .yml against the repository's .yaml convention for a stated reason: openwiki code --init creates openwiki-update.yml only when that exact path is missing, and under .yaml it would not see this file and would add a second workflow on the same schedule.

Coexistence of the marker block and the pointer file

The generator maintains a block between its own markers in both root files and leaves everything outside them alone. That had to be checked against the pointer arrangement rather than assumed, so the shipped generator's own code path was run against these exact files. Nine assertions, all passing:

  • a first run appends its block and preserves every hand-written line of AGENTS.md
  • exactly one marker pair lands in each file
  • CLAUDE.md still opens with @AGENTS.md; the block the generator writes there is itself only a pointer to AGENTS.md, so the file stays a pointer
  • a second run is byte-identical in both files and the hand-written content is still intact

It also surfaced two failure modes, both now recorded in AGENTS.md so they are not rediscovered by breaking them:

  • CLAUDE.md must stay a real file, not a symlink to AGENTS.md. The generator writes both files in one pass, so through a symlink both writes land on AGENTS.md: the block meant for AGENTS.md is lost, the file is left with unbalanced markers, and every later refresh refuses to touch it. This is worth stating explicitly because the symlink is otherwise a reasonable-looking way to arrange these two files.
  • The literal marker strings must not appear in AGENTS.md outside the managed block. The generator locates its block by first and last occurrence and treats a second pair as malformed, refusing the update and leaving the file unchanged. The section of AGENTS.md that documents all this therefore describes the markers rather than quoting them.

Verification

A fresh clone of this branch, with no symlink and no private repository present anywhere on the path:

  • AGENTS.md, CLAUDE.md, openwiki/INSTRUCTIONS.md, and the workflow are all tracked as regular files, mode 100644, not symlinks
  • the clone has no .git/info/exclude at all, so nothing depends on a machine-local exclusion
  • neither root file references the private repository
  • every repository-relative path AGENTS.md names resolves in that clone, and the skill counts re-derive from it as 18 packages and 132 skills

Checks run

nix build .#checks.aarch64-darwin.gitleaks — passing, no leaks over 11.5 MB. This is the check that matters for this change: it scans the whole flake source with gitleaks detect --no-git, so it covers newly committed files rather than only a staged diff, and this is the first context commit on a public repository.

actionlint on the new workflow — clean.

Deliberately not run: the full nix flake check. This change adds Markdown and one workflow file and touches no Nix, so the machine, container, package, and Kubernetes checks cannot be affected by it, and a full run would be a much longer wait for a result that is not evidence about this diff. treefmt only formats Nix and has nothing to say about these files.

Steps that remain, to be run by hand

These touch machine-local state outside any checkout and are not part of this branch. In the working clone at ~/projects/vanixiets:

# 1. Remove the two symlinks that stand where the committed files now live.
#    Both currently point at the same file in the private repository.
ls -l ~/projects/vanixiets/AGENTS.md ~/projects/vanixiets/CLAUDE.md   # confirm both are symlinks first
rm ~/projects/vanixiets/AGENTS.md ~/projects/vanixiets/CLAUDE.md

# 2. Drop the two entries from .git/info/exclude, which contains
#    exactly `AGENTS.md` and `CLAUDE.md` and nothing else.
: > ~/projects/vanixiets/.git/info/exclude

# 3. Take the committed files.
git -C ~/projects/vanixiets checkout -- AGENTS.md CLAUDE.md

Order matters: while either exclude entry is present, git ignores the committed files and step 3 silently does nothing. Afterwards git -C ~/projects/vanixiets status should be clean and both files should be regular files.

The source file in the private repository is left in place. Nothing reads it once this lands, but other repositories have not migrated yet and the manifest that tracks them stays usable until they do.

Move the project-level agent context into the repository as committed
files, per ADR-0022. AGENTS.md holds the content and CLAUDE.md is a
one-line pointer to it, so a clone or worktree on any machine comes up
context-primed without a machine-local provisioning step.

The source text was written for a private location and is scrubbed
before landing here. Removed: the machine-to-person mapping of the
workstation fleet; the current provisioning state of individual servers,
which is a property of an account rather than of this repository;
cross-references to repositories a reader of this one cannot resolve;
and the narrative of whichever migration happened to be in flight, which
is what dates a context file fastest. Kept: the architecture, the
conventions, and the vocabulary, all of which outlive any one change.

Stale claims were re-derived from the tree rather than carried over. The
skill inventory is now 132 skills across 18 packages, and the note that
`.claude/` is absent and unignored is corrected: the directory exists and
carries a machine-local settings file excluded per checkout.

The provenance section is rewritten rather than deleted. It previously
instructed agents not to commit the file, which would have contradicted
the file's own status the moment it landed; it now describes the
arrangement that exists.
Add openwiki/INSTRUCTIONS.md, the user-authored brief the generator reads
for scope and priorities and never rewrites, and the weekly workflow that
runs the refresh and opens a pull request when the generated pages move.

The brief carries the same exclusions the committed context was scrubbed
against, so the generator does not reintroduce by inference what was
removed by hand: no mapping of machines to people, no claims about which
machines are currently running, nothing read out of the encrypted paths.

The workflow is weekly rather than the generator's daily default, because
the wiki describes architecture rather than individual commits and a
daily run mostly spends model budget confirming nothing changed. It is
guarded to this repository so scheduled runs do not fire on forks that
have no credential, and it does not list its own file among the paths the
bot may commit.

Also records in AGENTS.md the two constraints that let the generator's
marker blocks coexist with the pointer file: CLAUDE.md must stay a real
file, and the literal markers must not appear outside the managed block.
@mergify

mergify Bot commented Aug 19, 2026

Copy link
Copy Markdown

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant