Spec Studio

Every Spec, Pack, code unit and keyed term is a note, and every relation is a link

spec:consumers.obsidian-vault.notesUse Case / Behavior · storyready floor ready

Changed since the base graph base da4b141: design.packNoteBody; design.packProperties

Base input: schema 0.11.0, 405 Specs.

Packs: pack:obsidian-vault-v1, pack:self-hosting-v1

Design: 17 design entries · 8 pinned declarations · no decisions

Findings: no errors, no warnings

specs/consumers/obsidian-vault.notes.sdp.md

No open questions and no blocking questions; implementation binding present, verifier binding present, and expected-outcome oracle present.

A note carries the reader's values as flat properties, so Obsidian's tables filter on them, and the Spec's sections in the graph's order. Each declared relation is a wikilink in both directions with its reason, each mention in prose is a wikilink to its Spec or to its entry's block, and each keyed entry carries a block id named for its address. Backlinks and the graph view then show what rests on a Spec without a query.

Two findings from the prototypes shape the names and properties. Obsidian refuses a colon in a note's name, so a note cannot be named by its id as written. And Obsidian renders a text or list property as a link to an external address whenever its value holds no space and parses as a URL, which spec: followed by a path does, while it renders an alias as plain text. Every link also names the note's .md extension, so an id whose last segment reads like another file type's extension, such as base, still links to its note.

Intent
outcome
Write one note per Spec, Pack, code unit, test anchor, oracle anchor and keyed Model term, with graph and reader values as properties and every declared relation and checked mention as a wikilink, so a person follows the graph in both directions.
Behavior

The world writes a probe corpus whose Specs mention each other, runs the vault command, and reads the mentioning Spec's note from disk. A keyed Model term is written as spec:model.term-addresses states.

rule.oneNotePer line 26 · specs/consumers/obsidian-vault.notes.sdp.md:26
The vault holds one note per Spec, Pack, code unit, test anchor and oracle anchor, and one per Model term that carries a key, which spec:model.term-addresses gives an address; a term without a key appears only in its Spec's note, since no address can name it, and a ratified glossary term gains a note only where a Spec's Model section defines it with a key.

spec:consumers.obsidian-vault.notes.term-address-link · enabled

rule.termNoteGrain line 27 · specs/consumers/obsidian-vault.notes.sdp.md:27
A term defined in several Specs gets one note per defining Spec and term, so each definition keeps its authored owner; the term's aliases bring the notes together when a person types it.

no example exercises it

rule.noteNames line 28 · specs/consumers/obsidian-vault.notes.sdp.md:28
A note is named by its id with the colon after the namespace replaced by a dot, and a term note by term., its Spec's path, a dot and its key; one vault holds the notes of one corpus.

spec:consumers.obsidian-vault.notes.entry-address-link · enabled

rule.caseCollision line 29 · specs/consumers/obsidian-vault.notes.sdp.md:29
Two notes whose paths differ only in case refuse the run before it writes, naming both ids, so no two names collide on a file system that ignores case; the run writes and removes nothing and exits 1.

spec:consumers.obsidian-vault.notes.case-collision-refused · enabled

rule.idInAliases line 30 · specs/consumers/obsidian-vault.notes.sdp.md:30
A note's id, colon included, is written as plain text only in its aliases property and in the code span of its head line, since Obsidian shows an alias as plain text; a property that names another node holds a link to its note, and no other property value the generator composes is an id or an entry address. Authored text in a property, such as a title or a label, is written as authored, and the generator never treats one that looks like an address as an address.

spec:consumers.obsidian-vault.notes.entry-address-link · enabled

rule.readerProperties line 31 · specs/consumers/obsidian-vault.notes.sdp.md:31
A Spec note's properties are the reader's values for that Spec, listed under spec:consumers.obsidian-vault.notes#design.specProperties; every join, delivery fact, floor and rung among them is one the reader computed, and the generator computes none.

no example exercises it

rule.bindingProperties line 32 · specs/consumers/obsidian-vault.notes.sdp.md:32
A Spec's bindings are two booleans, implementationBinding true where the reader's delivery facts hold implemented and verifierBinding true where they hold has-verifier, and the note's body renders the four binding lines spec:consumers.binding-language-views states, so no rendered label is a delivery-fact name.

no example exercises it

rule.relationsBothWays line 33 · specs/consumers/obsidian-vault.notes.sdp.md:33
Each declared relation whose two ends have notes is a link on the notes at both ends, with its type, its reason, and for an example's verifies a link to the block of each rule it exercises in the verified Spec's note; an end with no note, such as a target that does not resolve, and an exercised key the verified Spec does not carry, appear on the source note as their id or key in a code span, with no link.

no example exercises it

rule.blockIds line 34 · specs/consumers/obsidian-vault.notes.sdp.md:34
Each keyed Design and UI entry, keyed open question, keyed rule or flow, and keyed Model term ends its line in its Spec's note with the block id ^<section>-<key>, with section design, ui, question, rule or term.

spec:consumers.obsidian-vault.notes.entry-address-link · enabled, spec:consumers.obsidian-vault.notes.term-address-link · enabled

rule.mentionLinks line 35 · specs/consumers/obsidian-vault.notes.sdp.md:35
A mention in any text the vault renders from the graph, found by the scanner the prose-mention validator uses, becomes a link when its Spec resolves and, for an entry address, its entry does; a mention that does not resolve stays as written. A code span holding exactly one mention becomes that link, and any other code span stays code.

