HOLONOGRAPH / The Guide · Surface topology scanner v0.23.0 all chapters

Chapter 09

Surface topology scanner

Reflects Holonograph v0.23.0 · ~8 min read

The scanner compares what you declared in your surface contract against what the lens actually observed in traffic, and returns the gaps: dimensions you promised the lens would see and it never did, dimensions the lens has been seeing that you never declared, and surfaces that look like they've gone quiet. There's also a bootstrap mode that reads recent traffic and proposes candidate dimensions to add to a new contract.

What it is

Three endpoints, each doing one job:

  • Structural inventory — you tell the scanner what your codebase says exists (surface ids you can enumerate, or a dispatch map). This becomes the third leg — alongside "declared on the contract" and "observed in traffic" — that the scan can reason about.
  • Scan — the scanner reads events over a window, joins them against the active contract and any recent structural inventory, and returns the coverage gaps as a set-difference across the three sources.
  • Bootstrap — when you have traffic against a surface but no contract entry yet, bootstrap reads the traffic and proposes dimensions to declare.

Why it matters

A contract that drifts away from reality is a contract that stops helping. Two ways it drifts:

  • A dimension gets added in code and the contract never gets updated. The lens sees it, the contract doesn't; downstream analyses skip it.
  • A dimension gets removed in code and the contract still declares it. Downstream analyses keep looking for it and quietly report it as always-null.

The scanner surfaces both directions at read time, so contract maintenance becomes a scheduled operator task with a concrete work-list, not an ad-hoc audit.

Three inputs, not two The scan is honest when it can compare against three inputs — declared (contract), observed (events), and enumerated (structural inventory). With two you can still find gaps; with three you can also tell a genuinely retired surface from a surface that just went quiet for a week.

How to use it

1. Declare a structural inventory

At startup, or on each deploy, tell the scanner what your codebase currently knows about. Two shapes are accepted:

  • surface-ids — a flat list of the surface ids your code can enumerate.
  • dispatch-map — a dispatch table mapping keys (intents, tools, or any other routing key) to surface ids.
POST /lens/topology/structural-inventory
x-holonograph-run-mode: production
Content-Type: application/json

{
  "agentId": "billing-triage",
  "consumerId": "billing-triage-agent",
  "inventoryKind": "surface-ids",
  "surfaceIds": ["classify-intent", "review-flagged-charge", "escalate-to-human"],
  "capturedAt": "2026-07-05T18:00:00Z"
}

Response:

{
  "inventoryId": "inv_01H...",
  "consumerId": "billing-triage-agent",
  "capturedAt": "2026-07-05T18:00:00Z",
  "created": true
}

2. Run a scan

A scan reads events over a window and returns a coverage report. Run it on a schedule (nightly, per deploy) or on-demand.

POST /lens/topology/scan
x-holonograph-run-mode: production
Content-Type: application/json

{
  "agentId": "billing-triage",
  "since": "2026-06-01T00:00:00Z",
  "until": "2026-07-05T00:00:00Z",
  "record": true
}

Set record: true to persist the scan result as an event of its own — useful for tracking how coverage changes over time.

3. Bootstrap a new surface's dimensions

When you're onboarding a new surface — traffic is flowing, but the contract entry is bare — bootstrap reads the traffic and proposes dimensions.

POST /lens/topology/bootstrap
x-holonograph-run-mode: production
Content-Type: application/json

{
  "surfaceId": "review-flagged-charge",
  "since": "2026-06-15T00:00:00Z",
  "until": "2026-07-05T00:00:00Z"
}

Each candidate comes back with an inference label:

  • deterministic — the dimension appeared consistently and with a stable shape across the window. Safe to declare.
  • lowConfidence — the dimension appeared, but sparsely or with an unstable shape. Worth reviewing before adding to the contract.

Reading the output

The scan report is a set-difference across three sources — the contract's declared, the events' observed, and (if you captured one) the code's structural inventory. The scanner returns per-surface lattices with these fields:

FieldWhat it tells you
declaredUnobservedDimensions on the contract that the lens has not seen in the window. Either they're broken in code, or the contract is stale.
observedUndeclaredDimensions the lens has seen that the contract does not declare. Add them to the contract or stop emitting them.
declaredUnstructuralDeclared on the contract but not present in the structural inventory. Strong retirement candidate — the code no longer references it.
structuralUnfiredPresent in the structural inventory but never observed. Wired but not exercised — possibly dead paths.
forwardDeclaredAbsentDeclared in the contract for a future rollout, not yet observed. Expected empty until the feature ships.
deprecatedAbsentMarked deprecated on the contract and no longer observed — a clean retirement completed.

Acting on the report

The usual cadence: a scan runs nightly, its report gets read by an operator, undeclared dimensions get added to the contract, retirement candidates get retired (see the supersededBy mechanism in Surface contracts). Over time, "clean scan" becomes the deploy readiness signal for contract changes.

Reference

Endpoints

Method & pathPurpose
POST /lens/topology/structural-inventoryDeclare what your codebase enumerates.
POST /lens/topology/scanCompare declared vs observed vs enumerated, return the coverage report.
POST /lens/topology/bootstrapPropose candidate dimensions for a surface based on recent traffic.

POST /lens/topology/structural-inventory — request

FieldShapeNotes
agentIdstring (req)The agent this inventory belongs to.
consumerIdstring (opt)Identifier of the code that's declaring the inventory (useful when multiple deployments feed one contract).
capturedAtISO 8601 (opt)When the inventory was taken. Defaults to now.
inventoryKindenum (req)surface-ids or dispatch-map.
surfaceIdsstring[] (opt)Required when inventoryKind = "surface-ids".
dispatchMapobject (opt)Required when inventoryKind = "dispatch-map".
artifactKindstring (opt)Freeform label for the source artifact (e.g. codegen, handwritten).

POST /lens/topology/scan — request

FieldShapeNotes
agentIdstring (opt)Restrict the scan to one agent. Omit to scan all.
sinceISO 8601 (opt)Inclusive lower bound on events considered.
untilISO 8601 (opt)Exclusive upper bound on events considered.
asOfISO 8601 (opt)Contract and inventory versions to compare against (defaults to latest).
recordboolean (opt)Persist the scan as an event.
artifactKindstring (opt)Restrict to inventories with this kind label.

POST /lens/topology/bootstrap — request

FieldShapeNotes
surfaceIdstring (req)The surface to propose candidates for.
sinceISO 8601 (opt)Inclusive lower bound on the traffic window.
untilISO 8601 (opt)Exclusive upper bound.