Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
139 commits
Select commit Hold shift + click to select a range
209f555
evidence: open the whole-repository review
darko-mijic Nov 3, 2026
4e78fd1
evidence: add the product-lens lanes to the review
darko-mijic Nov 3, 2026
5f528a1
chore(temporal): exempt an arc's evidence directory
darko-mijic Nov 3, 2026
1f25cd8
evidence: the whole-repository review's findings, inventory and proposal
darko-mijic Nov 3, 2026
aa0eb4f
evidence: open the arc that executes the whole-repository review
darko-mijic Nov 3, 2026
8503030
docs: correct the handbook, registry, recipe catalog, skill and walkt…
darko-mijic Nov 3, 2026
684844e
evidence: record the owner's rulings on the inventory
darko-mijic Nov 3, 2026
d46f634
fix(validate): close honesty and carrier gaps from the whole-reposito…
darko-mijic Nov 3, 2026
acc0bd5
fix(runner): dispatch shared contract keys by phase and refuse an uns…
darko-mijic Nov 3, 2026
61e8776
test: bind the body-grammar and structural-anchor regression suites a…
darko-mijic Nov 3, 2026
2094790
specs: apply the review's proposal on the agent surface and accepted …
darko-mijic Nov 3, 2026
47d5382
specs: capture the review's deferred questions and settle the ruled ones
darko-mijic Nov 3, 2026
292fb23
fix(cli): keep writes inside the root and stop discovery following links
darko-mijic Nov 3, 2026
3cecfc2
fix: polish the CLI, extractor and package surface from the review
darko-mijic Nov 3, 2026
e099c1c
merge: lane C, corpus
darko-mijic Nov 3, 2026
ba1293a
merge: lane W, writes-inside-the-root
darko-mijic Nov 3, 2026
a78af60
merge: lane H1, honesty-and-carriers
darko-mijic Nov 3, 2026
3e8ff1e
merge: lane H2, verification-runtime
darko-mijic Nov 3, 2026
60442ce
merge: lane P, cli-and-package-polish
darko-mijic Nov 3, 2026
58a1690
merge: lane D, docs-and-vocabulary
darko-mijic Nov 3, 2026
4ab1616
fix: integrate the review lanes
darko-mijic Nov 3, 2026
339081b
fix(extract): warn only for symbolic links that could hide a carrier …
darko-mijic Nov 3, 2026
53ad8d9
fix(studio): label gathered intents and preview the hand-off memo
darko-mijic Nov 3, 2026
4b3c485
specs(studio): rule that a Pack export leaves the slice page out
darko-mijic Nov 3, 2026
5c902a4
merge: lane S, studio-rulings
darko-mijic Nov 3, 2026
8baaeb7
merge: lane L, link-warning-scope
darko-mijic Nov 3, 2026
c70bf10
evidence: record the arc's results and open items
darko-mijic Nov 3, 2026
6780da5
fix(carrier): reserve kind in Then slots
darko-mijic Nov 3, 2026
1190c7d
merge: lane K, reserve-kind
darko-mijic Nov 3, 2026
c7368f4
evidence: record lane K
darko-mijic Nov 3, 2026
9022632
test(temporal): pin each genre exemption to the repository root
darko-mijic Nov 3, 2026
5226242
fix(extract): trust the extracted protocol package's own builders
darko-mijic Nov 3, 2026
29810f1
fix(runtime): require own properties for handlers and authored data
darko-mijic Nov 3, 2026
1c54770
docs(jtbd): narrow the panel's preview promise and name the shipped c…
darko-mijic Nov 3, 2026
3e5445d
docs(vocabulary): gloss carrier at both levels and keep the README's …
darko-mijic Nov 3, 2026
78e9e70
fix(codegen): reserve the coverage gap and avoid runtime name collisions
darko-mijic Nov 3, 2026
7aa5d99
fix(carriers): refuse reserved derived properties consistently
darko-mijic Nov 3, 2026
6140b97
fix(markdown): refuse block shapes with linear scans
darko-mijic Nov 3, 2026
f3bf5f6
test(runtime): type regression handlers and assertion callbacks
darko-mijic Nov 3, 2026
bdadb47
docs(skills): teach the Studio input refusal the command and its help…
darko-mijic Nov 3, 2026
613fc3e
docs(temporal): stop the guard's header calling the decision registry…
darko-mijic Nov 3, 2026
792247f
docs(recipes): name every recipe that reports an absent Spec or epic …
darko-mijic Nov 3, 2026
0b06088
specs(protocol): record the owner's acceptance of the inventory on th…
darko-mijic Nov 3, 2026
948a9c1
fix(cli): recheck output boundaries during publication and recovery
darko-mijic Nov 3, 2026
cccd91e
fix(cli): create scaffold parents through held directories
darko-mijic Nov 3, 2026
ad566d6
fix(ci): stamp only freshly published studio previews
darko-mijic Nov 3, 2026
3dedfaa
docs(evidence): record the owner's rulings and make the inventory exact
darko-mijic Nov 3, 2026
bc78c8c
test(docs): fail the gate on a relative Markdown link that reaches no…
darko-mijic Nov 3, 2026
410139d
fix(reader): place every body parse error at the engine's own position
darko-mijic Nov 3, 2026
798558b
fix(test): route every test-wrapper argument form through Vitest's ow…
darko-mijic Nov 3, 2026
c1f8698
fix(extract): judge a skipped link by the entry it stands for
darko-mijic Nov 3, 2026
527e005
fix(watch): rerun on skipped links and drop replaced directories
darko-mijic Nov 3, 2026
5c5f5ca
fix(reader): read an unratified kind or altitude as a floor not evalu…
darko-mijic Nov 3, 2026
05c3938
fix(package): declare the Node range the CommonJS root needs and type…
darko-mijic Nov 3, 2026
678d043
fix(extract): read anchor comment lines linearly at every line termin…
darko-mijic Nov 3, 2026
08f434d
fix(carrier): refuse line terminators inside Gherkin description lines
darko-mijic Nov 3, 2026
80b2b24
test(extract): verify commonjs root trust and correct base graph guid…
darko-mijic Nov 3, 2026
278ca50
fix(validate): keep prose, slot and search scans linear
darko-mijic Nov 3, 2026
2d27853
test(extract): write line separators in test sources as escapes
darko-mijic Nov 3, 2026
a51bf5c
test(vault): stop the vault snapshot helper racing the sync's staging…
darko-mijic Nov 3, 2026
a854865
fix(test): read link destinations across lines and skip fences inside…
darko-mijic Nov 3, 2026
9b1dc67
fix(markdown): align fence refusal diagnostics
darko-mijic Nov 3, 2026
46869d8
fix(watch): remember a replacement link when dropping a replaced ance…
darko-mijic Nov 3, 2026
49681b3
fix(codegen): index reserved then key checks
darko-mijic Nov 3, 2026
a9f9417
test: give the slow suites budgets that hold under a loaded parallel run
darko-mijic Nov 3, 2026
acc4b06
fix(cli): separate vault placement from publication checks
darko-mijic Nov 3, 2026
ee4942e
fix(projections): label a floor not evaluated in the Design Review, c…
darko-mijic Nov 3, 2026
88d03b6
fix(test): read documentation links with cmark-gfm's block and inline…
darko-mijic Nov 3, 2026
c722b6e
docs(skill): describe the extracted root's builder trust
darko-mijic Nov 3, 2026
4e7e9f9
evidence: open the second review pass over PRs #34, #38 and #39
darko-mijic Nov 3, 2026
5096fc5
merge: lane X4, linear scans and line terminators
darko-mijic Nov 3, 2026
d4cf35b
merge: lane X5, runtime and contract generation
darko-mijic Nov 3, 2026
9906ba6
merge: lane X8, builder trust and determinism
darko-mijic Nov 3, 2026
1dd632e
fix(gherkin): correct lookalike refusal wording
darko-mijic Nov 3, 2026
400e24f
specs(cli): state the scaffold write boundary
darko-mijic Nov 3, 2026
4b8a00b
test(projections): read a floor not evaluated through the root export…
darko-mijic Nov 3, 2026
b230006
fix(test): read the package-manager separator once and forward bench …
darko-mijic Nov 3, 2026
ccb9058
fix(watch): keep a link into a build output from the owned-output filter
darko-mijic Nov 3, 2026
a50a11b
fix(test): decode every named character reference before the link gat…
darko-mijic Nov 3, 2026
44cbfd0
fix(test): skip code examples, comments and HTML-block Markdown in th…
darko-mijic Nov 3, 2026
bd96f52
merge: lane X1, writes stay inside the root
darko-mijic Nov 3, 2026
4c99acf
merge: lane X2, discovery and watch links
darko-mijic Nov 3, 2026
eb29ea5
merge: lane X3, carrier honesty and block shapes
darko-mijic Nov 3, 2026
7e8aeee
merge: lane X6, readiness not evaluated
darko-mijic Nov 3, 2026
3da51b8
merge: lane X7, CLI, package and test infrastructure
darko-mijic Nov 3, 2026
3a22c91
merge: lane X9, docs and vocabulary
darko-mijic Nov 3, 2026
4e43119
fix(extract): share compiler line locations across typescript authoring
darko-mijic Nov 4, 2026
6bf0d68
fix(carriers): clarify reserved properties and refuse empty lists
darko-mijic Nov 4, 2026
659a030
fix(gherkin): refuse embedded line separators in titles and steps
darko-mijic Nov 4, 2026
4d00db4
fix(runner): preserve class-instance step handlers
darko-mijic Nov 4, 2026
fcee9b0
fix(reader): guard kind labels against inherited properties
darko-mijic Nov 4, 2026
b421065
fix(cli): create registrar parents through held directories
darko-mijic Nov 4, 2026
c6587fe
fix(codegen): index example-space children once
darko-mijic Nov 4, 2026
2f27e4a
fix(recipes): count unratified dependency readiness
darko-mijic Nov 4, 2026
7456699
fix(stamp): remove the staging file when a stamp fails
darko-mijic Nov 4, 2026
d9e6972
fix(vault): refuse a default vault only when it resolves outside the …
darko-mijic Nov 4, 2026
b3c21b8
fix(watch): watch a directory that replaces a watched one
darko-mijic Nov 4, 2026
d97b8b2
test(watch): pin the reconciliation of a replaced or vanished directory
darko-mijic Nov 4, 2026
f662a7e
test(new-spec): pin each containment recheck of the scaffold write bo…
darko-mijic Nov 4, 2026
36588a8
docs(cli): say in `sdp new spec --help` where PATH must resolve
darko-mijic Nov 4, 2026
5b21448
docs(cli): say that the build's filesystem hooks see every guarded mu…
darko-mijic Nov 4, 2026
8c694a3
docs(skills): teach where a linked default vault may lead
darko-mijic Nov 4, 2026
2532ee0
fix(extract): locate typescript parse errors with compiler lines
darko-mijic Nov 4, 2026
738df5e
test(watch): type the injected lstat hook as node's Stats
darko-mijic Nov 4, 2026
f97cd62
test: keep two tests independent of where the temporary directory sits
darko-mijic Nov 4, 2026
611e1bd
test: give three more slow tests budgets that hold under load
darko-mijic Nov 4, 2026
2ccbb54
fix(test): merge a split run's reports into the one report the caller…
darko-mijic Nov 4, 2026
16ec924
test(links): check each link's fragment against the headings of the p…
darko-mijic Nov 4, 2026
db340c9
test(links): check the notes written for docs/lineage, not only the o…
darko-mijic Nov 4, 2026
126871d
fix(runner): refuse inherited constructors as step handlers
darko-mijic Nov 4, 2026
f9aacdd
fix(gherkin): guard kind explanations against inherited properties
darko-mijic Nov 4, 2026
a11a4ec
fix(test): merge a split run's reports with the configuration its pas…
darko-mijic Nov 4, 2026
19151fa
fix(runner): refuse function prototype methods as step handlers
darko-mijic Nov 4, 2026
a84d350
fix(watch): watch a directory that replaces the root
darko-mijic Nov 4, 2026
498b9b9
test(links): skip headings inside HTML comments and check query-only …
darko-mijic Nov 4, 2026
59077d3
fix(test): merge a split run's reports when its configuration file as…
darko-mijic Nov 4, 2026
e6bbb6d
merge: lane W1, runtime, reader and recipes
darko-mijic Nov 4, 2026
111f5f0
merge: lane W2, writes, vault, stamp, scaffold and watch
darko-mijic Nov 4, 2026
16ae0b9
merge: lane W3, carrier text and honesty wording
darko-mijic Nov 4, 2026
a36aa91
fix(test): read the configuration in Vitest's test environment before…
darko-mijic Nov 4, 2026
e9b2761
merge: lane W4, test infrastructure and the link gate
darko-mijic Nov 4, 2026
1224617
merge: the whole-repository review from PR #38
darko-mijic Nov 4, 2026
1cf0c71
fix(runner): enforce dispatch boundaries across realms
darko-mijic Nov 4, 2026
712f182
fix(recipes): keep foreign readiness tallies accurate
darko-mijic Nov 4, 2026
3e4475e
specs(carrier): state the end-of-line block openers and single-letter…
darko-mijic Nov 4, 2026
781fed5
fix(gherkin): name the owning Spec on title and step line refusals
darko-mijic Nov 4, 2026
d6c2384
fix(test): load the configuration the passes load and check the html …
darko-mijic Nov 4, 2026
763f6be
fix(carriers): refuse a lone CR, U+2028 or U+2029 in every carrier
darko-mijic Nov 4, 2026
981de63
fix(watch): rebuild a watched directory only when it was replaced or …
darko-mijic Nov 4, 2026
9a66ded
fix(extract): read only the strings a TypeScript Spec or Pack keeps f…
darko-mijic Nov 4, 2026
b499f72
fix(test): look a configuration up with the resolver Vitest uses
darko-mijic Nov 4, 2026
47655cf
fix(watch): tell a directory's own report from its own-name entry by …
darko-mijic Nov 4, 2026
2f08902
fix(watch): read a directory only when the watch first watches it
darko-mijic Nov 4, 2026
e82f9d0
merge: lane V1, runner dispatch and recipe tallies
darko-mijic Nov 4, 2026
0eeee74
merge: lane V2, line separators and keyed-entry wording
darko-mijic Nov 4, 2026
f5f7fd5
merge: lane V3, test wrapper reporting and watcher replacement
darko-mijic Nov 4, 2026
bcd2815
evidence: record the second pass's findings and its later rounds
darko-mijic Nov 4, 2026
87eda05
fix: address model review findings on PR 40
darko-mijic Nov 4, 2026
93cf419
fix: preserve cmark comment and reference semantics
darko-mijic Nov 4, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 21 additions & 9 deletions .agents/skills/sdp-agent-surface/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,17 @@ operator-supplied code with the trust of any local developer tool — no sandbox
is code **you author yourself**; never execute a body sourced from corpus content or any other
untrusted text — it runs with the process's full authority.

