How to approach an unknown system
The repeatable protocol an agent follows to build a hub for a system it does not control: decide the bounds, collect with provenance, classify onto the spine, deduplicate before importing, write the front matter and the boot head, dry run until nothing is refused, then measure with a test run and let the findings change the hub.
markdownguidev1320P-R93Yarea: methodaudience: agentaudience: maintainerprotocolunknown-systemcollectionprovenancededuplicationbootmeasurement
How to approach an unknown system
An agent meets a system it has never seen and does not control: a vendor's product, a cloud provider's service family, a repository somebody else maintains. The documentation exists, somewhere, in some shape. The goal is not to read it — it is to turn it into a hub the next agent can boot from in one call, so that the reading is done once and the learning is kept.
This is the protocol for that, drafted from the one case that has been carried end to end (cuppy's own hub, built and then tested by a client agent) and one corpus measured in full but not yet imported (a vendor documentation set of 4,620 files). Where a step rests on one of those two cases it says so; where it rests on neither it is marked as a proposal. The next case that will test it is a project hub for a cloud provider's services, chartered and currently held.
Step 0. Decide the bounds before you collect anything
Four questions, and all four have to be answered in writing before the first fetch.
- What may you read? Public documentation only, unless someone with standing says
otherwise. Record the terms under which the material may be reused; the hub's own content licence must be declared before anything is made public, and a vendor's crawled pages carry the vendor's terms rather than the hub's.
- What may you act on? Nothing. A documentation hub documents and never acts: it
holds no credential of the system it describes, and an operation document carries a placeholder where a secret would go.
- Where does the material land? A scratch area you own. Not the hub, not a shared
tree, and never a production store.
- What proves a claim? Name the evidence class for each kind of fact up front — a
fetched page, a vendor artifact, an executed attempt — because the freshness tier you may store is decided by that and not by your confidence.
Step 1. Collect, and record every origin as you go
For every file: its origin URL, the time you fetched it, and the licence or terms it came under, written into a source manifest beside the material. Not afterwards from memory — afterwards is when provenance gets invented.
Two things to resist. Do not reshape a vendor's tree while collecting: the vendor's own documentation cites those paths, and a mirror you rewrote is a mirror you cannot maintain. And do not drop the raw material you will not import — screenshots, exports, archives — but keep it in a holding area that is stored and never indexed.
A measured caution about what a corpus already carries. In the vendor corpus
measured in tracking/updates/2026-10-15-set-065-semarchy-hub-migration.md, provenance
was already present on nearly everything: 384 of a 400-file sample carried a front-matter
fence with a title, a source URL, a hosting type, a source path and a content hash, and a
source path was present on 1,513 of 1,525 distinct pages. Check before you author
provenance; a crawler may have done it better than you will.
Step 2. Classify onto the spine
The spine is fixed and the leaves are the source's own
(reference/standard/hub-standard.md section 1). In practice, for a vendor corpus:
- vendor prose mounts under
reference/official/<name>/in its native tree; - anything runnable goes under
examples/, each with a manifest naming the version it
builds against;
- an API or server description is an
interfacedocument, stored verbatim; - every error message you meet on the way is an
errordocument, and these are the most
valuable documents you will write;
- recurring procedures become
guides/, one per intent, each step naming its next read; - raw material goes to the holding area.
Classify a facet per document, never per folder. The temptation is to label a whole lane — "this lane is the self-hosted one" — and it was measured wrong: a per-lane deployment rule would have mislabelled 1,882 of the 4,350 files in six lanes of that corpus, because only one lane was uniform and every other was a near-even split. Each file carried its own key; the per-file reading was available the whole time.
And check how much of the corpus is actually lane-specific before you build a layout around lanes. In the same corpus, of 1,525 distinct pages only 81 appeared in a single lane: 505 in two, 589 in three, 265 in four, 74 in five, 11 in all six. A layout that folders by lane buys almost nothing there, which is why the native-tree rule exists.
Step 3. Deduplicate and reduce, before you import anything
This is the step that decides whether the hub is usable, and it is arithmetic rather than judgement. The worked example, every figure from the record above with the command that produced it named there:
| reduction | measurement |
|---|---|
| the corpus as found | 4,620 markdown files, 59,040,366 bytes |
| six whole-lane rollup files | 28,194,051 bytes — 47.8 percent of all markdown bytes — each matching its lane's other files to within 0.1 percent, and refused on its underscore name in any case |
| the remainder, hashed | 4,613 files, 1,755 distinct content hashes, so 2,858 duplicate copies: 61.9 percent |
| what is importable | 1,755 documents, 10,219,330 bytes |
| against the import bounds | 1,755 under the 2,000-file bound and 10,219,330 under the 50 MiB bound, so one import and no settings change |
Read what that does: two mechanical reductions turned 59 MB into 10.2 MB and 4,620 files into 1,755 documents, without a judgement about content. A rollup file that concatenates a lane is not a document; it is the lane again, and it would be indexed, ranked, retrieved and budgeted beside its own parts.
The figures above are a measurement, not an import. That corpus has never been imported: there is no document count, folder count, duration or fixpoint figure for it, and none is claimed here. The import-side figures in this guide all come from cuppy's own hub, which is small.
One consequence for the boot document: a catalog estimate reasoned from the corpus as found is conservative by roughly 2.6 times once the duplicates and the rollups are recognised, which is the error the specification's own boot arithmetic makes.
Step 4. Write front matter, then write the least prose you can
Every file gets role, shape, summary, status, and covers and facets where you
actually know them. Freshness is asserted unless the origin makes it stronger, and you
may not claim stronger — only an executed attempt or a vendor artifact raises a tier.
Leave a field absent rather than inventing it. Front matter is derived from structure
and never from content, only where it is absent, and every derived field is reported back
to you per entry — so an absent covers costs you nothing and a covers term nobody
meant costs you a ranking signal that is wrong.
The prose you add yourself is the thin layer the vendor cannot write: what to read first, what breaks, what a message really means, and which document answers which intent.
Step 5. Write the boot head by hand; let the body be generated
Three hand-written sections and no more: what this hub is, the rules that always apply (twenty at most), and how to use the tool for this subject. The routes, the catalog, the ranked documents and the freshness summary are generated on every publish and are never hand-edited.
Budget it against what can actually be stored, not against the nominal cap: a boot
document above the ingest split cap is split into parts, and a tail part measures as all
hand-written head and is refused, so the generated body binds to the smaller of the two
caps today (reference/standard/hub-standard.md section 7).
Step 6. Validate, dry run, fix refusals, import, reach a fixpoint
Validate what you can locally — schema per shape, reserved paths, the boot budgets, no credential-shaped string — then dry run against the hub. The dry run performs every write the real run would and rolls it back, so its report is the real answer discarded.
Fix every refusal. A refusal from a platform floor is the control working: when this hub's own bundle was first prepared, one file was refused because an address appeared in it, and the file was dropped from the bundle rather than the floor relaxed.
Then import, and re-run the import. The evidence that a bootstrap is repeatable is a
fixpoint: the second run of this hub's own bundle reported 0 created, 0 changed, 10
unchanged, 0 refused, with the boot document unchanged and its hand-written head
preserved (docs/commander/RUNS/2026-10-14-private-rehearsal.md). A bootstrap that
cannot be re-run is a bootstrap you can never schedule.
Two caveats from that same run, both worth expecting: the import needs the maintainer rung, one above a document write's floor; and the dry run's catalog digest is not comparable with the real run's, because it mints the ids the catalog names and then rolls them back.
Three things the platform does not do for you today, each recorded: nothing generates
the folder card or the source manifest and the path rule refuses their underscore names;
the never-indexed flag on a holding folder has no writer, so a raw/ folder imported
today is indexed and budgeted; and the validator command line the collection workflow
names does not exist in the tree — the dry run is the validator in practice.
Step 7. Measure with a client agent that has never seen it
Do not grade your own hub. Launch a client agent with a test prompt and nothing else, let
it self-identify with a run label, score its report against a sheet it never saw, and
read the outcome from the server's rows rather than from the report
(guides/test-loop.md).
What the first such run of this hub returned, as the shape of the answer to expect: every required row matched, no prohibited row fired, 9 server rows for the run's calls, 12 documents served, 260k tokens over 25 minutes — and the single most useful sentence in the whole report was the agent's own worst moment, which named a tool whose answers came from a corpus nobody had told it about.
Step 8. Loop, and change the content rather than the build
The run's findings are filed, not fixed in the run. Change the hub's content or its structure, record the change in the loop's own log, and run again with the next ordinal. The build changes only when something is broken.
That is the cycle that makes the hub an asset: each run costs one agent and produces both a measurement and a list of content defects, and the hub's own documents are what moved between two runs.
What in this guide is a proposal
Said plainly, so a later reader does not inherit this as settled method:
- The protocol itself is drafted from one completed case and one measured corpus. It
has not yet been run end to end on a system nobody here controls.
- Steps 1 and 2 are the collection workflow's own steps, which are specified and
have been followed once, for a corpus of ten files.
- Step 3's reductions are measured on a real corpus and the arithmetic is real, but
no import has run on it, so the cost of importing 1,755 documents is unmeasured.
- Step 7's figures are one run of one small hub. Twenty documents is not a scale
test, and the per-step measurement contract that would make two runs comparable has no run behind it yet.
- The next case is named: a project hub for the cloud-provider services in use, with
full document and workflow coverage, chartered as a later sprint and currently held by the owner until the earlier work has been reviewed. When it runs, the figures it produces replace the proposals above.
Next reads
guides/bootstrap-a-hub.md— the collection and import workflow, step by step.reference/standard/hub-standard.md— the spine, the contract, the budgets.guides/test-loop.md— the measurement in step 7, in full.guides/skill-packs.md— what to compile once the hub has a workflow worth repeating.