spec:consumers.obsidian-vault.notes.entry-address-link · enabled, spec:consumers.obsidian-vault.notes.term-address-link · enabled, spec:consumers.obsidian-vault.notes.unresolved-mention-stays · enabled

rule.textEscaped line 36 · specs/consumers/obsidian-vault.notes.sdp.md:36
Text from the graph renders as written, except that the generator escapes what Obsidian would read as a link, an embed, a tag, a block id, a comment, a highlight or math, so no note holds a link, tag or block id the graph does not.

no example exercises it

rule.addressRoundTrip line 37 · specs/consumers/obsidian-vault.notes.sdp.md:37
Every note name and block id converts back to what it names: a note name to its id by restoring the colon after the namespace, a term note's name to its term address, and a block id in a Spec's note to its entry address, so an agent reading a link a person wrote names the entry it cites.

no example exercises it

Cited at

  • test/skills.test.ts:2143

0 unkeyed rules.

Verifying examples

Two Specs whose notes differ only in case refuse the run · spec:consumers.obsidian-vault.notes.case-collision-refused · ready floor ready

Executable Spec

Given a corpus holding the Specs {first: "spec:probe.Member"} and {second: "spec:probe.member"}
When the vault command runs over that corpus
Then the run exits {exitCode: 1}
Then the refusal names {named: "spec:probe.Member and spec:probe.member"}
Then nothing under the generated folder was written: {nothingWritten: true}

Open example

An entry address in prose opens the entry's block in its Spec's note · spec:consumers.obsidian-vault.notes.entry-address-link · ready floor ready

Executable Spec

Given a corpus holding the Spec {source: "spec:probe.source"} whose narrative mentions {mention: "spec:probe.target#design.limit"}
Given the Spec {target: "spec:probe.target"} keys the Design entry {key: "limit"}
When the vault command runs over that corpus
Then the mentioning Spec's note is {notePath: "sdp/specs/probe/spec.probe.source.md"}
Then the mention renders as {rendered: "[[sdp/specs/probe/spec.probe.target.md#^design-limit|spec:probe.target#design.limit]]"}
Then the note's aliases open with {alias: "spec:probe.source"}
Then no property but aliases holds an id or an entry address as plain text: {plainProperties: true}

Open example

A keyed Model term gets a note, and its address in prose opens the term's block · spec:consumers.obsidian-vault.notes.term-address-link · ready floor ready

Executable Spec

Given a corpus holding the Spec {source: "spec:probe.source"} whose narrative mentions {mention: "spec:probe.target#term.limit"}
Given the Spec {termSpec: "spec:probe.target"} defines a Model term with the key {termKey: "limit"}
When the vault command runs over that corpus
Then the term's note is {termNotePath: "sdp/terms/term.probe.target.limit.md"}
Then the defining Spec's note carries the block id {blockId: "term-limit"}
Then the mention renders as {rendered: "[[sdp/specs/probe/spec.probe.target.md#^term-limit|spec:probe.target#term.limit]]"}

Open example

A mention of an entry that does not exist stays as written · spec:consumers.obsidian-vault.notes.unresolved-mention-stays · ready floor ready

Executable Spec

Given a corpus holding the Spec {source: "spec:probe.source"} whose narrative mentions {mention: "spec:probe.target#design.missing"}
Given the Spec {target: "spec:probe.target"} keys the Design entry {key: "limit"}
When the vault command runs over that corpus
Then the mention renders as {rendered: "spec:probe.target#design.missing"}

Open example

Example space

Given a corpus holding the Spec {source:string} whose narrative mentions {mention:string}
Given a corpus holding the Specs {first:string} and {second:string}
Given the Spec {target:string} keys the Design entry {key:string}
Given the Spec {termSpec:string} defines a Model term with the key {termKey:string}
When the vault command runs over that corpus
Then the run exits {exitCode:number}
Then the refusal names {named:string}
Then nothing under the generated folder was written: {nothingWritten:boolean}
Then the mentioning Spec's note is {notePath:string}
Then the mention renders as {rendered:string}
Then the term's note is {termNotePath:string}
Then the defining Spec's note carries the block id {blockId:string}
Then the note's aliases open with {alias:string}
Then no property but aliases holds an id or an entry address as plain text: {plainProperties:boolean}
Design
noteName line 40 · specs/consumers/obsidian-vault.notes.sdp.md:40
<namespace>.<path> for an id <namespace>:<path>, as spec.model.rule-keys, pack.design-iteration-v1 and impl.protocol.reader; term.<path>.<key> for the term address spec:<path>#term.<key>.

no citation recorded

linkForm line 41 · specs/consumers/obsidian-vault.notes.sdp.md:41
[[<path from the vault>.md|<id or address>]], with #^<block id> after .md for an entry; every link names the file's extension, and an embedded Base is ![[sdp/packs/<note>.base]] or ![[sdp/specs.base]].

no citation recorded

blockId line 42 · specs/consumers/obsidian-vault.notes.sdp.md:42
<section>-<key>, written as ^<section>-<key> at the end of the entry's line, so spec:<id>#design.limit opens as [[sdp/specs/<family>/<note>.md#^design-limit|spec:<id>#design.limit]].

no citation recorded