## The entry adapters
## Entry adapters and reader joins

An agent arrives holding a string, a file or a changeset, not the Spec id it wants, so the entry
adapters are `g.findByConcept(term)`, `g.byFile(path)` and `g.blastRadius(files)`
(`spec:consumers.agent-surface#rule.entryAdapters`). `g.specContext(id)`, `g.packContext(id)` and
`g.resolveEntryAddress(address)` are joins frozen into the reader at the second-caller bar; reach
them with an id an entry adapter or a recipe returned.

`g.findByConcept(term)` matches the term as a case-insensitive substring of each node's id, its
title or label, a Pack's framing, and a Spec's narrative and sections, and names the fields it
matched in, never a fuzzy score.
`g.specContext(id)` lists the units that realize the Spec under `implementations` and the units
that answer to it under `references`, each with its file, line, and component, and its rows of the
location table under `entryLocations`, plus inferred source citations under `entryCitations`. `g.packContext(id)` carries the Pack design: each member's
Expand All @@ -225,10 +234,11 @@ current (`spec:consumers.wholesale-view-rewrite#rule.buildInvalidates`).
graph, synchronizes the vault first except under `--check-clean`, and writes the Studio without
optional inputs: it takes neither `--base` nor `--runs`.
- Use `sdp studio` for a page set with `--base PATH`, `--base-label TEXT`, or repeatable
`--runs PATH`; that run invalidates the other four page roots. Keep supplied inputs outside the
paths the build writes or removes, `generated/` included
(`spec:consumers.spec-studio.data.inputs`). `sdp studio --watch` rebuilds after carrier edits;
source and input edits start no cycle (`spec:consumers.spec-studio.publisher.watch`).
`--runs PATH`; that run invalidates the other four page roots. Keep supplied inputs outside
`generated/`: the run refuses an input at a path the build writes or removes, such as
`generated/graph.json` or a file beneath a page root (`spec:consumers.spec-studio.data.inputs`).
`sdp studio --watch` rebuilds after carrier edits; source and input edits start no cycle
(`spec:consumers.spec-studio.publisher.watch`).
- After the final Studio build, run `sdp stamp` with the corpus commit, then upload the stamped
page set. A later build removes the stamp
(`spec:consumers.spec-studio.sharing#rule.stampLifetime`). Follow `sdp-studio` for previews,
Expand Down Expand Up @@ -343,9 +353,10 @@ An empty list or a zero is an answer, and some read as more than they say:

