Move project agent context into the repository - #2772
Open
cameronraysmith wants to merge 2 commits into
Open
Conversation
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.
|
Tick the box to add this pull request to the merge queue (same as
|
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.
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.mdsymlink 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.mdholds the content,CLAUDE.mdis a one-line@AGENTS.mdpointer 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-contexthas 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
enabledtoggle inmodules/terranix/, what flipping it does, and the standing rule that a machine present inmachines/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.mdis 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.ymlruns 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_KEYrepository 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
.ymlagainst the repository's.yamlconvention for a stated reason:openwiki code --initcreatesopenwiki-update.ymlonly when that exact path is missing, and under.yamlit 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:
AGENTS.mdCLAUDE.mdstill opens with@AGENTS.md; the block the generator writes there is itself only a pointer toAGENTS.md, so the file stays a pointerIt also surfaced two failure modes, both now recorded in
AGENTS.mdso they are not rediscovered by breaking them:CLAUDE.mdmust stay a real file, not a symlink toAGENTS.md. The generator writes both files in one pass, so through a symlink both writes land onAGENTS.md: the block meant forAGENTS.mdis 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.AGENTS.mdoutside 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 ofAGENTS.mdthat 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, mode100644, not symlinks.git/info/excludeat all, so nothing depends on a machine-local exclusionAGENTS.mdnames resolves in that clone, and the skill counts re-derive from it as 18 packages and 132 skillsChecks 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 withgitleaks 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.actionlinton 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.treefmtonly 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:Order matters: while either exclude entry is present, git ignores the committed files and step 3 silently does nothing. Afterwards
git -C ~/projects/vanixiets statusshould 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.