6.6 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. verify-mermaidparses every repo-authored```mermaidfence with Mermaid's own parser, so syntax errors faildoc-synclocally and in CI instead of showing up as broken GitHub-rendered diagrams.
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-graphsandverify-mermaid, so graph drift and Mermaid syntax errors are 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.