- **Do not parse `.sdp.md` files to answer graph questions.** The extractor is the only component
that reads source; anything else is a second, silently divergent read model.
- **Do not propose new query verbs.** Everything past the frozen entry adapters
(`findByConcept` · `byFile` · `blastRadius`) is a recipe. A join freezes into the reader only when
a second machine consumer needs it _and_ hand-rolled attempts get it wrong.
- **Do not propose new query verbs.** Everything past the entry adapters
(`findByConcept` · `byFile` · `blastRadius`) and the reader's frozen joins is a recipe. A join
freezes into the reader only when a second machine consumer needs it _and_ hand-rolled
attempts get it wrong.
- **Do not read `has-verifier` as "the tests pass."** It says a resolving verifier binding _exists_.
Pass, fail, skip, and quarantine are CI's.
- **Do not read `implemented` as "it is live."** It says a code anchor binds to the Spec. Runtime
Expand All @@ -361,7 +372,8 @@ An empty list or a zero is an answer, and some read as more than they say:
binding from source, `inferred` is machine-derived structure. Carry the claim into your answer.
- **Do not treat stated readiness as derived readiness.** `statedReadiness` is the author's
statement; `derivedReadiness` is the highest rung whose floor clauses pass. Report both when they
disagree.
disagree. A Spec carrying `floorNotEvaluated` has an unratified kind or altitude and no floor was
evaluated: report it as not evaluated, never as below `idea` or as a rung nothing blocks.
- **Do not read narrowing from a field name.** Whether a refinement narrows a decision is that
decision's own text or its relation's reason.
- **Do not author a delivery fact or a derived edge.** They are computed; writing one by hand is an
Expand Down
17 changes: 10 additions & 7 deletions .agents/skills/sdp-authoring/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ runner.
delete, or rename. Findings print and the process stays alive; operator stop (SIGINT) exits 0.
`validate --watch` cannot combine with `--check-clean`. The watcher ignores
`generated`, `dist`, `node_modules`, `coverage`, dot-directories, configured `--exclude` prefixes,
and non-carrier paths, except named rules and parameter files. Events during a run coalesce to
and non-carrier paths, except named rules and parameter files and the symbolic links discovery
warns about. Events during a run coalesce to
one pending rerun. In this source checkout, invoke it through the repository `sdp` script with the three fixture exclusions; do
not invent extra watch flags:

