docs(agent-context): teach brownfield-adoption direction doctrine in migration skills#183
Merged
Merged
Conversation
…d UUID rule
The metaobjects-* skills were framed greenfield-only ("metadata is the spine,
generated code is disposable"), which licensed a backward migration loop: change
metadata → regenerate → treat the resulting compile/type errors in existing code
as bugs to fix. On an adoption onto existing working code / a live DB the
direction is the reverse — metadata FOLLOWS the code.
- authoring: new "Adopting onto an existing codebase — metadata FOLLOWS the code"
section (conditional on the brownfield predicate, reconciled with model-first):
author metadata + tune codegen to reproduce the existing native types, names,
and nullability; minimize churn to code the generator isn't replacing; ask on
ambiguity, default to least existing-code change. Hardened the UUID row + a
smell callout: NEVER field.string + @dbColumnType:uuid (generates a String over
a uuid column, forcing coercions; verify --db can't see it). field.uuid is the
match-the-code choice.
- audit: promoted UUID-as-string from non-failing advisory (axis I) to a real
correctness-adjacent finding (axis H2) with blast-radius counting; added an
adoption-direction guardrail on every proposed cutover.
- codegen: "make codegen match the code, not the code match codegen" — customize
owned generators / outputPattern / naming to reproduce the existing shape before
editing working call sites.
- always-on: one concise direction bullet (within the 120-line size gate).
- verify: "what verify can't catch — semantic mismodeling" + a project-local CI
ratchet lint (grep-fail on field.string paired with @dbColumnType:uuid) as the
migration's completion criterion and a permanent backstop.
Goldens regenerated across all four stacks; agent-context conformance, size-gate,
and capability-grounding suites green (42/42). The SDK agent-context bundle is a
build-time artifact (gitignored) and is not committed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013VXidfNN755CyTZTg1w8UV
dmealing
added a commit
that referenced
this pull request
Jul 7, 2026
Ships the updated agent-context skills (brownfield-adoption direction doctrine + hardened UUID rule, #183) — bundled into the SDK, delivered via the CLI. Isolated patch: the other 12 npm packages stay 0.15.14; PyPI/NuGet/Maven unaffected (no runtime/codegen change). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013VXidfNN755CyTZTg1w8UV
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.
Intent
Fix the metaobjects agent-context skills so they teach the RIGHT direction for a brownfield migration/adoption. User-reported production failure: the skills were framed greenfield-only ('metadata is the spine, generated code is disposable'), which led an agent to change metadata, regenerate, and then force the existing downstream code to fix the resulting type errors as if they were bugs — the backward direction. The concrete disaster: a UUID column modeled field.string + @dbColumnType:uuid generated a String (not UUID), inherited via BaseEntity across 262 fields / 91 files of String<->UUID coercions; verify --db can't catch it because the column really is uuid. Correct doctrine (what this change encodes): on adoption onto existing working code / a live DB, author metadata AND tune codegen to REPRODUCE what the code already is (native types, column/table names, nullability), minimize churn to code the generator isn't replacing, ask the user when a modeling choice is ambiguous, and default to the least existing-code change; the only existing code that should change is the hand-written layer codegen replaces (parity-gate, then delete). Deliberate choices a reviewer should NOT flag: (a) the direction doctrine is intentionally CONDITIONAL on a brownfield predicate and reconciled with the existing greenfield model-first guidance (both must coexist — do not treat the greenfield 'disposable generated code' language as contradictory). (b) The UUID hardening reinforces an already-present field.uuid recommendation; a control-vs-treatment micro-test on Sonnet showed the UUID case is already self-correcting on capable models, so this is intentionally reinforcement + weaker-model insurance + an audit reclassification (advisory axis-I -> real axis-H2 finding), NOT a claimed behavior flip. The migration-DIRECTION doctrine was the piece that micro-tested as a clean RED->GREEN (control led with a greenfield remodel + schema/data migration; treatment matched existing storage with zero churn and deferred the modernization). (c) Only a project-local grep CI-ratchet lint was added as guidance; an actual semantic-lint subverb is intentionally left as a noted follow-up, not implemented here. (d) The SDK agent-context/ bundle copy is a gitignored build artifact, intentionally not committed; only the canonical agent-context/ source (5 files) + regenerated conformance goldens (24 files across 4 stacks) are committed. Scope: docs/skills only, no runtime or product code. Local gates already green: agent-context conformance + size-gate (always-on stayed within the 120-line budget) + capability-grounding = 42/42.
What Changed
metaobjects-authoring,-audit,-codegen,-verify) plus a line intemplates/always-on.md.mustache: when adopting onto existing working code or a live DB, author metadata and tune codegen to reproduce what the code already is (native types, column/table names, nullability), minimize churn, ask when a modeling choice is ambiguous, and change only the hand-written layer codegen replaces. The doctrine is gated on a brownfield predicate and left to coexist with the existing greenfield model-first ("generated code is disposable") guidance.field.uuidrecommendation and reclassified thefield.string+@dbColumnType: uuidString↔UUID coercion case from an advisory audit finding to a real (axis-H2) finding, with an illustrative project-local grep CI-ratchet noted as guidance (a semantic-lint subverb left as a follow-up)..claude/skills/*/SKILL.mdand.metaobjects/AGENTS.md/CLAUDE.md) across all four stacks so they match the updated canonical source. Local gates stayed green (agent-context conformance, size-gate within the always-on line budget, capability-grounding — 42/42).Risk Assessment
✅ Low: Docs-only change to agent-context skills with regenerated conformance goldens; goldens are byte-in-sync with the canonical source, all conformance gates (drift, grounding, size) are satisfied, and no runtime or product code is touched.
Testing
Baseline: fresh checkout needed
bun install(root) and the gitignored SDK agent-context bundle rebuilt via its bundle script — a setup step, not a product failure — after which the full agent-context suite is 42/42. The four gates the change targets (conformance golden byte-match, capability-grounding registry check, 120-line size-gate, vocabulary-drift scan) all pass. Beyond tests, I exercised the actual deliverable: I ran the real assemble() API for a realistic typescript+react+tanstack adopter stack (whatmeta initscaffolds) and captured the brownfield-adoption doctrine exactly as it reaches the end user — the always-on file now leads with "Metadata FOLLOWS the code" reconciled against the greenfield model-first guidance, and the UUID hardening, axis-H2 audit finding, CI-ratchet lint, and adoption-direction guardrail all render into the scaffolded skills. This is a documentation change with no rendered-UI surface, so the reviewer-visible artifacts are the assembled Markdown files themselves rather than screenshots. Transient build output was removed; the worktree is clean and evidence lives under /tmp.Evidence: Scaffolded always-on AGENTS.md (what an adopter imports into their repo root)
Evidence: Scaffolded always-on CLAUDE.md variant
Evidence: Brownfield doctrine as it lands in .claude/skills/* (authoring direction + UUID smell, codegen match-the-code, verify CI-ratchet lint, audit axis-H2 + guardrail)
Evidence: End-user-surface assertions from the live assemble() run
Evidence: Full agent-context gate result after bundling
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
agent-context/skills/metaobjects-verify/SKILL.md:91- The illustrative CI-ratchet grep in metaobjects-verify usesgrep -Ez ... "field\.string"[^}]*"@dbColumnType"[^}]*"uuid". Because-zmakes[^}]*stop at the first}, afield.stringnode whose object contains a nested child (e.g. achildrenarray orview.*sub-object closing a}) before@dbColumnTypewill NOT match — a false negative. That quietly undermines the doc's own claim that the ratchet 'can't go green until the last offending field is migrated' / is a 'permanent backstop': offenders with intervening braces could remain while the gate reads green. The existing caveat ('tighten to per-node scope if a coarse co-occurrence match is too broad') addresses over-matching but not this under-match. Consider adding a one-line note that a per-node (JSON-aware) matcher is needed for a reliable completion criterion. Advisory only — it is explicitly labeled 'Illustrative' guidance, not committed CI.✅ **Test** - passed
✅ No issues found.
agent-context conformancecapability-groundingsize-gatevocabulary driftfull agent-context suite (42 tests)end-to-end bundle assembly✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.