propertyEncoding line 43 · specs/consumers/obsidian-vault.notes.sdp.md:43
the properties sit between two --- lines at the top of the note, one per line as <key>: <JSON value>, in the order listed below; a property the graph does not hold is left out.
specProperties line 44 · specs/consumers/obsidian-vault.notes.sdp.md:44
aliases (the id, then the title), title, specKind, altitude, statedReadiness, derivedReadiness (none when no rung derives), statedNextRung (left out when the Spec states ready), statedNextRungFailures (the failing clause ids), implementationBinding, verifierBinding, designEntries, declarations, openQuestions (a count), blockingQuestions, decisions (links to the notes of the resolving decisions the design columns name), packs (links to the Pack notes), carrier (the root-relative carrier path).

no citation recorded

packProperties line 45 · specs/consumers/obsidian-vault.notes.sdp.md:45
aliases (the id, then the title), title, manifest (the root-relative manifest path), and optional order, present as "priority" only when the Pack states it.

no citation recorded

codeProperties line 46 · specs/consumers/obsidian-vault.notes.sdp.md:46
aliases (the id), label, role, layer, context, component (a link to the component's note), sourceFile (root-relative), sourceLine.

no citation recorded

termProperties line 47 · specs/consumers/obsidian-vault.notes.sdp.md:47
aliases (the term, then its address), definedIn (a link to the defining Spec's note).

no citation recorded

banner line 48 · specs/consumers/obsidian-vault.notes.sdp.md:48
the first line after the properties, > [!info] Generated by `sdp vault` from the graph. Edit the <carrier|Pack manifest|source file> `<root-relative path>`, never this note: a regeneration refuses while a note it wrote has changed. , naming the Spec's carrier, the Pack's manifest or the unit's source file.
headLine line 49 · specs/consumers/obsidian-vault.notes.sdp.md:49
under a Spec note's title, `<id>` · <kind display label> · <altitude> · stated <rung> · floor <rung or none> , then · <stated next rung>: <failing clause ids, or nothing blocks> when the Spec states less than ready.
specNoteBody line 50 · specs/consumers/obsidian-vault.notes.sdp.md:50
the banner, # <title>, the head line, the narrative's paragraphs, each section under ## <Section> in the graph's order with Intent's open questions under ### Open questions and an example's steps or an example space's vocabulary in a fenced gherkin block, then ## Relations with ### From this Spec and ### Toward this Spec, ## Bindings, ## Packs and ## Findings, each heading left out when it has nothing under it.
bindingLines line 51 · specs/consumers/obsidian-vault.notes.sdp.md:51
under ## Bindings, - Implementation binding: present or none with each realizing unit, the units that reference the Spec, - Verifier binding: present or none with each verifier, - Expected-outcome oracle: present or none, and - Runtime observation: not tracked.
packNoteBody line 52 · specs/consumers/obsidian-vault.notes.sdp.md:52
the banner, # <title>, the framing, ## Members, filterable with the Pack's Base embedded, ## Members, in advisory priority order when order is "priority", otherwise ## Members, in reading order, as a numbered list in manifest order, each a link with its stated rung, floor and stated next rung or nothing blocks, then ## Boundary with the reader's four boundary lists and ## Findings. A roadmap states Priority confers no permission or sequencing requirement. before its ordered list heading.
codeNoteBody line 53 · specs/consumers/obsidian-vault.notes.sdp.md:53
the banner, # <id>, the label, `<file>:<line>` , then link lists under ## Member of, ## Members, ## Uses, ## Used by, ## Satisfies, ## References, ## Verifies and ## Models, each left out when empty.
termNoteBody line 54 · specs/consumers/obsidian-vault.notes.sdp.md:54
the banner, # <term>, the definition, and Defined in [[<Spec note>.md#^term-<key>|<term address>]].
caseCollisionMessage line 55 · specs/consumers/obsidian-vault.notes.sdp.md:55
sdp vault: <first id> and <second id> name notes whose paths differ only in case; nothing was written, one line per colliding pair, the ids in code-unit order.

no citation recorded

escapes line 56 · specs/consumers/obsidian-vault.notes.sdp.md:56
a backslash before [[, %%, ==, $, a # that opens a tag after a space or at a line's start, and a ^ that would end a line as a block id; text inside a code span is left as written.
Verification

Verifier bindings

  • spec:consumers.obsidian-vault.notes.case-collision-refused · Two Specs whose notes differ only in case refuse the run · declared · example enabled · specs/consumers/obsidian-vault.notes.case-collision-refused.sdp.md

    External run evidence from test/vault-examples.test.ts

    Test anchors: test:protocol.consumers.obsidian-vault.bases.views-match-sources, test:protocol.consumers.obsidian-vault.changed-note-refused, test:protocol.consumers.obsidian-vault.failed-extraction-keeps-notes, test:protocol.consumers.obsidian-vault.failed-extraction-recovered, test:protocol.consumers.obsidian-vault.fresh-vault, test:protocol.consumers.obsidian-vault.hidden-file-refused, test:protocol.consumers.obsidian-vault.interrupted-run-recovered, test:protocol.consumers.obsidian-vault.iteration.watch-rewrites-changed-notes, test:protocol.consumers.obsidian-vault.iteration.watch-source-anchor, test:protocol.consumers.obsidian-vault.notes.case-collision-refused, test:protocol.consumers.obsidian-vault.notes.entry-address-link, test:protocol.consumers.obsidian-vault.notes.term-address-link, test:protocol.consumers.obsidian-vault.notes.unresolved-mention-stays, test:protocol.consumers.obsidian-vault.person-notes-survive, test:protocol.consumers.obsidian-vault.unknown-note-refused, test:protocol.consumers.obsidian-vault.vault-in-build-path-refused. Specs verified by those bindings: spec:consumers.obsidian-vault, spec:consumers.obsidian-vault.bases, spec:consumers.obsidian-vault.bases.views-match-sources, spec:consumers.obsidian-vault.changed-note-refused, spec:consumers.obsidian-vault.failed-extraction-keeps-notes, spec:consumers.obsidian-vault.failed-extraction-recovered, spec:consumers.obsidian-vault.fresh-vault, spec:consumers.obsidian-vault.hidden-file-refused, spec:consumers.obsidian-vault.interrupted-run-recovered, spec:consumers.obsidian-vault.iteration, spec:consumers.obsidian-vault.iteration.watch-rewrites-changed-notes, spec:consumers.obsidian-vault.iteration.watch-source-anchor, spec:consumers.obsidian-vault.notes, spec:consumers.obsidian-vault.notes.case-collision-refused, spec:consumers.obsidian-vault.notes.entry-address-link, spec:consumers.obsidian-vault.notes.term-address-link, spec:consumers.obsidian-vault.notes.unresolved-mention-stays, spec:consumers.obsidian-vault.person-notes-survive, spec:consumers.obsidian-vault.unknown-note-refused, spec:consumers.obsidian-vault.vault-in-build-path-refused.

    Run 1: external run evidence from vitest 4.1.10

    Build: CI 380 · Branch: feature/roadmap-and-slices-v0 · Commit: 34909918bf0be0e849959644401797191cae379f · Start: 2026-10-22T17:40:31.456Z · Stop: 2026-10-22T17:42:16.171Z

    NameSuiteResultDuration
    keeps incomplete oracle points unspecifiednot recordedpassed1.89 ms
    executes the bound example against a fresh worldA fresh vault is written the same way twice and every link resolves (spec:consumers.obsidian-vault.fresh-vault)passed39.02 ms
    executes the bound example against a fresh worldA regeneration removes a note that left the graph and keeps a person's notes (spec:consumers.obsidian-vault.person-notes-survive)passed20.74 ms
    executes the bound example against a fresh worldA note a person wrote inside the generated folder refuses the regeneration (spec:consumers.obsidian-vault.unknown-note-refused)passed5.75 ms
    executes the bound example against a fresh worldA generated note a person changed refuses the regeneration and keeps the edit (spec:consumers.obsidian-vault.changed-note-refused)passed4.83 ms
    executes the bound example against a fresh worldA person's file under a temporary's name refuses the regeneration (spec:consumers.obsidian-vault.hidden-file-refused)passed6.02 ms
    executes the bound example against a fresh worldA vault directory the build removes refuses the run and keeps a person's notes (spec:consumers.obsidian-vault.vault-in-build-path-refused)passed1.15 ms
    executes the bound example against a fresh worldA run after a stopped synchronization finishes it (spec:consumers.obsidian-vault.interrupted-run-recovered)passed33.58 ms
    executes the bound example against a fresh worldA failed extraction keeps the notes and says so on the index (spec:consumers.obsidian-vault.failed-extraction-keeps-notes)passed10.21 ms
    executes the bound example against a fresh worldThe run after a failed extraction passes the guard and restores the index (spec:consumers.obsidian-vault.failed-extraction-recovered)passed20.42 ms
    executes the bound example against a fresh worldAn entry address in prose opens the entry's block in its Spec's note (spec:consumers.obsidian-vault.notes.entry-address-link)passed15.36 ms
    executes the bound example against a fresh worldA mention of an entry that does not exist stays as written (spec:consumers.obsidian-vault.notes.unresolved-mention-stays)passed9.95 ms
    executes the bound example against a fresh worldA keyed Model term gets a note, and its address in prose opens the term's block (spec:consumers.obsidian-vault.notes.term-address-link)passed14.06 ms
    executes the bound example against a fresh worldTwo Specs whose notes differ only in case refuse the run (spec:consumers.obsidian-vault.notes.case-collision-refused)passed2.55 ms
    executes the bound example against a fresh worldEach standing view selects what its source selects (spec:consumers.obsidian-vault.bases.views-match-sources)passed24.64 ms
    executes the bound example against a fresh worldA carrier edit under watch rewrites only the notes it changes (spec:consumers.obsidian-vault.iteration.watch-rewrites-changed-notes)passed446.54 ms
    executes the bound example against a fresh worldAn anchor added in a source file under watch rewrites the Spec's note (spec:consumers.obsidian-vault.iteration.watch-source-anchor)passed516.04 ms
  • spec:consumers.obsidian-vault.notes.entry-address-link · An entry address in prose opens the entry's block in its Spec's note · declared · example enabled · specs/consumers/obsidian-vault.notes.entry-address-link.sdp.md
  • spec:consumers.obsidian-vault.notes.term-address-link · A keyed Model term gets a note, and its address in prose opens the term's block · declared · example enabled · specs/consumers/obsidian-vault.notes.term-address-link.sdp.md
  • spec:consumers.obsidian-vault.notes.unresolved-mention-stays · A mention of an entry that does not exist stays as written · declared · example enabled · specs/consumers/obsidian-vault.notes.unresolved-mention-stays.sdp.md
  • test:protocol.vault-priority · anchored · test anchor binding present · test/vault.test.ts:53

    External run evidence from test/vault.test.ts

    Test anchors: test:protocol.vault-priority. Specs verified by those bindings: spec:consumers.obsidian-vault.notes.

    Run 1: external run evidence from vitest 4.1.10

    Build: CI 380 · Branch: feature/roadmap-and-slices-v0 · Commit: 34909918bf0be0e849959644401797191cae379f · Start: 2026-10-22T17:40:31.456Z · Stop: 2026-10-22T17:42:16.171Z

    NameSuiteResultDuration
    writes a fresh vault from the CLInot recordedpassed20.11 ms
    changes the Pack note's meaning when only advisory priority changesnot recordedpassed8.45 ms
    refuses vault placement generated/graph.json before the build changes anythingnot recordedpassed2.01 ms
    refuses vault placement generated/graph.json.tmp before the build changes anythingnot recordedpassed1.16 ms
    refuses vault placement generated/contracts before the build changes anythingnot recordedpassed1.16 ms
    refuses vault placement generated/contracts.tmp before the build changes anythingnot recordedpassed1.06 ms
    refuses vault placement generated/registrars.json before the build changes anythingnot recordedpassed1 ms
    refuses vault placement generated/registrars.json.tmp before the build changes anythingnot recordedpassed1.04 ms
    refuses vault placement generated/imports.json before the build changes anythingnot recordedpassed1.16 ms
    refuses vault placement generated/imports.json.tmp before the build changes anythingnot recordedpassed1.09 ms
    refuses vault placement generated/design-review before the build changes anythingnot recordedpassed1.18 ms
    refuses vault placement generated/design-review.tmp before the build changes anythingnot recordedpassed4.25 ms
    refuses vault placement generated/census before the build changes anythingnot recordedpassed1.12 ms
    refuses vault placement generated/census.tmp before the build changes anythingnot recordedpassed1.87 ms
    refuses vault placement generated/mermaid before the build changes anythingnot recordedpassed1.1 ms
    refuses vault placement generated/mermaid.tmp before the build changes anythingnot recordedpassed1.13 ms
    refuses vault placement generated/gherkin before the build changes anythingnot recordedpassed0.86 ms
    refuses vault placement generated/gherkin.tmp before the build changes anythingnot recordedpassed4.68 ms
    refuses vault placement generated/spec-studio before the build changes anythingnot recordedpassed1.09 ms
    refuses vault placement generated/spec-studio.tmp before the build changes anythingnot recordedpassed1.53 ms
    refuses vault placement generated/Design-Review before the build changes anythingnot recordedpassed0.76 ms
    refuses vault placement generated/CONTRACTS/new before the build changes anythingnot recordedpassed0.84 ms
    refuses vault placement generated before the build changes anythingnot recordedpassed0.71 ms
    refuses vault placement . before the build changes anythingnot recordedpassed0.76 ms
    refuses discoverable notes before the buildnot recordedpassed0.98 ms
    refuses discoverable src/vault before the buildnot recordedpassed0.89 ms
    accepts an explicitly excluded vault and a vault outside the extraction rootnot recordedpassed12.34 ms
    refuses invalid vault options "--root"not recordedpassed0.2 ms
    refuses invalid vault options "--out"not recordedpassed0.07 ms
    refuses invalid vault options "--root"not recordedpassed0.05 ms
    refuses invalid vault options "--out"not recordedpassed0.05 ms
    refuses invalid vault options "--root"not recordedpassed0.05 ms
    refuses invalid vault options "--out"not recordedpassed0.24 ms
    refuses invalid vault options "."not recordedpassed0.07 ms
    refuses invalid vault options "--root"not recordedpassed0.05 ms
    refuses invalid vault options "--check-clean"not recordedpassed0.05 ms
    refuses invalid vault options "--vault"not recordedpassed0.04 ms
    refuses invalid vault options "--wat"not recordedpassed0.04 ms
    rejects malformed lists, including duplicate and reordered pathsnot recordedpassed1.5 ms
    guards hidden unknowns, changed notes, links and special files without cleanupnot recordedpassed12.78 ms
    refuses a symlink as the generated foldernot recordedpassed0.35 ms
    recognizes a complete interrupted note and refuses a truncated temporarynot recordedpassed3.63 ms
    escapes Obsidian constructs and preserves other code spansnot recordedpassed3.61 ms
    renders unresolved relation ends and missing exercised rules as codenot recordedpassed5.03 ms
    puts subject findings on notes and every other finding on the indexnot recordedpassed2.73 ms
    keeps build outputs untouched on a case collisionnot recordedpassed2.83 ms
    makes generate refuse an edited vault before invalidating any rootnot recordedpassed14.86 ms
    uses --vault for generate and leaves it alone in check modenot recordedpassed97.8 ms
    preserves literal backslashes before escaped Obsidian constructsnot recordedpassed0.56 ms
    orders integer-looking file-list paths by code unitsnot recordedpassed0.37 ms
    vault preserves a note saved during extractionnot recordedpassed13.75 ms
    generate preserves a note saved during extractionnot recordedpassed8.76 ms
    vault preserves a note saved during failed extractionnot recordedpassed9.9 ms
    generate preserves a note saved during failed extractionnot recordedpassed14.19 ms
    rejects stale synchronization state before writing a transitional listnot recordedpassed1.01 ms
    keeps rule block ids separate from example-space prosenot recordedpassed3.14 ms
    rejects links whose target block id has a lazy paragraph continuationnot recordedpassed1.15 ms
    refuses case collisions in family directories before changing any filenot recordedpassed2.09 ms
    vault renders only extraction errors in the failed indexnot recordedpassed3.43 ms
    generate renders only extraction errors in the failed indexnot recordedpassed2.9 ms
    prunes every empty directory under sdp after removing stale notesnot recordedpassed1.32 ms
    refuses a vault holding a prior registrar sibling before the buildnot recordedpassed1.76 ms
    wraps the generate help paragraph within the established widthnot recordedpassed0.18 ms

Example space

  • source · string · declared by a corpus holding the Spec {source} whose narrative mentions {mention}
  • mention · string · declared by a corpus holding the Spec {source} whose narrative mentions {mention}
  • first · string · declared by a corpus holding the Specs {first} and {second}
  • second · string · declared by a corpus holding the Specs {first} and {second}
  • target · string · declared by the Spec {target} keys the Design entry {key}
  • key · string · declared by the Spec {target} keys the Design entry {key}
  • termSpec · string · declared by the Spec {termSpec} defines a Model term with the key {termKey}
  • termKey · string · declared by the Spec {termSpec} defines a Model term with the key {termKey}

Bound points

ExamplesourcementionfirstsecondtargetkeytermSpectermKey
spec:consumers.obsidian-vault.notes.case-collision-refusedunboundunbound"spec:probe.Member""spec:probe.member"unboundunboundunboundunbound
spec:consumers.obsidian-vault.notes.entry-address-link"spec:probe.source""spec:probe.target#design.limit"unboundunbound"spec:probe.target""limit"unboundunbound
spec:consumers.obsidian-vault.notes.term-address-link"spec:probe.source""spec:probe.target#term.limit"unboundunboundunboundunbound"spec:probe.target""limit"
spec:consumers.obsidian-vault.notes.unresolved-mention-stays"spec:probe.source""spec:probe.target#design.missing"unboundunbound"spec:probe.target""limit"unboundunbound

Oracle binding: present · oracle:protocol.vault-notes · test/vault-examples.test.ts:291

Coverage

source: "spec:probe.source" · spec:consumers.obsidian-vault.notes.entry-address-link, spec:consumers.obsidian-vault.notes.term-address-link, spec:consumers.obsidian-vault.notes.unresolved-mention-stays · not enumerable

mention: "spec:probe.target#design.limit" · spec:consumers.obsidian-vault.notes.entry-address-link; "spec:probe.target#term.limit" · spec:consumers.obsidian-vault.notes.term-address-link; "spec:probe.target#design.missing" · spec:consumers.obsidian-vault.notes.unresolved-mention-stays · not enumerable

first: "spec:probe.Member" · spec:consumers.obsidian-vault.notes.case-collision-refused · not enumerable

second: "spec:probe.member" · spec:consumers.obsidian-vault.notes.case-collision-refused · not enumerable

target: "spec:probe.target" · spec:consumers.obsidian-vault.notes.entry-address-link, spec:consumers.obsidian-vault.notes.unresolved-mention-stays · not enumerable

key: "limit" · spec:consumers.obsidian-vault.notes.entry-address-link, spec:consumers.obsidian-vault.notes.unresolved-mention-stays · not enumerable

termSpec: "spec:probe.target" · spec:consumers.obsidian-vault.notes.term-address-link · not enumerable

termKey: "limit" · spec:consumers.obsidian-vault.notes.term-address-link · not enumerable

Unbound

Design view

Requirement drawing

Requirement drawing for spec:consumers.obsidian-vault.notes
The diagram as text
  • spec:consumers.obsidian-vault.notes: Every Spec, Pack, code unit and keyed term is a note, and every relation is a link · declared Spec
  • spec:consumers.obsidian-vault.notes.case-collision-refused: Two Specs whose notes differ only in case refuse the run · declared Spec
  • spec:consumers.obsidian-vault.notes.entry-address-link: An entry address in prose opens the entry's block in its Spec's note · declared Spec
  • spec:consumers.obsidian-vault.notes.term-address-link: A keyed Model term gets a note, and its address in prose opens the term's block · declared Spec
  • spec:consumers.obsidian-vault.notes.unresolved-mention-stays: A mention of an entry that does not exist stays as written · declared Spec
  • spec:consumers.obsidian-vault: An Obsidian vault lets a person iterate on designs from the one graph · declared Spec
  • impl:protocol.vault-notes: renders reader contexts, declared relations and keyed terms as linked notes · anchored code · src/projections/vault/notes.ts:45
  • impl:protocol.vault-sections: renders sections in graph order with keyed entry block ids · anchored code · src/projections/vault/sections.ts:10
  • impl:protocol.vault-text: renders checked mentions and escapes Obsidian syntax outside code spans · anchored code · src/projections/vault/text.ts:30
  • oracle:protocol.vault-notes: oracle:protocol.vault-notes · anchored oracle binding · test/vault-examples.test.ts:291
  • test:protocol.consumers.obsidian-vault.notes.case-collision-refused: test:protocol.consumers.obsidian-vault.notes.case-collision-refused · anchored test binding · binding present · test/vault-examples.test.ts:740
  • test:protocol.consumers.obsidian-vault.notes.entry-address-link: test:protocol.consumers.obsidian-vault.notes.entry-address-link · anchored test binding · binding present · test/vault-examples.test.ts:719
  • test:protocol.consumers.obsidian-vault.notes.term-address-link: test:protocol.consumers.obsidian-vault.notes.term-address-link · anchored test binding · binding present · test/vault-examples.test.ts:733
  • test:protocol.consumers.obsidian-vault.notes.unresolved-mention-stays: test:protocol.consumers.obsidian-vault.notes.unresolved-mention-stays · anchored test binding · binding present · test/vault-examples.test.ts:726
  • test:protocol.vault-priority: test:protocol.vault-priority · anchored test binding · binding present · test/vault.test.ts:53
  • spec:consumers.obsidian-vault.notes refines spec:consumers.obsidian-vault · declared
  • spec:consumers.obsidian-vault.notes.case-collision-refused refines spec:consumers.obsidian-vault.notes · declared
  • spec:consumers.obsidian-vault.notes.case-collision-refused verifies spec:consumers.obsidian-vault.notes · declared
  • spec:consumers.obsidian-vault.notes.entry-address-link refines spec:consumers.obsidian-vault.notes · declared
  • spec:consumers.obsidian-vault.notes.entry-address-link verifies spec:consumers.obsidian-vault.notes · declared
  • spec:consumers.obsidian-vault.notes.term-address-link refines spec:consumers.obsidian-vault.notes · declared
  • spec:consumers.obsidian-vault.notes.term-address-link verifies spec:consumers.obsidian-vault.notes · declared
  • spec:consumers.obsidian-vault.notes.unresolved-mention-stays refines spec:consumers.obsidian-vault.notes · declared
  • spec:consumers.obsidian-vault.notes.unresolved-mention-stays verifies spec:consumers.obsidian-vault.notes · declared
  • impl:protocol.vault-notes satisfies spec:consumers.obsidian-vault.notes · anchored
  • impl:protocol.vault-sections satisfies spec:consumers.obsidian-vault.notes · anchored
  • impl:protocol.vault-text satisfies spec:consumers.obsidian-vault.notes · anchored
  • oracle:protocol.vault-notes models spec:consumers.obsidian-vault.notes · anchored
  • test:protocol.consumers.obsidian-vault.notes.case-collision-refused verifies spec:consumers.obsidian-vault.notes.case-collision-refused · anchored
  • test:protocol.consumers.obsidian-vault.notes.entry-address-link verifies spec:consumers.obsidian-vault.notes.entry-address-link · anchored
  • test:protocol.consumers.obsidian-vault.notes.term-address-link verifies spec:consumers.obsidian-vault.notes.term-address-link · anchored
  • test:protocol.consumers.obsidian-vault.notes.unresolved-mention-stays verifies spec:consumers.obsidian-vault.notes.unresolved-mention-stays · anchored
  • test:protocol.vault-priority verifies spec:consumers.obsidian-vault.notes · anchored
Mermaid source

Copyable source; the Studio draws static SVG.

Preferred syntax: requirementDiagram. Chosen syntax: flowchart TB because models, folds require exact labels unavailable in requirement syntax.

Decisions

No decision record named.

Runtime
  • component:protocol.projections · read-only output, layout and owned publication · src/projections/design-review.ts:29 · layer edge · context protocol

    Uses

    • component:protocol.extract · the carrier and source pipeline · src/extract/index.ts:192 · layer application · context protocol
    • component:protocol.graph · the one graph and its semantic decisions · src/graph/schema.ts:34 · layer domain · context protocol
    • component:protocol.model · the authored contracts and stable ids · src/model/anchors.ts:100 · layer domain · context protocol
    • component:protocol.notation · the leaf step codec · src/notation/slots.ts:261 · layer domain · context protocol
    • component:protocol.reader · the typed graph contract and body evaluator · src/reader/reader.ts:671 · layer application · context protocol
    • component:protocol.validate · one finding currency and ordered checks · src/validate/validators.ts:72 · layer domain · context protocol
  • impl:protocol.vault-notes · renders reader contexts, declared relations and keyed terms as linked notes · src/projections/vault/notes.ts:45

    Component: component:protocol.projections · read-only output, layout and owned publication · src/projections/design-review.ts:29 · layer edge · context protocol

    Uses

    • impl:protocol.reader · typed graph queries, entry adapters and context joins · src/reader/reader.ts:687
  • impl:protocol.vault-sections · renders sections in graph order with keyed entry block ids · src/projections/vault/sections.ts:10

    Component: component:protocol.projections · read-only output, layout and owned publication · src/projections/design-review.ts:29 · layer edge · context protocol

    Uses

    None.

  • impl:protocol.vault-text · renders checked mentions and escapes Obsidian syntax outside code spans · src/projections/vault/text.ts:30

    Component: component:protocol.projections · read-only output, layout and owned publication · src/projections/design-review.ts:29 · layer edge · context protocol

    Uses

    None.

Runtime observation: not tracked.

Evidence

Runtime observation: not tracked.

Build attestations: not tracked.

Deployments: not tracked.

Bills of materials: not tracked.

Impact
Relations of spec:consumers.obsidian-vault.notes
The diagram as text
  • spec:consumers.binding-language-views: Views speak binding language, never the internal fact name
  • spec:consumers.obsidian-vault: An Obsidian vault lets a person iterate on designs from the one graph
  • spec:consumers.obsidian-vault.notes: Every Spec, Pack, code unit and keyed term is a note, and every relation is a link
  • spec:consumers.obsidian-vault.notes.case-collision-refused: Two Specs whose notes differ only in case refuse the run
  • spec:consumers.obsidian-vault.notes.entry-address-link: An entry address in prose opens the entry's block in its Spec's note
  • spec:consumers.obsidian-vault.notes.term-address-link: A keyed Model term gets a note, and its address in prose opens the term's block
  • spec:consumers.obsidian-vault.notes.unresolved-mention-stays: A mention of an entry that does not exist stays as written
  • spec:consumers.vault-on-ramp: The vault skill teaches agents to keep an Obsidian vault of the graph
  • spec:model.term-addresses: A Model term may carry a key that addresses it
  • spec:validation.prose-mentions: Every Spec id written in prose resolves
  • spec:consumers.obsidian-vault.notes dependsOn spec:consumers.binding-language-views · declared — rendered binding labels must state existence rather than liveness
  • spec:consumers.obsidian-vault.notes dependsOn spec:model.term-addresses · declared — a term note exists for a Model term that carries a key and so an address
  • spec:consumers.obsidian-vault.notes dependsOn spec:validation.prose-mentions · declared — a mention can become a link because validation already refuses one that does not resolve
  • spec:consumers.obsidian-vault.notes refines spec:consumers.obsidian-vault · declared
  • spec:consumers.vault-on-ramp dependsOn spec:consumers.obsidian-vault.notes · declared — the skill converts a note name or block id back to the id or entry address it names
  • spec:consumers.obsidian-vault.notes.case-collision-refused refines spec:consumers.obsidian-vault.notes · declared
  • spec:consumers.obsidian-vault.notes.entry-address-link refines spec:consumers.obsidian-vault.notes · declared
  • spec:consumers.obsidian-vault.notes.term-address-link refines spec:consumers.obsidian-vault.notes · declared
  • spec:consumers.obsidian-vault.notes.unresolved-mention-stays refines spec:consumers.obsidian-vault.notes · declared
  • spec:consumers.obsidian-vault.notes.case-collision-refused verifies spec:consumers.obsidian-vault.notes · declared
  • spec:consumers.obsidian-vault.notes.entry-address-link verifies spec:consumers.obsidian-vault.notes · declared
  • spec:consumers.obsidian-vault.notes.term-address-link verifies spec:consumers.obsidian-vault.notes · declared
  • spec:consumers.obsidian-vault.notes.unresolved-mention-stays verifies spec:consumers.obsidian-vault.notes · declared
Mermaid source

Copyable source; the Studio draws static SVG.

Preferred syntax: flowchart. Chosen syntax: labelled flowchart, preserving exact relations, claims and folds.

Rests on

Rested on by

Distance 1

Relations

Relation and directionOther endClaimReasonExercised keys
dependsOn · outgoingViews speak binding language, never the internal fact name
spec:consumers.binding-language-views · resolves
declaredrendered binding labels must state existence rather than livenessNone
dependsOn · outgoingA Model term may carry a key that addresses it
spec:model.term-addresses · resolves
declareda term note exists for a Model term that carries a key and so an addressNone
dependsOn · outgoingEvery Spec id written in prose resolves
spec:validation.prose-mentions · resolves
declareda mention can become a link because validation already refuses one that does not resolveNone
refines · outgoingAn Obsidian vault lets a person iterate on designs from the one graph
spec:consumers.obsidian-vault · resolves
declaredNoneNone
dependsOn · incomingThe vault skill teaches agents to keep an Obsidian vault of the graph
spec:consumers.vault-on-ramp · resolves
declaredthe skill converts a note name or block id back to the id or entry address it namesNone
refines · incomingTwo Specs whose notes differ only in case refuse the run
spec:consumers.obsidian-vault.notes.case-collision-refused · resolves
declaredNoneNone
refines · incomingAn entry address in prose opens the entry's block in its Spec's note
spec:consumers.obsidian-vault.notes.entry-address-link · resolves
declaredNoneNone
refines · incomingA keyed Model term gets a note, and its address in prose opens the term's block
spec:consumers.obsidian-vault.notes.term-address-link · resolves
declaredNoneNone
refines · incomingA mention of an entry that does not exist stays as written
spec:consumers.obsidian-vault.notes.unresolved-mention-stays · resolves
declaredNoneNone
verifies · incomingTwo Specs whose notes differ only in case refuse the run
spec:consumers.obsidian-vault.notes.case-collision-refused · resolves
declaredNonecaseCollision
verifies · incomingAn entry address in prose opens the entry's block in its Spec's note
spec:consumers.obsidian-vault.notes.entry-address-link · resolves
declaredNonenoteNames, idInAliases, blockIds, mentionLinks
verifies · incomingA keyed Model term gets a note, and its address in prose opens the term's block
spec:consumers.obsidian-vault.notes.term-address-link · resolves
declaredNoneoneNotePer, blockIds, mentionLinks
verifies · incomingA mention of an entry that does not exist stays as written
spec:consumers.obsidian-vault.notes.unresolved-mention-stays · resolves
declaredNonementionLinks

Bindings

Implementation binding: present

  • impl:protocol.vault-notes · renders reader contexts, declared relations and keyed terms as linked notes · src/projections/vault/notes.ts:45 · role projection · component component:protocol.projections · layer edge · context protocol
  • impl:protocol.vault-sections · renders sections in graph order with keyed entry block ids · src/projections/vault/sections.ts:10 · role projection · component component:protocol.projections · layer edge · context protocol
  • impl:protocol.vault-text · renders checked mentions and escapes Obsidian syntax outside code spans · src/projections/vault/text.ts:30 · role codec · component component:protocol.projections · layer edge · context protocol

Design reference: none

Verifier binding: present

Expected-outcome oracle: present

  • oracle:protocol.vault-notes · test/vault-examples.test.ts:291

Runtime observation: not tracked.

Run results: not recorded in the graph.

Findings

None.

Composing (0)

Composing needs the script.