Skip to content

🔧 Add shared Claude Code agent tooling - #212

Merged
ker0x merged 3 commits into
mainfrom
tech/issue-000-claude-code-tooling
Aug 12, 2026
Merged

🔧 Add shared Claude Code agent tooling#212
ker0x merged 3 commits into
mainfrom
tech/issue-000-claude-code-tooling

Conversation

@ker0x

@ker0x ker0x commented Aug 12, 2026

Copy link
Copy Markdown
Member

Adds a committed .claude/ so the conventions in AGENTS.md are enforced rather than merely remembered, corrects four documented claims that did not match the code, and fixes two stray typographic quotes.

⚠️ This changes behaviour for everyone

.claude/settings.json and .mcp.json are checked in, so the two hooks below start running on every contributor's machine as soon as this merges. That is the intent, but it is worth knowing before approving rather than discovering it mid-edit. Both shell into the php container and no-op silently when the stack is down.

Tooling

Hooks

Script Event Behaviour
hooks/fix-style.sh after Edit/Write Runs PHP CS Fixer or Twig CS Fixer on the edited file. Skips vendor/, var/, generated assets, migrations/.
hooks/guard-protected-files.sh before Edit/Write Refuses edits to already-applied migrations and to .env*.local. Creating a new migration file is still allowed.

Skills/ci-check mirrors ci.yaml in order, adding the container-up and make cc preflight CI gets for free (PHPStan reads the compiled container XML, so a stale var/cache/dev/ produces false positives). /new-module scaffolds a DDD module across the eight places it touches, with templates taken from the real Experience/Resume code.

Subagentsddd-boundary-reviewer and i18n-parity-reviewer, both scoped to the diff rather than the whole tree. The DDD one carries an explicit allow-list of accepted deviations (Doctrine repositoryClass, elao/enum, Clock, Security interfaces in Domain/); without it, it would fire on every existing entity.

MCPpostgres-dev gives read-only access to the dev database. compose.override.yaml publishes Postgres as ports: - "5432", so Docker assigns a random host port on every up — a hardcoded connection string would break on first restart. The wrapper resolves the port via docker compose port and reads credentials from the running container, so no password is stored in the repo.

Doc corrections

Four claims in AGENTS.md / CLAUDE.md did not match the code:

Claim Reality
templates/components/ templates/component/, singular
`base.html.twig` (4 spots) templates/app/base.html.twig
Entities map onto constructor-promoted properties Only PageView promotes; Experience, Settings, User use plain public properties
Repository interfaces live in Domain Only Analytics has one; the other four modules inject the concrete repository

The last two mattered most — both were stated as established patterns, so following them produced code that did not match its neighbours. Both now describe what the code actually does, plus when the Domain interface is worth adding.

Also documents the template inheritance chain, including the chrome-less pages (CV, login, error) that extend app/base.html.twig directly instead of the intermediate bases.

Typographic quotes

Two French strings used a curly apostrophe, against the straight-quotes rule in AGENTS.md. Both sat inside single-quoted strings, so the quoting changed with them — the PHP one is escaped, the YAML one switched to double quotes to match its neighbours. The surrounding copy already uses straight apostrophes throughout (n'a, d'expériences, j'ai, aujourd'hui), so these were outliers, not deliberate French typography.

Verification

  • All JSON and all four skill/agent frontmatter blocks parse
  • guard-protected-files.sh passes 7/7 cases: blocks applied migrations, allows new ones, blocks .env.local, allows plain .env
  • The fixer command was run for real against a scratch file — it applied declare(strict_types=1), Yoda, trailing comma and blank-line-before-return
  • php -l passes; PHP CS Fixer reports 0 fixable issues on the changed controller; both message catalogues parse through Symfony's YAML component
  • Scripts are committed as mode 100755

Not verified: no project images exist locally, so make up means a full FrankenPHP build and I did not run one. The fixer was therefore exercised on the host rather than in-container; what is untested is only the /app/$rel path prefix, which follows from ./:/app and WORKDIR /app. Same for the MCP wrapper. Both fail safe — they no-op rather than corrupt anything. Worth one make up plus a PHP edit before merging.

ker0x added 3 commits August 12, 2026 08:12
Adds a committed .claude/ so the conventions in AGENTS.md are enforced
rather than merely remembered. Everything shells into the php container,
since the toolchain exists nowhere else, and no-ops when it is down.

Hooks:
- fix-style.sh runs PHP CS Fixer / Twig CS Fixer on each edited file
- guard-protected-files.sh blocks edits to applied migrations and
  .env*.local, while still allowing new migration files

Skills: /ci-check mirrors ci.yaml with the container-up and cache-warm
preflight CI gets for free; /new-module scaffolds a DDD module.

Subagents: ddd-boundary-reviewer and i18n-parity-reviewer, both scoped
to the diff. The former carries an allow-list of accepted deviations so
it does not flag the Doctrine and elao/enum idioms already in Domain/.

MCP: postgres-dev resolves the randomly-assigned host port and the
credentials from the running container, keeping secrets out of the repo.
Four documented claims did not match the code:

- components live in templates/component/, not templates/components/
- the base template is templates/app/base.html.twig
- only PageView uses constructor promotion; Experience, Settings and
  User declare plain public properties
- only Analytics has a Domain repository interface, the other modules
  inject the concrete repository

The last two were stated as established patterns, so following them
produced code that did not match its neighbours. Both now describe what
the code does, and note when the Domain interface is worth adding.

Also documents the template inheritance chain, including the
chrome-less pages that extend app/base.html.twig directly, and adds a
section covering the committed .claude/ tooling.
Two French strings used a curly apostrophe, against the straight-quotes
convention in AGENTS.md. Both sat inside single-quoted strings, so the
quoting had to change with them: the PHP one is now escaped, the YAML
one switched to double quotes to match its neighbours in the catalogue.

The surrounding copy already uses straight apostrophes throughout
(n'a, d'expériences, j'ai, aujourd'hui), so these were outliers rather
than deliberate French typography.
@ker0x
ker0x merged commit 278d094 into main Aug 12, 2026
1 check passed
@ker0x
ker0x deleted the tech/issue-000-claude-code-tooling branch August 18, 2026 20:38
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