One canonical agent instruction file, and a parallel verification gate - #4
Merged
Merged
Conversation
Mirrors the structural work done in uptizm, which forks this boilerplate, adapted rather than copied where the two repos genuinely differ. Four tools now work these repos and each looked for a different instruction file, so a rule written for one was invisible to the others. AGENTS.md becomes the single hand-edited source; CLAUDE.md is a symlink, because Claude Code reads CLAUDE.md and has no native AGENTS.md discovery, so there is one lookup key and no double-load. The Copilot mirrors under .github/ are generated copies rather than symlinks: GitHub does not document symlink following for its instruction files and there is an open bug against the VS Code extension for that setup. The path-scoped rule could not be symlinked regardless, since .claude/rules/*.md spells its globs as a YAML list under paths: and Copilot wants one comma-separated string under applyTo:, so bin/sync-instructions rewrites the frontmatter and --check fails CI on drift. bin/check is the gate. Two things in it are load-bearing and were both learned by watching it fail: flutter analyze and flutter test each resolve dependencies on their own and collide on .dart_tool and ios/Flutter/ephemeral, so one prepare step owns resolution and both commands take --no-pub; and a Blade view calling @Vite throws without a manifest that lives in gitignored public/build, so the manifest is ensured before any test renders a page. The backend suite runs sequentially here on purpose: with a handful of tests, paratest would spend more time booting workers than it saves. Where this repo differs from the fork, the adaptation is deliberate: no worker scope, no paratest, no sibling checkouts in CI (this repo resolves from pub.dev, and CI resolving the PUBLISHED versions is what catches a dependency on unreleased sibling code), and PHP 8.4 rather than 8.5 because that is the floor the lock actually demands and a boilerplate is worth testing at its floor. config/magic-starter.php picks up a pre-existing Pint fix, so the new gate is green on arrival rather than red for a reason nobody introduced.
There was a problem hiding this comment.
Pull request overview
Establishes a single canonical agent-instruction source (AGENTS.md), adds generation + CI drift checking for Copilot instruction mirrors, and introduces a unified parallel verification gate (bin/check) backed by CI and a documented verification loop.
Changes:
- Added
AGENTS.mdas the canonical instructions source and generated Copilot mirrors under.github/viabin/sync-instructions(with--checkfor CI drift detection). - Introduced
bin/checkas a parallel, buffered-output verification gate for Flutter + backend suites, plus CI jobs to run equivalent checks per half. - Added verification documentation (
docs/verification-loop.md) and a PR template emphasizing evidence-based verification.
Reviewed changes
Copilot reviewed 9 out of 12 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| docs/verification-loop.md | Documents the 3-layer verification loop (static, visual, dusk E2E) and evidence expectations. |
| bin/sync-instructions | Generates .github/ Copilot instruction mirrors from canonical + path-scoped Claude rules; supports CI drift checking. |
| bin/check | Adds a parallelized local verification gate to run Flutter/backend suites with buffered logs and worktree bootstrapping. |
| backend/config/magic-starter.php | Refactors feature references to use an imported Features symbol for readability/consistency. |
| AGENTS.md | Consolidates canonical agent instructions into a single source intended for all tools. |
| .github/workflows/ci.yml | Adds CI workflow gating PRs with instruction mirror checks plus Flutter/backend suites. |
| .github/pull_request_template.md | Adds an evidence-forward PR template aligned to the verification loop. |
| .github/instructions/design.instructions.md | Adds generated Copilot path-scoped design rules for lib/**. |
| .github/copilot-instructions.md | Adds generated Copilot repo-wide instruction mirror sourced from AGENTS.md. |
| .claude/rules/design.md | Extends design rules with an explicit anti-pattern table and blockers. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Adding CI proved this repo could not be installed anywhere but this machine, which matters more here than in a product repo: apps fork this one as their starting point. composer.json still carried a path repository pointing at ../../magic-starter-laravel and required it as @dev, so composer.lock held a "type": "path" entry that no other checkout can resolve; CI failed with "Source path is not found". The package has been on Packagist through 0.0.5 for a while, so this moves to ^0.0.5 and drops the repository. Develop both together by adding the path repo locally and reverting it before committing. Guzzle was pinned at 7.12.3 by a stale lock, with six advisories against it including a high-severity host-check bypass. Updating it alone changed nothing because 7.15.2 also needs newer promises and psr7, so this updates the three together. composer audit is now clean. package-lock.json was missing, so exited non-zero and the asset build could not run at all. It is committed now, and bin/check falls back to rather than reporting an asset failure that is really a missing lockfile.
design.md told every agent that a className setting a color must carry its dark: counterpart, and then said the alias system already handles it. The second half is the true one: an alias expands to both modes, so dark:bg-surface is nonsense. sync-instructions skipped a rule it could not parse while --check reported "up to date", because it compares generated output against generated output: a whole path-scoped rule could be invisible to Copilot with CI green. Unparseable frontmatter, a malformed glob list and an empty body are now fatal. bin/check demands backend/vendor rather than failing pint with rc 127, runs config:clear before the suite (a cached config outranks phpunit.xml's sqlite pin and would migrate:fresh a real database), kills its jobs on the way out so a tool-call timeout does not orphan them, and names the scope in the summary because "all green" read identically after --fast, which runs no tests. The workflow no longer cancels a main run and every job has a timeout.
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.
What changed
Mirrors the structural work done in
uptizm(which forks this boilerplate), adapted rather than copied where the two repos genuinely differ.AGENTS.mdbecomes the single canonical instruction file;CLAUDE.mdis a symlink to it. Codex, opencode, and Copilot's agent surface readAGENTS.mdnatively; Claude Code readsCLAUDE.mdand has noAGENTS.mddiscovery, so one lookup key means no double-load.bin/sync-instructionsgenerates the Copilot mirrors under.github/, rewriting the path-scoped rule'spaths:list into Copilot'sapplyTo:string.--checkfails CI on drift.bin/checkis one gate that fans the suites out across cores.docs/verification-loop.mdcarries the three verification layers, including the dusk end-to-end walk at desktop and mobile width.Why
Several agents can work this repo at once, four different tools each looked for a different instruction file, and nothing measured a change before merge. Since production apps fork this project, the boilerplate is where the convention belongs.
Evidence
bin/checkon this branch, exit 0:Two failures found by running it rather than by reading it, both now fixed and both worth knowing about:
flutter analyzeandflutter testeach resolve dependencies on their own and collide on.dart_toolandios/Flutter/ephemeral. Serializing apub getfirst was not enough;--no-pubon both is what removes the race.@vitethrows without a manifest, which lives in the gitignoredpublic/build. A fresh worktree or runner has none, so a page test fails on Vite rather than on its subject.config/magic-starter.phppicks up a pre-existing Pint fix so the new gate is green on arrival.bin/checkgreenDeliberate differences from the fork
>=8.4.1, socomposer.json's^8.3is stale), and a boilerplate is worth testing at its floor.