The cuppy hub standard
How a hub is laid out and how a document declares itself: the folder spine, the front-matter contract per shape, ids and paths, visibility, provenance, the next read, the boot document and its budgets, and the order an agent reads in.
markdownreferencev1SWMJ-MF8Warea: standardaudience: agentaudience: maintainerhub-standardspinefront-mattershapesshort-idsvisibilitybootreading-order
The cuppy hub standard
This is the standard a hub on this platform is built to. It is normative for cuppy's
own hub, which is the hub you are reading it in, and it is the source of the document
half of the open standard (reference/standard/open-standard.md).
Three things it is not. It is not the product: the tool surface, the command registry and the settings registry are versioned with the platform and are not standardised. It is not a description of what is built today: where the build and this standard disagree, the paragraph says so and names the record. And it is not a style guide; it says where a document goes and what it must declare, never how to write prose.
Every figure below is read from the specification revision 24 named in this document's front matter, or from the code or a record named at the figure; where a number is a reading rather than a spec statement, the sentence says which.
1. The spine, and what each folder holds
A hub has one spine every hub shares, and any number of sources whose internal layout it does not dictate (AE1). The spine is fixed because the boot call, the routes generator, the catalog and the bundle composer read it by name.
| folder | what it holds |
|---|---|
HUB.md | the hub's own root card: what this hub is, its facets, where an agent starts |
_boot/ | the first read, sorted first: START.md, the always-active rules, the generated routes, one agent document per role under personas/ |
guides/ | task workflows, one per intent, each step naming its next read |
reference/ | facts, by domain and object; the inheritable truth. reference/official/ holds a vendor's own documentation per release, reference/entities/<type>/ holds dossiers |
examples/ | projects, each with a manifest naming the version it builds on |
templates/ | stubs and scaffolds |
patterns/ | known-good and known-bad; a promoted learned pattern lands here |
notes/ | the platform's view of field notes by path and context |
decisions/ | the platform's view of structuring assumptions and the decision log |
changelog/ | hub release notes and upstream-changed summaries per version |
raw/ | mirrors, exports, screenshots: stored, never indexed, never budgeted |
Four rules make the spine work.
- Layers fill, never fork. A child layer adds its own
guides/,reference/
overrides, examples/ and notes/. It never copies reference/official/.
- A source keeps its native tree. A mirrored repository, an uploaded bundle or a
crawl mounts under one spine folder with its own layout untouched, because the vendor's own documentation cites those paths.
- Underscore means read first, and the platform owns the name (D87).
_boot/is
the only underscore folder on the spine. _index.md is the generated folder card
and _source.md the generated source manifest.
raw/is a holding area, not content. Importers read from it; retrieval never
does.
Two of those rules are not yet enforced by the build, and both are recorded in
tracking/updates/2026-10-15-set-065-semarchy-hub-migration.md. Nothing generates
_index.md or _source.md, and the write path refuses an underscore-prefixed file
name, so neither card can be authored either (finding 4). folders.settings.indexed
has no writer anywhere in the API source while the folder scope function honours it, so
a raw/ folder imported today is indexed, retrieved and budgeted (finding 3). Treat
both as owed work, not as properties you can rely on.
2. The front-matter contract
Every document is a markdown file with YAML front matter and a body. Two fields
classify it and they are independent (AB1): role is where the document sits in
the boot ladder and answers when an agent reads this; shape is how the body is
built and answers what an agent does with it.
role is one of five: boot, guide, reference, example, pattern. shape is
one of seven and defaults to markdown. Both vocabularies are read from
apps/api/src/shapes/markdown.ts, which is the authority the validator uses.
The common fields
| field | required | what it is |
|---|---|---|
role | yes | one of the five above. kind is accepted as an alias until Phase 4 |
shape | defaults to markdown | one of the seven below |
summary | yes | the whole payload of a lite card, so write it for a reader deciding whether to load. Capped at 500 characters by the validator, which is a reading rather than a spec number |
status | yes | draft, review, published or deprecated |
covers[] | defaults to empty | the terms this document covers; a ranking signal, so a term nobody meant is worse than none |
facets{} | defaults to empty | context keys whose values are a string or a list of strings, never a number |
depends_on[] | defaults to empty | the stack this document needs, each entry a short id or a UUID and never a path |
short_id | minted | assigned by the platform at creation; absent on a first write and present on every stored row |
freshness | stored | the tier and its verifier. An authored write may claim asserted and nothing stronger |
token_estimate | computed | computed on write, accepted on input and recomputed |
A hub may carry its own extra keys: the validator preserves unknown fields. What it
refuses by name is a key that belongs to another shape, because a document declaring
shape: markdown while carrying an operation's request block is mis-shaped rather
than merely decorated.
The seven shapes
| shape | the question it answers | body |
|---|---|---|
markdown | what does it say | free text |
operation | how do I call this | a request template, its parameters, constraints, a cost model, the success and error responses |
interface | what does this API or server accept | the vendor's own OpenAPI, Swagger or MCP manifest, preserved verbatim |
dataset | what does this data look like | a manifest, a few real rows per file, keys, joins, a source link |
workflow | what do I do, in what order | ordered steps, each naming its documents at a depth and the outcome that proves it |
error | what does this message mean and what fixes it | signatures, what it appears to say, each cause with a diagnostic, each fix with its kind and evidence |
agent | what should this role read, run and avoid here | the role, its boot stack, its workflows and packs, its routing and its observed limits |
A dossier is not an eighth shape: an entity dossier is role: reference,
shape: markdown with an entity: block the markdown validator checks when it is
present (D101, Part AG). Dossiers are a later feature of this standard and no document
in this hub is one yet.
Two consequences of the shape split bite authors. An operation never carries a
resolved credential: its request template carries a placeholder, the agent supplies its
own, and the platform never executes the call. And an interface body is stored rather
than re-authored, so authority stays with the vendor and an operation cites it
instead of restating it.
3. Ids and paths
The short id is the permanent address. Every document and every folder carries one:
eight characters of Crockford base32 in NNNN-NNNN form, with no I, L, O or U
so it can be read aloud and typed from a screen. It is minted at creation, at random,
and is unique within its hub and against every ancestor visible at mint time. A
rename or a move does not change it; a path does not survive either. Cite the short id.
Two consequences for anything written down. A depends_on[] entry is a pointer, so it
is a short id or a UUID and the validator refuses a path there. And a short id is
per hub: the ids minted for this hub's documents are not the ids another hub mints
for the same bytes, so a record quoting one must name the hub and the run it came from.
A dry run's ids never exist at all, because it mints them inside the transaction it
rolls back (docs/commander/RUNS/2026-10-14-private-rehearsal.md, finding F7).
Paths are validated at the edge: a folder label is drawn from a restricted
alphabet, the tree is bounded by tree.max_depth (12) and tree.max_nodes (500, then
a cursor), and scope is resolved as a subtree by one function before anything else
runs, so no caller composes the predicate.
4. Visibility
Visibility is a property of a folder and of a document, not only of a hub (D98,
specification revision 24). folders.settings.visibility and
documents.visibility_override each take inherit (the default), public,
unlisted, private or paid:<plan>, and the effective value is computed down the
folder path by the same propagation that maintains folder cards.
Three rules carry the weight. A child may always be more restrictive than its
ancestors with no permission beyond the write. A child may be less restrictive only
by an owner, only while the hub's widening flag is on (default off), and the widening
is audited. And paid:<plan> never hides: the lite card is always served with
an upgrade hint, and only the body requires the plan.
Build state. This is specification revision 24 and nothing more: no
effective_visibility appears anywhere in the API source or in the migrations, read by
grep over apps/api/src and apps/api/migrations at the base commit this document was
written on. Write to the rules above; do not assume a document in this hub is gated by
them today.
5. Provenance and freshness
Freshness is the strongest evidence the hub holds for a claim, and it decays (AD2).
Four tiers, strongest first: probed (an attempt executed the operation and observed
the result), sourced (a vendor artifact with provenance), crawled (a vendor page
with a URL and a fetch time), asserted (written by a person or an agent without a
source).
An authored write stores asserted and may not claim better. A front matter
carrying a stronger tier is refused with the field named; one carrying a verifier field
has it dropped and the drop reported. A new version re-asserts, because the content that
was verified is gone. Only an attempt or a vendor artifact raises a tier, which is what
makes the tier mean anything.
Provenance in the authored sense — who wrote this, and from what — belongs in front
matter. The documents in this hub's reference/standard/ and guides/ folders carry a
provenance block naming the specification revision and the records their claims are
derived from, so a reader can check a figure without trusting the sentence quoting it.
6. How a document names its next read
Drilldown is the ladder (N3). _boot/START.md names a persona; the persona names a
guide; the guide names its reference and example documents. Each hop is one small read
that names the next one, and the validator warns when a boot or guide document
names none.
Name the next read by short id where you can, since an id survives every rename; by a markdown link for a reader navigating by hand; by path where the ids do not exist yet. A bundle prepared outside the hub has only the third available, which is why the pointers in these standard documents are paths.
A workflow document is the strong form of the same thing: each step names the
documents it needs and the depth it needs them at, plus the observable outcome that
proves the step is done. That is what the pack compiler reads, and it is why a workflow
is the only document that can be compiled.
7. The boot document, and the three tiers
The first boot is three tiers, each with its own cap (AF7):
| tier | when | cap |
|---|---|---|
_hello {intent} | the first call: a banner, an opener, three to seven routes chosen for the intent, a pointer to _boot/. Reads no hub content and mints nothing | boot.hello_max_tokens 400 |
session start {format: visual} | once per session, on request: the readiness screen, the routes, the system map, the role and plan, the session handle | boot.visual_max_tokens 1,200 |
_boot/START.md | when the persona's boot stack names it, or the agent asks | boot.max_tokens 20,000 |
START.md is a hand-written head and a generated body (AF8), split by one marker
line. Everything before the marker is the author's and no generator touches a byte of
it; everything from the marker on is the generator's and is rewritten whole on every
publish. One marker, not two: a generator writing between two markers would have to
parse the author's text to find its slot.
The reading order is: what this hub is; the rules that always apply; how to use the tool; then the generated sections — how the surface works, the routes, the catalog, the top documents by signal, the known-issues head and the freshness summary, and where to go for everything else. The physical order differs, because one marker cannot interleave: the three hand-written sections, then the marker, then the six generated.
The budgets, and where each is measured. The hand-written budget
(boot.handwritten_max_tokens, 4,000) is measured over the bytes before the marker;
the whole-file budget (boot.max_tokens, 20,000) over head and tail together. Both are
enforced identically on an authored write and on an import, because an oversized agent
entry that installed cleanly through an import is paid for by every later session.
The 20,000 is not reachable today, and the interim is smaller. A _boot/ document
above embed.max_tokens (6,000) is split into parts at ingest, and a tail part carries
no marker, so it measures as all head and is refused above the hand-written cap. The
interim in force binds the generated body to the smaller of the two caps; the four
candidate answers are in the specification at AF8 and the question is the owner's open
decision D-5. Budget a boot catalog against the ingest cap, not against the 20,000.
The catalog is tiered, because a full file-level catalog does not fit a real hub: every folder card first, then file lines ordered by the persona's workflows and the decayed signals until the cap, with the depth reached and the listed-over-total counts on the version line. The full catalog is one call away. The generated body is deterministic — no wall clock, every list ordered by a stable key, and a catalog digest over the ordered id-and-version pairs rather than over the rendered text — so two runs over an unchanged hub produce identical bytes and a cached copy is detectably stale.
8. What to read first, and in what order
_hellowith your intent: one call, the routes for that intent, a pointer to
_boot/.
_boot/START.md— the head, then the routes and the catalog. Everything else in the
hub is reachable from there.
- The persona document for your role, if the hub has one, then the workflow it names.
- The documents the workflow names, at the depth it pins. Ask for
liteto decide
whether to load, normal to do the work, verbose to learn why something keeps
failing. Nothing you ask for is truncated; the envelope states the cost first.
- When you hold an error, read the error documents before you search: the error call
answers from the signatures and names what is nearest when nothing matches exactly.
And report what happened. One outcome call is the only way the hub learns which document was right, and the ranking the next agent gets is built from it.
Next reads
reference/standard/open-standard.md— the three artifact specs, what is normative,
and how a product other than cuppy implements them.
guides/connect-a-client.md— how to connect to this hub from each client, with deep
links.
guides/bootstrap-a-hub.md— the workflow that builds a hub from public
documentation; this hub is its worked example.
guides/approach-an-unknown-system.md— the generic protocol for a system you do
not control.
reference/cuppy/served-surface.md— the surface itself, generated from the registry
the deployment dispatches on: the tools, the command rows, the universal parameters and
the refusals. reference/cuppy/mcp-architecture.md is the design blueprint beside it —
the roadmap, not the build.