Wanderland

How to Use Wanderland Introspection

Every wanderland-core service exposes the same introspection surface — every route, every boundary, every framework schema, every halt diagnostic, every registered scenario, every boundary's reference doc. The same JSON answers come back regardless of how you ask: HTTP request, CLI subcommand, MCP tool call (when that adapter lands). One catalogue, three lenses.

This guide walks the surface from broad to narrow: routes → a single route → boundaries → a single boundary → schemas → scenarios → diagnostics → generated docs.

One catalogue, two lenses

Every example below appears twice — HTTP and CLI — because the data is the same. The CLI subcommand path mirrors the URL path: /inspect/route/:nameinspect route --name <value>. Slashes become spaces; :capture becomes --capture VALUE. The CLI reaches the same compiled route through the same Dispatch.invoke seam.

Two output lenses:

Form How to ask for it (HTTP) How to ask for it (CLI)
JSON default, or Accept: application/json --accept application/json
YAML (CLI default) Accept: text/plain (or none) default
Markdown Accept: application/x.wanderland.template --accept application/x.wanderland.template

Examples in this guide use CLI YAML for sample output — the most readable for humans skimming the surface. Substitute --accept application/json to get JSON when piping into tooling.

Liveness — the broadest probes

Three endpoints answer in increasing depth.

# Cheapest: load-balancer ping. Always answers.
curl http://localhost:9295/health
bundle exec bin/wanderland --type cli config.yml health
status: ok
service: sprout-engine
timestamp: '2026-04-30T11:41:46-04:00'
# Identity + registered surface count.
curl http://localhost:9295/status
bundle exec bin/wanderland --type cli config.yml status
status: ok
service: sprout-engine
boundaries:
- adapter_cli
- adapter_http
- echo
- enforce_denials
- format
- ...
routes: 18
timestamp: '2026-04-30T11:41:46-04:00'
# Full compliance snapshot — manifest + routes + diagnostics.
curl http://localhost:9295/healthcheck
bundle exec bin/wanderland --type cli config.yml healthcheck

/healthcheck returns the full boundary manifest (one entry per registered boundary), the compiled routes list, and the diagnostics summary nested under diagnostics:. status: ok on a clean boot, degraded if any boot-time error landed.

Routes — list, then drill in

/inspect/routes is the user-declared route names — the surface the site actually advertises. Framework routes (the inspect family, the liveness triptych) aren't in here; they're documented elsewhere as core machinery.

curl http://localhost:9295/inspect/routes
bundle exec bin/wanderland --type cli config.yml inspect routes
routes:
- captures
- chain
- hello
- secret

Each name is what :name is set to on the route. Pick one and ask for its full shape:

curl http://localhost:9295/inspect/route/hello
bundle exec bin/wanderland --type cli config.yml inspect route --name hello
name: hello
method: get
path: /hello
dispatcher: chain
user_chain:
- echo
compiled_chain:
- enforce_denials
- echo
- verify_route
- trace_emit
- format
- seal
grid:
scenarios: []
registered_injections:
- boundary: enforce_denials
  position: interleave
- boundary: verify_route
  position: last
- boundary: trace_emit
  position: last
- boundary: format
  position: last
- boundary: seal
  position: last

Two chain views matter:

grid is set when the route uses the grid dispatcher (declared via grid: shorthand); null for chain routes. scenarios lists scenario names attached to this route.

Boundaries — list, then drill in

/inspect/boundaries is every registered boundary — framework-shipped and site-declared together, sorted alphabetically.

curl http://localhost:9295/inspect/boundaries
bundle exec bin/wanderland --type cli config.yml inspect boundaries
boundaries:
- adapter_cli
- adapter_http
- archetype_inspect
- boot_load_boundaries
- boot_mount_routes
- collect_boundary_reference
- echo
- enforce_denials
- format
- health
- ...
- verify_route

Pick one and inspect the registered manifest:

curl http://localhost:9295/inspect/boundary/echo
bundle exec bin/wanderland --type cli config.yml inspect boundary --name echo
name: echo
identity: boundary:echo
requirements: []
capabilities:
- echo
description: Echo input params back as result
when_shape:
input_shape:
  params: true
output_shape:
  echoed: true
source: Wanderland::Boundaries::Echo

The fields are the registered manifest verbatim:

A 404 includes the registered list under available: so you know what you can ask for next.

Schemas — framework (input) and shape (output)

Two registries document what the framework itself reserves. The framework-schema endpoint covers the input envelope (what every boundary receives); the shape-schema endpoint covers the output side (what every boundary may write without per-boundary declaration).

Framework schema (input)

curl http://localhost:9295/inspect/framework-schema
bundle exec bin/wanderland --type cli config.yml inspect framework-schema
stages:
  request:
  - key: params
    type: hash
    description: Callable arguments (path captures + query + body, merged)
  - key: headers
    type: hash
    description: Canonical header map
  - key: route
    type: hash
    description: The compiled route record
  - key: runtime
    type: object
    description: The booted runtime instance
  - key: context
    type: object
    description: The append-only Context
  - ...
  slot_input:
  - ...

Each stage names the framework keys present at that point in the chain. request is what Dispatch.invoke builds; slot_input is what each chain slot receives (request keys + args from chain config).

Filter to one stage:

curl http://localhost:9295/inspect/framework-schema/request
bundle exec bin/wanderland --type cli config.yml inspect framework-schema --stage request

Shape schema (output)

curl http://localhost:9295/inspect/shape-schema
bundle exec bin/wanderland --type cli config.yml inspect shape-schema
framework_keys:
- status
- error
- cause
- missing
modules:
- name: signals
  framework_keys:
  - status
  - error
  - cause
  - missing
  schemas:
  - type_addr: ':signals:stop:halt'
    payload:
      status: true
      error: true
  - type_addr: ':signals:stop:error'
    payload:
      status: true
      error: true
      cause: true
  - type_addr: ':signals:stop:denied'
    payload:
      status: true
      error: true
      missing: true

