Quickstart: Drupal Dries Agent Profile

Mission: drupal-dries-profile-01M28X69 Branch: feat/drupal-dries-profile

For the implementer picking up a work package on this mission. Read plan.md for the why; this is the operational path.


0. Environment first — this is not optional

This checkout has no .venv, and the repository's own code does not currently import without one. Before anything else:

cd /Users/nicolas/Projects/spec-kitty
make dev-setup          # or: uv sync --frozen --all-extras

Why it comes first. A globally installed spec-kitty operates on the pack bundled inside its own venv, not this repository's. Verified during Phase 0:

$ spec-kitty doctrine regenerate-graph --check
DRG graph is fresh:
/Users/nicolas/.local/pipx/venvs/spec-kitty-cli/lib/python3.14/site-packages/packs/built-in

That green says nothing about your changes. Every command below must run against repository source.


1. Establish the baseline before touching anything

uv run spec-kitty doctrine regenerate-graph --check   # expect: exit 0, repo path
uv run spec-kitty doctor doctrine --json | head -40   # expect: 0 skipped profiles

If either is already red on main, that is a pre-existing condition to report, not to absorb into this mission's diff. Record it in the WP and continue.


2. Read the precedents before writing

Do not invent shapes. Three files define everything you need:

packs/built-in/agent_profiles/java-jenny.agent.yaml            # profile shape (185 lines)
packs/built-in/styleguides/python-conventions.styleguide.yaml  # patterns + anti-patterns (170)
packs/built-in/toolguides/maven-review-checks.toolguide.yaml   # descriptor shape

The distillation source is fetched fresh from https://raw.githubusercontent.com/amazeeio/drupal-agents-md/main/Vanilla/AGENTS.md — 1,492 lines. Section map in research.md.


3. The one non-obvious step

Lineage is not in the YAML. Add to _CURATED_ARTIFACT_EDGES in src/charter/offering/drg/migration/extractor.py (~line 267), beside the four existing specialists:

(
    "agent_profile:drupal-dries",
    _AGENT_PROFILE_IMPLEMENTER_IVAN,
    Relation.SPECIALIZES_FROM,
),

A specializes-from field in the profile YAML is rejected by the model — it will not work.


4. Regenerate; never hand-edit a graph fragment

uv run spec-kitty doctrine regenerate-graph        # writes the fragments
uv run spec-kitty doctrine regenerate-graph --check # proves them fresh
git diff --stat packs/built-in/*.graph.yaml        # expect: only your 4 nodes + their edges

--check regenerates into a temp directory and compares. A hand-edit is indistinguishable from staleness — both go red.


5. Verify

make test-fast                                             # baseline
uv run pytest tests/doctrine/agent_profiles/ -q            # profile load/resolution
uv run pytest tests/doctrine/styleguides/ -q               # styleguide models
uv run pytest tests/doctrine/ tests/charter/ -q            # both — src/charter/offering/ was touched
uv run pytest tests/architectural/test_no_legacy_terminology.py -q   # ~0.1s, prose gate
uv run ruff check . && uv run ruff format --check .        # format is a SEPARATE gate from lint

ruff check passing says nothing about formatting — CI runs ruff format --check over the whole repo and an unformatted file reds regardless.

Before recording any failure as pre-existing, classify it against the baseline-red categories in CLAUDE.md — known-P0 reds, CI-environment failures, stale-install, stale-venv. A ModuleNotFoundError for a pinned package means step 0 was skipped, not that something regressed.


6. Definition of done for the mission

  • □ 8 files: 5 new pack artifacts, 2 edits, 1 regenerated fragment set
  • □ regenerate-graph --check green against the repository pack
  • □ doctor doctrine --json reports 0 skipped profiles
  • □ All 14 source anti-patterns carried (SC-003)
  • □ Boundary reciprocal in both profiles, with the verification/authorship distinction (R-006)
  • □ Provenance credited in every delivered artifact (FR-010)
  • □ Profile within 140-215 lines (NFR-001)
  • □ No invented PHPStan level, coverage number, or threshold (NFR-006)
  • □ Only avoidance-boundary changed in frontend-freddy.agent.yaml (NFR-007)
  • □ Test commands and pass/fail counts recorded in the PR's Tests run section

Traps, collected

TrapSymptomFix
Global CLI checks the wrong pack--check green, pointing at a pipx pathRun via uv run from the repo
Hand-editing a *.graph.yaml--check red, "stale"Regenerate instead
specializes-from in profile YAMLRejected at loadUse the extractor table
ModuleNotFoundError: spec_kitty_events.diaryImport failsuv sync --frozen --all-extras
Lint green, CI redFormat gateuv run ruff format --check .
Inventing a PHPStan levelPasses tests, violates NFR-006Use the project's configured level
Editing .claude/ or another agent copyChange vanishes on upgradeEdit packs/built-in/ only (C-001)