Expand Down Expand Up @@ -397,12 +398,14 @@ or a sandboxed function runtime, imports the same builders from the zero-depende
builders and nothing else.

Trust comes from the import. The builder import must be a Protocol builder binding: the public
package, its `/anchors` subpath, or a relative import that resolves to the package's `ids`, `anchors` or
`model/code-anchor` module. A consumer-local lookalike mints nothing and reports nothing, because
a source file that never bound to the Protocol is not authoring drift to report. On the CommonJS
package surface the trusted relative-module set is empty, so relative bindings mint no anchors
there while package imports stay trusted. When a constant-form anchor fails to appear in the
graph, suspect the import before the syntax.
package, its `/anchors` subpath, or a relative import that resolves to `src/ids.ts`,
`src/anchors.ts` or `src/model/code-anchor.ts` in the running engine's package or in an
extraction root whose own `package.json` names `@libar-dev/software-delivery-protocol`. A
consumer-local lookalike mints nothing and reports nothing, because a source file that never
bound to the Protocol is not authoring drift to report. On the CommonJS package surface,
relative bindings are trusted only in such an extraction root; package imports stay trusted
everywhere. When a constant-form anchor fails to appear in the graph, suspect the import before
the syntax.

### The comment form

Expand Down
11 changes: 6 additions & 5 deletions .agents/skills/sdp-studio/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,12 @@ pnpm --silent sdp studio . --exclude explorations --exclude examples --exclude t
it with that commit's own engine, as the design diff's catalog entry (recipe 35) shows: the
catalog is `docs/agent-surface/recipes.md` in the Protocol repository and
`node_modules/@libar-dev/software-delivery-protocol/docs/agent-surface/recipes.md` in an adopter.
- Keep every input outside `generated/` and every other path the build writes or removes. The run
refuses an input at such a path, `generated/graph.json` among them, before it changes a file
(`spec:consumers.spec-studio.data.inputs#rule.inputPlacement`). Run reports are CTRF JSON files,
one `--runs` each, read in flag order. An unreadable input refuses the run before extraction.
Pages name each input in words, the base by its `--base-label`, and never show its path.
- Keep every input outside `generated/`. The run refuses an input at a path the build writes or
removes, `generated/graph.json` or a file beneath a page root among them, or at a link resolving
to one, before it changes a file (`spec:consumers.spec-studio.data.inputs#rule.inputPlacement`).
Another file under `generated/` is read as given. Run reports are CTRF JSON files, one `--runs`
each, read in flag order. An unreadable input refuses the run before extraction. Pages name each
input in words, the base by its `--base-label`, and never show its path.
- Findings never withhold the page set: the run shows them on the index and on their subject's
page, and returns validate's exit code. A run whose extraction fails publishes nothing.
- `--watch` republishes after every carrier create, change, delete or rename, byte for byte what a
Expand Down
3 changes: 3 additions & 0 deletions .agents/skills/sdp-vault/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ pnpm --silent sdp vault . --exclude explorations --exclude examples --exclude te
`dist/`, `coverage/` or a dot-directory) or under an excluded prefix, and apart from every path
the build writes or removes (`spec:consumers.obsidian-vault#design.buildOwnedPaths`). The run
refuses any other directory before the build, writing nothing.
- A link at the default folder places the vault where it resolves, under the same rules, but never
outside the root: a default that resolves outside the root, or nowhere, refuses the run. Name an
outside vault with `--out` (`spec:consumers.obsidian-vault#rule.defaultInsideRoot`).
- Open the vault directory itself in Obsidian, never its `sdp/` folder: every link and Base filter
names its target by a path from that directory.