The top-level framework_keys is the union of every registered shape module's keys. Boundaries may write these without declaring them in their per-boundary output_shape — strict-output enforcement skips framework keys.

Each module documents the type_addr → payload pairings it owns. signals is the built-in module covering halt forms; sites can register additional modules at boot.

Filter to one module:

curl http://localhost:9295/inspect/shape-schema/signals
bundle exec bin/wanderland --type cli config.yml inspect shape-schema --module signals

Scenarios — list, then per-route

Sites that declare a scenarios: block in config.yml expose them through introspection too. The site without scenarios returns an empty hash.

curl http://localhost:9295/inspect/scenarios
bundle exec bin/wanderland --type cli config.yml inspect scenarios
scenarios:
  hello:
    default:
      description: Canonical example
      has_input: true
      has_expected: true
      input:
        params:
          message: Hello world
      expected:
        echoed: Hello world
  greet:
    alice:
      description: greeting alice with the canonical format
      has_input: true
      has_expected: true
      input:
        params:
          name: alice
      expected:
        greeting: Hello, alice!

The endpoint reports every scenario the runtime registered at boot, grouped by route name. has_input / has_expected are convenience flags; the full input and expected blocks ride alongside.

Filter to one route:

curl http://localhost:9295/inspect/scenarios/hello
bundle exec bin/wanderland --type cli config.yml inspect scenarios --route hello

wanderland --type test config.yml walks this same registry, dispatches each through verify_route, and reports pass/fail. The introspection endpoint is the read-only view of what the runner will exercise.

Diagnostics — boot-time conditions

Some boundaries record warnings or errors during boot — a missing boundary_path, a config field that referenced a fixture that didn't load, an adapter mode unrecognized. These don't halt boot but are surfaced for operators to act on.

curl http://localhost:9295/inspect/diagnostics
bundle exec bin/wanderland --type cli config.yml inspect diagnostics
summary:
  errors: 0
  warnings: 0
  total: 0
severity:
entries: []

A clean boot returns zero entries. If boundary_path had pointed at a missing directory, a warning entry would land here without halting the process. summary.errors > 0 is what flips /healthcheck to degraded.

Filter to one severity level:

curl http://localhost:9295/inspect/diagnostics/warning
bundle exec bin/wanderland --type cli config.yml inspect diagnostics --severity warning

Documentation — boundary reference

The doc-generator endpoint folds the boundary registry, the framework schema, and the shape schema into one tree. Default JSON returns the raw tree; the template MIME renders it through the gem-bundled ERB template into AWS-SDK-style markdown.

# JSON tree (raw data — feed into your own renderer if you want)
curl http://localhost:9295/inspect/docs/boundaries
bundle exec bin/wanderland --type cli config.yml inspect docs boundaries

# Markdown (gem-bundled template)
curl -H "Accept: application/x.wanderland.template" \
     http://localhost:9295/inspect/docs/boundaries
bundle exec bin/wanderland --type cli config.yml \
  --accept application/x.wanderland.template inspect docs boundaries

Markdown looks like:

# Boundary Reference

80 boundaries registered.

## Framework signal shapes

| key | declared by |
| --- | --- |
| `status` | signals |
| `error`  | signals |
| ...

### `signals` schemas

- **`:signals:stop:halt`** — payload keys: `status`, `error`
- **`:signals:stop:error`** — payload keys: `status`, `error`, `cause`
- **`:signals:stop:denied`** — payload keys: `status`, `error`, `missing`

## Boundaries

### `echo`

Echo input params back as result

- **identity**: `boundary:echo`
- **source**: `Wanderland::Boundaries::Echo`
- **capabilities**: `echo`

**Input shape**

\`\`\`yaml
params: true
\`\`\`

**Output shape**

\`\`\`yaml
echoed: true
\`\`\`

---

### `format`
...

For one boundary instead of all:

curl http://localhost:9295/inspect/docs/boundary/echo
bundle exec bin/wanderland --type cli config.yml inspect docs boundary --name echo

# Markdown for one boundary
curl -H "Accept: application/x.wanderland.template" \
     http://localhost:9295/inspect/docs/boundary/echo
bundle exec bin/wanderland --type cli config.yml \
  --accept application/x.wanderland.template inspect docs boundary --name echo

Operators who want a custom template ship one alongside their config and pass it as a query param:

curl -H "Accept: application/x.wanderland.template" \
     "http://localhost:9295/inspect/docs/boundaries?template=docs/templates/refguide.md.erb"

The template path is resolved under the runtime's config_dir; .. segments are rejected. Gem-bundled templates use the wanderland: prefix (wanderland:templates/<file>).

CLI command name conventions

The CLI runner derives a subcommand name from each route's path. The mapping is mechanical:

A full URL → CLI translation:

URL CLI form
GET /health health
GET /inspect/routes inspect routes
GET /inspect/route/:name inspect route --name <value>
GET /inspect/scenarios/:route inspect scenarios --route <value>
GET /inspect/diagnostics/:severity inspect diagnostics --severity <value>
GET /inspect/framework-schema/:stage inspect framework-schema --stage <value>
GET /inspect/shape-schema/:module inspect shape-schema --module <value>
GET /inspect/docs/boundaries inspect docs boundaries
GET /inspect/docs/boundary/:name inspect docs boundary --name <value>

Run bundle exec bin/wanderland --type cli config.yml help to see the full list a particular site exposes — the CLI table includes user-declared routes alongside the inspect family.

Notes

Site Audit

wanderland.dev

oculus-view: fence: fence execute HTTP 404