Jerry Orta
← Concepts

Framework Source as Agent Reference

  • claude
  • tooling
  • workflow

A model's knowledge of a framework is a snapshot, and the framework has moved since. Training data is fixed at a moment in time, so a pattern an agent recalls as current can trail the installed version by a release or two — a signature that has gained a parameter, an idiom the framework has since retired, an API that now lives behind a different import. The correction is not a sharper prompt but a better source: ground the agent in the framework's own code, pinned to the exact version the repository builds against, and read it directly.

This is the third substrate an agent here reads from. The skills note describes the actions an agent performs, and the agent-files architecture describes the internal context those actions are read against — the repository's own tracked instruction files. Both are authored inside the project. The substrate described here is different in kind: it is upstream source, written by the framework teams and checked out read-only beside the repository, so that a question about how the current stack does a thing is answered by the implementation rather than by a memory of it.

Where recalled knowledge drifts

Two gaps separate what a model remembers from what a project runs. The first is time. A fast-moving framework ships on a cadence measured in weeks, and any model's built-in knowledge was fixed before the versions a project installs today existed; the "latest pattern" recalled in good faith may be the pattern from two majors ago. The second gap is depth. Even when the installed version is the one in mind, node_modules carries only the built artifact — the compiled JavaScript and the generated .d.ts declarations. The readable source, the unit tests that document intended behavior, and the migration schematics that show how the framework itself rewrites an old API into a new one are all absent from the published package. An agent inferring an idiom from a type signature is reconstructing the shape of a thing from its shadow.

A read-only reference beside the repository

The reference is a sibling directory, not a dependency. One level above the repository root sits an open-source/ tree holding the upstream clones, and its placement outside the repository is deliberate: Nx, the TypeScript compiler, ESLint, and git are all scoped to the repository root, so a sibling is invisible to every one of them. Nothing indexes it, nothing type-checks it, nothing attempts to build it. It exists only to be read.

<parent>/
├── ngx-experiments/   ← the repository — Nx, tsc, ESLint, git all scoped here
└── open-source/       ← pinned upstream source, read-only, indexed by nothing
    ├── angular/   components/   platform/   rxjs/
    └── d3/   d3-array/   d3-axis/   …   d3-zoom/

One command, npm run oss.sync, guarantees the tree is present, and it resolves per repository. When a machine already keeps a shared checkout whose tags match the versions this repository pins, the command symlinks the sibling to it, so a single physical copy serves every clone of the repository on that machine. When no shared copy exists, or when its versions differ from the pins, the command clones the pinned set fresh rather than shadow the repository with the wrong framework source. The operation is idempotent: re-running it is how a newly added pin propagates, and a clone already present is left untouched. The pins themselves live in scripts/clone-open-source.sh.

What is pinned

The set is small where the stack is authored and exhaustive where it is composed. Four framework sources are cloned — Angular, the Angular CDK and component library, the NgRx platform, and RxJS — each pinned to the exact tag matching the version installed in the repository. Beside them sits the full D3 module set: the d3 meta-repository and its roughly thirty constituent d3-* modules, pinned together because charting work reaches across many of them at once. Every clone is shallow and single-branch, fixed to a tag rather than tracking a moving branch, and none of it is ever imported or built — it is reference, not dependency. When a framework is bumped, the pins are re-cut from the newly installed versions, so the reference and the build never disagree on what "current" means.

Reading source over guessing

With the tree in place, a question about a current API has a definite answer. Writing against a newer NgRx signalStore, an agent opens the platform source under ../open-source/platform and reads the actual generic signature instead of approximating it. Working on the charts library's custom axis, it consults the d3-axis source the axis was forked from. The move is the same each time: when the installed version is newer than the model's memory, prefer the pinned implementation to the recollection. And because the practice is a convention rather than a feature of any single codebase, it travels between repositories unchanged — the same sibling tree and the same command, whichever project an agent works in. The public ngx-experiments workspace is arranged this way.

Why it holds together

Three substrates share one discipline. The skills are the actions an agent takes; the agent-files are the internal context it reads them against; and the pinned framework source is the external ground truth it checks a current API against. What unites them is a preference for reading over remembering. A model's memory is a strong prior and a poor authority on a version that shipped after its training, so the reference fixes the authority in place — pinned, read-only, and beside the work — and lets the agent consult the framework as it is now rather than as it once was. That is the source I hand to Claude Code when the version on disk has moved past what any model can recall.