Expand Down
14 changes: 14 additions & 0 deletions .github/workflows/studio-preview.yml
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,20 @@ jobs:
if [[ -n "$RUNS_ARTIFACT" && -d "$RUNNER_TEMP/studio-runs" ]]; then
while IFS= read -r -d '' report; do inputs+=(--runs "$report"); done < <(find "$RUNNER_TEMP/studio-runs" -type f -name '*.json' -print0 | sort -z)
fi
# Discard the prior page set before Studio can reject its inputs. A surviving index must be fresh.
node --input-type=module <<'JS'
import { lstatSync, realpathSync, rmSync } from 'node:fs';
import { join, resolve } from 'node:path';
const root = realpathSync(resolve(process.env.ROOT));
const generated = join(root, 'generated');
const state = lstatSync(generated, { throwIfNoEntry: false });
if (state && !state.isDirectory()) throw new Error('generated must be a real directory');
for (const name of ['spec-studio', 'spec-studio.tmp']) {
const current = lstatSync(generated, { throwIfNoEntry: false });
if (current && (!current.isDirectory() || current.dev !== state?.dev || current.ino !== state?.ino)) throw new Error('generated directory changed');
rmSync(join(generated, name), { recursive: true, force: true });
}
JS
studio_status=0
sdp studio "$ROOT" "${exclusions[@]}" "${inputs[@]}" || studio_status=$?
if (( studio_status != 0 )); then
Expand Down
16 changes: 9 additions & 7 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,9 +277,10 @@ that reader brings. The standard, set by PR #19 (the universal-Spec arc) buildin
## Cursor Cloud specific instructions

