corn · the core
Deterministic kernel
The stalk that holds everything up. A small core, predictable and boring on purpose: abundance grows on top of it, not inside it.
milpa/core · zero dependencies — contracts and primitives only
modular php framework · built for humans and agents · contract-first
Siembra módulos, cosecha aplicaciones.
sow modules, harvest applications
A milpa is not a crop: it's a system. Modules that grow together and feed one another — on a deterministic core, with contracts that protect them.
the system
The three sisters — corn, beans, and squash — grow together and feed one another. Deterministic, cultivated agriculture: order that yields abundance. That is the framework.
corn · the core
The stalk that holds everything up. A small core, predictable and boring on purpose: abundance grows on top of it, not inside it.
milpa/core · zero dependencies — contracts and primitives only
beans · the modules
Modules that connect through events and compose with each other. They fix nitrogen: each one feeds the whole system.
provides / requires in milpa.json — providers load before consumers
squash · the contracts
It covers the soil: machine-readable contracts that validate every piece. Nothing is sown without one.
*.contract.json · validated at boot, gated in CI
one tool, every caller
Most PHP frameworks are built for one kind of caller: a human writing code, or a browser sending requests. Milpa is built for two — humans and agents operating the same application through the same declared surface.
final class NoteTools{ #[Tool('list_notes', 'List saved notes', scopes: ['notes:read'])] public function listNotes( #[Param('Page number', clamp: [1, 1000])] int $page = 1 ): ToolResult { return ToolResult::success(['notes' => [], 'page' => $page]); }}
Declare it once with #[Tool]. The registry
runs the same pipeline on every call — resolve, validate, authorize, execute, audit — whether it came
from the CLI, an HTTP request, or an agent speaking MCP. And when a call is denied, the result says
exactly why.
try it — the same operation, projected to three doors:
An operation is declared once. coa, MCP and HTTP are adapters of the same handler — but changing doors can change the policy.
crear:tarea
Honest coverage gap: This is not a desirable HTTP guarantee. It is a radiography of the current implementation. MCP enforces scopes today; HTTP does not yet read scopes from Operation. This gap must be closed in runtime/policy before production. See Runtime x-ray. Source: Operation.php.
coa crear:tarea --titulo=… --yes
Pick a door to project.
tools/call · crear:tarea
Pick a door to project.
POST /crear/tarea
Pick a door to project.
| Surface | Confirm | Scopes applied |
|---|---|---|
| coa | flag --yes | no (local/trusted) |
| MCP | inherited gate (tool-runtime) | yes (PolicyGate) |
| POST | token 428→201 | no (pending · middleware) |
The handler never changed. You changed doors and the framework synthesized the invocation — but the door can change the policy, and today not all of them apply the same scopes.
Didactic model over an audited implementation. This artifact does not claim that HTTP applies scopes, nor that the in-memory token store is production-grade.
milpa/command: getmilpa-command/src/Operation.php, CommandProvider.php, SurfaceProjector.php.skeleton, ns App\Command, not part of the package): getmilpa-skeleton/src/Command/{CliProjector,McpProjector,HttpProjector}.php.ConfirmTokenStore.php (in-memory, single-process — not production), SchemaCoercer.php.docs/GUION-WEBINAR-JUNIORS.md (Artifact 2).→ the full lesson in the Academy
plugin → capability → tool → verification → event → result
agent-native · deterministic
Agents don't need more freedom — they need better rails.
coa is deterministic first: it inspects,
validates and diagnoses with machine-readable answers, and generators produce the file
in memory — you can inspect, diff or dry-run a generation
before anything touches the filesystem.
The loop is generate → verify → inspect: scaffolding follows
the same conventions the runtime enforces, verifiers reflect the real class against the real rules, and
validators read the whole plugin ecosystem — every hard requires satisfied,
the graph acyclic — before it becomes a boot-time failure.
next: every failure links to the concept it broke · coming soon
trust, by design
Autonomy without brakes is a demo, not a system. In Milpa, verification is a first-class primitive: a mutating action can be gated behind a deterministic check, a human approval, or a pending async result — and every passage is recorded.
the seam
A verifier gates the action; the result is tri-state. Waiving a gate is an explicit, recorded decision — never a silent skip.
milpa/core · the verification seam
the flow
States, transitions and gates live in data, not in constants — change a flow without redeploying code, and ask the machine which transitions are legal right now.
milpa/workflow · data-driven state machine
the memory
Every call is resolved, authorized and audited; sensitive fields are redacted before they're logged. Identity is an opaque principal — the host owns its domain.
milpa/tool-runtime · audit built into the pipeline
the harvest map
The dependency graph is the milpa, literally: roots with zero dependencies, rows grown from the core, compositions that climb — and a skeleton where you harvest. Every layer builds with the one below, never couples downward — and new rows are sown all the time.
tier 0 · the roots
The contracts, and standalone pieces that depend on nothing — not even on each other.
tier 1 · the rows
Each one implements a seam of the contracts: containers, events, routing, live components, tools, plugins, workflow, event log.
tier 2 · the climbers
The rows composed into engines: a bootable kernel, an LLM gateway, an MCP server, live HTML, event-sourced process orchestration.
the harvest
composer create-project milpa/skeleton
boots the kernel, serves a real response and answers coa — with zero database.
the first harvest
@milpa/design is
published: dark-first tokens verified WCAG AA, motion with a reduced-motion contract, and 68
pieces, every one with a machine-readable contract. It's the framework's thesis proven small —
and it stands on its own.
npm i @milpa/design
Pure CSS + JSON contracts: no framework in between, no dependencies. The quality floor — AA contrast, light/dark parity, reduced-motion parity, keyboard — runs under npm test on every change: 193 AA pairs verified in CI. And theming is a contract too: swap the skin — down to glass — without touching structure.
no layer pretends — theming is a contract (theme.contract.json), live.
Those buttons swap this entire page, not just the card — the real skins from the theme-swap proof: same structure, same pieces, only tokens change. That's theming as a contract.
milpa applied to itself
A component, a plugin, a theme — every piece declares what it exposes and what it demands, in a machine-readable spec. A human or an agent can assemble the system knowing exactly what's there, without guessing.
{ "name": "button", "layer": "primitive", "class": "mui-btn", "states": { "loading": "[aria-busy=\"true\"] — ::before spinner; the text stays visible", "disabled": "[disabled] — state is styled via ARIA attributes, never classes" }, "a11y": { "contrast": "every pair verified in npm test" }, "motion": { "reducedMotion": "global contract — nothing moves against the user" }}{ "name": "acme/mail-plugin", "version": "2.1.0", "namespace": "Acme\\MailPlugin", "entrypoint": "MailPlugin.php", "contracts": { "provides": ["mail"], "requires": ["database"] }}// providers load before consumers — Kahn's algorithm, the graph must be acyclic{ "requiredTokens": { "color": ["--bg", "--surface", "--accent", "…"] }, "contrast": { "pairs": "193 WCAG AA pairs — dark and light" }, "invariants": [ "reduced-motion parity — nothing moves against the user", "--bg must be opaque (the composition reference)" ]}
Drift fails CI. A theme is validated before it ships — the gate even composes translucent surfaces over
--bg and measures the effective contrast. Nothing is sown without a
contract; not even a skin.
the root
I don't know computers — but I do know cars. If you buy one, it's worth learning how to fix it.
He was the first in his region to bet on mango where everyone sowed sorghum. I planted the first grafts myself, at twelve, with a coa — the planting stick: hard rootstock below to hold more fruit, the bearing branch grafted above. Years later, time proved him right — twenty hectares of ataulfo and tommy mangos.
That's this framework, if you look at it right. A deterministic root that holds. Modules grafted on top that bear the fruit. A CLI named after the tool that sowed the real thing. And his lesson as the contract under it all: what's yours, you should be able to understand and repair.
Milpa doesn't promise to save you from thinking; it promises to teach you to think while you build.
He never saw this framework. The field it grows from is his.
— Rodrigo Vicente · creator of Milpa
the first sowing
A modular PHP core, event-driven modules, contracts at the root — published on Packagist, Apache-2.0. Pre-1.0 and honest about it: the field is planted, and it grows in the open.
$ composer create-project milpa/skeleton my-app
$ coa siembra mail-module · coming soon