6.3 KiB
RFC: Documentation graph atlas for maintainers and SDK users
Status: implemented (accepted 2026-07-03)
Context
The repo already had several high-trust documentation surfaces, each on a different axis: module-graph.md is generated from package peerDependencies, cordis-catalog/events-and-services.md is generated from Cordis Events and Context declarations, tool-catalog/tools.md is generated by booting shipped tool plugins, and core-data-structures/ uses ts type-equiv blocks to keep pasted type definitions synchronized with source.
Those references are accurate, but they are mostly catalogs. A maintainer still has to synthesize the relationships: which packages form a capability seam, which app bundles a concrete spine, which event is durable vs live, where a hook or policy plugin can intercept work, and which model-facing tool depends on which service. An SDK user has the same problem from another angle: "Which package do I install or load for the behavior I want, and which event/service/tool do I extend?"
The pressure is already visible in the open stacks even though this implementation is based on origin/master: the hooks stack through PR #129 makes event producer/consumer topology and interception points much more important, while the filesystem stack through PR #128 makes capability seams, policy vetoes, tool presentation, and SDK assembly paths much more important. Graphs based only on today's small bash/todo/subagent surface would become obsolete as soon as those stacks land.
Decision
Add a generated graph atlas under docs/graphs/, produced by scripts/gen-doc-graphs.ts and verified by pnpm run verify-doc-graphs as part of doc-sync.
The atlas is a relationship layer above the existing catalogs. It does not replace exact references; instead, it links to them and explains how their pieces fit together.
Maintenance modes
Every graph page declares one maintenance mode:
- Generated: all nodes and edges are discovered from source;
--checkfails if the committed artifact is stale. - Hybrid generated: source discovers the inventory, a small manifest classifies irreducible policy, and a completeness guard fails if discovered items are unclassified.
- Curated: the diagram explains design intent, temporal order, or ownership; it is emitted by the generator so the atlas remains a single regenerated unit, but the content is deliberately authored.
First shipped atlas
The first atlas ships twelve files: the index plus eleven graph pages.
| Graph | Maintenance mode | Source of truth |
|---|---|---|
| package topology by group | generated | packages/*/*/package.json peer dependencies plus package group paths |
| capability seams and core services | hybrid generated | Cordis service declarations plus a role manifest in gen-doc-graphs.ts |
| app composition | hybrid generated | examples/*/cordis.yml plugin lists plus curated app/bundle expansions |
| event producer/consumer matrix | hybrid generated | Cordis event declarations, AST-scanned ctx.on/emit/parallel/serial/waterfall sites, and explicit dynamic dispatch overrides |
| tool affordance map | hybrid generated | boot-harvested tool catalog plus a manifest of required services and shipped aliases |
| agent turn and step lifecycle | curated | architecture.md loop lifecycle, Cordis catalog links, and session event semantics |
| tool execution pipeline | curated | tool pipeline semantics and the tools/execute waterfall |
| session surface and message projection | curated | session surface/event-sourcing docs |
| subagent and session lineage | curated | subagent seam docs and replay/fork semantics |
| plugin disposal and hot reload ownership | curated | Cordis fiber/effect ownership conventions |
| ACP snapshot replay | curated | snapshot harness behavior |
Why one generator
Keeping the atlas behind one generator gives reviewers one freshness gate and keeps cross-page terminology synchronized. The tradeoff is that curated diagrams are edited in TypeScript string blocks rather than directly in Markdown. That is acceptable for this first cut because the user-facing artifact is still plain Markdown/Mermaid, and a future change can split the curated pages out if authorship ergonomics matter more than one-command regeneration.
Completeness guards
The hybrid pages must fail loud when their manifests are stale:
- The capability seam graph imports the Cordis service collector and asserts every discovered harness
ctx.<key>is classified inSERVICE_ROLES, and every classified key still exists. - The tool affordance graph boot-harvests the shipped tool catalog and asserts every tool package has
TOOL_PACKAGE_META. - The event producer/consumer matrix labels itself hybrid because subagent lifecycle events deliberately use
ctx.events.dispatchfor per-listener containment; those dynamic edges are explicit overrides rather than invisible omissions.
Format choices
Use Mermaid for committed diagrams because GitHub renders it in Markdown and it adds no new docs build dependency. Use Markdown tables for dense many-to-many data such as event producer/consumer relationships. Do not adopt PlantUML, hosted diagram services, or generated SVGs until Mermaid becomes the limiting factor.
Consequences
- Maintainers get visual entry points for topology, seams, event flow, lifecycle, session replay, and snapshot behavior.
- SDK users get a path from use case to package composition instead of only bottom-up package references.
doc-syncnow includesverify-doc-graphs, so graph drift is caught with the other doc freshness gates.- Future fs and hooks work has a concrete place to land new complexity: fs should expand the capability and tool graphs, while hooks should expand the event matrix and tool execution pipeline.