This repo is a self-contained TypeScript CLI (`sdp`) — no servers, databases, or external services
to run. Development is terminal-driven. Node ≥ 20 (Node 22 is installed); dependencies install from
the committed `package-lock.json` (npm is the lockfile-native package manager; `pnpm` scripts also
work, but never a bare `sdp`).
to run. Development is terminal-driven. Node `^20.19.0 || >=22.12.0`, the `engines` range (Node 22
is installed); dependencies install from the committed `package-lock.json` (npm is the
lockfile-native package manager; `pnpm` scripts also work, but never a bare `sdp`). `npm test`
reaches the npm registry: the package smoke suite installs the packed package's dependencies.

`npm ci` builds the package through its `prepare` script. CI installs with `--ignore-scripts`
and builds in `npm run check`. `npm run check:git-install` checks installation from a commit.
Expand All @@ -293,7 +294,8 @@ self-hosting/example checks → preflight correctly, so prefer it after engine e
The `check:example` step reports 0 errors and 0 warnings. The unbound `defined` example stays
visible in the Design Review verifier bindings and recipe 10, declared versus enabled verifiers.

The `check:self-hosting` step emits two kinds of intentional warning: `honesty/gaps`, one per
owner-ratified ready Spec without a resolving verifier binding, and `conformance/prose-mentions`,
one per mentioning Spec and target pair with no declared relation either way (recipe 22 lists the
pairs). The self-hosting oracle pins both sets; they are expected, not a regression.
The `check:self-hosting` step emits one kind of intentional warning: `honesty/gaps`, one per
owner-ratified ready Spec, decisions aside, without a resolving verifier binding. The self-hosting
oracle pins that set and pins that no prose mention lacks a declared relation (recipe 22's
`unbacked` stays empty), so a `conformance/prose-mentions` warning, like any other new warning, is
a regression.
2 changes: 1 addition & 1 deletion CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ a sibling set back as a table — the graph never holds a multi-point example.

