aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrett Parson <brett@brett-parson.com>2026-08-29 15:56:32 -0500
committerBrett Parson <brett@brett-parson.com>2026-08-29 15:56:32 -0500
commita2b29fe6ffa16a0af5635505df7250f27724260a (patch)
tree8ccadc420e2bf8cd997f76d8b54e2bcfc83dbf17
parent965551532d684456b74baf960157c0c2cef7335d (diff)
downloadminiroute-a2b29fe6ffa16a0af5635505df7250f27724260a.tar.gz
miniroute-a2b29fe6ffa16a0af5635505df7250f27724260a.zip
Restructure roadmap and add changelogv0.1.0
Phase plan for v0.2.0 through v1.0.0, Keep-a-Changelog conventions, and agent docs with build/test and beads-operations guidance.
-rw-r--r--AGENTS.md27
-rw-r--r--CHANGELOG.md52
-rw-r--r--CLAUDE.md38
-rw-r--r--docs/roadmap.md103
4 files changed, 162 insertions, 58 deletions
diff --git a/AGENTS.md b/AGENTS.md
index ee9b430..47aa32b 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -11,7 +11,16 @@ bd ready # Find available work
bd show <id> # View issue details
bd update <id> --claim # Claim work atomically
bd close <id> # Complete work
-bd create # Create v0.1.0 beads individually (see docs/roadmap.md)
+bd create # Create beads per the phase plan (see docs/roadmap.md)
+```
+
+## Build & Test
+
+```bash
+composer install # once (phpunit is dev-only)
+composer check # lint + unit tests — the quality gate
+composer test # vendor/bin/phpunit only
+composer bench # registration/dispatch scaling benchmark (manual, not CI)
```
## Conventions
@@ -21,6 +30,22 @@ bd create # Create v0.1.0 beads individually (see docs/roadmap.md)
- Attributes live in `src/Attribute/`.
- Keep runtime dependencies at zero; `phpunit` is dev-only. See `README.md`.
- Controllers accept `RequestInterface` and return `ResponseInterface`.
+- Known-issue baselines live in `tests/Regression/KnownIssuesTest.php` and
+ flip to desired behavior when their fix lands — never delete them.
+- Every user-facing change gets a line in `CHANGELOG.md` under Unreleased.
+
+## Beads operations
+
+- The embedded Dolt database allows ONE writer at a time: never run two `bd`
+ commands in parallel (they collide on the lock). Serialize them.
+- Never use `bd edit` (opens an editor). Use `bd update --title/--description`.
+- `bd prime` restores full workflow context after compaction or a new session.
+
+## Changelog
+
+- Add a line under `[Unreleased]` for every user-facing change.
+- Release: rename Unreleased to the version, bump `composer.json`, tag `vN.N.N`,
+ push. See `CHANGELOG.md` header for the full convention.
## Non-Interactive Shell Commands
diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..111aaf6
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,52 @@
+# Changelog
+
+All notable changes to this project are documented in this file.
+
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
+
+How it works:
+
+- Every user-facing change gets a line under **Unreleased** as it lands
+ (Added / Changed / Fixed / Removed / Deprecated / Security).
+- At release time, "Unreleased" is renamed to the new version (e.g.
+ `## [0.2.0] - 2026-09-xx`) and a fresh Unreleased section is opened.
+- The version number comes from `composer.json` and the matching `git tag`
+ (`v0.2.0`). Bugfix releases bump the patch (`0.2.1`), features bump the
+ minor (`0.3.0`), and breaking changes bump the major after 1.0 (`2.0.0`).
+
+## [Unreleased]
+
+### Added
+
+- Integration suite (`tests/Integration/RealisticRouteTableTest.php`):
+ the 22-route brett-parson.com model, `/admin` group + POST-only CSRF
+ ordering, literal `preview` beating `{id}`, param injection, 5-layer
+ onion order.
+- Regression baselines (`tests/Regression/KnownIssuesTest.php`): six
+ known-issue probes pinning v0.1.0 behavior, each linked to its v0.2.0
+ fix bead.
+- Benchmark script (`composer bench`, `tests/bench/bench.php`):
+ registration/dispatch scaling at 100/300/600 routes.
+- Router boundary tests: trailing-slash normalization, method
+ case-insensitivity, case-sensitive paths, leading double slash,
+ cross-controller duplicate detection, custom not-found handler.
+- Composer scripts: `test`, `bench`, `lint`, `check`.
+
+## [0.1.0] - 2026-08-29
+
+### Added
+
+- Attribute route declaration (`Get`, `Post`, `Put`, `Patch`, `Delete`)
+ compiled by a reflection-based `RouteLoader`.
+- Deterministic matching: literal segments beat `{parameter}` segments at
+ the same position, so registration order never matters.
+- Onion middleware pipeline (`MiddlewarePipeline`) with `Middleware`
+ attributes on classes and methods, plus router-level `group()` prefix
+ middleware with optional method restriction.
+- Controller resolution seam (`ControllerResolverInterface`) so apps plug
+ in their own container wiring.
+- Thin HTTP contracts (`RequestInterface`, `ResponseInterface`) that
+ application HTTP objects implement.
+- Duplicate route detection at registration (`RouteRegistrationException`).
+- Unit test suite covering loader, matcher, pipeline, and router.
diff --git a/CLAUDE.md b/CLAUDE.md
index 50af487..e0820ca 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -1,6 +1,23 @@
# Project Instructions for AI Agents
-This file provides instructions and context for AI coding agents working on this project.
+**Source of truth: [AGENTS.md](AGENTS.md) — read it first.**
+
+This file is a lightweight mirror for agents that look for `CLAUDE.md`. If the
+two disagree, `AGENTS.md` wins. The beads block below is auto-managed by the
+`bd` hooks.
+
+The short version:
+
+- **Build & Test**: `composer install` once, then `composer check` (lint +
+ unit tests) before finishing work. `composer bench` for the scaling
+ benchmark.
+- **Tracking**: use `bd` for ALL task tracking — never TodoWrite or markdown
+ TODO lists. Serialize `bd` commands (embedded Dolt is single-writer).
+- **Changelog**: every user-facing change gets a line under `[Unreleased]` in
+ `CHANGELOG.md`.
+- **Session close**: file issues for remaining work, run `composer check`,
+ update issue status, then push (`git pull --rebase`, `bd dolt push`,
+ `git push`). Work is not complete until the push succeeds.
<!-- BEGIN BEADS INTEGRATION v:1 profile:minimal hash:ca08a54f -->
## Beads Issue Tracker
@@ -48,22 +65,3 @@ bd close <id> # Complete work
- NEVER say "ready to push when you are" - YOU must push
- If push fails, resolve and retry until it succeeds
<!-- END BEADS INTEGRATION -->
-
-
-## Build & Test
-
-_Add your build and test commands here_
-
-```bash
-# Example:
-# npm install
-# npm test
-```
-
-## Architecture Overview
-
-_Add a brief overview of your project architecture_
-
-## Conventions & Patterns
-
-_Add your project-specific conventions here_
diff --git a/docs/roadmap.md b/docs/roadmap.md
index 59eb6c9..fd2e698 100644
--- a/docs/roadmap.md
+++ b/docs/roadmap.md
@@ -1,50 +1,79 @@
-# v0.1.0 Roadmap
+# MiniRoute Roadmap
-Initial release of the routing/middleware kernel.
+Status: **v0.1.0 released** (2026-08-29) · next: **v0.2.0 hardening**
+Issue tracking: beads — the epics below are live in the database (`bd ready`,
+`bd show <id>`). Full issue IDs carry a `miniroute-` prefix (e.g. `miniroute-uhs`).
-## Proposed beads
+## Version policy
-### [EPIC] miniroute v0.1.0 — attribute routing + middleware kernel
+- **0.x era** — the contract is still settling. Breaking changes are allowed
+ at minor bumps (`0.2`, `0.3`); patches (`0.1.1`) are for fixes within a
+ minor. Every behavior change lands in `CHANGELOG.md`.
+- **1.0** — API freeze. From `v1.0.0` on: strict SemVer (major = breaking,
+ minor = feature, patch = fix). The freeze review is `miniroute-18h.1`.
-- Type: epic
-- Priority: P2
+## v0.1.0 — Initial kernel [released]
-Children (create with `--parent`):
+Attribute routes, deterministic matching (literal beats `{param}` regardless
+of registration order), onion middleware pipeline, resolver seam, thin HTTP
+contracts. Closed via epic `miniroute-c5e` (children 1–6; 7–8 completed the
+release ceremony: tag + cgit publish).
-1. **Core: attribute route declaration and reflection loader**
- - Type: task, Priority: P2
- - Description: Implement `Get`/`Post`/`Put`/`Patch`/`Delete`/`Middleware`
- attributes and `RouteLoader` reflection scanning.
- - Acceptance: `RouteLoaderTest` passes.
+## v0.2.0 — Hardening (epic `miniroute-uhs`)
-2. **Core: deterministic route matching**
- - Type: task, Priority: P2
- - Description: `RouteMatcher` with `{param}` support and
- literal-before-parameter precedence.
- - Acceptance: `RouteMatcherTest` passes.
+Fix the failure modes confirmed by the stress test; each fix flips a baseline
+in `tests/Regression/KnownIssuesTest.php` from "v0.1.0 behavior" to desired:
-3. **Core: middleware pipeline and groups**
- - Type: task, Priority: P2
- - Description: `MiddlewarePipeline` onion composition and router-level
- `group()` prefix middleware.
- - Acceptance: `MiddlewarePipelineTest` and router group coverage pass.
+| Bead | Fix | Current (v0.1.0) behavior |
+|---|---|---|
+| `uhs.1` | Validate param names (unique, `[A-Za-z_][A-Za-z0-9_]*`) at registration → `RouteRegistrationException` | Duplicate params = dead route + preg warning; malformed `{a-b}` degrades to literal |
+| `uhs.2` | 405 detection: path-only fallback → `MethodNotAllowedException` with `allowed()`; app renders 405 + `Allow` | Wrong method = plain 404 |
+| `uhs.3` | HEAD → GET mapping (matcher); app's response layer suppresses body | HEAD = 404 |
+| `uhs.4` | Fail loud: route attribute on non-public method → `RouteRegistrationException` | Non-public methods silently skipped |
+| `uhs.5` | Lazy single sort in `Router` (dirty flag, sort at first dispatch) | `usort` per add: 600 routes ≈ 770ms registration |
+| `uhs.6` | Memoize compiled patterns in `RouteMatcher` | Regex recompiled per route per match |
-4. **Core: controller resolution and dispatch**
- - Type: task, Priority: P2
- - Description: `ControllerResolverInterface` seam and `Router::dispatch`.
- - Acceptance: `RouterTest` passes.
+Gate: `composer check` green with baselines flipped; bench shows registration
+cost collapse at 600 routes. Middleware singleton-state rule is a *usage
+contract*, documented in v0.3.0 ADRs (`k4i.3`), not a kernel change.
-5. **Tests: unit coverage for loader/matcher/pipeline/router**
- - Type: task, Priority: P2
- - Acceptance: `vendor/bin/phpunit` green.
+## v0.3.0 — API completeness (epic `miniroute-k4i`)
-6. **Docs: ADRs, README, usage**
- - Type: task, Priority: P2
+- `k4i.1` — `RequestInterface::input()` / `query()` so real middleware (CSRF)
+ reads form/query data through the contract instead of `$_GET` or narrowing.
+- `k4i.2` — `match(): ?ResponseInterface` (or richer result) so fall-through
+ composition doesn't need try/catch.
+- `k4i.3` — ADRs: middleware ordering contract (group/class/method onion),
+ singleton-middleware state rule, exception hygiene (sessions closed in
+ `finally`), and the rejected decision on `{id:\d+}` param constraints
+ (controllers already validate; don't add scope).
-7. **Release: Composer metadata and git tags**
- - Type: task, Priority: P2
- - Description: `composer.json` PSR-4 autoload, MIT license, tag `v0.1.0`.
+## v0.4.0 — parsonwebsite integration (epic `miniroute-g3j`)
-8. **Repo: publish to src.brett-parson.com**
- - Type: task, Priority: P2
- - Description: Add cgit remote, push, set `git-daemon-export-ok` marker.
+- `g3j.1` — Port `RequireAdmin` / `RequireCSRF` / `AdminSession` onto
+ `MiddlewareInterface` (the per-route closures become `/admin` groups).
+- `g3j.2` — App `Request`/`Response` implement the interfaces directly
+ (drop `ToyRequest`/`ToyResponse`; add `Response::status()`).
+- `g3j.3` — Full route table behind the existing flag; old router as fallback
+ until green, then cut over.
+
+Gate: the realistic stress section passes against the real controllers.
+
+## v1.0.0 — Release (epic `miniroute-18h`)
+
+- `18h.1` — API freeze review of the public surface (attributes, interfaces,
+ exceptions, `Router` methods).
+- `18h.2` — Dogfood via Composer: parsonwebsite consumes the package from the
+ published VCS remote.
+- `18h.3` — CI benchmark gates: full-table registration < 5ms, dispatch
+ < 0.1ms, full suite green.
+- `18h.4` — Tag `v1.0.0`, publish, strict-SemVer policy from here.
+
+## Cross-cutting infrastructure
+
+- Test suite epic `miniroute-4dh` — regression/integration coverage:
+ realistic route table (`4dh.1`), known-issue baselines (`4dh.2`), router
+ boundary cases (`4dh.3`), benchmark script (`4dh.4`).
+- `miniroute-ouq` — changelog + roadmap + agent docs (this file,
+ `CHANGELOG.md`, `AGENTS.md`/`CLAUDE.md`).
+- `miniroute-br6` — configure a beads Dolt remote for issue sync/backup.