YAML schema (full)
Status: spec stream 1, project semver 0.1.0 (pre-1.0). In-place tightening allowed until the project hits 1.0.0. See the Versioning policy.
A sightmap is a directory of YAML files at the root of a project, under .sightmap/. It describes the app’s views, components, and requests, with optional memory entries that carry notes agents can use at runtime.
This document is the human-readable reference. The machine-readable contract is sightmap.schema.json.
File discovery
Section titled “File discovery”- Every
*.yamland*.ymlfile under.sightmap/is discovered recursively. - All files are loaded and merged at load time. The directory layout is a convenience for authors; it has no semantic meaning.
- Every file must begin with
version: 1. - Merging is shallow-append per top-level collection (
views,components,requests). Two files may define the same view; the runtime behavior in that case is implementation-defined and SDKs SHOULD emit a warning.
File root
Section titled “File root”version: 1memory: # optional, string[] — file-level notes (see "Memory")views: # optional, View[]components: # optional, Component[] — global, matched on every viewrequests: # optional, Request[] — global, matched on every view| Field | Type | Required | Description |
|---|---|---|---|
version | integer | yes | Must be 1. |
memory | string[] | no | File-level memory entries. Surfaced as context to the agent for any view in this file. |
views | View[] | no | Views defined in this file. |
components | Component[] | no | Global components — matched against every view. |
requests | Request[] | no | Global requests — matched against every view. |
A named screen in the app, identified by a URL route.
- name: FlightSearch route: /search description: Main search page with date and origin/destination pickers source: src/pages/FlightSearch.tsx memory: - The search form lives inside a modal on mobile; selectors differ components: [...] requests: [...]| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Shown in the snapshot header. Should be unique across the sightmap. |
route | string | yes | Glob pattern matched against the URL pathname. See Route matching. |
description | string | no | Free-text. Not surfaced at runtime but useful for PR review and future maintenance. |
source | string | no | Relative path to the source file. |
dependencies | string[] | no | Supplementary files (minimatch globs, project-root-anchored, ! negates) whose changes should trigger re-curation of this view. See Dependencies. |
memory | string[] | no | View-level memory entries. |
components | (Component | ComponentRef)[] | no | View-scoped components. Additive with globals. Entries may be inline definitions or $ref reference objects. |
requests | Request[] | no | View-scoped requests. Additive with globals. |
Component
Section titled “Component”A named DOM subtree, identified by one or more CSS selectors.
- name: DepartureDatePicker selector: '[data-picker="departure"]' source: src/components/DatePicker.tsx description: Departure date picker, calendar + typed input memory: - Accepts typed YYYY-MM-DD — skips the calendar - Past dates render but are aria-disabled children: - name: date-input selector: input - name: day selector: '[role="gridcell"]'| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Replaces the generic a11y role in enriched snapshots. |
selector | string | string[] | yes | CSS selector, or a list of alternatives. First match wins. |
source | string | no | Path to the source file. Rendered inline as [src: …] in enriched snapshots. |
dependencies | string[] | no | Supplementary files (minimatch globs, project-root-anchored, ! negates) whose changes should trigger re-curation of this component. See Dependencies. |
description | string | no | Free-text. Not surfaced at runtime. |
memory | string[] | no | Component-level memory entries. |
children | (Component | ComponentRef)[] | no | Nested components. Child selectors are scoped to the parent’s subtree. Entries may be inline definitions or $ref reference objects. |
Selector semantics
Section titled “Selector semantics”- A single string is a standard CSS selector.
- A list of strings is tried in order; the first selector that matches wins.
- Selectors in
childrenare evaluated within their parent’s matched subtree, not globally. This scoping is how Sightmap avoids naming collisions between, say, two different card components that both contain abutton.primary. - Selectors are not required to be unique at their level. If a selector matches multiple elements, all matches are named.
Component references
Section titled “Component references”Any entry in a components: array — at file root, within a view, or under children: — may be a reference object instead of an inline definition:
- $ref: ComponentNameA $ref entry is expanded inline (deep copy) to the named component’s full definition before matching. The name is resolved against a registry built from the root-level components: arrays of all loaded files.
| Field | Type | Required | Description |
|---|---|---|---|
$ref | string | yes | Name of a component defined at file root. The entry MUST contain no other keys. |
Lookup scope. Only components defined at the root of some file’s components: array are addressable. Components nested under children:, or defined inside a view’s components:, are not in the registry. First-seen wins on duplicate names (sorted by source-file path); conforming SDKs SHOULD emit a merge-collision-component warning.
Recursive expansion. Nested children of an inlined definition are themselves re-expanded if they contain further $ref entries. The cloned subtree is fully resolved before being inlined.
Source attribution. The expanded clone carries the registry definition’s source and dependencies verbatim — not the $ref site’s. A $ref attests where a component is expected to appear; the definition still lives at its root entry.
View attestation. When a view lists - $ref: ComponentName, it asserts “this component is expected on this page.” When the same name is also present in the file-root registry (i.e. the global auto-match would otherwise add it), the view-attested expansion takes precedence: the component appears once in the resolved output for that view, scoped to the view.
Conformance. SDKs MUST expand $ref before matching, MUST emit ref-unresolved (error) for an unknown name, MUST emit ref-circular (error) for a self-referential chain, and MUST NOT produce two matches for the same view when a view-scoped $ref and a file-root global share a name. See SEP-0002 for the full proposal and rationale.
# .sightmap/components.yaml — definitionsversion: 1components: - name: SiteHeader selector: '#site-header' children: - name: SearchBox selector: 'form#header-search' - name: CartButton selector: 'a[data-testid="header-cart-icon"]' - name: NavFooter selector: '#site-footer'
# .sightmap/views/plp.yaml — view-scoped, attests its expected globals by referenceversion: 1views: - name: PLP route: /b/** components: - $ref: SiteHeader # attests SiteHeader is expected on this view - $ref: NavFooter # attests NavFooter is expected on this view - name: ProductGrid # view-specific definition selector: '[data-component="ProductGrid"]' children: - name: ProductCard selector: '[data-testid="product-pod"]'Dependencies
Section titled “Dependencies”The dependencies field on a view or component declares supplementary files whose changes SHOULD trigger re-curation of the entry. It is purely curation-time metadata — runtime adapters (sightmap_runtime_snapshot, browser-driving SDKs) read DOM/fiber state, not source files, and MUST NOT introduce page-load runtime cost on the basis of this field.
What belongs
Section titled “What belongs”- Hooks the view or component consumes (e.g.
useChecklist,useAuth) - Services, stores, and shared utilities
- CSS / style files the entry loads
- Helper modules that don’t warrant their own entry
What does NOT belong
Section titled “What does NOT belong”- Tests (
*.test.ts,*.spec.tsx) - Type-only imports
- Framework code (React, Vue, etc.)
- Files that have their own component or request entry — use the existing entry-level binding, don’t restate it here
Glob semantics
Section titled “Glob semantics”Strings in dependencies are interpreted as minimatch globs, project-root-anchored (the directory containing .sightmap/). A ! prefix negates. When multiple positive globs match the same file, the first positive glob in declaration order wins for provenance reporting (matchedBy in explain --by path output).
Normative rules
Section titled “Normative rules”A conforming SDK MUST surface a diagnostic when:
- An entry’s resolved
dependencies[]set contains its ownsource. Diagnostic code:dependencies.self-redundant. - An entry’s resolved
dependencies[]set contains a path that is thesourceof any other entry in the same.sightmap/. Diagnostic code:dependencies.overlaps-entry. - A glob in
dependencies[]resolves to zero files. Diagnostic code:unknown-source(existing vocabulary, narrowed to apply todependencies[]globs).
views: - name: ListView route: /lists/:id source: src/views/ListView.tsx dependencies: - src/hooks/useChecklist.ts - src/stores/listStore.ts - src/styles/list-card.css components: - name: ListCard selector: '[data-component="ListCard"]' source: src/components/ListCard.tsx dependencies: - src/components/ListCard.module.cssSee SEP-0001 for the full proposal and rationale.
Request
Section titled “Request”A named API endpoint.
- name: SearchFlights route: /api/flights/search method: POST description: Run a flight search and return results source: src/api/flights.ts request: fields: - name: origin type: string - name: destination type: string - name: departureDate type: string description: ISO-8601 date response: fields: - name: results type: array headers: [x-request-id] memory: - 429s on more than 10 requests/min per user| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | Shown in network list and detail output. |
route | string | yes | Glob pattern. Express-style :param segments are normalized to *. See Route matching. |
method | string | no | HTTP method filter (GET, POST, …). Match-any if omitted. |
description | string | no | What the endpoint does. |
source | string | no | Relative path to the source file. |
request | Payload | no | Expected payload shape. |
response | Payload | no | Expected response shape. |
headers | string[] | no | Notable header names to highlight in the network detail view. |
memory | string[] | no | Request-level memory entries. |
Payload
Section titled “Payload”request: fields: - name: origin type: string description: IATA code| Field | Type | Required | Description |
|---|---|---|---|
fields | Field[] | no | Expected fields. Not exhaustive; extra fields are not rejected. |
| Field | Type | Required | Description |
|---|---|---|---|
name | string | yes | The field name. |
type | string | no | Free-text type label: string, number, boolean, array, object, or anything else an SDK author finds useful. |
description | string | no | Free-text description. |
Memory
Section titled “Memory”Memory entries are short freeform notes attached to any definition — file, view, component, or request. They exist so that agents can carry forward context that isn’t recoverable from the source code: quirks, invariants, workarounds, “you have to click this twice” lore.
memory: - Past dates render but are aria-disabled - Range: 1st click = start, 2nd = end, 3rd resetsDesign points:
- Each entry is a single human-readable sentence or short bullet.
- Entries on a component apply whenever that component is matched on the current view.
- Entries on a view apply whenever the current URL matches that view’s route.
- File-level entries apply whenever any definition from that file is active.
- Entries on a request apply in the network-trace detail view.
- Conforming SDKs SHOULD surface applicable memory entries in a
[Guide]section at the top of enriched output.
Route matching
Section titled “Route matching”Routes use glob patterns against the URL pathname.
*matches exactly one path segment:/users/*matches/users/42, not/users/42/edit**matches any depth of segments:/admin/**matches/admin,/admin/users,/admin/users/42/edit- Literal segments match themselves
- Matching is case-sensitive
- Query string and fragment are ignored
- Trailing slashes are normalized away before matching
For requests, Express-style :param segments are normalized to *. These are equivalent:
- route: /api/users/:id/orders # same as below- route: /api/users/*/ordersViews: most specific wins. When several views match the URL, the most specific route wins — scored per segment (literal 3, :param 2, * 1, **/empty 0; root / scores 1). Definition order does not set priority; it only breaks ties between equally specific routes. See Views › Most specific wins. Requests are matched independently — see Requests.
Global vs view-scoped
Section titled “Global vs view-scoped”Components and requests can be declared at the file root or nested inside a view.
- Global (
components:orrequests:at file root): matched against every view. - View-scoped (nested inside a
view): matched only when that view is active. - They are additive. A view that defines its own components receives both the global components and its own.
components: - name: Navigation # global — matched everywhere selector: 'nav[data-component="Navigation"]'
views: - name: Dashboard route: /dashboard components: - name: DashboardLayout # scoped — only on /dashboard selector: '[data-component="DashboardLayout"]'Conformance
Section titled “Conformance”A conforming SDK:
- MUST accept any file that validates against
sightmap.schema.json - MUST reject any file that does not
- MUST implement route matching as specified
- MUST implement global vs view-scoped precedence as specified
- SHOULD surface
memoryentries to the agent when the parent definition is active - MAY ignore fields it doesn’t use (e.g.
descriptionis never surfaced at runtime by Subtext today) - MAY implement additional, non-standard behavior as long as it doesn’t change the meaning of conforming inputs
See Conformance fixtures for the language-agnostic test suite.
Open questions
Section titled “Open questions”These are explicitly unresolved in v1 and candidates for SEPs:
- Inheritance or import across files (today the only merge is implicit directory-level concatenation)
- Parameterized memory — interpolating runtime values into memory entries
- Schema for validating the shape of
response.fieldsagainst real responses (todayfieldsis documentary, not enforced) - Macros — learned trajectories that replay and heal when the site changes (teased in the website; not yet in the spec)
See seps/README.md to propose.