| Term | Definition | Aliases to avoid |
|---|---|---|
| **carrier** | the text format that carries the authored `Spec` document — the envelope, the prose, and the owned notation; **ruled: Markdown (`.sdp.md`) for all eight kinds**, Gherkin (`.sdp.gherkin`) as a lawful per-ID carrier for behavior and example Specs, and the TS DSL as the import source and a lawful per-ID option (one canonical surface per ID, `spec:decisions.carrier-ruling`, completed for Packs and Gherkin by their carrying decisions); bare `.feature` is non-canonical import-source territory | "format"/"file type" (say which level) · a carrier is never a second store |
| **carrier** | the text format that carries the authored `Spec` document — the envelope, the prose, and the owned notation; **ruled: Markdown (`.sdp.md`) for all eight kinds**, Gherkin (`.sdp.gherkin`) as a lawful per-ID carrier for behavior and example Specs, and the TS DSL as the import source and a lawful per-ID option (one canonical surface per ID, `spec:decisions.carrier-ruling`, completed for Packs and Gherkin by their carrying decisions); bare `.feature` is non-canonical import-source territory. "A carrier" or "a carrier file" is also one file written in that format; say which level when it matters | "format"/"file type" (say which level) · a carrier is never a second store |
| **notation** | the Protocol-**owned** typed step language inside the carrier's fenced blocks — Given/When/Then step text and the slot vocabulary; owned by the Protocol whatever the carrier | "grammar" (the dismissed own-language direction) · "DSL" (reserved for the TS DSL) |

## Relations (authored, typed, directed `Spec`→`Spec` edges — → `spec:model.relations`)
Expand Down
35 changes: 28 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ Libar Software Delivery Protocol is a typed, executable, self-validating meta-mo
delivery: author `Spec` documents in the repository, derive one graph, and check conformance and
honesty.

**Carrier rule:** Specs and Packs default to Markdown; the TS DSL survives as import source and a
lawful per-ID option, while behavior and example Specs may use Gherkin canonically per ID (the
carrier ruling, MD-18, the Pack syntax ruling, MD-25, and the Gherkin carrier option, MD-27).
You write Specs as Markdown files (`*.sdp.md`) and group them into Packs. `sdp` derives one graph
from those files and from anchors in your code, then checks it.

Read the [concept](docs/concept/README.md), the [ubiquitous language](CONTEXT.md), and the
[checkout-v1 walkthrough](examples/checkout-v1/README.md).
Expand All @@ -26,6 +25,10 @@ export files and a shipped recipe. The archive route exercises the build used by
dependencies locally; it makes no request to GitHub. The check needs network access for
dependencies and tests only committed work, so CI runs it after `npm run check`.

