Skip to content

Put the guide where the agent actually looks: miakapp agent-pack - #14

Merged
Mathieu2301 merged 1 commit into
mathieu/agent-mcpfrom
mathieu/agent-pack
Sep 14, 2026
Merged

Mathieu2301 merged 1 commit into
mathieu/agent-mcpfrom
mathieu/agent-pack

Conversation

@Mathieu2301

Copy link
Copy Markdown
Member

Atelier F, livrable 1 — installable pack for Codex and Claude Code. Stacked on #13; base is mathieu/agent-mcp, not main.

The gap this closes

We built the guide (#11), the discovery command (#12) and the MCP server (#13). None of them is where a coding agent actually looks. An agent handed someone's house opens the owner's repository and reads AGENTS.md or CLAUDE.md — and finds whatever the owner wrote there, which is not our guide. The exit gate for this workshop says a fresh agent should get to a working component "without undocumented human intervention". Until now the undocumented intervention was: a human tells the agent this repository exists.

What miakapp agent-pack writes

File Why
.miakapp/agent-guide.md the full guide, copied out of the package — readable offline, no stale bookmark
AGENTS.md the instruction file Codex reads
CLAUDE.md the instruction file Claude Code reads
.mcp.json project-scope MCP config registering miakapp mcp

It reports an action per file (created / updated / unchanged) rather than one summary line, because "I installed the pack" is not the same claim as "I replaced your AGENTS.md".

The repository is the owner's

The CLI already refuses to rewrite what it did not generate — nodeFileSystem.write opens with wx. That invariant is what shaped every merge here rather than something this command had to work around:

  • the guide is a file the command owns outright, so it is replaced freely;
  • the instruction files are edited only between <!-- miakapp:begin --> and <!-- miakapp:end -->. Prose above and below is copied through byte for byte; the block is appended at the end on first run, because the top of an instruction file is where the owner put what matters to them; a second run rewrites the block in place instead of stacking another copy. An unterminated marker is refused rather than guessed at;
  • .mcp.json is merged as a structure, one key by name. Every other server survives. A file that does not parse is refused — an owner who hand-edited it into a syntax error still wants their edit back, not a valid file where theirs used to be.

FileSystem gains replace and makeDirectory. replace is deliberately a separate method from write: overwriting stays something a command asks for by name, never something it falls into.

The server is registered as the bare miakapp command, not an absolute path. The file is committed, and the next machine to check it out will not have this one's directory layout.

Drift is a red test, not a surprise

The guide ships as packages/cli/assets/agent-guide.md and files now includes assets. A test asserts it is byte-equal to docs/agent-guide.md. Editing the doc without copying it across fails the suite — I confirmed that by editing the doc first and watching it go red, then copying. A pack that teaches an agent rules the CLI no longer has is worse than no pack.

The command is also a tool, miakapp_agent_pack, because #13's every command except help, version and mcp itself is a tool test does not let it be anything else. That test doing its job unprompted is the design working.

Verified against the built binary

Not only through injected tests:

  • installed into a scratch repository that already had its own AGENTS.md and an .mcp.json holding a sentry server: the owner's prose stayed on top, sentry survived, the block was appended;
  • claude mcp get miakapp in that repository reads the generated entry back — Scope: Project config (shared via .mcp.json), type stdio, command miakapp, args mcp. The consuming client parses what we wrote; that is not my assertion about the format, it is the client's;
  • a second run reported all four files unchanged;
  • miakapp_agent_pack installed a pack over real MCP stdio (initializenotifications/initializedtools/call), isError: false;
  • npm pack --dry-run lists assets/agent-guide.md in the tarball.

bun run check 301 pass / 0 fail / exit 0. bun run check:packages exit 0 — CLI 113 (was 93), component 38, template 8. No dependency added.

What I did not do

Codex MCP wiring is not written by this command. AGENTS.md is Codex's instruction file and the pack writes it, but Codex's own MCP configuration format could not be verified in this environment — no codex binary, no local config, no network. .mcp.json was verified by running the client that consumes it. I would rather ship the half I proved than emit a TOML file in a schema I guessed at; the .mcp.json entry and miakapp mcp are enough for a Codex user to wire it with their client's own tooling. Worth closing when someone can check it against a real Codex install.

Stack

Fifth level, and nothing below is merged: #10#11#12#13 → this. Flagging it rather than adding quietly. The value of all five arrives when the stack comes down, starting at #10.

The toolchain, the guide and the contract all existed, and none of them
were where a coding agent actually looks. An agent opening the owner's
home repository reads AGENTS.md or CLAUDE.md, and finds whatever the
owner wrote there — which is not this.

`miakapp agent-pack` puts the knowledge in the repository: the guide as
a file under .miakapp/, a pointer to it in both instruction files, and
the MCP server registered in .mcp.json so the tools are wired rather
than described.

The CLI's rule that it never rewrites what it did not generate is what
shapes every merge. The guide is a file the command owns outright. The
instruction files are edited only between markers it wrote, so prose
above and below survives byte for byte and a second run rewrites the
block in place instead of stacking another copy. .mcp.json is merged as
a structure, one key by name: every other server survives, and a file
that does not parse is refused rather than replaced with a valid one.
Two new FileSystem methods carry this — `replace` is deliberately
separate from `write`, so overwriting stays something a command asks
for rather than something it falls into.

The guide ships as a package asset, and a test asserts it is byte-equal
to docs/agent-guide.md. Editing the doc without copying it across is a
red test, not a pack that teaches an agent rules the CLI no longer has.

Verified against the built binary, not only through injected tests: the
pack installed into a repository with its own AGENTS.md and its own
.mcp.json kept both, `claude mcp get miakapp` reads the generated entry
back as a project-scope stdio server, a second run reported every file
unchanged, and miakapp_agent_pack installed a pack over real MCP stdio.
@Mathieu2301

Copy link
Copy Markdown
Member Author

Répétition de la porte de sortie de l'atelier F — elle ne tient pas encore

J'ai joué la porte de sortie de l'atelier F contre le binaire construit depuis l'union locale de main + #10#14, dans un dépôt propriétaire neuf, sans jamais lire MiakAPI — la position exacte d'un agent frais. L'union se fabrique proprement : les cinq branches fusionnent sans conflit sur main, bun run check 301 pass / 0 fail et bun run check:packages sortent à 0 (CLI 113, component 38, template 8).

Les trois premières étapes sont solides :

Étape Résultat
miakapp agent-pack ✅ 4 fichiers créés
miakapp discover --flows … ✅ inventaire juste, 6 constats dont 3 critiques
miakapp init --home … --control-plane … miakapp.yaml écrit
miakapp check No artifact at dist/component.js
obtenir les sources du composant ❌ impasse

L'export de test est volontairement dérivé du producteur : chaque nom de champ vient de miakapi.html du paquet node-red-contrib-MiakAPI, pas de test/support/flows.ts. Sinon on teste le parseur contre lui-même. discover s'en sort très bien sur une maison qu'il n'avait jamais vue — secret en clair, deux actions sans groupe dont une serrure, joker d'abonnement, broker sans TLS, 5 types non modélisés comptés.

L'impasse : une cause racine, trois manifestations

L'agent frais arrive à check, découvre qu'il lui faut un artefact, ouvre le guide pour savoir comment en produire un — et tout ce que le guide lui donne sort du dépôt.

  1. Le guide installé pointe hors du dépôt. agent-pack copie un seul fichier, et ce fichier dit « Start from templates/home », puis renvoie à packages/cli/README.md, templates/home/README.md, docs/rfcs/0001..0005, component-runtime/src/runtime-broker.ts. Vérifié dans le dépôt propriétaire : les quatre chemins sont absents.
  2. Les paquets ne sont pas distribuables. templates/home/README.md prescrit bun add miakapi @miakapp/component et bun add -d @miakapp/cli. Or @miakapp/component et @miakapp/cli sont private: true et renvoient 404 sur npm.
  3. Pire que 404 : npm view miakapi version3.0.31. C'est la V3. Le SDK V4 d'ici est 4.0.0-alpha.0, non publié. Un agent qui suit le README à la lettre installe silencieusement la V3 en croyant tenir la V4. Piège de version, pas erreur visible.

Corollaire pour cette PR précisément : le .mcp.json qu'écrit agent-pack lance "command": "miakapp", un binaire nu sur le PATH. Il suppose lui aussi @miakapp/cli publié et installé globalement. Même cause racine.

Aucune commande ne comble le trou : help n'offre ni new ni scaffold, et init n'écrit que le manifeste.

Ce que je n'ai pas retenu comme défaut

discover marque capteurs.salle de bain.humidite et l'action scene soirée legal_v4_name: true. J'ai cru à un bug, j'ai vérifié : RFC 0001 §5.2 autorise 1..256 octets UTF-8 sans caractère de contrôle ni *, sans point en tête/queue ni segment vide, comparés octet à octet. Espaces et accents sont légaux, isDottedName applique exactement la grammaire. Durcir au-delà de la RFC serait une dérive. Seule nuance : le guide §3 range name_needs_rename parmi les constats « qu'on découvrirait tard », ce qui laisse croire que les noms malcommodes sortiront ; ils ne sortent pas.

La décision n'est pas de mon ressort

Le trou se referme par une décision de distribution, pas par du code : publier @miakapp/cli et @miakapp/component, ou faire de agent-pack un amorçage qui dépose le template chez le propriétaire, ou assumer que l'atelier F ne ferme qu'après la première publication npm. Je n'ai donc rien poussé : tant que ce n'est pas tranché, la porte reste ouverte quoi qu'on ajoute au CLI.

Matériel et mode opératoire complet conservés hors dépôt, dans rehearsals/2026-09-14-atelier-f-gate/ de mon espace de travail (export synthétique + README reproductible).

@Mathieu2301
Mathieu2301 merged commit c2d45ab into mathieu/agent-mcp Sep 14, 2026
1 check passed
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