`npm test`, and so `npm run check`, also needs the npm registry: the package smoke suite installs
the packed package's dependencies into a scratch consumer. It keeps its own npm cache in the
system temporary directory, so a read-only user cache does not stop it.

Then query this repository's self-hosting graph with either supported script runner:

```sh
Expand Down Expand Up @@ -57,6 +60,13 @@ fails with `xcode-select: error: tool 'sdp' requires Xcode`. The checked-in pnpm
disables pnpm 11's dependency auto-reconciliation for repository scripts, so the supported
`pnpm sdp` / `pnpm sdp:q` forms do not rewrite an npm-installed dependency tree.

## Carriers

A carrier is the text format a Spec or a Pack is written in; a carrier file is one file written in
it. Specs and Packs default to Markdown; the TypeScript DSL survives as import source and a lawful
per-ID option, and behavior and example Specs may use Gherkin canonically per ID (the carrier
ruling, MD-18, the Pack syntax ruling, MD-25, and the Gherkin carrier option, MD-27).

## Installed CLI (adopter repositories)

Pin the Protocol to a full commit SHA in your adopter's `package.json`:
Expand Down Expand Up @@ -108,6 +118,16 @@ build permissions, then run `pnpm install`. See npm's
The `./vitest` subpath needs Vitest 2 or later installed beside the package. Install it in the
adopter with `npm install --save-dev vitest` or `pnpm add --save-dev vitest` when using that adapter.

The package runs on Node.js 20.19 or later in the 20 line, and on 22.12 or later
(`engines.node` is `^20.19.0 || >=22.12.0`). Those releases load an ES module through `require()`,
which the CommonJS root entry needs: some of its dependencies ship only as ES modules.

TypeScript reads the package's types with `moduleResolution` set to `node16`, `nodenext` or
`bundler`. The root offers both `import` and `require`. The subpaths (`./anchors`,
`./concept-match`, `./runner`, `./vitest`, `./testing`) are ES modules only, so a CommonJS file
imports the root alone. The older `node10` resolution, the default under `module: commonjs`,
reads no export map and cannot resolve the package.

Verify either install through the linked binary:

```sh
Expand Down Expand Up @@ -145,10 +165,11 @@ diagrams, `gherkin` the Gherkin-shaped read view, and `studio` the static Spec S
JavaScript query body against a freshly derived graph. Run `sdp --help` for the complete option
contract. Adopters own their root and exclusion policy.

The Studio's phase 1 adds static SVG diagrams, the architecture and tests lenses, all Spec-page
panels, registers, the owner queue and a glossary. A base graph adds a design diff; CTRF reports
add external run evidence. The composing panel hands off scoped proposals, every Pack downloads
as one HTML file, and pages print as documents. Open `generated/spec-studio/index.html` through
The Studio is a static page set: five lenses (Packs, capabilities, architecture, tests and
evidence), static SVG diagrams, every Spec-page panel, registers, the owner queue, the roadmap and a
glossary. A base graph adds a design diff; CTRF reports add external run evidence. The composing
panel hands off scoped proposals, every Pack downloads as one HTML file, and pages print as
documents. Open `generated/spec-studio/index.html` through
`file://` or a static host. `studio --watch` rebuilds on carrier changes, with no server; source
and input edits start no cycle. Copy a base graph outside `generated/` before using `--base`.
Run `stamp` after building to record publishing metadata. The reusable
Expand Down
7 changes: 5 additions & 2 deletions check-git-install.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,11 @@ try {
const version = run(cli, ["--version"], consumer).trim();
assert.ok(version.includes(commit), `${version} does not name ${commit}`);
const manifest = JSON.parse(readFileSync(join(installed, "package.json"), "utf8"));
for (const surface of Object.values(manifest.exports)) {
for (const path of Object.values(surface)) assert.ok(existsSync(join(installed, path)), path);
// Conditions nest (the root export pairs each of import and require with its own types).
const exportedPaths = (target) =>
typeof target === "string" ? [target] : Object.values(target).flatMap(exportedPaths);
for (const path of exportedPaths(manifest.exports)) {
assert.ok(existsSync(join(installed, path)), path);
}
const recipe = readFileSync(join(installed, "dist/recipes/25-address-resolution.js"), "utf8");
writeFileSync(
Expand Down
Loading
Loading