Source Test
+The input can be a plain Playwright-style system test or a Blackbox BDD-DSL test. Plain tests are decompiled best-effort; DSL-authored tests preserve more intent.
+
+
-
-
Suites
-
-
- - Automatically generate mock objects, eliminate manual setup and reduce - boilerplate code of your unit tests -
- > - ), - icon: faAreaChart, - link: { - ref: "/docs/guides/", - text: "Developer Guide", - }, - }, - { - title: "Scale Your Test Suites", - description: ( - <> -- Suites' flexible architecture supports projects of all sizes, from - small microservices to large monoliths -
- > - ), - icon: faArrowUpWideShort, - link: { - ref: "/docs/get-started/", - text: "Getting Started", - }, - }, -]; - -function Feature({ title, description, icon, link }: FeatureItem) { - return ( - - ); -} - -export function HomepageFeatures(): JSX.Element { - return ( -404
-- We may have moved or renamed it during the recent docs refresh. - Try one of these instead: -
- -- Still stuck? Go to the homepage or{" "} - - open an issue on GitHub - - . -
-Step through the package workflow: load a test, analyze its AAA/Given-When-Then shape, emit Gherkin, then run syntax and drift gates.
+The input can be a plain Playwright-style system test or a Blackbox BDD-DSL test. Plain tests are decompiled best-effort; DSL-authored tests preserve more intent.
+
+ The analyzer turns test structure into a behavior trace. The linter checks that the trace has a valid AAA shape: `Given*`, `When+`, `Then+`.
+
+ The feature file is a readable projection from the test source. It is useful for review, but it is still checked against the source instead of trusted as disconnected prose.
+
+ The feature gate combines Cucumber-compatible Gherkin syntax validation with test-to-feature drift detection. Runtime effect contracts are a separate layer and remain the core Blackbox behavioral gate.
+
+ {`test.describe('subscribing as a pro tier user', { tag: '@flow:subscribe-flow' }, () => {
+ test('alice is an existing user', async ({ capture, request }) => {
+ await request.post('/subscriptions', { data: { userId: 'alice' } });
+ await expect(capture).toMatchCatalog();
+ });
+});`}
+ {`# the file is generated; run the simulation to see it appear`}
+ subscribe-flow.feature appears. Every line is backed by a captured effect.expect(response.status()).toBe(201);
+ + await expect(capture).toMatchCatalog();
+ Step through how concurrent Playwright execution becomes isolated system-test evidence.
+{steps[0].body}
+{steps[0].snippet}
+ scripts/demo-isolation.sh: two per-worker compose stacks running concurrently, each Playwright worker hitting its own Postgres / Redis / SQS / services. The overlap window is the proof.+ Last updated + +
diff --git a/src/components/docs/PageActions.astro b/src/components/docs/PageActions.astro new file mode 100644 index 0000000..36a744f --- /dev/null +++ b/src/components/docs/PageActions.astro @@ -0,0 +1,116 @@ +--- +/* + * Docs page-actions cluster. + * + * Three affordances, dark-mode-first: + * 1. Copy Markdown -- copies the page's raw markdown body to the clipboard so + * the reader can paste it into an LLM, an issue, or their notes. The body + * is rendered as a hidden + + diff --git a/src/components/docs/PrevNext.astro b/src/components/docs/PrevNext.astro new file mode 100644 index 0000000..2b8d723 --- /dev/null +++ b/src/components/docs/PrevNext.astro @@ -0,0 +1,39 @@ +--- +import sidebar, { productFromPath } from '@/config/sidebar'; + +interface Props { + slug: string; +} +const { slug } = Astro.props; + +const currentHref = `/docs/${slug}`.replace(/\/$/, ''); +const product = productFromPath(`${currentHref}/`); +const flat = sidebar[product].flatMap((group) => group.items); + +const idx = flat.findIndex((item) => item.href.replace(/\/$/, '') === currentHref); + +const prev = idx > 0 ? flat[idx - 1] : null; +const next = idx >= 0 && idx < flat.length - 1 ? flat[idx + 1] : null; +--- +{(prev || next) && ( + +)} diff --git a/src/components/docs/Sidebar.astro b/src/components/docs/Sidebar.astro new file mode 100644 index 0000000..b2777f2 --- /dev/null +++ b/src/components/docs/Sidebar.astro @@ -0,0 +1,46 @@ +--- +import sidebar, { productFromPath } from '@/config/sidebar'; + +const currentPath = Astro.url.pathname.replace(/\/$/, '') || '/'; +const activeProduct = productFromPath(Astro.url.pathname); +const groups = sidebar[activeProduct]; + +function isGroupActive(items: { href: string }[]) { + return items.some((item) => { + const h = item.href.replace(/\/$/, ''); + return currentPath === h || currentPath.startsWith(h + '/'); + }); +} +--- + diff --git a/src/components/docs/TOC.astro b/src/components/docs/TOC.astro new file mode 100644 index 0000000..7ff2a49 --- /dev/null +++ b/src/components/docs/TOC.astro @@ -0,0 +1,163 @@ +--- +interface Heading { + depth: number; + text: string; + slug: string; +} +interface Props { + headings: Heading[]; +} +const { headings } = Astro.props; +const filtered = headings.filter((h) => h.depth >= 2 && h.depth <= 4); +--- +{filtered.length > 0 && ( +
+ Mermaid render error: {error}
+
+ );
+ }
+
+ const accessibleLabel = alt ?? caption ?? 'Diagram';
+
+ return (
+ {desc}
} + --json
+```
+
+The coordinator may route to a specialist Skill or a deterministic CLI command. It stops when the next operation needs a person to approve meaning or behavior.
+
+## `$blackbox-requirements`
+
+Use `$blackbox-requirements` to translate selected intent into proposed `requirements/**/*.ears` files. For existing projects, it can translate reviewed Gherkin back into proposed requirements.
+
+Validate proposals with:
+
+```bash
+blackbox requirements validate requirements/checkout.ears --json
+blackbox requirements check --flow checkout-payment --json
+```
+
+The Skill can repair structural findings. A person approves requirement meaning.
+
+## `$blackbox-gherkin`
+
+Use `$blackbox-gherkin` to propose readable behavior from approved requirements or sharpen baseline Gherkin extracted from an existing suite.
+
+```bash
+blackbox features check \
+ --feature features/checkout-payment.feature \
+ --json
+```
+
+The Skill may clarify scenario language, flow boundaries, and stable IDs. It must not claim the existing test reveals complete product intent. A person approves behavior language before suite alignment.
+
+## Deterministic Suite Translation
+
+Suite source belongs to the CLI, not a Skill:
+
+```bash
+blackbox suites align \
+ --feature features/checkout-payment.feature \
+ --suite ./e2e/checkout.spec.ts \
+ --write \
+ --json
+```
+
+The command writes the native `.ts` file atomically and returns changed paths, source ranges, and digests. It does not create a patch artifact. A person reviews the actual source diff.
+
+## `$blackbox-effects`
+
+Use `$blackbox-effects` only after a run has produced observed effects:
+
+```bash
+blackbox effects show --flow checkout-payment --run latest --json
+```
+
+The Skill can propose `features/.effects.yaml` changes that:
+
+- mark selected observed effects as required;
+- add effects that must remain absent as forbidden;
+- leave incidental observations outside the policy;
+- flag observations that may indicate a defect.
+
+Validate the proposal:
+
+```bash
+blackbox effects check --flow checkout-payment --json
+```
+
+The Skill does not create observations. `blackbox verify` already produced them. A person approves effect meaning.
+
+## Read Review Boundaries Correctly
+
+A source-changing operation can return:
+
+```json
+{
+ "status": "awaiting-review",
+ "data": {
+ "review": {
+ "required": true,
+ "boundary": "suite-source"
+ }
+ }
+}
+```
+
+`awaiting-review` is a successful transformation that must pause. It does not record approval. In alpha, use normal diff or pull-request review before running the suggested next command.
+
+## Summary
+
+- **Skills propose meaning.**
+- **The CLI computes facts and transforms native suite structure.**
+- **Humans approve accepted behavior.**
+- **Agents repair implementation while the accepted harness stays fixed.**
diff --git a/src/content/docs/blackbox/guides/generating-feature-files.md b/src/content/docs/blackbox/guides/generating-feature-files.md
new file mode 100644
index 0000000..4b0ac76
--- /dev/null
+++ b/src/content/docs/blackbox/guides/generating-feature-files.md
@@ -0,0 +1,73 @@
+---
+title: "Extract Gherkin From Existing Suites"
+description: "Use deterministic suite AST extraction to create baseline Gherkin, then review and sharpen its behavior language."
+sidebar_position: 2
+keywords:
+ ["Blackbox features extract", "Gherkin from tests", "existing suite adoption"]
+---
+
+Use `features extract` when an existing system-test suite is the starting point for Blackbox adoption.
+
+The CLI derives a literal baseline from native suite structure. It does not claim that test titles express complete product intent.
+
+## Discover the Suite First
+
+```bash
+pnpm exec blackbox suites discover ./e2e --json
+```
+
+Resolve ambiguous suite roots or conflicting flow IDs before writing feature files.
+
+## Preview the Extraction
+
+```bash
+pnpm exec blackbox features extract ./e2e/checkout.spec.ts --json
+```
+
+Without `--write`, the command returns a plan and findings.
+
+## Write Baseline Gherkin
+
+```bash
+pnpm exec blackbox features extract \
+ ./e2e/checkout.spec.ts \
+ --write \
+ --json
+```
+
+The result includes the written paths and an `awaiting-review` status. Review the `.feature` diff before accepting it.
+
+## Sharpen Meaning Inferentially
+
+Use `$blackbox-gherkin` to:
+
+- replace vague test titles with reviewable behavior language;
+- choose durable flow IDs;
+- split or combine scenarios at meaningful boundaries;
+- identify claims the existing suite does not prove.
+
+The Skill may change the proposed feature. It must not edit the native suite.
+
+## Check and Align
+
+```bash
+pnpm exec blackbox features check \
+ --feature features/checkout-payment.feature \
+ --json
+
+pnpm exec blackbox suites align \
+ --feature features/checkout-payment.feature \
+ --suite ./e2e/checkout.spec.ts \
+ --write \
+ --json
+```
+
+Review the actual TypeScript diff created by `suites align`, then run `blackbox suites check --flow checkout-payment --json`.
+
+`features emit` may remain temporarily as a compatibility alias in some builds. New documentation and automation should use `features extract`.
+
+## Summary
+
+- `features extract` recovers literal baseline behavior from existing suite structure.
+- `$blackbox-gherkin` may propose clearer meaning but cannot edit suite source.
+- `suites align` writes the reviewed behavior back to the native suite deterministically.
diff --git a/src/content/docs/blackbox/guides/playwright-isolation-and-parallelism.mdx b/src/content/docs/blackbox/guides/playwright-isolation-and-parallelism.mdx
new file mode 100644
index 0000000..8e17ab8
--- /dev/null
+++ b/src/content/docs/blackbox/guides/playwright-isolation-and-parallelism.mdx
@@ -0,0 +1,93 @@
+---
+title: "Playwright Flows, Isolation, and Parallelism"
+description: "Use native Playwright flow tags, fixtures, trace propagation, reset groups, and per-worker SUT stacks without mixing runtime evidence."
+sidebar_position: 2
+keywords:
+ [
+ "Playwright flow ID",
+ "Blackbox Playwright",
+ "parallel system tests",
+ "testbed isolation",
+ ]
+---
+
+import PlaywrightParallelismSimulator from "@/components/blackbox/PlaywrightParallelismSimulator.astro";
+
+Blackbox uses native Playwright APIs. You declare one behavioral flow with `test.describe(..., { tag: "@flow:" })`, then let Playwright schedule the tests normally.
+
+
+
+## Declare One Flow
+
+```ts
+import { expect, test } from "./blackbox-testbed";
+
+test.describe(
+ "Reject an unknown subscriber",
+ { tag: "@flow:subscribe-unknown-user" },
+ () => {
+ test("request stops before payment", async ({ request, capture }) => {
+ const response = await request.post("/subscriptions", {
+ data: { userId: "ghost-user", tier: "pro" },
+ });
+
+ expect(response.status()).toBe(404);
+ await expect(capture).toMatchCatalog();
+ });
+ },
+);
+```
+
+Every test inside the `describe` inherits `@flow:subscribe-unknown-user`. The capture fixture uses that ID to load `features/subscribe-unknown-user.effects.yaml`, record coverage, and connect optional requirement and feature tags.
+
+## Keep Flow Scope Narrow
+
+A flow should describe one reviewable behavior, not an entire user journey. Prefer:
+
+- one request and its direct effects;
+- one negative path and its forbids;
+- one webhook or message-handling path;
+- one branch arm that needs observable decision evidence.
+
+Split flows when two scenarios have different required or forbidden effects.
+
+## Run In Parallel Safely
+
+Playwright can still run workers in parallel:
+
+```bash
+npx playwright test --config ./e2e/playwright.config.ts --workers 4
+```
+
+Blackbox isolation depends on the testbed. Per-worker SUT stacks prevent spans, databases, queues, and caches from bleeding across flows.
+
+## Avoid Shared Writes
+
+Parallel tests must not write accepted artifacts. `blackbox verify` writes runtime evidence and reports only. Skills may propose requirements, feature files, and effect contracts; `suites align --write` transforms native suite source deterministically. Each accepted change pauses for human review.
+
+Generated reports can be merged after the run:
+
+```text
+.blackbox-coverage/.coverage-partials/catalog-coverage.w0.json
+.blackbox-coverage/.coverage-partials/catalog-coverage.w1.json
+-> .blackbox-coverage/catalog/coverage.json
+```
+
+## Use Stable Artifact Names
+
+Keep each flow's reviewed artifacts aligned:
+
+```text
+features/subscribe-unknown-user.feature
+features/subscribe-unknown-user.effects.yaml
+@flow:subscribe-unknown-user
+```
+
+The CLI checks that feature basename, Gherkin `@flow`, Playwright tag, and effect YAML `flow` agree.
+
+## Summary
+
+- **Use native Playwright `test.describe` tags** for flow IDs.
+- **Keep one flow narrow** enough to review.
+- **Run workers in parallel** only when the testbed isolates SUT state.
+- **Never write accepted artifacts during `verify`.**
diff --git a/src/content/docs/blackbox/guides/reports-and-ci-gates.mdx b/src/content/docs/blackbox/guides/reports-and-ci-gates.mdx
new file mode 100644
index 0000000..b8b797c
--- /dev/null
+++ b/src/content/docs/blackbox/guides/reports-and-ci-gates.mdx
@@ -0,0 +1,173 @@
+---
+title: "Reports and CI Gates"
+description: "Read Blackbox effect, shape, observable decision, and requirement reports in the right order, then enforce reviewed behavior in CI."
+sidebar_position: 4
+keywords:
+ [
+ "Blackbox CI gate",
+ "effect coverage report",
+ "observable decision coverage report",
+ "requirement coverage",
+ "Playwright behavioral verification",
+ ]
+---
+
+import Aside from "@/components/mdx/Aside.astro";
+
+Blackbox reports answer different questions. Read the narrowest failure first instead of treating `.blackbox-coverage/` as one score.
+
+## Report Map
+
+| Artifact | Question |
+| ---------------------------- | ------------------------------------------------------------------------------------------- |
+| `catalog/coverage.json` | Which flow contracts were satisfied, failed, or uncovered? |
+| `shape/coverage.json` | Which catalog clauses were asserted, unasserted, or inline-only? |
+| `omcdc/verdict.md` | Which decisions propagated to distinguishable effects, were masked, or lacked arm coverage? |
+| `omcdc/verdict.html` | Where in source did those decision verdicts occur? |
+| `omcdc/verdict.json` | What structured observable decision data should automation consume? |
+| `requirements/coverage.json` | Which EARS requirements are proven, violated, unproven, or unbound? |
+| reporter outputs | What human summary, HTML, JUnit, or CI annotation should be published? |
+
+Catalog and shape coverage are the default runtime-evidence views. Observable decision coverage is available when the Node adapter registers its producer. `blackbox verify` writes requirement coverage after the Playwright run when that layer is configured.
+
+## Reading Order
+
+1. Start with the `blackbox verify` layer summary and first finding.
+2. Run `blackbox flows show ` to assemble the affected flow.
+3. Open `catalog/coverage.json` for the required or forbidden effect result.
+4. Open `shape/coverage.json` when the issue is an unasserted clause or inline-only effect.
+5. Inspect observable decision coverage only when the review question concerns distinguishable arm evidence or missing arms.
+6. Inspect requirement coverage when normative requirements inherit the runtime result.
+
+Do not begin with a global percentage. A single forbidden payment call in a rejected-user flow matters more than a high aggregate count.
+
+## Catalog Coverage
+
+The terminal summary mirrors the JSON artifact:
+
+```text
+effect coverage
+metric value
+catalog entries 2
+satisfied 2 (100%)
+failed 0
+uncovered 0
+```
+
+For each entry, inspect `runs`, `passes`, `failures`, and `forbidViolations`. A `failed` entry means the flow ran but no captured run satisfied its contract. An `uncovered` entry means the current suite did not check it.
+
+Configure the Playwright reporter to fail on either condition when the suite is mature:
+
+```ts
+blackboxReporter({
+ outputDir: "./e2e/.blackbox-coverage",
+ failOnUncovered: true,
+ failOnAlwaysFailing: true,
+});
+```
+
+## Observable Decision Reports
+
+Read verdicts as evidence quality:
+
+- `propagating`: both arms were exercised and their captured evidence signatures differed;
+- `masking-candidate`: both arms were exercised but the signatures were identical;
+- `coverage-gap`: only one arm was exercised;
+- `undecidable`: the run could not support a sound comparison;
+- `multi-arm`: more than two branch arms were observed and the binary comparator did not apply;
+- `unsupported-mcdc`: a reserved producer token, not a verdict emitted by the current comparator.
+
+Use `verdict.md` for review, HTML for source inspection, and JSON for automation. Do not automatically fail every non-propagating branch. Choose critical decisions and make the policy explicit.
+
+## Requirement Verdicts
+
+Run the configured facade after the Playwright flow and requirements are connected:
+
+```bash
+pnpm exec blackbox verify --flow subscribe-unknown-user --json
+```
+
+Use `--fail-on violated` as the conservative first requirement gate. Move to `unproven` or `unbound` only when every selected requirement is expected to have complete feature tags and runtime evidence in that job.
+
+Use `blackbox requirements coverage` directly when debugging or regenerating only the requirement artifact.
+
+## Add Gates Progressively
+
+Use structural gates before runtime infrastructure is available:
+
+```bash
+pnpm exec blackbox requirements validate 'requirements/**/*.ears' --json
+pnpm exec blackbox requirements check --json
+pnpm exec blackbox features check --json
+pnpm exec blackbox suites check --json
+```
+
+These commands can establish that accepted artifacts and native suites remain connected. They do not verify the running system.
+
+Add the runtime gate when the job can start and instrument the selected topology:
+
+```bash
+pnpm install --frozen-lockfile
+pnpm build:instr-image
+pnpm exec blackbox doctor --json
+pnpm exec blackbox verify --json
+```
+
+`blackbox verify` returns the configured layers without collapsing their verdicts. A project without EARS or Gherkin can still verify a reviewed effect contract. A project without runtime observation can run structural gates but cannot claim that the running system satisfied accepted behavior.
+
+Use specialized commands in separate jobs only when the pipeline needs independent ownership or faster feedback:
+
+```bash
+pnpm exec blackbox requirements check --json
+pnpm exec blackbox features check --json
+pnpm exec blackbox coverage replay --no-html --json
+```
+
+Do not configure or gate a layer when the team does not review its artifacts.
+
+## Use Pull Requests as the Alpha Review Gate
+
+Blackbox approval is external in alpha. Use normal repository review for changes to:
+
+- EARS requirements;
+- Gherkin behavior and stable flow IDs;
+- native suite source written by `suites align --write`;
+- required and forbidden effect policy.
+
+A successful source transformation may return `awaiting-review`. Exit `0`, a commit, or the next command does not prove that a person approved the change.
+
+## Prevent CI Baselines
+
+CI verifies reviewed behavior; it should not create it.
+
+```ts title="e2e/playwright.config.ts"
+export default defineConfig({
+ updateSnapshots: "none",
+});
+```
+
+`blackbox verify` writes evidence and reports only. A missing effect contract fails without writing a contract. Use `$blackbox-effects` to propose a contract from evidence, then review the exact diff before accepting it.
+
+
+
+## Reporter and Sink Behavior
+
+The current default reporter is the effects report. The default sink writes files; GitHub Actions adds the GitHub Actions sink when that environment is detected. Additional registered reporters can produce HTML and JUnit views.
+
+Use the [Reference hub](/docs/blackbox/reference) for the current reporter, sink, artifact, and exit-code contracts.
+
+## Replay Saved Decision-Coverage Inputs
+
+When a coverage directory contains the required saved inputs, regenerate observable decision outputs without rerunning the SUT:
+
+```bash
+pnpm exec blackbox coverage replay \
+ --coverage-dir ./e2e/.blackbox-coverage \
+ --out ./reports
+```
+
+Pass `--no-html` when automation needs only JSON and Markdown.
diff --git a/src/content/docs/blackbox/guides/set-up-the-testbed.mdx b/src/content/docs/blackbox/guides/set-up-the-testbed.mdx
new file mode 100644
index 0000000..a24b6e0
--- /dev/null
+++ b/src/content/docs/blackbox/guides/set-up-the-testbed.mdx
@@ -0,0 +1,197 @@
+---
+title: "Testbed and Instrumentation"
+description: "Start a Docker Compose or Testcontainers SUT per Playwright worker, inject Node instrumentation for the test run, and write Blackbox artifacts."
+sidebar_position: 1
+keywords:
+ [
+ "Blackbox testbed",
+ "Docker Compose system tests",
+ "OpenTelemetry test instrumentation",
+ "Playwright testbed",
+ "Node SUT instrumentation",
+ ]
+---
+
+import TestbedArchitectureDiagram from "@/components/blackbox/TestbedArchitectureDiagram.astro";
+import InstrumentationFlowDiagram from "@/components/blackbox/InstrumentationFlowDiagram.astro";
+import Aside from "@/components/mdx/Aside.astro";
+
+The Blackbox testbed owns the system-test environment. It starts one SUT topology per Playwright worker, injects the Node observation payload into configured services, resets managed state between groups, and finalizes reports after the run.
+
+
+
+## Before You Configure It
+
+The current happy path assumes:
+
+- Playwright system tests;
+- a modern Docker Compose v2 installation, preferably 2.24 or newer;
+- Node SUT containers with a shell and a Node binary the wrapper can shadow;
+- declared Compose ports for SUT endpoints;
+- a test-owned reset strategy for stateful dependencies.
+
+Install the runtime, Node adapter, bootstrap payload package, and test dependencies in the workspace that owns the system tests:
+
+```bash
+pnpm add -D \
+ @suites/blackbox \
+ @suites/blackbox-adapter-node \
+ @suites/blackbox-instr-node \
+ @playwright/test \
+ testcontainers
+```
+
+When working from a Blackbox source checkout, build the local payload image once:
+
+```bash
+pnpm -w build:instr-image
+```
+
+Set `BLACKBOX_INSTR_IMAGE` when CI should use a published or internally mirrored image instead of `blackbox-instr-node:local`.
+
+## Create the Testbed
+
+```ts title="e2e/blackbox-testbed.ts"
+import { resolve } from "node:path";
+import { createBlackboxTestbed } from "@suites/blackbox/testbed";
+import "@suites/blackbox-adapter-node/register";
+import { resetManagedState } from "./reset-managed-state.js";
+
+export const testbed = createBlackboxTestbed({
+ source: {
+ compose: resolve("e2e/services/compose.user.yml"),
+ profiles: undefined,
+ },
+ services: {
+ bff: {},
+ "order-service": {},
+ "fraud-check": {
+ wait: { log: /\[fraud-check\] listening on/ },
+ },
+ } as const,
+ reset: async ({ infra }) => resetManagedState(infra),
+ grouping: undefined,
+ coverageDir: resolve("e2e/.blackbox-coverage"),
+ projectNames: undefined,
+ ambient: null,
+});
+```
+
+`resetManagedState` is project-owned. It should clear the Postgres, Redis, queue, or other managed state addressed by the worker-specific `infra` map.
+
+The alpha input type uses explicit `undefined` for omitted options. Keep those keys until the public type changes.
+
+The testbed introspects the Compose configuration:
+
+- services with `build:` become candidate SUT services;
+- image-only services become managed infrastructure;
+- a healthcheck becomes the default wait strategy;
+- `/src` becomes the default source directory;
+- Docker-assigned host ports avoid collisions between workers.
+
+Declare service overrides only when introspection is wrong. The current public sources are Compose and a custom Testcontainers provisioner. A Dockerfile-only source is represented in types but is not implemented as a runnable source yet.
+
+## What Instrumentation Does
+
+
+
+For each configured Node SUT service, the adapter-generated overlay:
+
+1. starts an init container from the instrumentation image;
+2. copies `/blackbox-otel` into a named volume;
+3. mounts the volume read-only into the SUT container;
+4. shadows the configured Node binary with `node-wrap`;
+5. preloads `bootstrap.cjs` before application code;
+6. publishes the in-container debug endpoint on a Docker-assigned host port.
+
+Production source and production Dockerfiles do not need Blackbox imports. This is test-environment instrumentation.
+
+The default Node path is `/usr/local/bin/node`. Override it globally with `BLACKBOX_NODE_BINARY_PATH` or for one service with `BLACKBOX_NODE_BINARY_PATH_` when the image uses a different path.
+
+
+
+## Wire Playwright
+
+```ts title="e2e/playwright.config.ts"
+import { defineConfig } from "@playwright/test";
+import {
+ blackboxReporter,
+ defineBlackboxConfig,
+} from "@suites/blackbox/playwright";
+import { testbed } from "./blackbox-testbed.js";
+
+export default defineConfig({
+ ...defineBlackboxConfig({ mode: "testbed", testbed }),
+ testDir: "./e2e",
+ testMatch: ["tests/**/*.system.test.ts"],
+ fullyParallel: true,
+ workers: 4,
+ reporter: [
+ ["list"],
+ blackboxReporter({
+ outputDir: "./e2e/.blackbox-coverage",
+ failOnUncovered: true,
+ failOnAlwaysFailing: true,
+ }),
+ ],
+});
+```
+
+`defineBlackboxConfig()` contributes the packaged global setup and teardown. `blackboxReporter()` contributes the reporter tuple without replacing Playwright reporters you already use.
+
+Use `workers: 1` while diagnosing first setup. Raise the worker count when the topology starts and resets correctly; parallel execution is a supported testbed shape.
+
+## Expose the System Fixture
+
+Use `defineSystemTest({ provision: { bootstrap } })` to turn the per-worker connect map into the `system` fixture your tests need:
+
+```ts title="e2e/tests/testbed.ts"
+import { defineSystemTest } from "@suites/blackbox/runners/playwright";
+import "../blackbox-testbed.js";
+
+const { test, expect } = defineSystemTest({
+ provision: {
+ bootstrap: async ({ perWorker }) => {
+ if (perWorker === null)
+ throw new Error("worker stack was not provisioned");
+
+ return {
+ app: perWorker.connect.bff,
+ debugUrls: () =>
+ Object.values(perWorker.connect).map((service) => service.debugUrl),
+ dispose: async () => {},
+ };
+ },
+ },
+});
+
+export { test, expect };
+```
+
+The showcase has a richer fixture with typed Postgres, Redis, and SQS helpers. Keep your fixture limited to the controls and inspection surfaces tests actually use.
+
+## Verify the Environment
+
+Run one file first:
+
+```bash
+npx playwright test \
+ --config ./e2e/playwright.config.ts \
+ ./e2e/tests/subscribe.system.test.ts \
+ --workers 1
+```
+
+Verify, in order:
+
+1. the worker stack starts;
+2. the public SUT endpoint is reachable;
+3. each configured SUT has a readable debug endpoint;
+4. the request carries trace context;
+5. the accepted effect contract is loaded;
+6. `catalog/coverage.json` is written at teardown.
+
+Continue with [Playwright Flows, Isolation, and Parallelism](/docs/blackbox/guides/playwright-isolation-and-parallelism) to structure flows across workers. Use [Troubleshooting](/docs/blackbox/troubleshooting) if the test passes but observations or artifacts are missing.
diff --git a/src/content/docs/blackbox/guides/spec-driven-and-agentic-verification.mdx b/src/content/docs/blackbox/guides/spec-driven-and-agentic-verification.mdx
new file mode 100644
index 0000000..7fa49c0
--- /dev/null
+++ b/src/content/docs/blackbox/guides/spec-driven-and-agentic-verification.mdx
@@ -0,0 +1,119 @@
+---
+title: "Spec-Driven and Agentic Verification"
+description: "Govern behavior changes through inferential proposals, deterministic CLI operations, human review, and runtime verification."
+sidebar_position: 3
+keywords:
+ [
+ "spec-driven development",
+ "agentic verification",
+ "EARS",
+ "Gherkin",
+ "suite alignment",
+ ]
+---
+
+import Aside from "@/components/mdx/Aside.astro";
+
+Blackbox does not turn a specification into trusted code in one step. It separates meaning, computation, authority, and implementation repair.
+
+| Responsibility | Owner | Examples |
+| ------------------------- | ------------ | ---------------------------------------------------------------- |
+| Inferential proposal | Skills | EARS, Gherkin, effect-policy changes |
+| Deterministic computation | CLI | Validation, extraction, suite AST alignment, execution, verdicts |
+| Behavioral authority | Humans | Approval of meaning, suite diffs, policy, and final evidence |
+| Implementation repair | Coding agent | Product-code changes against a fixed accepted harness |
+
+## Govern New Behavior
+
+For a new flow:
+
+1. `$blackbox-requirements` proposes selected obligations as EARS.
+2. `blackbox requirements validate` checks structure and IDs.
+3. A person approves requirement meaning.
+4. `$blackbox-gherkin` proposes readable behavior with stable bindings.
+5. `blackbox features check` validates Gherkin and traceability.
+6. A person approves behavior language.
+7. `blackbox suites align --write` translates accepted behavior into native suite structure.
+8. A person reviews the actual TypeScript diff.
+9. `blackbox suites check` confirms the accepted artifacts and suite agree.
+
+The CLI writes suite source directly through the runner adapter. Skills do not author suite source, and no separate patch artifact exists.
+
+## Govern Existing Behavior
+
+For an existing system-test suite:
+
+1. `blackbox suites discover` reports candidate flows and conflicts.
+2. `blackbox features extract --write` creates literal baseline Gherkin.
+3. `$blackbox-gherkin` sharpens descriptions and flow boundaries.
+4. A person approves the recovered behavior.
+5. `$blackbox-requirements` proposes requirement meaning from the reviewed behavior.
+6. A person approves the requirements.
+7. `blackbox suites align --write` binds and reshapes only the selected suite AST nodes.
+8. A person reviews the native source diff.
+
+Extraction is computational; recovering complete product intent is inferential. Existing tests cannot reveal every obligation, exception, or missing scenario.
+
+## Understand the First Milestone
+
+After suite alignment and structural checks, Blackbox can establish that the accepted harness is structurally connected and ready for execution.
+
+
+
+## Complete the Runtime Verification Loop
+
+The first run creates evidence and observed effects before effect policy:
+
+```bash
+blackbox verify --flow checkout-payment --json
+blackbox effects show --flow checkout-payment --run latest --json
+```
+
+`$blackbox-effects` can then propose required and forbidden policy. A person approves `features/checkout-payment.effects.yaml`, and the CLI validates it:
+
+```bash
+blackbox effects check --flow checkout-payment --json
+blackbox verify --flow checkout-payment --json
+```
+
+The second run can compute an effect verdict against accepted policy. Requirement and observable-decision verdicts remain separate.
+
+## Bound Autonomous Repair
+
+A coding agent can repeat:
+
+```text
+verify -> read deterministic findings -> repair implementation -> verify
+```
+
+The agent stops when passing requires a change to:
+
+- accepted EARS meaning;
+- accepted Gherkin or stable flow IDs;
+- native suite scope or assertions;
+- required or forbidden effect policy;
+- final human interpretation of evidence.
+
+That change reopens the behavior governance lifecycle.
+
+## Use External Review in Alpha
+
+Blackbox returns operation metadata and `awaiting-review` for source-changing operations. Approval remains external:
+
+1. Inspect the working-tree diff.
+2. Approve or revise the changed artifact.
+3. Commit through the repository's normal process.
+4. Run the suggested deterministic check.
+
+Do not treat a commit made by an agent or the invocation of the next command as human approval.
+
+Start with [Choose Your Starting Point](/docs/blackbox/quickstart/) and continue to [Complete the Verification Loop](/docs/blackbox/quickstart/add-runtime-evidence).
+
+## Summary
+
+- Skills propose meaning; the CLI computes deterministic transformations and verdicts.
+- Humans govern accepted behavior through normal source review.
+- Agents may repair implementation while the accepted target remains fixed.
diff --git a/src/content/docs/blackbox/guides/writing-scenarios.mdx b/src/content/docs/blackbox/guides/writing-scenarios.mdx
new file mode 100644
index 0000000..cbaf385
--- /dev/null
+++ b/src/content/docs/blackbox/guides/writing-scenarios.mdx
@@ -0,0 +1,71 @@
+---
+title: "Write Playwright Flows"
+description: "Write Blackbox flows with native Playwright APIs, stable @flow tags, reviewed Gherkin, and accepted effect contracts."
+sidebar_position: 20
+keywords:
+ [
+ "Blackbox Playwright flows",
+ "Playwright flow tags",
+ "Gherkin feature files",
+ "effect contracts",
+ ]
+---
+
+Blackbox flows use native Playwright. Do not use a TypeScript Scenario DSL for new alpha docs or suites.
+
+## Start With a Flow Tag
+
+```ts
+import { expect, test } from "./blackbox-testbed";
+
+test.describe("Subscribe user", { tag: "@flow:subscribe-flow" }, () => {
+ test("subscribes a pro tier user", async ({ request, capture }) => {
+ const response = await request.post("/subscriptions", {
+ data: { userId: "alice", tier: "pro" },
+ });
+
+ expect(response.status()).toBe(201);
+ await expect(capture).toMatchCatalog();
+ });
+});
+```
+
+The `@flow` tag connects Playwright, Gherkin, effect YAML, runtime evidence, and verdicts.
+
+## Keep Gherkin in Feature Files
+
+Use Gherkin only in `.feature` files:
+
+```gherkin
+@flow:subscribe-flow
+@requirement:REQ-010
+Feature: Subscribe user
+
+ Scenario: subscribes a pro tier user
+ When Alice posts a pro subscription request
+ Then the response status is 201
+```
+
+The feature file is reviewed behavior language. The Playwright file is executable behavior.
+
+## Keep Effects in YAML or Inline Assertions
+
+Use `features/.effects.yaml` when the effect contract should be a standalone review artifact:
+
+```yaml
+specVersion: "0.1"
+flow: subscribe-flow
+requires:
+ - { boundary: postgres, op: INSERT, key: subscriptions }
+forbids:
+ - { boundary: http, op: POST, key: /v1/refunds }
+```
+
+Use `toObserveEffects()` for focused inline assertions that belong directly inside one test.
+
+## Summary
+
+- **Use native Playwright `test.describe` tags.**
+- **Use Gherkin only in `.feature` files.**
+- **Use YAML only for effect contracts.**
+- **Review native suite diffs after `suites align --write`.**
diff --git a/src/content/docs/blackbox/overview/adopt-blackbox-in-layers.mdx b/src/content/docs/blackbox/overview/adopt-blackbox-in-layers.mdx
new file mode 100644
index 0000000..76b3604
--- /dev/null
+++ b/src/content/docs/blackbox/overview/adopt-blackbox-in-layers.mdx
@@ -0,0 +1,95 @@
+---
+title: "Adopt Blackbox Incrementally"
+description: "Establish an accepted behavioral harness first, then add runtime observation to complete the Blackbox verification loop."
+sidebar_position: 4
+keywords:
+ [
+ "Blackbox adoption",
+ "behavior governance",
+ "runtime verification",
+ "incremental harness engineering",
+ ]
+---
+
+import Aside from "@/components/mdx/Aside.astro";
+
+Blackbox is incremental, but its layers do not support equal claims. Start with the lightest machinery that creates a useful reviewed artifact, then add runtime observation when you need to verify the running system.
+
+## Follow the Claim Ladder
+
+| Available surfaces | What Blackbox can establish |
+| -------------------------------------- | ------------------------------------------------------------------------------- |
+| Requirements or Gherkin | Accepted artifacts are structurally valid |
+| Accepted artifacts and aligned suite | The behavioral harness is structurally connected and ready for execution |
+| Runtime effects without specifications | The selected flow satisfied its reviewed effect policy |
+| Full connected chain | Accepted requirements are connected to current evidence from the running system |
+
+Do not promote a structural result into a runtime claim. A clean feature check does not prove implementation. A passing effect contract without requirement bindings does not prove normative traceability.
+
+## Milestone 1: Establish the Target
+
+The behavior governance lifecycle works without runtime infrastructure.
+
+For an existing project:
+
+```text
+discover suite -> extract baseline behavior -> review -> align suite -> check
+```
+
+For new behavior:
+
+```text
+propose requirements -> review -> propose Gherkin -> review -> align suite -> check
+```
+
+This milestone gives reviewers and agents a stable behavioral target. The CLI owns deterministic suite transformation; Skills propose meaning; humans approve the actual diffs.
+
+**Start:** [Choose Your Starting Point](/docs/blackbox/quickstart/)
+
+## Milestone 2: Observe the Running System
+
+Add the runtime packages and supported test-time instrumentation only after one accepted flow exists.
+
+```text
+accepted flow -> execute -> runtime evidence -> observed effects
+```
+
+The first run creates facts. It can report `effects: not-configured` because no reviewed effect policy exists yet.
+
+
+
+**Continue:** [Complete the Verification Loop](/docs/blackbox/quickstart/add-runtime-evidence)
+
+## Milestone 3: Accept Effect Policy
+
+Use observed facts to propose, not infer automatically, what behavior is required or forbidden:
+
+```text
+observed effects -> policy proposal -> human review -> effect contract
+```
+
+The effect contract is the only Blackbox-owned public YAML artifact. Do not copy every observed operation into it. Keep contractual effects, add meaningful forbids, and leave incidental observations outside the policy.
+
+## Milestone 4: Gate the Repository
+
+Add gates only for artifacts the team actively reviews.
+
+| Gate | Typical checks |
+| ---------- | ------------------------------------------------------------------------------- |
+| Structural | `requirements validate/check`, `features check/drift`, `suites check` |
+| Runtime | `blackbox verify` and separate test, effect, requirement, and decision verdicts |
+| Review | Human approval of EARS, Gherkin, native suite, and effect-contract diffs |
+
+Alpha approval remains external. Git and pull requests expose the changes; CI computes findings. Neither a commit nor the next CLI command proves that a human approved the previous operation.
+
+## Add Advanced Evidence Last
+
+Observable decision coverage compares evidence from exercised branch arms. Add it after runtime capture is trustworthy and the review question needs propagation, masking, or arm-coverage evidence.
+
+It does not compute full MC/DC atomic-condition independence.
+
+Read [When to Use Blackbox](/docs/blackbox/overview/when-to-use-blackbox) before expanding beyond the first consequential flow.
diff --git a/src/content/docs/blackbox/overview/specs-tests-runtime-evidence.mdx b/src/content/docs/blackbox/overview/specs-tests-runtime-evidence.mdx
new file mode 100644
index 0000000..0cf2a37
--- /dev/null
+++ b/src/content/docs/blackbox/overview/specs-tests-runtime-evidence.mdx
@@ -0,0 +1,135 @@
+---
+title: "Intent, Flows, and Runtime Evidence"
+slug: "blackbox/overview/runtime-evidence-gap"
+description: "Understand the three verification surfaces Blackbox connects: reviewed requirements, executable Playwright flows, and evidence from the running system."
+sidebar_position: 2
+keywords:
+ [
+ "runtime evidence gap",
+ "executable system behavior",
+ "EARS and Gherkin",
+ "specification drift",
+ "system verification",
+ ]
+seo:
+ primary_keyword: "runtime evidence gap"
+ secondary_keywords: ["EARS and Gherkin", "executable system behavior"]
+ search_intent: "developers comparing specifications, executable tests, and runtime evidence"
+ snippet_angle: "show why requirements, tests, and observations have separate jobs and how a flow ID connects them"
+---
+
+import VerificationTriangleDiagram from "@/components/blackbox/VerificationTriangleDiagram.astro";
+import InputOutputGapDiagram from "@/components/blackbox/InputOutputGapDiagram.astro";
+import Aside from "@/components/mdx/Aside.astro";
+
+Blackbox connects three surfaces that software teams often maintain separately: **what the system must do, how a concrete case is exercised, and what the running system actually did**.
+
+
+
+The framework does not collapse those surfaces into one artifact. It gives each one a precise job and verifies the links between them.
+
+## Reviewed Intent States the Obligation
+
+A product specification, ticket, Kiro document, OpenSpec artifact, Spec Kit spec, or design note explains the goal and constraints. EARS can normalize selected obligations into stable, reviewable requirement statements:
+
+```text
+REQ-004: When an unknown user subscribes, the billing system shall not request payment, persist a subscription, or publish a subscription order.
+```
+
+EARS validation can establish that this statement follows an accepted structure and carries a usable ID. It cannot establish that the requirement is complete, approved, internally consistent, or implemented.
+
+That distinction matters. The requirement is **normative intent**, not runtime truth.
+
+## An Executable Flow Exercises One Case
+
+A Playwright system test turns selected intent into a concrete execution:
+
+```ts
+test.describe(
+ "Reject an unknown subscriber",
+ { tag: "@flow:subscribe-unknown-user" },
+ () => {
+ test("request stops before payment", async ({ request, capture }) => {
+ const response = await request.post("/subscriptions", {
+ data: { userId: "missing-user", tier: "pro" },
+ });
+
+ expect(response.status()).toBe(404);
+ await expect(capture).toMatchCatalog();
+ });
+ },
+);
+```
+
+The stable flow ID is more important than textual similarity. The reviewed feature file can connect `REQ-004` to `subscribe-unknown-user` explicitly with tags. Blackbox does not ask a model to infer that the test probably proves the requirement because their wording looks alike.
+
+Gherkin gives the executable behavior a readable review surface:
+
+```gherkin
+@flow:subscribe-unknown-user
+@requirement:REQ-004
+Feature: rejecting unknown subscription users
+
+ Scenario: an unknown user attempts to subscribe
+ When the user posts a pro subscription request
+ Then the response status is 404
+```
+
+The feature file helps humans and agents inspect the concrete behavior. A feature check keeps its tags and flow relationship valid. It is not independent runtime proof.
+
+## Runtime Evidence Shows What Happened
+
+The public assertion still leaves the middle of the workflow unseen:
+
+
+
+During the flow, Blackbox records supported boundary operations and compares them with the reviewed effect contract. For the negative subscription path, the meaningful evidence may be:
+
+- the user lookup occurred;
+- no payment request occurred;
+- no subscription row was inserted;
+- no subscription-order message was published.
+
+Those observations are facts about this run in this environment. The effect contract supplies reviewed meaning: which facts are required, which are forbidden, and which are incidental.
+
+## The Edges Are What Blackbox Verifies
+
+| Relationship | Mechanism | Failure it exposes |
+| ------------------------------ | --------------------------------------------- | ------------------------------------------------------ |
+| Requirement to flow | Gherkin `@requirement` and `@flow` tags | Unbound or unknown requirements and flows |
+| Test to readable behavior | Feature check and flow-tag consistency | Missing, stale, orphaned, or unparseable scenarios |
+| Flow to runtime behavior | Instrumentation, effects, and effect coverage | Missing required effects or observed forbidden effects |
+| Requirement to runtime verdict | Feature tags joined with effect coverage | `violated`, `unproven`, or `unbound` requirements |
+
+This is why Blackbox is a framework rather than one matcher. The value is not only in capturing spans; it is in preserving the verification relationships across later changes.
+
+## Independent Evidence Reduces Circular Confidence
+
+The same developer or coding agent may interpret a requirement, implement it, and write its test. That workflow is fast, but a mistaken interpretation can reproduce itself in all three outputs.
+
+Blackbox contributes an independently observed input: what the instrumented system did during the flow. The evidence still requires a reviewed contract, but it is not derived from the implementation summary or test name.
+
+
+
+## EARS and Gherkin Are Complementary
+
+EARS answers, “What must the system guarantee?” Gherkin answers, “How can a reviewer read a concrete executable example?” They may appear in the same workflow, but neither replaces the other.
+
+The stronger chain is:
+
+```text
+reviewed requirement
+ -> explicit feature tags
+ -> executable Playwright behavior
+ -> observed runtime effects
+ -> deterministic requirement verdict
+```
+
+Gherkin sits inside that chain as a readable, checked review artifact.
+
+Continue to [Behavior Governance and Runtime Verification](/docs/blackbox/overview/verification-loop) to see how these surfaces repeat through implementation and refactoring.
diff --git a/src/content/docs/blackbox/overview/tests-effects-and-feature-files.mdx b/src/content/docs/blackbox/overview/tests-effects-and-feature-files.mdx
new file mode 100644
index 0000000..d7e1edd
--- /dev/null
+++ b/src/content/docs/blackbox/overview/tests-effects-and-feature-files.mdx
@@ -0,0 +1,150 @@
+---
+title: "Behavior Governance and Runtime Verification"
+slug: "blackbox/overview/verification-loop"
+description: "Understand how Blackbox governs an accepted behavioral harness, verifies the running system, and returns implementation changes to a bounded repair loop."
+sidebar_position: 3
+keywords:
+ [
+ "behavior governance lifecycle",
+ "runtime verification loop",
+ "behavioral harness engineering",
+ "agentic software verification",
+ ]
+seo:
+ primary_keyword: "runtime verification loop"
+ secondary_keywords: ["behavior governance lifecycle", "behavioral harness"]
+ search_intent: "developers designing a governed behavioral harness and deterministic runtime verification loop"
+ snippet_angle: "separate the lifecycle that changes accepted behavior from the loop that verifies and repairs implementation"
+---
+
+import VerificationLoopDiagram from "@/components/blackbox/VerificationLoopDiagram.astro";
+import Aside from "@/components/mdx/Aside.astro";
+
+Blackbox connects two parts that operate at different cadences:
+
+- The **behavior governance lifecycle** changes what success means.
+- The **runtime verification loop** repeatedly checks implementation against that fixed target.
+
+
+
+The distinction is operational. A coding agent may run the verification loop repeatedly. It must stop when passing requires a change to the accepted harness.
+
+## Govern the Behavioral Harness
+
+The governance lifecycle begins from product intent or an existing system-test suite. It ends when a person accepts a structurally connected harness that is ready for execution.
+
+### New Behavior
+
+```text
+product intent
+ -> Skill proposes EARS
+ -> CLI validates requirements
+ -> human approves meaning
+ -> Skill proposes Gherkin
+ -> CLI checks the feature
+ -> human approves behavior language
+ -> CLI aligns native suite source
+ -> human reviews the actual source diff
+```
+
+### Existing Suite
+
+```text
+existing native suite
+ -> CLI discovers flows
+ -> CLI extracts baseline Gherkin
+ -> human reviews the extracted baseline
+ -> Skill sharpens recovered behavior
+ -> CLI checks the feature
+ -> human approves behavior language
+ -> Skill proposes EARS
+ -> CLI validates requirements
+ -> human approves meaning
+ -> CLI aligns native suite source
+ -> human reviews the actual source diff
+```
+
+The CLI owns deterministic suite translation through `blackbox suites align --write`. Skills do not write suite source, and Blackbox does not create an intermediate patch artifact. The person reviews the real TypeScript diff.
+
+At this point, Blackbox can establish that accepted artifacts and the native suite are structurally connected. **It has not verified the behavior of the running system.**
+
+## Observe Facts Before Defining Policy
+
+The first trustworthy execution creates runtime facts before an effect policy exists:
+
+```text
+blackbox verify
+ -> runtime evidence
+ -> normalized observed effects
+ -> effects: not-configured
+```
+
+Observed effects report what this execution did at supported boundaries. They do not decide what the system should have done.
+
+The `$blackbox-effects` Skill or a person can use those observations to propose required and forbidden effects. A human reviews the resulting `features/.effects.yaml` before it becomes accepted policy.
+
+
+
+## Run the Full Verification Loop
+
+After the harness and effect policy are accepted, Blackbox can run the full loop:
+
+```text
+accepted harness
+ -> execute the selected flow
+ -> observe the running system
+ -> compute separate verdicts
+ -> repair implementation or reopen governance
+ -> rerun
+```
+
+The CLI keeps verdicts separate because they answer different questions:
+
+| Verdict | Question |
+| ----------------------- | ------------------------------------------------------------------------ |
+| **Test** | Did the native system-test assertions pass? |
+| **Feature** | Do accepted behavior and native suite structure agree? |
+| **Effect** | Did required effects occur and forbidden effects remain absent? |
+| **Requirement** | What does current accepted evidence establish about a bound requirement? |
+| **Observable decision** | Did exercised decision arms leave distinguishable observed evidence? |
+
+An agent may repair product implementation inside the accepted scope. It must stop when success would require changing:
+
+- accepted EARS meaning;
+- accepted Gherkin or flow IDs;
+- accepted suite scope or assertions;
+- required or forbidden effect policy;
+- instrumentation or captured boundaries;
+- human interpretation of final evidence.
+
+Reopening one of those decisions returns the change to the corresponding governance boundary.
+
+## Keep Authority Outside the Agent
+
+| Responsibility | Owner |
+| ------------------------------------------- | ------------ |
+| Propose requirement or behavior meaning | Skills |
+| Validate artifacts and transform suite ASTs | CLI |
+| Approve accepted behavior | Humans |
+| Repair implementation | Coding agent |
+
+One command crosses at most one review boundary. A source-changing command can return `awaiting-review`, but it never treats the next command, a commit, or an agent action as proof that a person approved the change.
+
+## Use Git and CI at the Boundaries
+
+Approval is external in the alpha. Use the repository's normal diff and pull-request workflow:
+
+1. A Skill or CLI operation changes one artifact layer.
+2. A person reviews the actual diff.
+3. The accepted change is committed through the normal repository process.
+4. CI runs deterministic structural checks or runtime verification.
+
+Natural checkpoints include approved EARS, approved Gherkin, an approved native suite diff, an approved effect contract, and a passing implementation repair. Future hosts may record these checkpoints explicitly, but the alpha CLI does not claim approval state.
+
+## Start at the Right Boundary
+
+Use [Choose Your Starting Point](/docs/blackbox/quickstart/) to begin from repository state. Start with specifications, an existing suite, or runtime effects from an accepted native flow.
diff --git a/src/content/docs/blackbox/overview/what-is-blackbox.mdx b/src/content/docs/blackbox/overview/what-is-blackbox.mdx
new file mode 100644
index 0000000..2383586
--- /dev/null
+++ b/src/content/docs/blackbox/overview/what-is-blackbox.mdx
@@ -0,0 +1,121 @@
+---
+title: "What is Blackbox?"
+description: "Suites Blackbox is a behavioral verification framework for agentic software engineering. It connects human-approved intent, executable system flows, runtime evidence, and deterministic verdicts."
+sidebar_position: 1
+keywords:
+ [
+ "behavior harness",
+ "behavioral verification framework",
+ "agentic software engineering",
+ "coding agent verification",
+ "runtime evidence",
+ "Suites Blackbox",
+ ]
+seo:
+ primary_keyword: "behavior harness"
+ secondary_keywords: ["behavioral verification framework", "runtime evidence"]
+ search_intent: "developers evaluating behavior harnesses and deterministic verification for coding agents"
+ snippet_angle: "connect human-approved intent, executable flows, observed runtime effects, and deterministic verdicts agents cannot redefine"
+---
+
+import BehaviorHarnessOverviewDiagram from "@/components/blackbox/BehaviorHarnessOverviewDiagram.astro";
+import Aside from "@/components/mdx/Aside.astro";
+
+**Suites Blackbox is a behavioral verification framework for agentic software engineering.**
+
+It connects a human-governed behavioral harness to a deterministic runtime verification loop. Coding agents repair implementation against its verdicts without redefining the accepted target.
+
+
+
+Specifications guide the agent. Blackbox verifies what the running system actually did.
+
+Blackbox combines two related parts:
+
+- The **behavior governance lifecycle** defines and reviews the target. It can start from product intent or an existing system-test suite.
+- The **runtime verification loop** executes that target, observes the running system, and computes deterministic verdicts against accepted policy. Agents may repair implementation and rerun while the target stays fixed.
+
+
+
+## Catch Green Tests That Miss the Behavior
+
+An agent can implement and test the same mistaken interpretation. The test passes because the code and assertion agree with each other.
+
+Blackbox adds an independent observation channel. For a rejected subscription, a Playwright flow can check both the response and the effects behind it:
+
+```ts
+expect(response.status()).toBe(404);
+
+await expect(capture).toObserveEffects({
+ requires: [effect.postgres("SELECT", { table: "users" })],
+ forbids: [
+ effect.http("POST", { path: "/v1/payment_intents" }),
+ effect.postgres("INSERT", { table: "subscriptions" }),
+ effect.sqs("SendMessage", { queue: "subscription-orders" }),
+ ],
+});
+```
+
+- The assertion proves the caller received `404`.
+- The observed effects prove the lookup occurred during this run.
+- The effect contract requires no captured payment, insert, or publication.
+
+A green assertion with a failed effect verdict means the visible result was correct while the accepted boundary behavior was not.
+
+## Use Only the Surfaces You Need
+
+Blackbox does not replace your specification framework or test runner. It connects the artifacts you already use through stable flow IDs and deterministic checks.
+
+| Adoption path | What it establishes |
+| ------------------------ | --------------------------------------------------------------------------------------- |
+| **Suite first** | Existing system tests become a reviewed, structurally aligned behavioral harness. |
+| **Specifications first** | Requirements and Gherkin govern a deterministically aligned native suite. |
+| **Runtime first** | A native flow produces observed effects and a reviewed required-or-forbidden policy. |
+| **Full chain** | Reviewed intent connects to an executable flow, current evidence, and bounded verdicts. |
+
+EARS requirements and Gherkin are optional. Runtime observation is also optional for structural governance, but it is required before Blackbox can claim what an execution actually did.
+
+Observed effects are facts from one run, not accepted policy. A person decides which effects become required, forbidden, or incidental before agents repair against them.
+
+## Keep Authority Separate
+
+- **Skills infer:** They propose requirements, scenarios, and effect policy.
+- **The CLI computes:** It validates, extracts, aligns native suite source, executes flows, records effects, and returns verdicts.
+- **Humans approve:** They review meaning, suite diffs, and effect policy through normal Git or pull-request review.
+- **Agents repair:** They change implementation and rerun deterministic checks.
+
+**Agents can change the implementation. They cannot change what success means.**
+
+Changing accepted requirements, scenarios, suite assertions, or effect policy reopens human review.
+
+## Read Each Verdict Separately
+
+Blackbox reports distinct results instead of one unexplained pass or fail:
+
+- **Test:** Did the native assertions pass?
+- **Feature:** Does reviewed behavior still align with the native flow?
+- **Effect:** Did required effects occur and forbidden effects remain absent?
+- **Requirement:** Is accepted intent `proven`, `violated`, `unproven`, or `unbound`?
+- **Observable decision:** Did exercised decision arms produce distinguishable evidence?
+
+Every verdict is bounded by the selected flow, accepted artifacts, captured boundaries, instrumentation, and environment. Missing evidence remains explicit; it never becomes confidence.
+
+## Start With One Consequential Flow
+
+First, [install and initialize Blackbox](/docs/blackbox/quickstart/install). Then inspect the repository:
+
+```bash
+pnpm exec blackbox init --mode auto --json
+pnpm exec blackbox status --json
+```
+
+Choose the path that matches its current state:
+
+- **[Adopt an existing suite](/docs/blackbox/quickstart/adopt-existing-suite)**
+- **[Define new behavior](/docs/blackbox/quickstart/define-new-behavior)**
+- **[Add runtime evidence to an accepted flow](/docs/blackbox/quickstart/add-runtime-evidence)**
+
+Read [Behavior Governance and Runtime Verification](/docs/blackbox/overview/verification-loop) for the full model.
diff --git a/src/content/docs/blackbox/overview/when-to-use-blackbox.mdx b/src/content/docs/blackbox/overview/when-to-use-blackbox.mdx
new file mode 100644
index 0000000..399c6cf
--- /dev/null
+++ b/src/content/docs/blackbox/overview/when-to-use-blackbox.mdx
@@ -0,0 +1,75 @@
+---
+title: "When to Use Blackbox"
+description: "Choose Blackbox for boundary-risk system and E2E flows where reviewed intent, executable assertions, and runtime behavior must remain connected."
+sidebar_position: 5
+keywords:
+ [
+ "when to use system tests",
+ "E2E effect coverage",
+ "legacy refactor testing",
+ "microservice regression testing",
+ "behavioral verification",
+ ]
+---
+
+import OverviewDiagram from "@/components/blackbox/OverviewDiagram.astro";
+import Aside from "@/components/mdx/Aside.astro";
+
+Use Blackbox when a change can preserve the visible response while breaking important behavior at a system boundary, or when reviewed intent needs a durable path to runtime evidence.
+
+
+
+## Strong First Uses
+
+Start with one flow whose boundary behavior is consequential and stable enough to review.
+
+| Situation | Why runtime evidence helps |
+| ----------------------- | ----------------------------------------------------------------------------------------------------------------------- |
+| Refactor or rewrite | Capture reviewed behavior before changing internals, then compare each candidate implementation with the same contract. |
+| Legacy modernization | Preserve known database, cache, queue, and service interactions while replacing code in stages. |
+| Incident regression | Record the required and forbidden effects that distinguish the fixed path from the failure. |
+| Microservice workflow | Verify that a public success or failure corresponds to the intended cross-service effects. |
+| Agent-authored change | Give the agent a deterministic repair signal and give the reviewer evidence independent of the diff summary. |
+| High-risk negative path | Prove that rejected or unauthorized work did not continue into payment, persistence, deletion, or publication. |
+
+The practical selection rule is **boundary risk**: if the important failure can happen after the input is accepted but before or beyond the output assertion, Blackbox is a strong candidate.
+
+## System Tests Before Broad E2E
+
+A controlled system test owns its topology and managed dependencies. It can reset databases, queues, caches, services, networks, and test data. That control makes a missing or forbidden effect credible as a merge gate.
+
+A broader E2E run often reaches unmanaged dependencies: shared authentication, remote email, third-party payment, or a deployed environment used by other tests. Blackbox can still add evidence, but failures may reflect environmental noise rather than the change under review.
+
+Start with the controlled system-test layer. Extend into broader E2E journeys when the extra realism is worth the operational variability.
+
+## Use a Smaller Test Instead When
+
+Do not move every assertion upward into a composed topology.
+
+Prefer a unit or integration test when:
+
+- the behavior is local logic with no meaningful runtime boundary;
+- a dependency double can express the contract clearly and cheaply;
+- the failure is easier to locate below the system layer;
+- the flow is too noisy or expensive to make a reliable gate;
+- nobody can explain which runtime effects should be reviewed.
+
+Blackbox complements the test pyramid. It does not make lower-level tests obsolete.
+
+
+
+## A Good First Candidate
+
+Choose a flow that:
+
+- already runs in Playwright or can be exercised narrowly;
+- crosses one or more supported boundaries;
+- has an outcome the team can state in required and forbidden terms;
+- runs in an environment the test owns or can reset;
+- would block a merge if its behavior changed unexpectedly.
+
+See [Adopt Blackbox Incrementally](/docs/blackbox/overview/adopt-blackbox-in-layers) to choose the first claim your team needs. Then [choose a starting point](/docs/blackbox/quickstart/) and select one accepted native flow. Add [runtime evidence](/docs/blackbox/quickstart/add-runtime-evidence) when the claim concerns what the running system did.
diff --git a/src/content/docs/blackbox/quickstart/define-new-behavior.mdx b/src/content/docs/blackbox/quickstart/define-new-behavior.mdx
new file mode 100644
index 0000000..cf1563a
--- /dev/null
+++ b/src/content/docs/blackbox/quickstart/define-new-behavior.mdx
@@ -0,0 +1,115 @@
+---
+title: "Define New Behavior"
+description: "Take new product intent through reviewed requirements, Gherkin, and deterministic native suite alignment before adding runtime observation."
+sidebar_position: 4
+keywords:
+ [
+ "spec-driven development",
+ "EARS requirements",
+ "Gherkin",
+ "Blackbox suites align",
+ ]
+---
+
+import Aside from "@/components/mdx/Aside.astro";
+
+Use this path when no existing system-test flow expresses the behavior you need. The governance lifecycle turns intent into an accepted, executable harness before runtime verification begins.
+
+## 1. Propose Requirements
+
+Use `$blackbox-requirements` to translate the selected product obligation into proposed EARS:
+
+```text
+$blackbox-requirements
+
+Input:
+- docs/subscriptions.md
+- target flow: subscribe-unknown-user
+
+Task:
+Propose atomic EARS requirements for this flow.
+```
+
+Validate the proposed file:
+
+```bash
+pnpm exec blackbox requirements validate requirements/subscriptions.ears --json
+```
+
+The CLI validates syntax, profile rules, and IDs. A person still approves the requirement meaning.
+
+## 2. Propose Readable Behavior
+
+After requirement approval, use `$blackbox-gherkin` to propose a feature with stable bindings:
+
+```gherkin
+@flow:subscribe-unknown-user
+@requirement:REQ-004
+Feature: Reject an unknown subscriber
+
+ Scenario: request stops before payment
+ When the unknown user posts a subscription request
+ Then the response status is 404
+```
+
+Check the feature:
+
+```bash
+pnpm exec blackbox features check \
+ --feature features/subscribe-unknown-user.feature \
+ --json
+```
+
+A person reviews the scenario language before suite translation.
+
+
+
+## 3. Align the Native Suite
+
+The CLI translates accepted Gherkin through the detected runner adapter. Preview first:
+
+```bash
+pnpm exec blackbox suites align \
+ --feature features/subscribe-unknown-user.feature \
+ --json
+```
+
+Apply the deterministic transformation:
+
+```bash
+pnpm exec blackbox suites align \
+ --feature features/subscribe-unknown-user.feature \
+ --write \
+ --json
+```
+
+If no bound suite exists, the adapter creates one. If a suite exists, it updates only the selected flow. Unsupported application-specific actions return a finding instead of invented test code.
+
+The command writes native suite source directly and returns `awaiting-review`. Review the actual TypeScript diff before continuing.
+
+## 4. Check the Accepted Harness
+
+```bash
+pnpm exec blackbox suites check --flow subscribe-unknown-user --json
+pnpm exec blackbox requirements check --flow subscribe-unknown-user --json
+pnpm exec blackbox status --flow subscribe-unknown-user --json
+```
+
+Your first success is one new behavior with approved meaning, readable examples, stable bindings, and a deterministically generated or aligned native suite.
+
+
+
+Next, check [Runtime Prerequisites](/docs/blackbox/quickstart/runtime-prerequisites), then [Complete the Verification Loop](/docs/blackbox/quickstart/add-runtime-evidence).
+
+## Summary
+
+- Approve requirement meaning and readable behavior before suite generation.
+- Let the CLI create or align native suite source deterministically.
+- Add runtime observation before claiming that the running system satisfies the accepted behavior.
diff --git a/src/content/docs/blackbox/quickstart/feature-files-from-tests.mdx b/src/content/docs/blackbox/quickstart/feature-files-from-tests.mdx
new file mode 100644
index 0000000..1e1a7ba
--- /dev/null
+++ b/src/content/docs/blackbox/quickstart/feature-files-from-tests.mdx
@@ -0,0 +1,120 @@
+---
+title: "Adopt an Existing Suite"
+slug: "blackbox/quickstart/adopt-existing-suite"
+description: "Recover reviewed behavior from one existing system-test flow and align its native suite deterministically without running the system."
+sidebar_position: 3
+keywords:
+ [
+ "existing system tests",
+ "Blackbox features extract",
+ "suite AST alignment",
+ "brownfield adoption",
+ ]
+---
+
+import Aside from "@/components/mdx/Aside.astro";
+
+Use this path when the repository already has a system or E2E suite. Adopt one consequential flow before converting more of the suite.
+
+This quickstart ends with reviewed behavior, stable bindings, and a deterministically aligned native suite. It does not require runtime instrumentation.
+
+## 1. Discover Candidate Flows
+
+```bash
+pnpm exec blackbox init --mode existing --json
+pnpm exec blackbox suites discover ./e2e --json
+```
+
+`suites discover` parses native suite ASTs and reports candidate test titles, steps, tags, source locations, and binding conflicts. It does not change source.
+
+Choose one stable, consequential flow. Keep its source path and provisional flow ID through the rest of the quickstart.
+
+## 2. Extract Baseline Behavior
+
+Preview the deterministic extraction:
+
+```bash
+pnpm exec blackbox features extract ./e2e/checkout.spec.ts --json
+```
+
+Write the baseline after checking the plan:
+
+```bash
+pnpm exec blackbox features extract ./e2e/checkout.spec.ts --write --json
+```
+
+The command creates a literal `.feature` baseline from suite structure and preserves source locations. It returns `awaiting-review`. It does not claim that existing test names express complete product intent.
+
+## 3. Review the Recovered Behavior
+
+Use `$blackbox-gherkin` to sharpen vague descriptions, choose a durable flow boundary, and identify behavior the suite does not prove. The Skill may edit the proposed `.feature` file; it must not edit suite source.
+
+Validate the reviewed feature:
+
+```bash
+pnpm exec blackbox features check \
+ --feature features/checkout-payment.feature \
+ --json
+```
+
+A person approves the behavior language before it becomes the source for suite alignment.
+
+## 4. Recover Requirement Meaning
+
+Use `$blackbox-requirements` to translate the accepted Gherkin into proposed EARS. The reverse translation is inferential because an existing test cannot reveal every product obligation or exception.
+
+```bash
+pnpm exec blackbox requirements validate requirements/checkout.ears --json
+pnpm exec blackbox requirements check --flow checkout-payment --json
+```
+
+A clean validation result establishes structure, not product truth. A person approves the requirement meaning.
+
+## 5. Align the Native Suite
+
+Preview the constrained AST transformation:
+
+```bash
+pnpm exec blackbox suites align \
+ --feature features/checkout-payment.feature \
+ --suite ./e2e/checkout.spec.ts \
+ --json
+```
+
+Apply it explicitly:
+
+```bash
+pnpm exec blackbox suites align \
+ --feature features/checkout-payment.feature \
+ --suite ./e2e/checkout.spec.ts \
+ --write \
+ --json
+```
+
+The CLI updates only the selected flow, preserves unrelated tests and helpers, and writes the TypeScript file atomically. It does not create an intermediate patch artifact. Review the actual `.ts` diff.
+
+## 6. Check the Accepted Harness
+
+After human approval:
+
+```bash
+pnpm exec blackbox suites check --flow checkout-payment --json
+pnpm exec blackbox requirements check --flow checkout-payment --json
+pnpm exec blackbox status --flow checkout-payment --json
+```
+
+Your first success is one existing flow with reviewed behavior, stable identities, and an aligned native suite.
+
+
+
+Next, check [Runtime Prerequisites](/docs/blackbox/quickstart/runtime-prerequisites), then [Complete the Verification Loop](/docs/blackbox/quickstart/add-runtime-evidence).
+
+## Summary
+
+- Extract baseline Gherkin from the existing native suite.
+- Review inferred meaning, then align the suite deterministically.
+- Add runtime observation before claiming that the running system satisfies the accepted behavior.
diff --git a/src/content/docs/blackbox/quickstart/first-proven-feature.mdx b/src/content/docs/blackbox/quickstart/first-proven-feature.mdx
new file mode 100644
index 0000000..1e1cea9
--- /dev/null
+++ b/src/content/docs/blackbox/quickstart/first-proven-feature.mdx
@@ -0,0 +1,159 @@
+---
+title: "Complete the Verification Loop"
+slug: "blackbox/quickstart/add-runtime-evidence"
+description: "Run one accepted flow, capture observed effects, review effect policy, and compute deterministic runtime verdicts."
+sidebar_position: 6
+keywords:
+ [
+ "Blackbox runtime evidence",
+ "effect contract",
+ "deterministic verdict",
+ "verification loop",
+ ]
+---
+
+import Tabs from "@/components/mdx/Tabs.astro";
+import TabItem from "@/components/mdx/TabItem.astro";
+import Aside from "@/components/mdx/Aside.astro";
+
+Continue here when the selected flow has an accepted native suite and stable flow ID. You can arrive from [Adopt an Existing Suite](/docs/blackbox/quickstart/adopt-existing-suite), [Define New Behavior](/docs/blackbox/quickstart/define-new-behavior), or an existing accepted flow that does not use requirements or Gherkin.
+
+This path does not require a specification layer. Runtime observation creates facts; reviewed effect policy and the next run complete the effect verification loop.
+
+## 1. Install Runtime Packages
+
+Install the runtime, Node adapter, instrumentation payload, Playwright, and Testcontainers in the package that owns the system tests.
+
+
+
+
+```bash
+pnpm add -D \
+ @suites/blackbox \
+ @suites/blackbox-adapter-node \
+ @suites/blackbox-instr-node \
+ @playwright/test \
+ testcontainers
+```
+
+
+
+
+```bash
+npm install --save-dev @suites/blackbox @suites/blackbox-adapter-node @suites/blackbox-instr-node @playwright/test testcontainers
+```
+
+
+
+
+```bash
+yarn add --dev @suites/blackbox @suites/blackbox-adapter-node @suites/blackbox-instr-node @playwright/test testcontainers
+```
+
+
+
+
+Keep `@suites/blackbox` and `@suites/blackbox-cli` on compatible versions.
+
+## 2. Check Runtime Readiness
+
+```bash
+pnpm exec blackbox doctor --json
+```
+
+`doctor` checks the test runner, topology, instrumentation, paths, and bindings. It does not run the SUT or modify source.
+
+Resolve setup findings before treating a run as trustworthy.
+
+## 3. Run and Observe
+
+Run one accepted flow:
+
+```bash
+pnpm exec blackbox verify --flow checkout-payment --json
+```
+
+The first run performs these computational steps:
+
+1. Validate the selected flow and any configured artifacts.
+2. Execute the native system-test flow.
+3. Capture run-scoped runtime evidence.
+4. Normalize evidence into observed effects.
+5. Compute every configured verdict that has enough evidence.
+
+An effect contract is not required to create observed effects. The first result can report `effects: not-configured` and still contain useful observations.
+
+Inspect them:
+
+```bash
+pnpm exec blackbox effects show \
+ --flow checkout-payment \
+ --run latest \
+ --json
+```
+
+Observed effects are generated facts beneath `.blackbox-coverage/runs//`. They are not accepted policy.
+
+## 4. Review Effect Policy
+
+Use `$blackbox-effects` or a person to classify the observations:
+
+- promote selected observed effects to `requires`;
+- add unsafe absent behavior to `forbids`;
+- leave incidental observations outside the contract;
+- flag observations that may reveal an implementation defect.
+
+The reviewed policy lives at `features/.effects.yaml`:
+
+```yaml
+specVersion: "0.1"
+flow: checkout-payment
+requires:
+ - { boundary: postgres, op: INSERT, key: orders }
+forbids:
+ - { boundary: http, op: POST, key: /refunds }
+```
+
+Validate the proposal:
+
+```bash
+pnpm exec blackbox effects check --flow checkout-payment --json
+```
+
+
+
+## 5. Compute the Accepted Verdicts
+
+Rerun against the accepted effect contract:
+
+```bash
+pnpm exec blackbox verify --flow checkout-payment --json
+```
+
+Read each layer independently:
+
+| Layer | Successful result establishes |
+| ------------------- | ---------------------------------------------------------------- |
+| Test | Native assertions passed |
+| Feature | Configured accepted behavior and suite structure agree |
+| Effect | Required effects occurred and forbidden effects remained absent |
+| Requirement | Bound requirements inherit current accepted evidence, if present |
+| Observable decision | Eligible branch arms produced distinguishable observed evidence |
+
+## 6. Repair and Rerun
+
+A coding agent can use deterministic findings to change implementation and rerun `verify`. It must stop when passing would require changing accepted requirements, Gherkin, suite scope or assertions, effect policy, or human interpretation of evidence.
+
+That stop is not a failure of autonomy. It is the authority boundary that prevents the agent from moving its own target.
+
+## Summary
+
+- One accepted flow is connected to current evidence from the running system.
+- Test, feature, effect, requirement, and observable-decision verdicts remain separate.
+- Every claim remains bounded by the selected flow, accepted contracts, captured boundaries, instrumentation, and test environment.
+
+Continue with [Reports and CI Gates](/docs/blackbox/guides/reports-and-ci-gates).
diff --git a/src/content/docs/blackbox/quickstart/index.mdx b/src/content/docs/blackbox/quickstart/index.mdx
new file mode 100644
index 0000000..ceebbfd
--- /dev/null
+++ b/src/content/docs/blackbox/quickstart/index.mdx
@@ -0,0 +1,76 @@
+---
+title: "Choose Your Blackbox Starting Point"
+description: "Start from an existing suite, new product intent, or runtime effects from an accepted native flow."
+sidebar_position: 2
+keywords:
+ [
+ "Blackbox quickstart",
+ "behavior governance",
+ "existing system tests",
+ "runtime effects",
+ ]
+---
+
+import Aside from "@/components/mdx/Aside.astro";
+
+Blackbox can start from specifications, existing system tests, or runtime behavior. Choose the path from the repository state and the claim you need.
+
+
+
+## Choose From Repository State
+
+| Starting point | Path | First useful result |
+| ------------------------------------------------- | ------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
+| Existing suite that needs readable behavior | [Adopt an Existing Suite](/docs/blackbox/quickstart/adopt-existing-suite) | Reviewed behavior and a structurally aligned native flow |
+| New product behavior without an applicable flow | [Define New Behavior](/docs/blackbox/quickstart/define-new-behavior) | Approved intent, readable examples, and a native flow ready to execute |
+| Accepted native flow that needs boundary evidence | [Add Runtime Evidence](/docs/blackbox/quickstart/add-runtime-evidence) | Reviewed effect policy and a current deterministic effect verdict |
+| Repository with several incomplete states | Start with one consequential existing flow | One bounded flow reaches a useful result without converting the project |
+
+These are equal entry points. Requirements and Gherkin are not prerequisites for runtime effect verification.
+
+## Choose the First Claim
+
+### Govern Structure Without Runtime
+
+Use the existing-suite or new-behavior path when reviewers first need a stable behavioral target.
+
+Blackbox can establish that:
+
+- accepted artifacts have stable identities;
+- the selected native suite is structurally aligned;
+- source transformations are deterministic and reviewable;
+- structural checks can run locally and in CI.
+
+It cannot establish what the running system did until the flow executes with runtime observation.
+
+### Verify Effects Without Specifications
+
+Use the runtime path when an accepted native flow already has a stable flow ID and the immediate question concerns database, HTTP, queue, cache, or other supported effects.
+
+The path is explicit:
+
+```text
+execute flow -> observe effects -> propose policy -> human review -> rerun -> effect verdict
+```
+
+The first run records facts. It may report `effects: not-configured` until a person accepts which effects are required, forbidden, or incidental.
+
+## Build the Full Connected Chain Later
+
+Teams can combine the surfaces when requirement traceability matters:
+
+```text
+reviewed intent -> readable behavior -> native flow -> runtime evidence -> bounded verdicts
+```
+
+Adding a surface strengthens only the claims that surface supports. It does not invalidate an earlier suite-first or effects-first result.
+
+## Summary
+
+- Install and initialize before choosing a path.
+- Start from existing suites, new intent, or runtime effects.
+- Treat observed facts and accepted effect policy as separate review stages.
diff --git a/src/content/docs/blackbox/quickstart/install.mdx b/src/content/docs/blackbox/quickstart/install.mdx
new file mode 100644
index 0000000..31cbac9
--- /dev/null
+++ b/src/content/docs/blackbox/quickstart/install.mdx
@@ -0,0 +1,102 @@
+---
+title: "Install and Initialize Blackbox"
+description: "Install the Blackbox CLI, inspect repository state, and choose a suite-first, specification-first, or effects-first path."
+sidebar_position: 1
+keywords:
+ [
+ "install Suites Blackbox",
+ "Blackbox CLI",
+ "blackbox init",
+ "behavioral harness",
+ ]
+---
+
+import Tabs from "@/components/mdx/Tabs.astro";
+import TabItem from "@/components/mdx/TabItem.astro";
+import Aside from "@/components/mdx/Aside.astro";
+
+Install the CLI first. You do not need Docker, Playwright instrumentation, or a running system to inspect the repository, validate behavior artifacts, or align a native suite.
+
+## Install the Computational Harness
+
+Install `@suites/blackbox-cli` in the workspace package that owns the system-test suite or will own the new flow.
+
+
+
+
+```bash
+pnpm add -D @suites/blackbox-cli
+```
+
+
+
+
+```bash
+npm install --save-dev @suites/blackbox-cli
+```
+
+
+
+
+```bash
+yarn add --dev @suites/blackbox-cli
+```
+
+
+
+
+Confirm the project-local binary:
+
+```bash
+pnpm exec blackbox --help
+```
+
+The command should list the framework facade and the `flows`, `requirements`, `features`, `suites`, `effects`, `coverage`, and `otel` topics.
+
+## Inspect the Repository
+
+Run initialization in automatic mode:
+
+```bash
+pnpm exec blackbox init --mode auto --json
+```
+
+`init` detects:
+
+- the system-test adapter and suite roots;
+- existing requirement, feature, and effect roots;
+- bound and unbound suite candidates;
+- whether the next path is `new`, `existing`, or mixed;
+- the recommended next command.
+
+It may create local Blackbox state and missing artifact directories. It does not modify accepted behavior or suite source.
+
+Read the structural state without running tests:
+
+```bash
+pnpm exec blackbox status --json
+```
+
+## Choose the Starting Point
+
+- Existing suite that needs readable behavior: [Adopt an Existing Suite](/docs/blackbox/quickstart/adopt-existing-suite)
+- New behavior without an applicable flow: [Define New Behavior](/docs/blackbox/quickstart/define-new-behavior)
+- Accepted native flow that needs boundary evidence: [Add Runtime Evidence](/docs/blackbox/quickstart/add-runtime-evidence)
+
+Requirements and Gherkin are optional for the runtime-effects path. Source-changing operations use preview mode before `--write`. A write can return `awaiting-review`; that means the transformation completed and the workflow must pause for a person to review the actual diff.
+
+
+
+## Add Runtime Packages Later
+
+Install the runtime, adapter, instrumentation payload, Playwright, and Testcontainers only when you are ready to observe the running system. [Runtime Prerequisites](/docs/blackbox/quickstart/runtime-prerequisites) lists the supported alpha stack and [Complete the Verification Loop](/docs/blackbox/quickstart/add-runtime-evidence) provides the install commands.
+
+## Summary
+
+- Install the CLI before runtime packages.
+- Use `init --mode auto` and `status` to select the first incomplete boundary.
+- Review every source-changing operation through the repository's normal process.
diff --git a/src/content/docs/blackbox/quickstart/requirements.mdx b/src/content/docs/blackbox/quickstart/requirements.mdx
new file mode 100644
index 0000000..26f78a5
--- /dev/null
+++ b/src/content/docs/blackbox/quickstart/requirements.mdx
@@ -0,0 +1,75 @@
+---
+title: "Runtime Prerequisites"
+slug: "blackbox/quickstart/runtime-prerequisites"
+description: "Prepare the supported Node, Playwright, Docker, and test-time instrumentation path before completing the Blackbox verification loop."
+sidebar_position: 5
+keywords:
+ [
+ "Blackbox runtime prerequisites",
+ "Playwright",
+ "Node instrumentation",
+ "Docker testbed",
+ ]
+---
+
+import InstrumentationFlowDiagram from "@/components/blackbox/InstrumentationFlowDiagram.astro";
+import Aside from "@/components/mdx/Aside.astro";
+
+You only need these prerequisites when Blackbox will observe a running system. Requirement validation, feature checks, suite discovery, and suite alignment do not require runtime infrastructure.
+
+Runtime observation completes the full verification loop. In the documented alpha path, Playwright drives a compatible Node system under test while Blackbox injects test-time OpenTelemetry instrumentation.
+
+## Supported Alpha Path
+
+| Requirement | Current expectation |
+| ------------------ | ----------------------------------------------------------------------------------- |
+| Node | A compatible current Node release; the workspace and showcase currently require 22+ |
+| Test runner | Playwright system or E2E tests |
+| Topology | A controlled Docker test environment |
+| System under test | A Node service image that starts through a shadowable Node binary |
+| Instrumentation | Blackbox test-time bootstrap and supported OpenTelemetry producers |
+| First run | One stable flow, run serially |
+| Artifact directory | A writable location such as `.blackbox-coverage/` |
+
+The default path is deliberately narrow. Non-Node services need an equivalent Blackbox-readable evidence integration. Distroless images and shared remote environments are not good first-run targets.
+
+## Test-Time Instrumentation
+
+Blackbox injects observability into compatible SUT containers for the test run. Production source and Dockerfiles do not need Blackbox imports.
+
+
+
+The compose testbed mounts the bootstrap payload, shadows the service's Node binary, preloads `bootstrap.cjs`, captures supported spans, and exposes them to the test runner. Existing tracing agents may need test-environment overrides if they register first.
+
+## Confirm the Environment
+
+Run these checks where the system tests live:
+
+```bash
+node --version
+docker version
+pnpm exec playwright --version
+```
+
+Confirm that:
+
+1. The SUT starts without Blackbox.
+2. One Playwright flow passes against that topology.
+3. The service image starts through a Node binary the wrapper can shadow.
+4. The bootstrap image is available locally or through `BLACKBOX_INSTR_IMAGE`.
+5. The test job can write run-scoped artifacts.
+6. The first proof can run with one Playwright worker.
+
+
+
+Continue with [Complete the Verification Loop](/docs/blackbox/quickstart/add-runtime-evidence).
+
+## Summary
+
+- Add runtime prerequisites only after the behavioral harness is accepted.
+- Prove the system and one native flow work before enabling Blackbox instrumentation.
+- Treat `doctor` as runtime readiness, not as validation of the governance work.
diff --git a/src/content/docs/blackbox/reference/api.md b/src/content/docs/blackbox/reference/api.md
new file mode 100644
index 0000000..5e34fb8
--- /dev/null
+++ b/src/content/docs/blackbox/reference/api.md
@@ -0,0 +1,76 @@
+---
+title: "API Reference"
+description: "Public package entry points for Blackbox core effects, Playwright fixtures, testbeds, diagnostics, mocks, and extensibility."
+sidebar_position: 2
+keywords:
+ [
+ "Blackbox API reference",
+ "@suites/blackbox exports",
+ "Playwright Blackbox API",
+ "effect coverage API",
+ ]
+---
+
+Blackbox is alpha. Treat documented package exports as the public surface and deep `dist/` imports as internal.
+
+## Package Entry Points
+
+| Import | Purpose |
+| ------------------------------------- | ----------------------------------------------------------------------------- |
+| `@suites/blackbox` | Main convenience exports |
+| `@suites/blackbox/core` | Effect builders, catalog model, evaluator, and predicates |
+| `@suites/blackbox/runners/playwright` | Playwright fixtures, matchers, captures, and trace helpers |
+| `@suites/blackbox/playwright` | `defineBlackboxConfig` and `blackboxReporter` config helpers |
+| `@suites/blackbox/testbed` | `createBlackboxTestbed`, testbed types, connect helpers, and disposal helpers |
+| `@suites/blackbox/diagnostics` | Topology and sequence diagnostics |
+| `@suites/blackbox/mocks` | Test-environment boundary mocks |
+| `@suites/blackbox/extensibility` | Runtime adapter, coverage producer, reporter, and sink contracts |
+
+Packaged Playwright global setup and teardown subpaths are implementation-facing config targets returned by `defineBlackboxConfig()`. Prefer the helper instead of importing those subpaths directly.
+
+## Minimal Runtime Use
+
+```ts
+import { effect } from "@suites/blackbox/core";
+import { expect, test } from "./blackbox-testbed";
+
+test.describe("Customer checkout", { tag: "@flow:checkout-flow" }, () => {
+ test("creates an order", async ({ capture }) => {
+ await expect(capture).toObserveEffects([
+ effect.postgres("INSERT", { table: "orders" }),
+ effect.forbid(effect.http("POST", { path: "/refunds" })),
+ ]);
+ });
+});
+```
+
+The `effect.forbid()` wrapper is for the single or array matcher form. In `{ requires, forbids }`, put bare effect shapes in `forbids`.
+
+## Configuration Use
+
+```ts
+import { defineConfig } from "@playwright/test";
+import {
+ blackboxReporter,
+ defineBlackboxConfig,
+} from "@suites/blackbox/playwright";
+import { testbed } from "./blackbox-testbed.js";
+
+export default defineConfig({
+ ...defineBlackboxConfig({ mode: "testbed", testbed }),
+ reporter: [
+ ["list"],
+ blackboxReporter({ outputDir: "./e2e/.blackbox-coverage" }),
+ ],
+});
+```
+
+## Error Model
+
+Runtime APIs reject with normal JavaScript errors. Playwright matchers return matcher failures that Playwright reports against the active test. CLI commands use a separate JSON envelope and exit-code contract documented in [CLI Reference](/docs/blackbox/reference/cli) and [Exit Codes](/docs/blackbox/reference/exit-codes).
+
+## Stability
+
+No stable-major compatibility guarantee applies during alpha. Pin versions through the lockfile and update the runtime, CLI, Node adapter, and instrumentation payload together.
+
+For detailed signatures, continue to [Testbed API](/docs/blackbox/reference/testbed-api), [Playwright Flow Tags](/docs/blackbox/reference/scenario-dsl), and [Matchers and Effect Builders](/docs/blackbox/reference/matchers-and-effect-builders).
diff --git a/src/content/docs/blackbox/reference/catalog-schema.md b/src/content/docs/blackbox/reference/catalog-schema.md
new file mode 100644
index 0000000..a9ecba4
--- /dev/null
+++ b/src/content/docs/blackbox/reference/catalog-schema.md
@@ -0,0 +1,75 @@
+---
+title: "Effect Contract Schema"
+description: "Effect contract v0.1 YAML format for required and forbidden runtime behavior."
+sidebar_position: 7
+keywords:
+ ["effect contract schema", "effect YAML", "Blackbox YAML", "requires forbids"]
+---
+
+An **effect contract** records the required and forbidden runtime effects for one flow. It is the only Blackbox-owned public YAML artifact.
+
+```text
+features/subscribe-unknown-user.feature
+features/subscribe-unknown-user.effects.yaml
+```
+
+## Complete Example
+
+```yaml
+specVersion: "0.1"
+flow: subscribe-unknown-user
+requires:
+ - { boundary: postgres, op: SELECT, key: users, service: bff }
+forbids:
+ - { boundary: http, op: POST, key: /v1/payment_intents, service: bff }
+ - { boundary: postgres, op: INSERT, key: subscriptions, service: bff }
+ - { boundary: sqs, op: SendMessage, key: subscription-orders }
+```
+
+## Envelope
+
+| Field | Meaning |
+| ------------- | --------------------------------------------------------------------- |
+| `specVersion` | Contract format version. The current public version is `"0.1"`. |
+| `flow` | Stable flow ID. Must match the feature basename and `@flow:` tag. |
+| `requires` | Effects that must match at least once unless constrained by `count`. |
+| `forbids` | Effects that must match zero times. |
+
+## Shape Fields
+
+`boundary` is structurally required. Other fields depend on the boundary:
+
+- common: `op`, `key`, `service`, `count`;
+- Redis: `ttl`;
+- Postgres: `schema`;
+- HTTP: `host`, `status`;
+- S3: `bucket`;
+- RabbitMQ: `exchange`, `routingKey`.
+
+Unknown fields remain forward-compatible in the parsed shape, but only fields understood by the evaluator affect matching.
+
+## Pattern Syntax
+
+```yaml
+key: "user:*:tier"
+key: { equals: "literal" }
+key: { regex: "^user:" }
+count: 1
+count: { gte: 1 }
+ttl: { gte: 60, lte: 3600 }
+```
+
+Bare strings use glob matching. Use `equals` for exact matches and `regex` only when a glob would be ambiguous.
+
+## Review Rules
+
+Effect contracts are accepted behavior. A Skill may propose a contract from runtime evidence, but a human decides whether each observed effect is required, forbidden, incidental, or a defect.
+
+`blackbox verify` writes evidence and reports. It does not silently update accepted effect contracts.
+
+## Summary
+
+- **One effect YAML file describes one flow.**
+- **The `flow` field must match the Gherkin and Playwright flow ID.**
+- **`requires` proves expected runtime behavior appeared.**
+- **`forbids` proves unsafe runtime behavior stayed absent.**
diff --git a/src/content/docs/blackbox/reference/cli.md b/src/content/docs/blackbox/reference/cli.md
new file mode 100644
index 0000000..339aa37
--- /dev/null
+++ b/src/content/docs/blackbox/reference/cli.md
@@ -0,0 +1,257 @@
+---
+title: "CLI Reference"
+description: "Reference for the Blackbox computational harness, including repository onboarding, artifact checks, suite AST transformations, runtime verification, and structured review boundaries."
+sidebar_position: 1
+keywords:
+ ["blackbox cli", "blackbox suites align", "blackbox verify", "blackbox json"]
+toc_min_heading_level: 2
+---
+
+The `blackbox` binary is the **computational harness**. It validates artifacts, extracts behavior from existing suites, transforms native suite ASTs, executes flows, observes effects, and computes bounded verdicts.
+
+Skills own inferential proposals. Humans approve accepted behavior. The CLI never changes accepted behavior merely to clear a failing verdict.
+
+## Public Command Surface
+
+```text
+blackbox init
+blackbox doctor
+blackbox status
+blackbox verify
+blackbox explain
+
+blackbox flows list
+blackbox flows show
+
+blackbox requirements validate [paths...]
+blackbox requirements check
+blackbox requirements drift
+blackbox requirements coverage
+
+blackbox features extract [suite-paths...]
+blackbox features check
+blackbox features drift
+
+blackbox suites discover [paths...]
+blackbox suites check
+blackbox suites align
+
+blackbox effects show
+blackbox effects check
+
+blackbox coverage replay
+blackbox otel instrument
+```
+
+`features emit` may remain as a temporary compatibility alias. Use `features extract` in new scripts and documentation.
+
+## Shared Options
+
+| Option | Meaning |
+| -------------------------------- | -------------------------------------------------------- |
+| `--flow ` | Select one stable flow; repeat to select several |
+| `--json` | Write one machine-readable result to stdout |
+| `--write` | Apply an explicit source transformation atomically |
+| `--run ` | Select retained runtime evidence |
+| `--mode ` | Select initialization behavior |
+| `--feature ` | Select an accepted Gherkin input |
+| `--suite ` | Select a native suite when discovery is ambiguous |
+| `--expected-revision ` | Require a repository revision before a future-safe write |
+
+Every command supports `--json`. JSON mode never prompts. Ambiguous discovery returns choices and exits without writing.
+
+## Framework Commands
+
+| Command | Responsibility | Writes |
+| ------------------------- | ------------------------------------------------------------------- | -------------------------------- |
+| `blackbox init` | Detect project state and select the onboarding path | Local state and scaffolding only |
+| `blackbox doctor` | Check tools, topology, instrumentation, paths, and bindings | Nothing |
+| `blackbox status` | Report structural readiness and latest retained run | Nothing |
+| `blackbox verify` | Validate, execute, observe, normalize effects, and compute verdicts | Run-scoped evidence and reports |
+| `blackbox explain ` | Explain a deterministic finding and its safe next action | Nothing |
+
+### `init`
+
+```bash
+blackbox init --mode auto --json
+blackbox init --mode new --json
+blackbox init --mode existing --json
+```
+
+`init` detects new, existing, and mixed repositories. It does not modify requirements, features, effect contracts, or suite source.
+
+### `doctor`
+
+```bash
+blackbox doctor --json
+```
+
+`doctor` checks configured layers. Runtime findings do not invalidate a structurally accepted harness; they mean runtime verification is not ready.
+
+### `status`
+
+```bash
+blackbox status --json
+blackbox status --flow checkout-payment --json
+```
+
+`status` reports the earliest structurally incomplete boundary without running tests. Alpha approval remains `external`.
+
+### `verify`
+
+```bash
+blackbox verify --flow checkout-payment --json
+```
+
+`verify` validates selected artifacts, runs the native flow, captures evidence, creates observed effects, evaluates configured effect policy, computes eligible decision evidence, and returns separate layered verdicts.
+
+The first run can return `effects: not-configured` while still writing observed effects.
+
+## Flow Commands
+
+```bash
+blackbox flows list --json
+blackbox flows show checkout-payment --json
+```
+
+The flow ID joins requirements, Gherkin, native suite nodes, effect policy, runtime evidence, and reports. `flows show` assembles those explicit relationships without inferring from similar text.
+
+## Requirement Commands
+
+| Command | Responsibility | Writes |
+| ----------------------- | ---------------------------------------------------------------- | ----------------- |
+| `requirements validate` | Validate EARS syntax, profile rules, and IDs | Nothing |
+| `requirements check` | Validate references across accepted artifacts | Nothing |
+| `requirements drift` | Find missing, stale, duplicate, or disconnected bindings | Nothing |
+| `requirements coverage` | Compute requirement verdicts from accepted bindings and evidence | Generated reports |
+
+```bash
+blackbox requirements validate requirements/checkout.ears --json
+blackbox requirements check --flow checkout-payment --json
+blackbox requirements drift --json
+blackbox requirements coverage --json
+```
+
+Validation and structural checks do not require runtime evidence. Requirement coverage can only make runtime-backed claims when accepted bindings and current evidence exist.
+
+## Feature Commands
+
+### `features extract`
+
+```bash
+blackbox features extract ./e2e/checkout.spec.ts --json
+blackbox features extract ./e2e/checkout.spec.ts --write --json
+```
+
+Parses existing suite ASTs and creates literal baseline Gherkin. A written baseline returns `awaiting-review`. It does not claim complete product intent.
+
+### `features check` and `features drift`
+
+```bash
+blackbox features check --feature features/checkout-payment.feature --json
+blackbox features drift --json
+```
+
+These commands validate syntax, IDs, tags, traceability, and accepted source relationships without running the system.
+
+## Suite Commands
+
+### `suites discover`
+
+```bash
+blackbox suites discover ./e2e --json
+```
+
+Parses candidate suites and reports flow candidates, source locations, and conflicts without changing source.
+
+### `suites check`
+
+```bash
+blackbox suites check --flow checkout-payment --json
+```
+
+Validates native suite AST bindings against accepted Gherkin.
+
+### `suites align`
+
+```bash
+blackbox suites align \
+ --feature features/checkout-payment.feature \
+ --suite ./e2e/checkout.spec.ts \
+ --json
+
+blackbox suites align \
+ --feature features/checkout-payment.feature \
+ --suite ./e2e/checkout.spec.ts \
+ --write \
+ --json
+```
+
+Without `--write`, the command returns a plan. With `--write`, it creates or reshapes only the selected native flow, writes atomically, and returns `awaiting-review` with changed paths and digests.
+
+The CLI writes the `.ts` suite directly. It never emits an intermediate patch artifact or invents unsupported application-specific behavior.
+
+## Effect Commands
+
+### `effects show`
+
+```bash
+blackbox effects show --flow checkout-payment --run latest --json
+```
+
+Reads generated observed effects and current classifications for a retained run. It writes nothing.
+
+### `effects check`
+
+```bash
+blackbox effects check --flow checkout-payment --json
+```
+
+Validates effect YAML, selectors, and flow ownership. It does not create or approve policy.
+
+## Coverage and Instrumentation
+
+```bash
+blackbox coverage replay --coverage-dir .blackbox-coverage --json
+blackbox otel instrument --input ./src --output ./instrumented --config ./otel.json
+```
+
+`coverage replay` recomputes reports from retained evidence without rerunning the suite. `otel instrument` writes an explicitly targeted instrumented source tree and is separate from the default testbed bootstrap path.
+
+## Structured Review Results
+
+Source-changing commands return an operation record:
+
+```json
+{
+ "schemaVersion": 1,
+ "command": "suites align",
+ "operationId": "op_01J_CHECKOUT",
+ "status": "awaiting-review",
+ "data": {
+ "flowIds": ["checkout-payment"],
+ "writes": [
+ {
+ "path": "e2e/checkout.spec.ts",
+ "kind": "suite-ast",
+ "beforeDigest": "sha256:before",
+ "afterDigest": "sha256:after"
+ }
+ ],
+ "review": { "required": true, "boundary": "suite-source" }
+ },
+ "findings": []
+}
+```
+
+`awaiting-review` means the transformation succeeded and must pause. It does not mean a person approved the diff.
+
+## Exit Codes
+
+| Code | Meaning |
+| ---- | ------------------------------------------------------------------------------------------ |
+| `0` | Command completed, including a successful write that now awaits review |
+| `1` | Command completed with behavioral or validation findings |
+| `2` | Invalid input, stale precondition, missing infrastructure, or engine failure blocked trust |
+
+See [Exit Codes](/docs/blackbox/reference/exit-codes) and [Files and Artifacts](/docs/blackbox/reference/files-and-artifacts).
diff --git a/src/content/docs/blackbox/reference/configuration.md b/src/content/docs/blackbox/reference/configuration.md
new file mode 100644
index 0000000..c49350d
--- /dev/null
+++ b/src/content/docs/blackbox/reference/configuration.md
@@ -0,0 +1,96 @@
+---
+title: "Project Conventions"
+description: "Reference for Blackbox convention-based discovery, Playwright ownership, effect YAML, artifacts, and environment overrides."
+sidebar_position: 5
+keywords:
+ [
+ "Blackbox conventions",
+ "Playwright Blackbox config",
+ "requirements files",
+ "effect YAML",
+ ]
+---
+
+Blackbox discovers the behavioral harness from repository conventions. This wave does not define a root Blackbox manifest.
+
+Run `blackbox init --mode auto --json` first during onboarding. Use `blackbox status` for structural state and `blackbox doctor` when runtime verification is configured.
+
+## Discovery Conventions
+
+| Convention | Purpose |
+| ------------------------------ | -------------------------------------------------------------------- |
+| `requirements/**/*.ears` | Reviewed EARS requirement sources. |
+| `features/**/*.feature` | Reviewed Gherkin features. |
+| `features/.effects.yaml` | Reviewed required and forbidden effects for one flow. |
+| `playwright.config.*` | Playwright owns scheduling, projects, reporters, and test selection. |
+| `.blackbox-coverage/` | Runtime evidence, coverage, and report artifacts. |
+
+The stable flow ID connects those files. Blackbox validates that the feature basename, Gherkin `@flow:` tag, effect YAML `flow`, and Playwright flow tag agree.
+
+## Playwright Configuration
+
+Playwright remains the test runner. Use normal Playwright configuration and native test APIs.
+
+```ts
+import { defineConfig } from "@playwright/test";
+import {
+ blackboxReporter,
+ defineBlackboxConfig,
+} from "@suites/blackbox/playwright";
+import { testbed } from "./blackbox-testbed";
+
+export default defineConfig({
+ ...defineBlackboxConfig({ mode: "testbed", testbed }),
+ testDir: "./e2e",
+ testMatch: ["**/*.system.test.ts"],
+ fullyParallel: true,
+ reporter: [["list"], blackboxReporter({ outputDir: ".blackbox-coverage" })],
+});
+```
+
+`defineBlackboxConfig()` supports:
+
+- `{ mode: "testbed", testbed }` for a managed Compose or Testcontainers lifecycle;
+- `{ mode: "connect", coverageDir? }` when the suite connects to an environment started elsewhere.
+
+## Testbed Configuration
+
+`createBlackboxTestbed()` owns topology source, service overrides, grouping, reset, artifact directory, project names, and ambient-span policy. See [Testbed API](/docs/blackbox/reference/testbed-api).
+
+Docker Compose and other topology files remain external project infrastructure. They are not Blackbox-owned YAML.
+
+## Effect YAML
+
+The only Blackbox-owned public YAML artifact is the effect contract:
+
+```yaml
+specVersion: "0.1"
+flow: subscribe-unknown-user
+requires:
+ - { boundary: postgres, op: SELECT, key: users, service: bff }
+forbids:
+ - { boundary: http, op: POST, key: /v1/payment_intents, service: bff }
+```
+
+The file lives beside the feature file as `features/subscribe-unknown-user.effects.yaml`.
+
+## Environment Overrides
+
+Use environment variables for runtime-only overrides such as the instrumentation image, artifact directory, and diagnostic logging. Do not use environment variables to redefine accepted requirements, features, or effect contracts.
+
+See [Environment Variables](/docs/blackbox/reference/environment-variables) for the public overrides.
+
+## Practical Defaults
+
+1. Keep requirements in `requirements/**/*.ears`.
+2. Keep Gherkin and effect YAML under `features/`.
+3. Declare flows with native Playwright `test.describe(..., { tag: "@flow:" })`.
+4. Ignore `.blackbox-coverage/` by default.
+5. Run `blackbox doctor` after changing the testbed, Playwright config, or artifact layout.
+
+## Summary
+
+- **Playwright owns execution configuration.**
+- **Blackbox discovers behavioral artifacts by convention.**
+- **Effects are the only Blackbox-owned YAML contract.**
+- **`status` reports structural readiness; `doctor` checks configured runtime readiness.**
diff --git a/src/content/docs/blackbox/reference/environment-variables.md b/src/content/docs/blackbox/reference/environment-variables.md
new file mode 100644
index 0000000..f5c5613
--- /dev/null
+++ b/src/content/docs/blackbox/reference/environment-variables.md
@@ -0,0 +1,67 @@
+---
+title: "Environment Variables"
+description: "Supported Blackbox environment variables for the testbed, instrumentation payload, artifacts, reporting, debugging, and advanced Node coverage."
+sidebar_position: 6
+keywords:
+ [
+ "Blackbox environment variables",
+ "BLACKBOX_INSTR_IMAGE",
+ "BLACKBOX_COVERAGE_DIR",
+ "OpenTelemetry test config",
+ ]
+---
+
+Prefer typed configuration and CLI flags. Use environment variables for environment-specific paths, CI behavior, and diagnostics.
+
+## Testbed and Instrumentation
+
+| Variable | Default | Purpose |
+| ------------------------------------- | --------------------------- | ---------------------------------------------------------------- |
+| `BLACKBOX_INSTR_IMAGE` | `blackbox-instr-node:local` | Instrumentation payload image used by the Node overlay |
+| `BLACKBOX_NODE_BINARY_PATH` | `/usr/local/bin/node` | Node binary path to shadow in every configured SUT |
+| `BLACKBOX_NODE_BINARY_PATH_` | global value | Per-service Node path; service name becomes uppercase snake case |
+| `BLACKBOX_KEEP_STACK=1` | off | Leave worker containers running after teardown for diagnosis |
+
+For service `fraud-check`, the override is `BLACKBOX_NODE_BINARY_PATH_FRAUD_CHECK`.
+
+## Artifact Locations
+
+| Variable | Default | Purpose |
+| -------------------------------- | -------------------------------------- | -------------------------------------------------- |
+| `BLACKBOX_COVERAGE_DIR` | `.blackbox-coverage` | Coverage root in connect mode and report lifecycle |
+| `BLACKBOX_COVERAGE_OUTPUT` | `/catalog/coverage.json` | Override the catalog coverage JSON path |
+| `BLACKBOX_SHAPE_COVERAGE_OUTPUT` | `/shape/coverage.json` | Override shape coverage output |
+| `BLACKBOX_FEATURES_DIR` | `features` | Feature-file discovery override |
+
+Prefer `coverageDir` and `blackboxReporter({ outputDir })` over setting output variables directly.
+
+## Reporting
+
+| Variable | Default | Purpose |
+| -------------------- | ----------------------------------------- | ----------------------------------------- |
+| `BLACKBOX_REPORTERS` | `effects-report` | Comma-separated registered reporter names |
+| `BLACKBOX_SINKS` | `file`, plus GitHub Actions when detected | Comma-separated registered sink names |
+
+Unknown reporter or sink names produce a warning and are skipped. The core registry exposes `effects-report`, `junit`, `file`, `stdout`, and `github-actions`; adapter-registered coverage modules produce their own artifacts.
+
+## Diagnostics
+
+| Variable | Purpose |
+| ------------------------ | --------------------------------------------------- |
+| `BLACKBOX_DEBUG=1` | Include raw span detail in matcher failure output |
+| `BLACKBOX_DEBUG_TRACE=1` | Print per-test trace and debug-endpoint diagnostics |
+| `BLACKBOX_KEEP_STACK=1` | Preserve the failing topology for manual inspection |
+
+Do not enable verbose diagnostics by default in CI; they can expose URLs, query text, and other test data.
+
+## Advanced Node Coverage
+
+| Variable | Purpose |
+| ----------------------------- | ------------------------------------------------------------------ |
+| `BLACKBOX_FUNCTION_SPANS=1` | Enable the advanced function-span coverage mode |
+| `BLACKBOX_FN_SPANS_MODE` | Select `loader` or `build-time` function instrumentation |
+| `BLACKBOX_STRICT_AST_DRIFT=1` | Fail instead of warning when source and coverage coordinates drift |
+
+These are advanced alpha controls. Use the default Node adapter path first and inspect observable decision coverage limits before enabling function-span instrumentation.
+
+Variables such as internal registry keys, run timestamps, partial-retention flags, and testbed markers are implementation details and are intentionally omitted.
diff --git a/src/content/docs/blackbox/reference/exit-codes.md b/src/content/docs/blackbox/reference/exit-codes.md
new file mode 100644
index 0000000..3f0d3ca
--- /dev/null
+++ b/src/content/docs/blackbox/reference/exit-codes.md
@@ -0,0 +1,40 @@
+---
+title: "Exit Codes"
+description: "Interpret Blackbox clean, findings, review-boundary, and engine-failure outcomes consistently in local automation and CI."
+sidebar_position: 2
+---
+
+Blackbox uses three process exit codes across the public command facade.
+
+| Code | Meaning |
+| ---- | ----------------------------------------------------------------------------------------------- |
+| `0` | The command completed. This includes a successful source write that now requires review. |
+| `1` | The command completed with behavioral or validation findings. |
+| `2` | Invalid input, stale state, missing infrastructure, or engine failure blocked a trusted result. |
+
+## Read Status Separately From Exit Code
+
+A source-changing command can exit `0` with:
+
+```json
+{
+ "status": "awaiting-review",
+ "data": {
+ "review": { "required": true }
+ }
+}
+```
+
+That result means the requested deterministic transformation succeeded. The workflow must pause for external human review.
+
+## CI Policy
+
+- Treat exit `1` as an actionable gate finding.
+- Treat exit `2` as an untrustworthy run, not a behavioral failure.
+- Never infer human approval from exit `0`.
+- Preserve JSON findings and run artifacts when a runtime job fails.
+- Use command-specific verdicts rather than collapsing all layer results into one Boolean.
+
+## Compatibility Alias
+
+Some alpha builds may expose `features emit` as an alias for `features extract`. New automation should use `features extract`; both follow the same exit-code contract while the alias remains available.
diff --git a/src/content/docs/blackbox/reference/files-and-artifacts.md b/src/content/docs/blackbox/reference/files-and-artifacts.md
new file mode 100644
index 0000000..bbfb360
--- /dev/null
+++ b/src/content/docs/blackbox/reference/files-and-artifacts.md
@@ -0,0 +1,117 @@
+---
+title: "Files and Artifacts"
+description: "Reference for Blackbox requirements, feature files, effect contracts, runtime evidence, reports, and recommended Git policy."
+sidebar_position: 8
+keywords: ["blackbox artifacts", "generated files", "git policy"]
+toc_min_heading_level: 2
+seo:
+ primary_keyword: "blackbox artifacts"
+ secondary_keywords:
+ [
+ "generated files",
+ "observable decision report",
+ "effect contract",
+ "feature files",
+ ]
+ search_intent: "reference intent from users who need to know which Blackbox files are inputs, outputs, review artifacts, or temporary evidence"
+ snippet_angle: "map EARS, feature files, effect YAML, spans, coverage reports, observable decision reports, and CI artifacts to their purpose and git policy"
+---
+
+Blackbox keeps accepted behavior separate from evidence produced by a test run. Commit the files that define behavior. Ignore generated evidence by default, then archive it from CI when a failure needs investigation.
+
+## Artifact Families
+
+Blackbox has four artifact families:
+
+1. **Intent artifacts:** EARS requirements and Gherkin feature files.
+2. **Executable flows:** Playwright tests with stable `@flow:` tags.
+3. **Effect contracts:** `features/.effects.yaml` files with required and forbidden effects.
+4. **Runtime evidence and reports:** `.blackbox-coverage/` spans, coverage, verdicts, and summaries.
+
+The first three are usually reviewed like source. The last family is generated evidence.
+
+## Files Blackbox Reads
+
+| File or directory | Purpose | Usually committed? |
+| --------------------------------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------- |
+| `requirements/**/*.ears` | Reviewed EARS requirement sources. | Yes, when using requirements. |
+| `features/**/*.feature` | Reviewed Gherkin scenarios with `@flow` and `@requirement` tags. | Yes, when using Gherkin. |
+| `features/.effects.yaml` | Required and forbidden effects for one flow. | Yes. |
+| `playwright.config.*` | Playwright scheduling, projects, reporters, and test selection. | Yes. |
+| Playwright system-test files | Execute flows and declare `@flow:` tags. | Yes. |
+| Project testbed module, such as `e2e/blackbox-testbed.ts` | Describes the runnable topology, managed services, reset policy, and artifact directory. | Yes. |
+| `docker-compose.yml` or equivalent topology config | Starts the SUT and managed dependencies. | Yes, as project infrastructure. |
+| Service source directories | Used to resolve observable decision branch locations and snippets. | Yes, as normal source. |
+
+There is no public root `blackbox.config.yaml` contract in this wave. Docker Compose can still use YAML because it is external topology configuration, not a Blackbox behavior artifact.
+
+## Files Blackbox Writes
+
+The default artifact directory is `.blackbox-coverage/`.
+
+| Artifact | What it means | Primary reader | Git policy |
+| -------------------------------------------------------- | -------------------------------------------------------------- | ------------------------------- | ----------------------------------------------------- |
+| `.blackbox-coverage/runs//effects.observed.json` | Normalized effects observed during one execution. | Skills, tools, and reviewers | Ignore; facts from one run, not accepted policy. |
+| `.blackbox-coverage/catalog/coverage.json` | Effect contract coverage summary. | Tools and reviewers | Usually ignored; useful for CI comparison. |
+| `.blackbox-coverage/shape/coverage.json` | Boundary-shape coverage summary. | Tools and reviewers | Usually ignored; useful for CI comparison. |
+| `.blackbox-coverage/effects-report.md` | Human-readable effect and shape coverage summary. | Reviewers and CI summaries | Usually ignored; attach to a run or PR. |
+| `.blackbox-coverage/effects-report.html` | Browser view of effect and shape coverage. | Developers investigating a run | Ignore; publish or attach as CI artifact. |
+| `.blackbox-coverage/requirements/coverage.json` | EARS verdicts produced by `verify` or `requirements coverage`. | Tools, CI, agents, reviewers | Usually ignored; archive when requirements gate CI. |
+| `.blackbox-coverage/omcdc/verdict.json` | Machine-readable observable decision evidence. | Tools, CI, agents | Usually ignored; archive in CI when useful. |
+| `.blackbox-coverage/omcdc/verdict.md` | Markdown observable decision report. | Humans in review or editor | Usually ignored; attach when branch evidence matters. |
+| `.blackbox-coverage/omcdc/verdict.html` | Interactive branch-arm evidence report. | Humans debugging coverage | Ignore; publish or attach as CI artifact. |
+| `.blackbox-coverage/omcdc.junit.xml` | JUnit XML form when the JUnit reporter is enabled. | CI test report UI | Ignore; CI consumes it. |
+| `.blackbox-coverage/code-coverage/coverage.json` | Istanbul-compatible coverage data. | Coverage tooling | Ignore; archive when needed. |
+| `.blackbox-coverage/code-coverage/html/index.html` | Istanbul HTML coverage report. | Humans comparing code coverage | Ignore; publish or attach as CI artifact. |
+| `.blackbox-coverage/spans/*.spans.json` | Per-flow runtime spans collected from SUT debug endpoints. | Diagnostics and replay | Ignore; archive only for debugging. |
+| `.blackbox-coverage/node/v8/*.json` | Per-test Node V8 coverage payloads. | Decision producer and replay | Ignore; archive only for debugging. |
+| `.blackbox-coverage/ambient/ambient.json` | Effects classified as ambient rather than flow-owned. | Diagnostics and policy tuning | Ignore; inspect when attribution is unclear. |
+| `.blackbox-coverage/image-manifest.json` | Instrumented testbed image metadata. | Reproducibility and diagnostics | Ignore; archive with a failing run. |
+
+## Feature And Effect Files
+
+Feature files, EARS requirements, and effect files answer different questions.
+
+Feature files are readable behavior. They use Gherkin language and carry flow and requirement tags.
+
+EARS files are normative requirements. Requirement IDs become traceable through Gherkin tags and flow IDs.
+
+Effect files are runtime contracts. They declare concrete required and forbidden effects such as Redis reads, Postgres writes, HTTP calls, queue messages, or forbidden deletes.
+
+## Artifact Routing
+
+Blackbox can write reports to files, stdout, or CI-facing surfaces. The important distinction is whether an output defines accepted behavior or records evidence from one run.
+
+1. File output is for durable review and later comparison.
+2. Stdout is for quick inspection and scripting.
+3. CI output is for gate signals and annotations.
+4. The same proof can be routed differently without changing what was proven.
+
+## Reporter And Sink Defaults
+
+Coverage modules write JSON and observable decision artifacts independently of presentation reporters. The default presentation reporter writes `effects-report.md` and `effects-report.html`:
+
+```bash
+BLACKBOX_REPORTERS=effects-report
+```
+
+JUnit is opt-in:
+
+```bash
+BLACKBOX_REPORTERS=effects-report,junit
+```
+
+By default, Blackbox writes files. In GitHub Actions, the default sink expands to files plus GitHub Actions annotations.
+
+```bash
+BLACKBOX_SINKS=file
+BLACKBOX_SINKS=file,stdout,github-actions
+```
+
+## Practical Defaults
+
+1. Commit EARS requirements, feature files, native system-test flows, and effect contracts when those layers are accepted.
+2. Ignore `.blackbox-coverage/` by default.
+3. Archive `.blackbox-coverage/` in CI when a failure needs investigation.
+4. Treat spans and runtime coverage payloads as diagnostic evidence, not hand-edited source.
+5. Treat effect YAML changes as behavior changes that require review.
diff --git a/src/content/docs/blackbox/reference/index.mdx b/src/content/docs/blackbox/reference/index.mdx
new file mode 100644
index 0000000..eedf98f
--- /dev/null
+++ b/src/content/docs/blackbox/reference/index.mdx
@@ -0,0 +1,40 @@
+---
+title: "Reference"
+description: "Find the current Blackbox CLI, Playwright and testbed APIs, matchers, configuration, artifact schemas, report formats, and exit codes."
+sidebar_position: 1
+keywords:
+ [
+ "Suites Blackbox reference",
+ "Blackbox CLI",
+ "Blackbox Playwright API",
+ "effect catalog schema",
+ "Blackbox artifacts",
+ ]
+---
+
+Use reference pages to confirm exact names, flags, files, and contracts. Start with the quickstart or guides when you need a workflow.
+
+## Commands
+
+- [CLI Reference](/docs/blackbox/reference/cli): Framework facade, flow inspection, artifact checks, suite AST transformations, effect inspection, coverage, and instrumentation.
+- [Exit Codes](/docs/blackbox/reference/exit-codes): clean, findings, and usage/environment outcomes.
+
+## Playwright and Testbed
+
+- [Testbed API](/docs/blackbox/reference/testbed-api): `createBlackboxTestbed`, sources, services, reset, grouping, and coverage directory.
+- [API Reference](/docs/blackbox/reference/api): package entry points and public runtime surfaces.
+- [Playwright Flow Tags](/docs/blackbox/reference/scenario-dsl): native Playwright `test.describe` tags, flow IDs, and Gherkin mapping.
+- [Matchers and Effect Builders](/docs/blackbox/reference/matchers-and-effect-builders): `toObserveEffects`, `toMatchCatalog`, predicates, and supported boundaries.
+
+## Project Conventions
+
+- [Project Conventions](/docs/blackbox/reference/configuration): convention discovery, Playwright ownership, effect YAML, and runtime artifacts.
+- [Environment Variables](/docs/blackbox/reference/environment-variables): instrumentation image, Node path, coverage, feature, and diagnostic overrides.
+
+## Artifacts and Reports
+
+- [Files and Artifacts](/docs/blackbox/reference/files-and-artifacts): repository artifacts versus per-run evidence.
+- [Effect Contract Schema](/docs/blackbox/reference/catalog-schema): effect YAML format and required/forbidden clauses.
+- [Report Formats](/docs/blackbox/reference/report-formats): catalog, shape, observable decision, requirement, HTML, Markdown, JSON, and JUnit outputs.
+
+The alpha surface changes. Prefer this reference and the exported TypeScript types over older package README examples.
diff --git a/src/content/docs/blackbox/reference/matchers-and-effect-builders.md b/src/content/docs/blackbox/reference/matchers-and-effect-builders.md
new file mode 100644
index 0000000..fd57b72
--- /dev/null
+++ b/src/content/docs/blackbox/reference/matchers-and-effect-builders.md
@@ -0,0 +1,98 @@
+---
+title: "Matchers and Effect Builders"
+description: "Reference for toObserveEffects, toMatchCatalog, effect builders, required and forbidden contracts, patterns, and count constraints."
+sidebar_position: 4
+keywords:
+ [
+ "toObserveEffects",
+ "toMatchCatalog",
+ "effect builders",
+ "required forbidden effects",
+ "Playwright matcher",
+ ]
+---
+
+Import Playwright matchers through the Blackbox runner and effect vocabulary through the core entry point:
+
+```ts
+import { atLeast, between, effect, exactly, glob } from "@suites/blackbox/core";
+import { expect } from "./testbed.js";
+```
+
+## `toObserveEffects()`
+
+All forms normalize to `{ requires, forbids }`.
+
+```ts
+await expect(capture).toObserveEffects(effect.redis("SET"));
+
+await expect(capture).toObserveEffects([
+ effect.postgres("INSERT", { table: "subscriptions" }),
+ effect.forbid(effect.redis("DEL")),
+]);
+
+await expect(capture).toObserveEffects({
+ requires: [effect.sqs("SendMessage", { queue: "subscription-orders" })],
+ forbids: [effect.http("POST", { path: "/v1/refunds" })],
+});
+```
+
+The matcher fails when a required shape is missing, a forbidden shape matches, or a count constraint is violated. Every call feeds effect-shape coverage, including failures.
+
+## `toMatchCatalog()`
+
+```ts
+await expect(capture).toMatchCatalog();
+```
+
+The matcher reads the active flow ID, loads `features/.effects.yaml`, and evaluates the same contract kernel as `toObserveEffects()`.
+
+A direct `toMatchCatalog()` assertion fails when its selected contract is missing. A facade run can still create observed effects and report the effect layer as `not-configured` before policy exists. `blackbox verify` writes evidence and reports, not accepted behavior files.
+
+## `toMatchEffectsSnapshot()`
+
+Use the snapshot matcher when a raw normalized effect snapshot is useful for diagnostics or migration. Prefer catalogs for reviewed required/forbidden behavior because a catalog expresses intent instead of preserving every observed detail.
+
+## Effect Builders
+
+| Builder | Options |
+| --------------------------- | -------------------------------------------- |
+| `effect.redis(op, opts)` | `key`, `ttl`, `count` |
+| `effect.postgres(op, opts)` | `key` or `table`, `schema`, `count` |
+| `effect.http(op, opts)` | `key` or `path`, `host`, `status`, `count` |
+| `effect.sqs(op, opts)` | `key` or `queue`, `count` |
+| `effect.s3(op, opts)` | `bucket`, `key`, `count` |
+| `effect.rabbitmq(op, opts)` | `key`, `exchange`, `routingKey`, `count` |
+| `effect.forbid(shape)` | Wraps a shape for single/array matcher input |
+
+HTTP and HTTPS both normalize to the `http` boundary.
+
+## String Patterns
+
+```ts
+equals("user:alice:tier");
+glob("user:*:tier");
+regex("^user:[a-z]+:tier$");
+```
+
+Bare strings use catalog glob semantics. Use `equals()` when `*` or path matching must not be interpreted as a pattern.
+
+## Numeric and Count Constraints
+
+```ts
+eq(1);
+lt(5);
+lte(5);
+gt(0);
+gte(1);
+between(60, 3600);
+
+exactly(1);
+atLeast(1);
+atMost(3);
+never();
+```
+
+Bare numbers mean exact equality.
+
+For concepts and examples, read [Effects, Catalogs, and Coverage](/docs/blackbox/concepts/effects-and-catalogs).
diff --git a/src/content/docs/blackbox/reference/report-formats.md b/src/content/docs/blackbox/reference/report-formats.md
new file mode 100644
index 0000000..4c93efe
--- /dev/null
+++ b/src/content/docs/blackbox/reference/report-formats.md
@@ -0,0 +1,121 @@
+---
+title: "Report Formats"
+description: "Reference for Blackbox effect, requirement, shape, observable decision, JUnit, Markdown, and HTML report artifacts."
+sidebar_position: 5
+keywords: ["report formats", "coverage json", "shape coverage json"]
+toc_min_heading_level: 2
+seo:
+ primary_keyword: "report formats"
+ secondary_keywords:
+ [
+ "coverage json",
+ "omcdc json",
+ "shape coverage json",
+ "junit coverage report",
+ ]
+ search_intent: "reference intent from users and automation authors consuming Blackbox generated reports"
+ snippet_angle: "explain each Blackbox report file, its producer, format, consumer, and stability expectation"
+---
+
+Blackbox produces machine-readable verdicts and human-readable reports from the same test run. Use JSON for gates and repair loops; use Markdown or HTML to understand why a gate failed.
+
+## Artifact Family
+
+| Producer or setting | Artifact | Format | Purpose |
+| ----------------------------- | ---------------------------- | -------- | ------------------------------------------------------------------- |
+| Catalog coverage module | `catalog/coverage.json` | JSON | Per-flow effect contract verdicts and totals. |
+| Shape coverage module | `shape/coverage.json` | JSON | Declared, asserted, and observed boundary shapes. |
+| `effects-report` reporter | `effects-report.md` | Markdown | Reviewable effect and shape coverage summary. |
+| `effects-report` reporter | `effects-report.html` | HTML | Browser view of the same summary. |
+| Node decision producer | `omcdc/verdict.json` | JSON | Machine-readable observable decision report. |
+| Node decision producer | `omcdc/verdict.md` | Markdown | Human-readable observable decision report. |
+| Node decision producer | `omcdc/verdict.html` | HTML | Interactive branch-arm evidence report. |
+| Facade or requirements engine | `requirements/coverage.json` | JSON | EARS requirement verdicts joined through feature tags and flow IDs. |
+| `junit` | `omcdc.junit.xml` | XML | CI-facing test-result view of decision verdicts. |
+
+## Stability Notes
+
+1. `catalog/coverage.json` and `requirements/coverage.json` are the direct inputs for CI and agent repair loops.
+2. `shape/coverage.json` explains whether catalog shapes were actually named by matchers.
+3. `omcdc/verdict.json` carries detailed branch evidence and may evolve while the engine is alpha.
+4. Markdown and HTML are presentation artifacts; do not parse them as APIs.
+5. Raw span and `node/v8` files are producer inputs, not public report contracts.
+
+## What Each Artifact Is For
+
+### `omcdc/verdict.json`
+
+Contains endpoints, branch coordinates, true-arm test IDs, false-arm test IDs, not-observed test IDs, verdicts, hints, and observed effect shapes. Use it when an agent or tool needs to understand why a branch is propagating, masked, or still a gap.
+
+### `omcdc/verdict.md`
+
+Contains the same observable decision story in a reviewable form: endpoint sections, verdict counts, branch tables, hints, and branch evidence. Use it when a reviewer needs to understand the result without opening the interactive report.
+
+### `omcdc/verdict.html`
+
+The interactive observable decision report. Use it when a developer needs to inspect branch arms, hints, source snippets when available, and the relationship between decisions and captured evidence.
+
+### `catalog/coverage.json`
+
+Summarizes effect contract coverage. It answers whether accepted contracts were seen, satisfied, failed, or uncovered.
+
+The shape is based on:
+
+1. `catalog`: service name, entry count, and catalog API version.
+2. `totals`: seen, satisfied, failed, uncovered, and forbidden-entry counts.
+3. `perEntry`: state, run/pass/failure counts, and `forbidViolations` with the matched shape and last observed location.
+
+Entry states are `satisfied`, `failed`, or `uncovered`. A flow can fail because a required effect is missing, a forbidden effect appeared, or a count constraint did not match.
+
+### `shape/coverage.json`
+
+Summarizes effect shapes, not whole catalog entries. It answers whether declared or inline boundary shapes were asserted and observed.
+
+Shape states are:
+
+1. `asserted`: declared in the catalog and named by a matcher.
+2. `unasserted`: declared in the catalog but never named by a matcher.
+3. `inline`: named by a matcher but not declared in the catalog.
+
+### `requirements/coverage.json`
+
+Joins EARS requirement IDs to the runtime result of their bound flows. A requirement is:
+
+1. `proven` when every bound flow is satisfied.
+2. `violated` when at least one bound flow failed.
+3. `unproven` when no bound flow failed but at least one was not exercised.
+4. `unbound` when the requirement has no accepted flow connection.
+
+When multiple flows bind to one requirement, the worst verdict wins.
+
+### `omcdc.junit.xml`
+
+Maps observable decision verdicts into CI test-result vocabulary:
+
+| Decision verdict | JUnit mapping |
+| ------------------- | ---------------------- |
+| `propagating` | pass |
+| `masking-candidate` | failure |
+| `coverage-gap` | skipped |
+| `undecidable` | pass with `system-out` |
+| `multi-arm` | pass with `system-out` |
+| `unsupported-mcdc` | pass with `system-out` |
+
+## Artifact Delivery
+
+Coverage modules and reporters render artifacts. Sinks deliver them.
+
+That separation matters: the same proof can become files, stdout output, GitHub Actions annotations, or CI test results without changing the evidence or the coverage model.
+
+The default file sink writes below the configured coverage directory. When `GITHUB_ACTIONS=true`, the default also includes the GitHub Actions sink. That sink reads `omcdc/verdict.json` and emits workflow annotations for actionable verdicts:
+
+1. `masking-candidate` becomes a warning.
+2. `coverage-gap` becomes a notice.
+3. Other verdicts are silent.
+
+## Practical Reading Order
+
+1. Start with the filename.
+2. Check whether the output is JSON, Markdown, HTML, or XML.
+3. Check whether it is intended for humans or automation.
+4. Use the related concept pages if you need the model behind it.
diff --git a/src/content/docs/blackbox/reference/scenario-dsl.md b/src/content/docs/blackbox/reference/scenario-dsl.md
new file mode 100644
index 0000000..681aca7
--- /dev/null
+++ b/src/content/docs/blackbox/reference/scenario-dsl.md
@@ -0,0 +1,91 @@
+---
+title: "Playwright Flow Tags"
+description: "Declare Blackbox flows with native Playwright test.describe tags and map them to reviewed Gherkin and effect contracts."
+sidebar_position: 4
+keywords:
+ [
+ "Playwright flow tags",
+ "Blackbox Playwright",
+ "native Playwright API",
+ "flow ID",
+ ]
+seo:
+ primary_keyword: "Playwright flow tags"
+ secondary_keywords: ["Blackbox Playwright", "flow ID"]
+ search_intent: "developers looking for the supported way to declare Blackbox flows in Playwright"
+ snippet_angle: "use native Playwright test.describe tags instead of a custom Scenario DSL"
+---
+
+Blackbox uses native Playwright APIs. A **flow ID** is declared with a `@flow:` tag on `test.describe`.
+
+```ts
+import { expect, test } from "./blackbox-testbed";
+
+test.describe(
+ "Reject an unknown subscriber",
+ { tag: "@flow:subscribe-unknown-user" },
+ () => {
+ test("request stops before payment", async ({ request, capture }) => {
+ await test.step("submit the subscription request", async () => {
+ const response = await request.post("/subscriptions", {
+ data: { userId: "ghost-user", tier: "pro" },
+ });
+
+ expect(response.status()).toBe(404);
+ });
+
+ await test.step("verify the response and captured effects", async () => {
+ await expect(capture).toMatchCatalog();
+ });
+ });
+ },
+);
+```
+
+## Mapping Rules
+
+| Playwright surface | Blackbox meaning |
+| -------------------------------- | ------------------------------------- |
+| `test.describe` tag `@flow:` | Stable flow ID. |
+| `test.describe` title | Flow description. |
+| `test` title | Scenario title. |
+| `test.step` title | Reviewable action or assertion label. |
+| `capture` assertions | Runtime effect verification. |
+
+The flow ID must match the reviewed Gherkin `@flow:` tag and the `flow` field in `features/.effects.yaml`.
+
+## Supported Shape
+
+Use one feature-level flow per feature file:
+
+```gherkin
+@flow:subscribe-unknown-user
+@requirement:REQ-004
+@requirement:REQ-005
+Feature: Reject an unknown subscriber
+
+ Scenario: request stops before payment
+ When the unknown user posts a subscription request
+ Then the response status is 404
+ And no payment request is sent
+```
+
+One feature can contain multiple scenarios, but the feature owns one flow ID. The CLI checks basename, Gherkin tag, Playwright tag, and effect YAML consistency.
+
+## Prohibited Public Surfaces
+
+Do not use a Blackbox TypeScript Scenario DSL in alpha docs or new suites:
+
+- no `scenario(...)`;
+- no `given(...)`, `when(...)`, or `then(...)` TypeScript helpers;
+- no `test.system(...)`;
+- no generated suite changes without human approval.
+
+Gherkin `Scenario`, `Given`, `When`, and `Then` belong only in `.feature` files.
+
+## Summary
+
+- **Declare flows with native Playwright `test.describe` tags.**
+- **Use `test.step` for readable structure.**
+- **Keep Gherkin in `.feature` files.**
+- **Review native suite diffs after `suites align --write`.**
diff --git a/src/content/docs/blackbox/reference/testbed-api.md b/src/content/docs/blackbox/reference/testbed-api.md
new file mode 100644
index 0000000..4b967f9
--- /dev/null
+++ b/src/content/docs/blackbox/reference/testbed-api.md
@@ -0,0 +1,109 @@
+---
+title: "Testbed API"
+description: "Reference for createBlackboxTestbed sources, services, reset groups, worker identity, coverage output, and lifecycle."
+sidebar_position: 3
+keywords:
+ [
+ "createBlackboxTestbed",
+ "Blackbox testbed API",
+ "Compose system test",
+ "Testcontainers Playwright",
+ ]
+---
+
+`createBlackboxTestbed(input)` creates the global lifecycle and worker-stack plan used by Playwright system tests.
+
+## Input
+
+```ts
+const testbed = createBlackboxTestbed({
+ source,
+ services: undefined,
+ grouping: undefined,
+ reset: undefined,
+ coverageDir: undefined,
+ projectNames: undefined,
+ ambient: null,
+});
+```
+
+The current alpha type requires every key, while omitted settings are represented by `undefined` and the default ambient policy by `null`.
+
+| Field | Required | Default | Meaning |
+| -------------- | -------- | ------------------------- | ------------------------------------------------------------ |
+| `source` | Yes | none | Compose or custom Testcontainers topology |
+| `services` | No | introspected SUT services | Per-SUT source and wait overrides; pass `undefined` for none |
+| `grouping` | No | `{ kind: 'auto' }` | How reset boundaries are derived |
+| `reset` | No | none | Reset managed state when the group key changes |
+| `coverageDir` | No | `.blackbox-coverage` | Artifact root, cleared during global setup |
+| `projectNames` | No | kit defaults | Compose project base names |
+| `ambient` | No | default classification | Health/readiness/background span policy |
+
+## Sources
+
+### Compose
+
+```ts
+source: {
+ compose: './e2e/compose.yml',
+ profiles: ['system-test'],
+}
+```
+
+`compose` accepts one path or an ordered array of Compose files. Blackbox introspects builds, images, healthchecks, ports, and source directories, then starts one project per Playwright worker.
+
+### Testcontainers
+
+```ts
+source: {
+ testcontainers: async (identity) => ({
+ connect,
+ infra,
+ stop: async () => stopContainers(identity),
+ }),
+}
+```
+
+The callback runs in the worker process. Return SUT endpoints in `connect`, managed infrastructure hosts in `infra`, and an optional worker teardown.
+
+### Dockerfile
+
+The type surface includes `{ dockerfile, context, ports }` for forward compatibility. The current resolver rejects this source because bring-up is not implemented.
+
+## Service Overrides
+
+```ts
+services: {
+ api: {
+ srcDir: './services/api/src',
+ wait: { log: /listening on/ },
+ },
+}
+```
+
+`srcDir` defaults to `/src`. `wait` accepts `healthcheck`, `ports`, `{ log: RegExp }`, or a Testcontainers `WaitStrategy`.
+
+## Reset Context
+
+```ts
+reset: async ({ connect, infra, groupKey, identity }) => {
+ await resetDatabase(infra.postgres);
+ await resetCache(infra.redis);
+ await purgeQueues(infra.localstack);
+};
+```
+
+`identity` includes Playwright worker indices. `groupKey` is auto-derived from BDD isolation tags or the Playwright file and title path unless a manual grouping policy overrides it.
+
+## Lifecycle
+
+| Phase | Work |
+| ---------------- | --------------------------------------------------------------------------------- |
+| Global setup | Resolve config, prepare coverage directory, validate/build SUT images and payload |
+| Worker bootstrap | Start one topology for the worker and expose connect/infra maps |
+| Group transition | Call the configured reset function |
+| Test capture | Reset observation buffers, execute, drain effects and coverage |
+| Worker teardown | Stop the worker topology unless `BLACKBOX_KEEP_STACK=1` |
+| Global teardown | Merge partials, finalize feature output, run reporters and sinks |
+
+Use [Testbed and Instrumentation](/docs/blackbox/guides/set-up-the-testbed) for the complete setup workflow.
diff --git a/src/content/docs/blackbox/troubleshooting/catalog-failures.md b/src/content/docs/blackbox/troubleshooting/catalog-failures.md
new file mode 100644
index 0000000..7c40153
--- /dev/null
+++ b/src/content/docs/blackbox/troubleshooting/catalog-failures.md
@@ -0,0 +1,45 @@
+---
+title: "Effect Contract Failures"
+description: "Explain missing required effects, forbidden effects, and inline shapes that should be promoted."
+sidebar_position: 3
+keywords:
+ ["effect contract failures", "requires forbids", "effect assertion failure"]
+toc_min_heading_level: 2
+seo:
+ primary_keyword: "Effect Contract Failures"
+ secondary_keywords: ["effect contract failures", "requires forbids"]
+ search_intent: "troubleshooting intent from users whose required effects are missing, forbidden effects appeared, or catalog matching failed"
+ snippet_angle: "compare observed effects to the contract, decide whether implementation or contract changed, then rerun the scenario"
+---
+
+Explain missing required effects, forbidden effects, and inline shapes that should be promoted.
+
+Effect contract failures mean the run did not satisfy the behavior the team accepted. The system may have behaved differently, omitted a required boundary effect, or emitted something that should have been forbidden.
+
+## Common Causes
+
+1. A required effect did not happen.
+2. A forbidden effect appeared in the run.
+3. The effect contract is too narrow for the real behavior.
+4. The effect contract is too broad and should be split into smaller shapes.
+
+## First Checks
+
+1. Compare the observed run with the effect contract.
+2. Decide whether the contract or the implementation changed.
+3. Confirm whether the missing effect is truly required or just incidental.
+4. Check whether the effect belongs in an inline shape or the accepted effect contract.
+
+## Recovery
+
+1. Update the effect contract if the new behavior is intentional and reviewed.
+2. Fix the implementation if the old effect is still required.
+3. Promote repeated inline shapes into effect contracts when they become part of the workflow.
+4. Re-run the scenario to confirm the gate now matches the intended behavior.
+
+## What To Report If It Still Fails
+
+1. The scenario or flow ID.
+2. The required or forbidden effect that failed.
+3. The observed output from the run.
+4. Any report or propagation artifact that explains the mismatch.
diff --git a/src/content/docs/blackbox/troubleshooting/diagnostics-and-debug-logs.md b/src/content/docs/blackbox/troubleshooting/diagnostics-and-debug-logs.md
new file mode 100644
index 0000000..84d7c3f
--- /dev/null
+++ b/src/content/docs/blackbox/troubleshooting/diagnostics-and-debug-logs.md
@@ -0,0 +1,51 @@
+---
+title: "Diagnostics and Debug Logs"
+description: "Explain how to collect useful logs, debug failed runs, and decide whether the issue is setup, traces, catalog drift, or Blackbox."
+sidebar_position: 5
+keywords:
+ [
+ "blackbox diagnostics",
+ "blackbox debug logs",
+ "effect coverage troubleshooting",
+ ]
+toc_min_heading_level: 2
+seo:
+ primary_keyword: "Diagnostics and Debug Logs"
+ secondary_keywords: ["blackbox diagnostics", "blackbox debug logs"]
+ search_intent: "troubleshooting intent from users collecting logs and artifacts for failed Blackbox runs"
+ snippet_angle: "separate setup, no-span, catalog, feature drift, and report generation failures before filing an issue"
+---
+
+Use the facade before opening raw logs. It separates project readiness, connected-artifact state, and a live verification failure.
+
+```bash
+blackbox doctor --json
+blackbox status --flow subscribe-unknown-user --json
+blackbox verify --flow subscribe-unknown-user --json
+```
+
+Run `blackbox explain ` when the JSON output includes an unfamiliar diagnostic code.
+
+## Common Failure Classes
+
+1. Setup failures.
+2. No-span failures.
+3. Catalog or feature drift.
+4. Report generation failures.
+5. Integration or environment failures.
+
+## First Checks
+
+1. Run `blackbox doctor --json` without starting the SUT.
+2. Run `blackbox status --flow --json` to detect stale or disconnected artifacts.
+3. Re-run only the affected flow with `blackbox verify --flow --json`.
+4. Save the layered result, report directory, logs, and generated artifacts from that run.
+5. Identify whether the failure is in setup, execution, evidence collection, comparison, or rendering.
+6. Reduce the case to a minimal reproduction before filing a bug.
+
+## What To Keep
+
+1. The command that failed.
+2. The smallest relevant log excerpt.
+3. The artifact or report that proves the failure.
+4. The configuration that reproduces it.
diff --git a/src/content/docs/blackbox/troubleshooting/docker-and-testbed.md b/src/content/docs/blackbox/troubleshooting/docker-and-testbed.md
new file mode 100644
index 0000000..dfbe008
--- /dev/null
+++ b/src/content/docs/blackbox/troubleshooting/docker-and-testbed.md
@@ -0,0 +1,71 @@
+---
+title: "Docker and Testbed"
+description: "Diagnose container startup, ports, waits, compose overlays, and local environment failures."
+sidebar_position: 4
+keywords: ["docker troubleshooting", "testbed errors", "compose testing"]
+toc_min_heading_level: 2
+seo:
+ primary_keyword: "docker testbed troubleshooting"
+ secondary_keywords:
+ ["docker troubleshooting", "testbed errors", "docker compose testing"]
+ search_intent: "troubleshooting intent from developers whose Blackbox container topology fails before evidence can be trusted"
+ snippet_angle: "diagnose compose startup, bootstrap image, init container, mounted node wrapper, ports, waits, and stale volumes"
+---
+
+Diagnose container startup, ports, waits, compose overlays, and local environment failures.
+
+This page covers the failures that happen before the run can even be trusted: containers not starting, ports colliding, waits never resolving, or the local testbed not matching the scenario.
+
+## Common Causes
+
+1. The compose stack did not start cleanly.
+2. A port mapping collided with another local process.
+3. A wait condition never became true.
+4. The local environment and the testbed configuration diverged.
+5. The OpenTelemetry bootstrap image was not built or could not be pulled.
+6. The init container did not populate the bootstrap volume.
+7. The SUT image does not have a shell for the current `node-wrap` script.
+8. The configured Node binary path does not match the SUT image.
+
+## First Checks
+
+1. Confirm the containers are healthy before the test starts.
+2. Check for port collisions and stale containers.
+3. Verify the wait conditions and any startup dependencies.
+4. Compare the local configuration with the CI configuration if the failure only appears in one place.
+5. Confirm the bootstrap image exists locally or is reachable from CI.
+6. Confirm the generated overlay mounted `/blackbox-otel` and `bin/node-wrap` into the SUT.
+
+## Bootstrap Image Checks
+
+In local development, the bootstrap image is commonly tagged as `blackbox-instr-node:local`. In packaged or CI usage, the image may come from a registry or from `BLACKBOX_INSTR_IMAGE`.
+
+The image must contain:
+
+1. `/blackbox-otel/bootstrap.cjs`
+2. `/blackbox-otel/node_modules/`
+3. `/blackbox-otel/bin/node-wrap`
+4. `/blackbox-otel/bin/real-node`
+
+If the image is missing, malformed, or built for the wrong architecture, the SUT may start without instrumentation or fail before it becomes healthy.
+
+## Node Binary Path Checks
+
+The default instrumentation path shadows `/usr/local/bin/node`. That matches common official Node images, but it is still an assumption.
+
+If your image puts Node somewhere else, configure the testbed to shadow the correct path. If your image is distroless, the current shell wrapper is not enough because there is no `/bin/sh` to execute it.
+
+## Recovery
+
+1. Restart the testbed from a clean state.
+2. Remove stale containers or volumes if the setup expects a fresh run.
+3. Rebuild or repull the bootstrap image.
+4. Fix the compose overlay, Node binary path, or port mapping that caused the failure.
+5. Re-run the sample project before trying the full system again.
+
+## What To Report If It Still Fails
+
+1. The compose or testbed command.
+2. The failing container or port.
+3. The wait condition or startup step that timed out.
+4. Any logs that show why the testbed never reached a ready state.
diff --git a/src/content/docs/blackbox/troubleshooting/feature-drift.md b/src/content/docs/blackbox/troubleshooting/feature-drift.md
new file mode 100644
index 0000000..1728b68
--- /dev/null
+++ b/src/content/docs/blackbox/troubleshooting/feature-drift.md
@@ -0,0 +1,44 @@
+---
+title: "Feature Drift"
+description: "Explain stale, missing, orphan, and unparseable feature files and how to recover."
+sidebar_position: 2
+keywords: ["feature drift", "stale feature files", "gherkin drift"]
+toc_min_heading_level: 2
+seo:
+ primary_keyword: "Feature Drift"
+ secondary_keywords: ["feature drift", "stale feature files"]
+ search_intent: "troubleshooting intent from users whose generated Gherkin files are stale, missing, orphaned, or unparseable"
+ snippet_angle: "identify feature-file drift, regenerate from executable tests, and keep readable behavior specs synchronized"
+---
+
+Explain stale, missing, orphan, and unparseable feature files and how to recover.
+
+Feature drift means the generated or checked feature file no longer matches the run the team expects. The file may be stale, missing, orphaned, or impossible to parse cleanly.
+
+## Common Causes
+
+1. The system behavior changed but the feature file was not regenerated.
+2. The generator produced a file for a run the repo no longer recognizes.
+3. A rename or refactor broke the link between scenario and artifact.
+4. The file format changed enough that the parser or checker no longer accepts it.
+
+## First Checks
+
+1. Compare the generated file with the current scenario or behavior.
+2. Check whether the source of truth is the latest runtime evidence.
+3. Confirm the file name and path match the current page or scenario slug.
+4. Inspect whether the artifact is stale, orphaned, or malformed.
+
+## Recovery
+
+1. Regenerate the feature file from the current run.
+2. Update the catalog or scenario naming if the behavior is intentionally new.
+3. Delete or quarantine orphaned files that no longer correspond to live scenarios.
+4. If the file is unparseable, reduce it to the smallest reproducible example.
+
+## What To Report If It Still Fails
+
+1. The feature file path and scenario name.
+2. The run that produced it.
+3. The expected versus actual behavior.
+4. Any parser or checker error text.
diff --git a/src/content/docs/blackbox/troubleshooting/index.mdx b/src/content/docs/blackbox/troubleshooting/index.mdx
new file mode 100644
index 0000000..8739bcc
--- /dev/null
+++ b/src/content/docs/blackbox/troubleshooting/index.mdx
@@ -0,0 +1,64 @@
+---
+title: Troubleshooting
+description: "Start here when a Blackbox run is empty, blocked, drifting, or failing in Docker, CI, catalog matching, or report generation."
+sidebar_position: 1
+keywords:
+ [
+ "blackbox troubleshooting",
+ "no spans captured",
+ "catalog failures",
+ "feature drift",
+ "docker testbed",
+ ]
+toc_min_heading_level: 2
+seo:
+ primary_keyword: "blackbox troubleshooting"
+ secondary_keywords:
+ ["no spans captured", "catalog failures", "feature drift", "docker testbed"]
+ search_intent: "developers diagnosing failed Blackbox setup, empty runtime evidence, catalog mismatches, feature drift, or CI output"
+ snippet_angle: "choose the symptom, run the first checks, and follow the focused Blackbox troubleshooting page"
+---
+
+Start here when a Blackbox run does not produce the evidence you expected.
+
+Most failures fall into one of four groups: the system did not run the intended path, the testbed did not instrument the SUT, the catalog contract no longer matches runtime behavior, or the generated feature files drifted from executable tests.
+
+## Choose The Symptom
+
+| Symptom | Start with |
+| --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
+| The test passed, but the report is empty or no spans were captured | [No Spans Captured](/docs/blackbox/troubleshooting/no-spans-captured) |
+| Docker starts fail, ports collide, services stay unhealthy, or the bootstrap image is missing | [Docker and Testbed](/docs/blackbox/troubleshooting/docker-and-testbed) |
+| `toMatchCatalog()` fails, required effects are missing, or forbidden effects appeared | [Catalog Failures](/docs/blackbox/troubleshooting/catalog-failures) |
+| `.feature` files are stale, missing, orphaned, or unparseable | [Feature Drift](/docs/blackbox/troubleshooting/feature-drift) |
+| The run fails in CI and you need useful logs before filing an issue | [Diagnostics and Debug Logs](/docs/blackbox/troubleshooting/diagnostics-and-debug-logs) |
+| You have a reproducible issue and need to report it cleanly | [Reporting a Bug](/docs/blackbox/troubleshooting/reporting-a-bug) |
+
+## First Checks
+
+1. Run `blackbox status --flow --json` to check connected artifacts and evidence age.
+2. Run `blackbox doctor --json` when the problem concerns runtime readiness or instrumentation.
+3. Confirm the Playwright flow actually reached the system boundary you expected.
+4. Confirm the SUT was started through the Blackbox testbed or another Blackbox-aware setup.
+5. Confirm the instrumentation image is available as `blackbox-instr-node:local` or through `BLACKBOX_INSTR_IMAGE`.
+6. Confirm the SUT container has `/blackbox-otel/bootstrap.cjs` and `/blackbox-otel/bin/node-wrap` mounted when using the compose testbed.
+7. Confirm the failure is about behavior before changing the catalog. Missing required effects and observed forbidden effects should be reviewed, not automatically accepted.
+
+## What To Keep
+
+When debugging, keep these artifacts from the failing run:
+
+| Artifact | Why it helps |
+| ------------------------- | ----------------------------------------------------------- |
+| Test command and output | Shows the runner, flags, and first failure signal |
+| `.blackbox-coverage/` | Shows captured spans, coverage summaries, and report inputs |
+| Generated compose overlay | Shows whether the SUT was instrumented for the run |
+| Effect catalog diff | Shows whether the reviewed behavior contract changed |
+| Generated `.feature` diff | Shows whether readable behavior specs drifted |
+
+## Useful Next Pages
+
+1. [Runtime Prerequisites](/docs/blackbox/quickstart/runtime-prerequisites)
+2. [Testbed and Instrumentation](/docs/blackbox/guides/set-up-the-testbed)
+3. [Effects, Catalogs, and Coverage](/docs/blackbox/concepts/effects-and-catalogs)
+4. [Reports and CI Gates](/docs/blackbox/guides/reports-and-ci-gates)
diff --git a/src/content/docs/blackbox/troubleshooting/no-spans-captured.md b/src/content/docs/blackbox/troubleshooting/no-spans-captured.md
new file mode 100644
index 0000000..9dd4b9b
--- /dev/null
+++ b/src/content/docs/blackbox/troubleshooting/no-spans-captured.md
@@ -0,0 +1,71 @@
+---
+title: "No Spans Captured"
+description: "Diagnose uninstrumented systems, missing trace propagation, and empty reports."
+sidebar_position: 1
+keywords:
+ ["no spans captured", "opentelemetry troubleshooting", "empty reports"]
+toc_min_heading_level: 2
+seo:
+ primary_keyword: "no spans captured"
+ secondary_keywords:
+ [
+ "opentelemetry troubleshooting",
+ "blackbox empty report",
+ "node options require",
+ ]
+ search_intent: "troubleshooting intent from users whose system test ran but produced empty Blackbox evidence"
+ snippet_angle: "walk through topology, bootstrap, node wrapper, trace propagation, and artifact checks for empty span reports"
+---
+
+Diagnose uninstrumented systems, missing trace propagation, and empty reports.
+
+If the report is empty, the run may still have happened, but Blackbox did not see the runtime evidence it needed. This page helps you separate "the system did nothing" from "the instrumentation path was missing."
+
+## Common Causes
+
+1. The test hit a code path that never crossed an instrumented boundary.
+2. The bootstrap image was not available to the testbed.
+3. The generated compose overlay did not mount `/blackbox-otel` into the SUT container.
+4. The service did not start through the Node binary path Blackbox shadowed.
+5. `NODE_OPTIONS` was explicitly set empty for the app process, bypassing the wrapper behavior.
+6. Another tracing agent registered first and blocked the Blackbox tracer.
+7. Trace propagation broke before the request reached the service that should emit spans.
+8. The scenario ended before evidence was collected or flushed.
+
+## First Checks
+
+1. Confirm the test actually exercised the boundary you expected.
+2. Confirm the testbed built or pulled the bootstrap image.
+3. Confirm the SUT container has `/blackbox-otel/bootstrap.cjs` and `/blackbox-otel/bin/node-wrap` mounted.
+4. Confirm the service command invokes the Node binary path Blackbox is configured to shadow.
+5. Inspect the debug output or report for trace IDs and span counts.
+6. Compare the empty run with a known-good sample if you have one.
+
+## Wrapper-Specific Checks
+
+The wrapper has one intentional bypass: if `NODE_OPTIONS` is set and its value is empty, it executes the real Node binary without the Blackbox preload. This allows healthchecks such as `NODE_OPTIONS= node -e "..."` to avoid starting a second debug server inside the same container.
+
+That bypass should be used for healthchecks, not for the app process itself. If the main service command or compose environment sets `NODE_OPTIONS` to an explicit empty value, Blackbox will not load.
+
+If your service already uses `NODE_OPTIONS`, Blackbox should preserve it. The wrapper prepends `--require=/blackbox-otel/bootstrap.cjs` to the resolved value rather than replacing it in the compose file.
+
+## Existing Tracing Agents
+
+Production-shaped images sometimes include `dd-trace/init`, Sentry tracing, or another OpenTelemetry provider. In a test environment, those agents can compete with Blackbox for the process tracer.
+
+If spans are empty or startup fails with a tracer-provider error, disable the production tracer for the test topology. Common examples are setting `DD_TRACE_ENABLED=false` or clearing `SENTRY_DSN` in the test compose override.
+
+## Recovery
+
+1. Re-run with debug logging enabled.
+2. Reduce the scenario to the smallest boundary that should emit spans.
+3. Verify the container or testbed config that carries the bootstrap and trace propagation.
+4. Temporarily disable competing tracing agents in the test environment.
+5. If the path is still empty, compare against the showcase system before filing a bug.
+
+## What To Report If It Still Fails
+
+1. The command you ran.
+2. The expected boundary.
+3. The actual output or log excerpt.
+4. The config that controls instrumentation or tracing.
diff --git a/src/content/docs/blackbox/troubleshooting/reporting-a-bug.md b/src/content/docs/blackbox/troubleshooting/reporting-a-bug.md
new file mode 100644
index 0000000..7cd1976
--- /dev/null
+++ b/src/content/docs/blackbox/troubleshooting/reporting-a-bug.md
@@ -0,0 +1,42 @@
+---
+title: "Reporting a Bug"
+description: "List the command output, config, environment, artifacts, and reproduction details maintainers need."
+sidebar_position: 5
+keywords: ["report bug", "debug blackbox", "issue template"]
+toc_min_heading_level: 2
+seo:
+ primary_keyword: "Reporting a Bug"
+ secondary_keywords: ["report bug", "debug blackbox"]
+ search_intent: "support intent from users preparing a reproducible Blackbox bug report"
+ snippet_angle: "list the command, expected result, actual result, environment, artifacts, logs, and redactions maintainers need"
+---
+
+List the command output, config, environment, artifacts, and reproduction details maintainers need.
+
+This page explains the minimum useful bug report. If maintainers cannot reproduce the issue or understand the run context, the report is not complete enough yet.
+
+## What A Useful Bug Report Includes
+
+1. The command or scenario that failed.
+2. The expected result and the actual result.
+3. The environment and configuration used.
+4. The relevant artifacts, logs, and screenshots.
+5. The exact steps needed to reproduce the issue.
+
+## What To Redact
+
+1. Secrets or tokens.
+2. Private URLs if they are not required to understand the issue.
+3. Sensitive customer data.
+4. Anything else that is not needed to reproduce the failure.
+
+## When To Report
+
+Report the issue after you have reduced it as far as you reasonably can and confirmed it is not just a setup mismatch or a missing local prerequisite.
+
+## What Maintainers Need First
+
+1. The failure mode.
+2. The config and version details.
+3. The artifact or log that shows the issue.
+4. A reproducible path if you have one.
diff --git a/src/content/docs/blackbox/use-cases/covering-before-refactor.md b/src/content/docs/blackbox/use-cases/covering-before-refactor.md
new file mode 100644
index 0000000..3db6c6e
--- /dev/null
+++ b/src/content/docs/blackbox/use-cases/covering-before-refactor.md
@@ -0,0 +1,90 @@
+---
+title: "Covering Before Refactor"
+description: "Use characterization testing and Blackbox runtime evidence to capture behavior before changing internals."
+sidebar_position: 1
+keywords:
+ [
+ "characterization testing",
+ "golden master testing",
+ "refactor safety",
+ "cover before refactor",
+ ]
+toc_min_heading_level: 2
+seo:
+ primary_keyword: "characterization testing"
+ secondary_keywords:
+ ["golden master testing", "refactor safety", "cover before refactor"]
+ search_intent: "legacy and refactor safety intent from teams capturing current behavior before changing internals"
+ snippet_angle: "capture current system behavior before a refactor, then compare runtime effects after the change"
+---
+
+Covering before refactor means capturing current behavior before changing the implementation. This is the classic characterization testing move: when the system is valuable but hard to reason about, first document what it does.
+
+Blackbox applies that idea to system behavior. It records runtime effects before the refactor, then lets the team compare what changed after the implementation moves.
+
+Teams about to rewrite, extract, modularize, upgrade, or clean up a system that already has user value and should not accidentally change behavior.
+
+## Why Refactors Need Behavior Proof
+
+Refactors often begin with a risky assumption: if the existing tests are green, behavior is safe. That can be true for local logic and still false for system behavior.
+
+A refactor can keep unit tests green while changing:
+
+1. A downstream HTTP call.
+2. An emitted event.
+3. A database write.
+4. A queue message.
+5. A cache invalidation.
+6. A forbidden side effect that should never happen.
+
+When those effects matter, line coverage and passing tests are not enough. The team needs a behavior baseline.
+
+## Characterization Testing And Golden Masters
+
+Characterization testing captures what a system currently does so future changes can be compared against it. Golden master testing often captures a larger output snapshot and treats it as a baseline.
+
+Blackbox uses the same instinct but produces more reviewable artifacts:
+
+1. Runtime evidence from a real system run.
+2. Effects derived from that evidence.
+3. Feature files that summarize behavior in readable form.
+4. Catalogs and reports that mark required, forbidden, missing, and newly observed effects.
+
+That makes the baseline easier to review than a raw snapshot alone.
+
+## Refactor Workflow
+
+A practical workflow is:
+
+1. Pick one high-risk behavior before changing internals.
+2. Run a system test that exercises the behavior.
+3. Capture the Blackbox artifacts as the baseline.
+4. Perform the refactor.
+5. Run the same scenario again.
+6. Review the effect drift.
+7. Accept intentional behavior changes and reject accidental ones.
+
+This gives reviewers a concrete artifact instead of only a diff and a green test suite.
+
+## What Counts As Success
+
+A good refactor run does not prove that the new design is better. It proves that selected externally visible behavior stayed stable or changed intentionally.
+
+Success looks like:
+
+1. Required effects still appear.
+2. Forbidden effects still stay absent.
+3. Newly observed effects are reviewed.
+4. Missing effects are investigated before merge.
+5. The final artifact explains why behavior is still acceptable.
+
+## What Not To Claim
+
+Blackbox does not make refactors risk-free. It does not replace unit tests for local logic, and it does not prove that every behavior in the system was covered. It gives the team stronger evidence for the workflows it actually exercised.
+
+## What To Read Next
+
+1. [Runtime Evidence](/docs/blackbox/concepts/runtime-evidence)
+2. [System Effects](/docs/blackbox/concepts/effects-and-catalogs)
+3. [Reports and CI Gates](/docs/blackbox/guides/reports-and-ci-gates)
+4. [Feature Drift](/docs/blackbox/troubleshooting/feature-drift)
diff --git a/src/content/docs/blackbox/use-cases/incident-regression.md b/src/content/docs/blackbox/use-cases/incident-regression.md
new file mode 100644
index 0000000..a8aa9c3
--- /dev/null
+++ b/src/content/docs/blackbox/use-cases/incident-regression.md
@@ -0,0 +1,65 @@
+---
+title: "Incident Regression"
+description: "Turn a known incident into a Playwright flow with required and forbidden runtime effects that fail if the behavior returns."
+sidebar_position: 3
+keywords:
+ [
+ "incident regression test",
+ "postmortem testing",
+ "forbidden effects",
+ "behavioral regression",
+ ]
+---
+
+An incident regression test should preserve the behavioral distinction that made the incident harmful, not only the response that happened to accompany it.
+
+## Example: Rejected User Was Charged
+
+Suppose the API returned `404` for an unknown user, but a payment request was already sent and an order message was published. A response-only regression test can pass while the incident returns.
+
+Create a named flow and keep the response assertion:
+
+```ts
+test.describe(
+ "Reject an unknown subscriber",
+ { tag: "@flow:subscribe-unknown-user" },
+ () => {
+ test("stops before downstream work", async ({ capture, request }) => {
+ const response = await request.post("/subscriptions", {
+ data: { userId: "ghost-user", paymentMethodId: "pm_card_visa" },
+ });
+
+ expect(response.status()).toBe(404);
+ await expect(capture).toMatchCatalog();
+ });
+ },
+);
+```
+
+Review and accept the incident boundary in the effect contract:
+
+```yaml
+specVersion: "0.1"
+flow: subscribe-unknown-user
+requires:
+ - { boundary: postgres, op: SELECT, key: users, service: bff }
+forbids:
+ - { boundary: http, op: POST, key: /v1/payment_intents, service: bff }
+ - { boundary: postgres, op: INSERT, service: bff }
+ - { boundary: sqs, op: SendMessage, key: subscription-orders }
+```
+
+The regression now fails if payment, persistence, or publication returns, even when the API response remains `404`.
+
+## Post-Incident Workflow
+
+1. Reproduce the narrow flow in a controlled testbed.
+2. Identify the required and forbidden effects that distinguish fixed from broken behavior.
+3. Review the effect contract with the incident owner.
+4. Add an EARS requirement when the rule should remain normative and traceable.
+5. Run the flow in CI without changing accepted behavior artifacts.
+6. Retain the failing runtime artifacts when the gate trips.
+
+Blackbox does not replace monitoring, incident management, or root-cause analysis. It turns one selected failure mode into a recurring pre-merge behavior check.
+
+See [Effects, Catalogs, and Coverage](/docs/blackbox/concepts/effects-and-catalogs) and [Reports and CI Gates](/docs/blackbox/guides/reports-and-ci-gates).
diff --git a/src/content/docs/blackbox/use-cases/index.mdx b/src/content/docs/blackbox/use-cases/index.mdx
new file mode 100644
index 0000000..358b907
--- /dev/null
+++ b/src/content/docs/blackbox/use-cases/index.mdx
@@ -0,0 +1,44 @@
+---
+title: "Use Cases"
+description: "Choose a Blackbox adoption path for refactors, legacy modernization, incident regressions, or distributed system workflows."
+sidebar_position: 1
+keywords:
+ [
+ "system test use cases",
+ "refactor regression testing",
+ "legacy modernization testing",
+ "microservices verification",
+ "incident regression",
+ ]
+---
+
+Blackbox is most valuable where a visible response can stay green while important boundary behavior changes. Choose the use case closest to the risk you need to control.
+
+## Choose a Starting Point
+
+| Use case | First contract | Read next |
+| ---------------------------------- | ---------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
+| Refactor a working system | Capture one consequential flow before changing internals | [Covering Before Refactor](/docs/blackbox/use-cases/covering-before-refactor) |
+| Modernize a legacy system | Preserve reviewed effects while replacing components in stages | [Legacy Modernization](/docs/blackbox/use-cases/legacy-modernization) |
+| Prevent an incident from returning | Encode the effect that must happen and the effect that must never recur | [Incident Regression](/docs/blackbox/use-cases/incident-regression) |
+| Verify a microservice workflow | Check the database, cache, HTTP, and queue behavior behind one public result | [Microservices Regression](/docs/blackbox/use-cases/microservices-regression) |
+
+## Common Pattern
+
+Every use case follows the same small loop:
+
+1. Choose one stable Playwright flow.
+2. Run it in a controlled topology.
+3. Capture the boundary effects.
+4. Review required and forbidden clauses.
+5. Change the implementation.
+6. Rerun against the same contract.
+7. Ratify any intentional behavior change.
+
+EARS requirements and Gherkin are governance layers. Use EARS when requirement-level traceability matters and Gherkin when reviewers need readable examples. Runtime effects are required when the claim concerns what the running system actually did.
+
+## Do Not Start With the Entire Suite
+
+Pick flows where the cost of silent behavior drift is clear: payment, authorization, publication, persistence, destructive operations, retries, or compensation.
+
+[Choose Your Starting Point](/docs/blackbox/quickstart/) starts from repository state. [When to Use Blackbox](/docs/blackbox/overview/when-to-use-blackbox) explains where a lower-level test is the better choice.
diff --git a/src/content/docs/blackbox/use-cases/legacy-modernization.md b/src/content/docs/blackbox/use-cases/legacy-modernization.md
new file mode 100644
index 0000000..616e8ef
--- /dev/null
+++ b/src/content/docs/blackbox/use-cases/legacy-modernization.md
@@ -0,0 +1,50 @@
+---
+title: "Legacy Modernization"
+description: "Build a reviewed behavior map around a legacy system, then modernize components without silently changing critical boundary effects."
+sidebar_position: 2
+keywords:
+ [
+ "legacy modernization testing",
+ "legacy refactor",
+ "brownfield system tests",
+ "characterization testing",
+ ]
+---
+
+Legacy modernization is risky when the implementation is the only reliable description of behavior. Blackbox can turn selected running behavior into a smaller, reviewed contract before components move.
+
+## Start With a Boundary, Not the Codebase
+
+Choose a workflow the business already depends on: subscription, invoice generation, account closure, reconciliation, or webhook processing.
+
+The first run records what the system currently does at supported boundaries. Review that recording into three sets:
+
+- behavior that must survive the migration;
+- behavior that is incidental and should not be frozen;
+- behavior that is wrong and should become forbidden or be fixed before baselining.
+
+Capturing the present is characterization. Approving selected effects is contract work. Keep those steps separate.
+
+## Incremental Migration Loop
+
+1. Drive the legacy path through one Playwright flow.
+2. Review its effect catalog.
+3. Bind existing requirements to the flow when traceability matters.
+4. Replace one component, datastore, queue, or service boundary.
+5. Run the same flow against the candidate topology.
+6. Repair missing or forbidden behavior.
+7. Ratify an intentional catalog change before moving to the next slice.
+
+The catalog can remain stable even when implementation technology changes. If a Postgres write intentionally becomes a queue publication, the contract should change through review rather than being silently accepted as migration noise.
+
+## Parallel Old/New Comparison
+
+When both systems can run, execute the same flow against each controlled topology and compare the behavior that should remain equivalent. Blackbox's experimental observation comparison can help during a test reshape or migration, but the effect catalog remains the stable reviewed contract.
+
+Generated Gherkin can provide a readable inventory for domain reviewers. EARS can retain normative requirements. Neither should be generated and ignored; use only artifacts that participate in migration decisions.
+
+## Limits
+
+Blackbox does not discover the whole legacy domain, make an unsupported runtime observable, or decide whether historical behavior is correct. It gives the team runtime facts and a gate for the slices they deliberately cover.
+
+Start with [Covering Before Refactor](/docs/blackbox/use-cases/covering-before-refactor), then use [Testbed and Instrumentation](/docs/blackbox/guides/set-up-the-testbed) to build the controlled topology.
diff --git a/src/content/docs/blackbox/use-cases/microservices-regression.md b/src/content/docs/blackbox/use-cases/microservices-regression.md
new file mode 100644
index 0000000..000fad5
--- /dev/null
+++ b/src/content/docs/blackbox/use-cases/microservices-regression.md
@@ -0,0 +1,70 @@
+---
+title: "Microservices Regression"
+description: "Verify HTTP, database, cache, and queue behavior behind one Playwright system flow across an isolated microservice topology."
+sidebar_position: 4
+keywords:
+ [
+ "microservices system testing",
+ "distributed system regression",
+ "queue effect testing",
+ "service boundary verification",
+ ]
+---
+
+A microservice endpoint can return the expected response while the distributed workflow behind it changes. Blackbox makes selected cross-service effects part of the review.
+
+## What One Flow Can Prove
+
+The subscription showcase drives `POST /subscriptions` through:
+
+```text
+Playwright -> BFF -> Redis
+ -> Postgres
+ -> payment HTTP
+ -> fraud-check
+ -> order-service -> SQS
+```
+
+The success flow can require a payment request, subscription insert, cache update, and queue publication. The unknown-user flow can require the lookup while forbidding payment, persistence, and publication.
+
+That is more precise than "all services were healthy" and more behavior-oriented than asking a reviewer to reconstruct the workflow from a trace waterfall.
+
+## Choose the Topology
+
+Use managed dependencies where possible:
+
+- one Compose or Testcontainers stack per Playwright worker;
+- Docker-assigned ports;
+- resettable database, cache, and queue state;
+- local or sandboxed substitutes for unmanaged vendors;
+- explicit waits for asynchronous completion.
+
+Broader E2E runs can include real identity, email, or vendor systems, but their variability makes strict merge gates harder to diagnose.
+
+## Contract Example
+
+```ts
+await expect(capture).toObserveEffects({
+ requires: [
+ effect.http("POST", { path: "/v1/payment_intents" }),
+ effect.postgres("INSERT", { table: "subscriptions" }),
+ effect.sqs("SendMessage", { queue: "subscription-orders" }),
+ ],
+ forbids: [
+ effect.http("POST", { path: "/v1/refunds" }),
+ effect.postgres("DELETE"),
+ ],
+});
+```
+
+Qualify shapes with `service` in the catalog when multiple services can produce the same operation.
+
+## Async Effects
+
+Do not assert a queue or worker effect before the flow has a durable completion signal. Poll a managed dependency, wait for an application-visible state transition, or expose a test synchronization endpoint. Sleeping for a fixed duration makes both capture and failure diagnosis weaker.
+
+## Limits
+
+Blackbox does not replace distributed tracing, service contracts, fault injection, production monitoring, or network resilience testing. It converts selected runtime evidence into a behavioral gate for selected flows.
+
+Continue with [Playwright Flows, Isolation, and Parallelism](/docs/blackbox/guides/playwright-isolation-and-parallelism) and [Reports and CI Gates](/docs/blackbox/guides/reports-and-ci-gates).
diff --git a/docs/changelog.md b/src/content/docs/changelog.md
similarity index 99%
rename from docs/changelog.md
rename to src/content/docs/changelog.md
index 959169e..8cf8341 100644
--- a/docs/changelog.md
+++ b/src/content/docs/changelog.md
@@ -4,8 +4,6 @@ title: Changelog
description: Version history and release notes for Suites
---
-# Changelog
-
All notable changes to Suites are documented here. For the complete version history, visit our [GitHub Releases](https://github.com/suites-dev/suites/releases).
---
diff --git a/docs/get-started/index.md b/src/content/docs/get-started/index.mdx
similarity index 93%
rename from docs/get-started/index.md
rename to src/content/docs/get-started/index.mdx
index 7142743..c20efcd 100644
--- a/docs/get-started/index.md
+++ b/src/content/docs/get-started/index.mdx
@@ -4,7 +4,8 @@ title: Get Started
description: Everything you need to start using Suites in minutes
---
-# Get Started
+import Aside from '@/components/mdx/Aside.astro';
+
Learn how to install Suites, configure the testing environment, and write the first automated test suite.
@@ -22,11 +23,11 @@ The following requirements must be met:
- **Framework** - NestJS, InversifyJS, or plain TypeScript classes with constructor injection
- **Testing library** - Jest, Vitest, or Sinon
-:::tip Framework Flexibility
+
## Recommended Path
@@ -41,4 +42,3 @@ For those new to Suites:
## Resources
- **[Suites Examples Repository](https://github.com/suites-dev/examples)** - Complete working examples for all testing patterns
-
diff --git a/docs/get-started/installation.mdx b/src/content/docs/get-started/installation.mdx
similarity index 95%
rename from docs/get-started/installation.mdx
rename to src/content/docs/get-started/installation.mdx
index 1b8d0b3..ac7d3ce 100644
--- a/docs/get-started/installation.mdx
+++ b/src/content/docs/get-started/installation.mdx
@@ -5,8 +5,9 @@ description: "Step-by-step installation of Suites for NestJS or Inversify with J
keywords: [install suites, nestjs unit testing setup, inversify testing, vitest nestjs, jest nestjs setup, emitDecoratorMetadata nestjs, nestjs tsconfig, experimentalDecorators]
---
-import Tabs from '@theme/Tabs';
-import TabItem from '@theme/TabItem';
+import Aside from '@/components/mdx/Aside.astro';
+import Tabs from '@/components/mdx/Tabs.astro';
+import TabItem from '@/components/mdx/TabItem.astro';
# Installation
@@ -76,10 +77,10 @@ This installs three packages:
**Suites will automatically detect the installed adapters and configure itself accordingly.**
-:::info Why reflect-metadata?
+
## Supported Libraries (Adapters)
@@ -110,9 +111,9 @@ This configuration is necessary for Suites to reflect class dependencies and con
}
```
-:::note NodeNext / ESM projects
+
## Type Reference Configuration
@@ -160,10 +161,10 @@ Suites will automatically detect the adapter and configure itself accordingly.
Install the corresponding adapter in each workspace separately. Configure the package manager's hoisting settings
to enable Suites to detect the adapter in each workspace.
-:::note
+
## For Vitest Users
@@ -196,13 +197,13 @@ export default defineConfig({
});
```
-:::note Vitest 4.x
+
\ No newline at end of file
+
diff --git a/docs/get-started/quickstart.md b/src/content/docs/get-started/quickstart.mdx
similarity index 97%
rename from docs/get-started/quickstart.md
rename to src/content/docs/get-started/quickstart.mdx
index b0f2dc6..593f91e 100644
--- a/docs/get-started/quickstart.md
+++ b/src/content/docs/get-started/quickstart.mdx
@@ -5,8 +5,9 @@ description: "Write your first Suites unit test in 5 minutes. Walkthrough for Ne
keywords: [suites quickstart, nestjs unit test example, inversify unit test, first nestjs test, vitest nestjs example, typescript unit test tutorial]
---
-import Tabs from '@theme/Tabs';
-import TabItem from '@theme/TabItem';
+import Aside from '@/components/mdx/Aside.astro';
+import Tabs from '@/components/mdx/Tabs.astro';
+import TabItem from '@/components/mdx/TabItem.astro';
# Quick Start Guide
@@ -17,9 +18,9 @@ Write the first Suites test in 5 minutes. No manual mocks, no dependency injecti
* Sociable tests with real dependencies
* Zero-config testing
-:::info
+
## Prerequisites
@@ -140,12 +141,12 @@ When `TestBed.solitary(UserService).compile()` is called, Suites automatically:
**What was not required:** Manually creating mocks, configuring dependency injection, or writing test setup boilerplate.
-:::tip Key Terminology
+
## Step 3: Testing with Real Dependencies (Sociable Mode)
@@ -180,11 +181,11 @@ describe('Notification Service Sociable Spec', () => {
});
```
-:::tip
+
## How It Works: No Modules, No Bootstrapping
diff --git a/docs/get-started/why-suites.md b/src/content/docs/get-started/why-suites.mdx
similarity index 97%
rename from docs/get-started/why-suites.md
rename to src/content/docs/get-started/why-suites.mdx
index a33e530..6215ada 100644
--- a/docs/get-started/why-suites.md
+++ b/src/content/docs/get-started/why-suites.mdx
@@ -4,10 +4,9 @@ title: Why Suites?
description: Eliminate boilerplate in dependency injection testing. Suites provides type-safe test doubles and automatic mocking for TypeScript applications following the IoC principle.
---
-import Tabs from '@theme/Tabs';
-import TabItem from '@theme/TabItem';
-
-# Why Suites?
+import Aside from '@/components/mdx/Aside.astro';
+import Tabs from '@/components/mdx/Tabs.astro';
+import TabItem from '@/components/mdx/TabItem.astro';
Unit testing TypeScript applications with complex dependencies is **expensive and slow**. Whether using dependency injection containers, plain constructor injection, or functional composition, manual mocking creates brittle tests, cryptic errors, and mountains of boilerplate that bury test intent. Teams waste weeks debugging broken test doubles, onboarding junior developers, and maintaining inconsistent unit testing patterns across projects.
@@ -173,7 +172,7 @@ container.register(Database, { useValue: { query: jest.fn() } });
Suites provides a **declarative API** that removes manual mocking entirely. A single call creates a fully-typed,
isolated unit testing environment with type-safe test doubles. No boilerplate, no cryptic errors, no silent failures.
-:::tip Current Testing Options
+
```typescript title="order.service.spec.ts" {1,9,11-13}
import { TestBed, type Mocked } from '@suites/unit';
diff --git a/docs/guides/fundamentals.md b/src/content/docs/guides/fundamentals.mdx
similarity index 98%
rename from docs/guides/fundamentals.md
rename to src/content/docs/guides/fundamentals.mdx
index 456f8a6..a1a52de 100644
--- a/docs/guides/fundamentals.md
+++ b/src/content/docs/guides/fundamentals.mdx
@@ -4,7 +4,7 @@ title: Unit Testing Fundamentals
description: Master unit testing fundamentals with the IoC principle. Learn solitary vs sociable testing, test doubles, and how Suites eliminates mock boilerplate for dependency injection and beyond.
---
-# Unit Testing Fundamentals
+import Aside from '@/components/mdx/Aside.astro';
> **What this covers:** Core principles of unit testing with the IoC principle and how Suites eliminates testing complexity \
> **Time to read:** ~10 minutes \
@@ -67,9 +67,9 @@ function createUserService(repo: UserRepository) {
This principle applies to any architectural choice: dependency injection frameworks, plain constructor injection, functional composition, or factory patterns. The key is that dependencies flow in from outside.
-:::info
+
## Prerequisites
@@ -128,11 +128,11 @@ Testing applications with IoC patterns presents several challenges:
const { unit, unitRef } = await TestBed.solitary(UserService).compile();
```
-:::tip 🤖 LLM-Friendly Design
+
## Testing Approaches Comparison
diff --git a/docs/guides/index.md b/src/content/docs/guides/index.mdx
similarity index 89%
rename from docs/guides/index.md
rename to src/content/docs/guides/index.mdx
index e0ca6be..1adb371 100644
--- a/docs/guides/index.md
+++ b/src/content/docs/guides/index.mdx
@@ -5,6 +5,8 @@ description: Practical guides for testing with Suites
toc_min_heading_level: 3
---
+import Aside from '@/components/mdx/Aside.astro';
+
# Testing Guides
Practical guides for writing solitary and sociable unit tests with Suites. Learn how to test components in isolation, verify real interactions between classes, and control external dependencies.
@@ -22,12 +24,10 @@ Practical guides for writing solitary and sociable unit tests with Suites. Learn
404
++ We may have moved or renamed it during the recent docs refresh. + Try one of these instead: +
+ ++ Still stuck? Go to the homepage or{' '} + open an issue on GitHub. +
++ + A unit testing framework for TypeScript backends working with + inversion of control and dependency injection + +
+
+ NestJS
+ Official
+
+
+
+ InversifyJS
+ Official
+
+
+ Vitest
+
+ Jest
+
+ Sinon
+
+
+ Suites' declarative API creates fully-typed, isolated test environments with a single declaration. Suites auto-generates all mocks and wires dependencies automatically.
+Generate type-safe mocks bound to implementations. Eliminate broken tests after refactors, silent runtime failures, and manual type casting.
+Change constructors, add dependencies, refactor classes - tests adapt automatically. Skip manual mock updates. Catch breaking changes at compile time, not runtime.
+One canonical pattern teaches AI agents the entire API. Coding agents like Claude Code and Cursor write correct tests in a single pass with 95% less context consumption compared to manual mocking patterns.
++ Using Suites?{' '} + Share your experience + {' '}and help us shape the future of Suites +
++ Stop relearning test patterns on every project. Suites provides a + consistent, standardized approach that works identically across + NestJS, InversifyJS, and any DI framework, giving teams a unified + testing experience. +
+
+ + Suites' declarative API removes 90% of test setup code. No more + scrolling through mock wiring, logic is front and center. New team + members write tests on day one, not day ten. +
+
+ + No more debugging broken mocks. Suites automatically generates + fully-typed mocks bound to implementation. Catch errors at compile + time, not runtime. Refactor with confidence while mocks stay valid + when dependencies change. +
+
+ + Manual mocking forces AI agents to hold 40+ lines of boilerplate + per test in context. Suites provides one canonical pattern that + reduces token consumption by 95%. AI coding assistants like Claude + Code, Cursor, and GitHub Copilot generate accurate tests in a + single pass without burning tokens on repetitive setup code. +
+
+ - - A unit testing framework for TypeScript backends working with - inversion of control and dependency injection - -
-Works with projects using
-
- NestJS
- Official
-
-
-
- InversifyJS
- Official
-
-
- Vitest
-
- Jest
-
- Sinon
- - Suites' declarative API creates fully-typed, isolated test environments with a single declaration. - Suites auto-generates all mocks and wires dependencies automatically. -
-- Generate type-safe mocks bound to implementations. Eliminate - broken tests after refactors, silent runtime failures, and - manual type casting. -
-- Change constructors, add dependencies, refactor classes - tests - adapt automatically. Skip manual mock updates. Catch breaking - changes at compile time, not runtime. -
-- One canonical pattern teaches AI agents the entire API. Coding - agents like Claude Code and Cursor write correct tests in a - single pass with 95% less context consumption compared to manual - mocking patterns. -
-Used by
-- Using Suites?{" "} - - Share your experience - {" "} - and help us shape the future of Suites -
-- Stop relearning test patterns on every project. Suites provides a - consistent, standardized approach that works identically across - NestJS, InversifyJS, and any DI framework, giving teams a unified - testing experience. -
- - See Framework Support → - -- Suites' declarative API removes 90% of test setup code. No more - scrolling through mock wiring, logic is front and center. New team - members write tests on day one, not day ten. -
- - See Quick Start → - -- No more debugging broken mocks. Suites automatically generates - fully-typed mocks bound to implementation. Catch errors at compile - time, not runtime. Refactor with confidence while mocks stay valid - when dependencies change. -
- - Learn about Mocking → - -- Manual mocking forces AI agents to hold 40+ lines of boilerplate - per test in context. Suites provides one canonical pattern that - reduces token consumption by 95%. AI coding assistants like Claude - Code, Cursor, and GitHub Copilot generate accurate tests in a - single pass without burning tokens on repetitive setup code. -
- - Suites and AI → - -sandbox
+
+ Iteration page for src/components/blackbox/OpeningProofClip.astro. Once we like it, we embed it on
+ /docs/blackbox/overview/what-is-blackbox above the Verification Debt diagram.
+
Use this variant to test the replay button in isolation.
+
+ Simulated stream of scripts/demo-isolation.sh Step 3 (per-worker compose). Lines appear in real time with per-line pacing; the command line types char-by-char.
+
✓ 201 pill on the right. Verdict: response 201.+ await expect(capture).toMatchCatalog() line slides in. Verdict: capturing….matching catalog….satisfied 1 / 1. Replay button fades in.sandbox
+
+ Typewriter replay of curated CLI output. Source: ~/projects/suites/blackbox/scripts/demo-isolation.sh step 3 (per-worker compose).
+ Content is a pretend recording; real demo lives in the kit repo, this is the styling rehearsal.
+
The full narrator-style demo. Use for a dedicated "see it run" page, not the front page.
+Just the meaningful output. Could embed near a Quickstart code block as the "what you see after the test passes" payoff.
+Press replay in the chrome bar to start.
header : magenta block headline with double-rulestep : STEP n/total title, single-rule abovesubhead : cyan ── label ──explain : blue │ bar, default body textnarrate : dim italiccmd : bold white with cyan $ promptout : default mono outputpass / fail / info / warn : colored mark badge plus messageblank : empty linepause : pure delay (ms) with nothing rendered inside prose. Without this, inline code inherits the
+ 16px body size and reads visually larger than 13px expressive-code blocks.
+ Per audit J.5 + Top-12 fix 8. */
+.article :not(pre) > code {
+ font-family: var(--font-code);
+ font-size: 0.9em;
+ font-weight: var(--fw-medium);
+ padding: 0.15em 0.4em;
+ border-radius: 6px;
+ background: rgba(255,255,255,.06);
+ color: var(--code-text);
+}
+
+/* Block-primitive rhythm.
+ Every block-level child of .article that isn't a heading or paragraph
+ needs an explicit bottom margin, otherwise it sits flush against the
+ following text (code blocks, asides, tables, quotes were all touching
+ the next sibling). Matches the existing 16px margin on .article p but
+ bumps to 24px because these blocks are heavier than a paragraph. */
+.article > pre,
+.article > [class*="expressive-code"],
+.article > .code,
+.article > .aside,
+.article > .alert,
+.article > table,
+.article > blockquote,
+.article > figure,
+.article > hr {
+ margin: 0 0 24px;
+}
+
+.article > blockquote {
+ border-left: 2px solid var(--border-strong);
+ padding: 4px 0 4px 16px;
+ color: var(--text-muted);
+ font-style: italic;
+}
+
+.article > hr {
+ border: 0;
+ border-top: 1px solid var(--border);
+ margin: 32px 0;
+}
+
+.article > figure {
+ margin-top: 8px;
+}
+
+/* Expressive Code renders shell snippets with terminal titlebar chrome.
+ Keep the code box and copy button, but remove the decorative window header
+ globally so command snippets read as docs snippets rather than app chrome. */
+.expressive-code .frame.is-terminal {
+ --button-spacing: 0.4rem !important;
+}
+
+.expressive-code .frame.is-terminal .header {
+ display: none !important;
+}
+
+.expressive-code .frame.is-terminal pre {
+ border-top: var(--ec-brdWd) solid var(--ec-brdCol) !important;
+ border-top-left-radius: calc(var(--ec-brdRad) + var(--ec-brdWd)) !important;
+ border-top-right-radius: calc(var(--ec-brdRad) + var(--ec-brdWd)) !important;
+}
+
+/* ============================================================
+ * Docs article header chrome
+ * Owns breadcrumb + title row (with badge + page-actions) + lede.
+ * Sits above the MDX body, below the topbar.
+ * ============================================================ */
+
+.article-header {
+ margin: 0;
+}
+
+/* The first body element directly after the header was stacking its own
+ top margin (h2 = 48, h3 = 32) on top of the h1's bottom margin (24),
+ producing a 70-90px gap. Zero out the top margin of whatever leads the
+ body so the only spacing is the h1's own bottom margin. */
+.article > .article-header + * { margin-top: 0; }
+
+/* Meta row: breadcrumb on the left, page-actions cluster pinned right.
+ Both elements vertically centered on each other's mid-line. */
+.article-meta-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 24px;
+ margin: 0 0 48px;
+}
+
+/* Breadcrumb */
+.breadcrumb {
+ margin: 0;
+ flex: 1;
+ min-width: 0;
+}
+.breadcrumb-list {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: baseline;
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ font-size: 0.9375rem;
+ line-height: 1.5;
+ color: var(--text-muted);
+}
+.breadcrumb-item {
+ display: inline-flex;
+ align-items: baseline;
+}
+.breadcrumb-link {
+ color: var(--text-muted);
+ text-decoration: none;
+ transition: color 160ms ease;
+}
+.breadcrumb-link:hover {
+ color: var(--text);
+}
+.breadcrumb-current {
+ color: var(--text);
+ font-weight: var(--fw-medium);
+}
+/* Inline slash separator. Sits between items with even breathing on each side. */
+.breadcrumb-sep {
+ display: inline-block;
+ padding: 0 8px;
+ color: var(--text-soft);
+ font-weight: var(--fw-regular);
+ user-select: none;
+}
+
+/* H1 now sits on its own row (page-actions moved into the meta row above).
+ Title + maturity badge stay on the same baseline via inline-flex. */
+.article-title {
+ margin: 0 0 16px;
+ display: inline-flex;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 12px;
+}
+
+/* Small pill next to the h1 indicating maturity. Same family as the
+ product-tab badge in the topbar. */
+.article-title-badge {
+ display: inline-flex;
+ align-items: center;
+ padding: 4px 10px;
+ font-size: 11px;
+ font-family: var(--font-body);
+ font-weight: var(--fw-semibold);
+ letter-spacing: 0.06em;
+ text-transform: uppercase;
+ border-radius: 999px;
+ line-height: 1;
+ vertical-align: middle;
+ align-self: center;
+}
+.article-title-badge[data-variant="alpha"] {
+ color: var(--primary-light);
+ background: var(--primary-soft);
+ border: 1px solid var(--primary-border);
+}
+.article-title-badge[data-variant="beta"] {
+ color: var(--info);
+ background: rgba(147, 197, 253, 0.12);
+ border: 1px solid rgba(147, 197, 253, 0.32);
+}
+.article-title-badge[data-variant="new"] {
+ color: var(--success);
+ background: rgba(134, 239, 172, 0.12);
+ border: 1px solid rgba(134, 239, 172, 0.32);
+}
+.article-title-badge[data-variant="deprecated"] {
+ color: var(--text-soft);
+ background: rgba(255, 255, 255, 0.04);
+ border: 1px solid var(--border);
+}
+:root[data-theme="light"] .article-title-badge[data-variant="deprecated"] {
+ background: rgba(15, 15, 18, 0.05);
+}
+
+/* Description (lede paragraph) directly under the h1. */
+.article-lede {
+ margin: 12px 0 0;
+ font-size: 1.1875rem;
+ line-height: 1.5;
+ color: var(--text-muted);
+ max-width: 64ch;
+}
+
+/* ============================================================
+ * Page actions cluster
+ * Three affordances: Copy Markdown / Open in LLM dropdown / Edit on GitHub.
+ * 36px tall pills on desktop, wraps below the title on mobile.
+ * ============================================================ */
+
+.page-actions {
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+ flex-shrink: 0;
+ flex-wrap: wrap;
+}
+
+.page-action {
+ display: inline-flex;
+ align-items: center;
+ gap: 6px;
+ height: 31px;
+ padding: 0 11px;
+ border-radius: 8px;
+ border: 1px solid var(--border);
+ background: transparent;
+ color: var(--text-muted);
+ font-size: 13px;
+ font-weight: var(--fw-medium);
+ font-family: var(--font-body);
+ text-decoration: none;
+ cursor: pointer;
+ transition: color 160ms ease, background-color 160ms ease, border-color 160ms ease;
+ user-select: none;
+}
+.page-action svg {
+ width: 14px;
+ height: 14px;
+}
+.page-action:hover {
+ color: var(--text);
+ background: rgba(255, 255, 255, 0.04);
+ border-color: var(--border-strong);
+}
+:root[data-theme="light"] .page-action:hover {
+ background: rgba(15, 15, 18, 0.05);
+}
+.page-action:focus-visible {
+ outline: 2px solid var(--primary);
+ outline-offset: 2px;
+}
+.page-action-icon {
+ flex: none;
+ color: currentColor;
+}
+.page-action-caret {
+ flex: none;
+ color: var(--text-soft);
+ transition: transform 160ms ease;
+}
+
+/* Open in LLM dropdown menu */
+.page-action-menu {
+ position: relative;
+}
+.page-action-menu > summary {
+ list-style: none;
+ cursor: pointer;
+}
+.page-action-menu > summary::-webkit-details-marker {
+ display: none;
+}
+.page-action-menu[open] > summary {
+ color: var(--text);
+ background: rgba(255, 255, 255, 0.04);
+ border-color: var(--border-strong);
+}
+:root[data-theme="light"] .page-action-menu[open] > summary {
+ background: rgba(15, 15, 18, 0.05);
+}
+.page-action-menu[open] .page-action-caret {
+ transform: rotate(180deg);
+}
+.page-action-menu-panel {
+ position: absolute;
+ top: calc(100% + 6px);
+ right: 0;
+ z-index: var(--z-overlay);
+ min-width: 220px;
+ padding: 6px;
+ background: var(--surface-raised);
+ border: 1px solid var(--border);
+ border-radius: 12px;
+ box-shadow: var(--shadow);
+ display: grid;
+ gap: 2px;
+}
+.page-action-menu-item {
+ display: block;
+ padding: 8px 10px;
+ font-size: 13px;
+ color: var(--text);
+ border-radius: 8px;
+ text-decoration: none;
+ transition: background-color 160ms ease;
+}
+.page-action-menu-item:hover {
+ background: rgba(255, 255, 255, 0.05);
+}
+:root[data-theme="light"] .page-action-menu-item:hover {
+ background: rgba(15, 15, 18, 0.06);
+}
+
+/* Last updated stamp (above prev/next pager) */
+.doc-last-updated {
+ margin: 40px 0 16px;
+ padding: 12px 0 0;
+ border-top: 1px solid var(--border);
+ font-size: 13px;
+ color: var(--text-soft);
+}
+.doc-last-updated-label {
+ margin-right: 6px;
+ font-weight: var(--fw-medium);
+ color: var(--text-muted);
+}
+
+/* Responsive: stack the meta row on narrow viewports so the breadcrumb keeps
+ its own line and the actions wrap below. */
+@media (max-width: 767px) {
+ .article-meta-row {
+ flex-direction: column;
+ align-items: stretch;
+ gap: 16px;
+ }
+ .page-actions {
+ align-self: flex-start;
+ }
+ .page-action {
+ /* 44x44 minimum touch target on mobile per ui-ux-pro-max touch-target-size. */
+ min-height: 44px;
+ padding: 0 14px;
+ }
+}
+
+/* Right TOC (prisma pattern): sticky, no background frame */
+.toc {
+ position: sticky;
+ top: var(--header-h);
+ align-self: start;
+ height: calc(100vh - var(--header-h));
+ max-height: calc(100vh - var(--header-h));
+ overflow-y: auto;
+ padding: 48px 16px 24px 24px;
+ font-size: 14px;
+ line-height: 20px;
+ border-left: 1px solid var(--border);
+}
+
+.toc-label {
+ font-size: 12px;
+ font-weight: var(--fw-semibold);
+ color: var(--text-soft);
+ text-transform: uppercase;
+ letter-spacing: 0.06em;
+ margin: 0 0 12px;
+ padding: 0 10px;
+}
+
+.toc-list { list-style: none; padding: 0; margin: 0; }
+
+.toc-list a {
+ display: block;
+ padding: 6px 10px;
+ color: var(--text-muted);
+ border-left: 2px solid transparent;
+ margin-left: -2px;
+ overflow-wrap: anywhere;
+ transition: color 160ms ease-out, border-left-color 160ms ease-out;
+}
+
+/* Hover: brighten text only (no pink) so it does not duplicate the active cue. */
+.toc-list a:hover {
+ color: var(--text);
+}
+
+/* Active section: pink left bar + pink text. Distinct from hover. */
+.toc-list a.active {
+ color: var(--primary-light);
+ border-left-color: var(--primary);
+ font-weight: var(--fw-semibold);
+}
+
+.toc-list .depth-3 { padding-left: 22px; }
+.toc-list .depth-4 { padding-left: 34px; }
+
+/* Match focus-ring radius to a comfortable corner for the inline link box. */
+.toc-list a:focus-visible { border-radius: 6px; }
+
+table {
+ width: 100%;
+ border-collapse: collapse;
+ /* The outer outline is drawn as an inset box-shadow rather than a `border:`
+ declaration. With `border-collapse: collapse` the cells' borders win and
+ the table's own border can render inconsistently at rounded corners. The
+ inset shadow always sits inside the radius and reads as a single hairline. */
+ border: 0;
+ box-shadow: 0 0 0 1px var(--border) inset;
+ border-radius: 10px;
+ overflow: hidden;
+}
+
+th, td {
+ padding: 14px 16px;
+ border-bottom: 1px solid var(--border);
+ text-align: left;
+ color: var(--text);
+ font-size: 1.0625rem;
+}
+
+th {
+ background: rgba(255,255,255,.04);
+ color: var(--text);
+ font-weight: var(--fw-semibold);
+}
+
+/* Zebra striping for the body rows. Even rows pick up a subtle tint so the
+ table reads as a structured grid rather than a wall of cells. The tint
+ alpha is low enough that --text on top still keeps high contrast. */
+tbody tr:nth-child(even) td {
+ background: rgba(255, 255, 255, 0.025);
+}
+:root[data-theme="light"] tbody tr:nth-child(even) td {
+ background: rgba(15, 15, 18, 0.035);
+}
+
+tr:last-child td { border-bottom: 0; }
+
+.type-specimen {
+ display: grid;
+ gap: 22px;
+}
+
+.specimen-line {
+ padding-bottom: 22px;
+ border-bottom: 1px solid var(--border);
+}
+
+.specimen-line:last-child { border-bottom: 0; padding-bottom: 0; }
+
+.specimen-label {
+ color: var(--text-soft);
+ font-family: var(--font-code);
+ font-size: 12px;
+ margin-bottom: 6px;
+}
+
+.display-sample {
+ font-family: var(--font-title);
+ font-size: clamp(40px, 7vw, 86px);
+ letter-spacing: -0.044em;
+ line-height: .92;
+ font-weight: var(--fw-display);
+}
+
+.heading-sample {
+ font-family: var(--font-title);
+ font-size: clamp(28px, 5vw, 48px);
+ letter-spacing: -0.034em;
+ line-height: 1;
+ font-weight: var(--fw-display);
+}
+
+.body-sample {
+ max-width: 760px;
+ color: var(--text-muted);
+ font-size: 18px;
+ line-height: 1.68;
+}
+
+.mono-sample {
+ font-family: var(--font-code);
+ color: var(--code-text);
+ background: var(--code-bg);
+ border: 1px solid var(--border);
+ border-radius: 18px;
+ padding: 16px;
+ overflow: auto;
+}
+
+.scale {
+ display: grid;
+ grid-template-columns: 90px 1fr;
+ gap: 12px;
+ align-items: center;
+ margin: 12px 0;
+}
+
+.scale-label {
+ color: var(--text-soft);
+ font-family: var(--font-code);
+ font-size: 12px;
+}
+
+.scale-bar {
+ height: 12px;
+ border-radius: 999px;
+ background: rgba(255,255,255,.06);
+ overflow: hidden;
+ border: 1px solid var(--border);
+}
+
+.scale-fill {
+ height: 100%;
+ border-radius: 999px;
+ background: var(--primary);
+}
+
+@media (max-width: 980px) {
+ .navlinks { display: none; }
+ .cols-5, .cols-4, .cols-3, .cols-2 {
+ grid-template-columns: 1fr;
+ }
+ .section-head {
+ align-items: start;
+ flex-direction: column;
+ }
+ .usage-row {
+ grid-template-columns: 1fr;
+ }
+ .ruler-track {
+ grid-template-columns: repeat(3, 1fr);
+ }
+}
+
+/* Skip-to-main-content link. BaseLayout renders this as the first
+ focusable element; off-screen until keyboard-focused. */
+.skip-link {
+ position: absolute;
+ top: -100px;
+ left: 16px;
+ z-index: var(--z-skip);
+ padding: 10px 16px;
+ background: var(--surface-raised);
+ color: var(--text);
+ border: 1px solid var(--border-strong);
+ border-radius: 10px;
+ font-size: 14px;
+ font-weight: var(--fw-semibold);
+ transition: top 150ms ease-out;
+}
+
+.skip-link:focus,
+.skip-link:focus-visible {
+ top: 16px;
+ outline: 2px solid var(--primary);
+ outline-offset: 2px;
+}
+
+/* Cursor affordance on interactive non-link elements. */
+.btn, .tab, [role="button"] { cursor: pointer; }
+.btn:disabled, .tab:disabled { cursor: not-allowed; }
+
+/* Icon-only action button used in header right cluster. */
+.icon-link {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 36px;
+ height: 36px;
+ color: var(--text-muted);
+ border-radius: 8px;
+}
+.icon-link:hover { color: var(--text); background: rgba(255,255,255,.04); }
+.icon-link svg { width: 18px; height: 18px; }
+
+/* Light-mode icon-link hover wash. The dark rgba(255,255,255,.04) would be
+ invisible on white, so use a neutral graphite tint. */
+:root[data-theme="light"] .icon-link:hover {
+ background: rgba(15, 15, 18, 0.06);
+}
+
+/* Theme toggle button: same hit-box as .icon-link but with stacked sun/moon
+ icons. One icon is visible per active theme so the glyph always shows the
+ destination (clicking it produces the depicted state). */
+.theme-toggle {
+ background: transparent;
+ border: 0;
+ cursor: pointer;
+ padding: 0;
+}
+.theme-toggle .theme-toggle-sun,
+.theme-toggle .theme-toggle-moon {
+ display: none;
+}
+/* In dark mode the sun icon is shown (click goes to light). */
+:root[data-theme="dark"] .theme-toggle .theme-toggle-sun {
+ display: inline-block;
+}
+/* In light mode the moon icon is shown (click goes to dark). */
+:root[data-theme="light"] .theme-toggle .theme-toggle-moon {
+ display: inline-block;
+}
+
+/* Brand divider + product slug in header (Prisma's "logo / docs" pattern). */
+.brand-divider {
+ color: var(--text-soft);
+ margin: 0 4px;
+}
+.brand-product {
+ font-family: var(--font-code);
+ font-size: 15px;
+ color: var(--text-muted);
+ font-weight: var(--fw-medium);
+}
+
+/* Header right-cluster action (text links). */
+.nav-action {
+ font-size: 14px;
+ font-weight: var(--fw-medium);
+ color: var(--text-muted);
+ padding: 8px 4px;
+}
+.nav-action:hover { color: var(--text); }
+
+/* Screen-reader-only utility. */
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip: rect(0,0,0,0);
+ white-space: nowrap;
+ border: 0;
+}
+
+/* Homepage card decorative icon container. */
+.card-icon {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 36px;
+ height: 36px;
+ border-radius: 10px;
+ background: var(--primary-soft);
+ color: var(--primary-light);
+ margin-bottom: 12px;
+}
+.card-icon svg { width: 20px; height: 20px; }
+
+/* ===========================================================================
+ Utilities added to satisfy component markup contract (post-de-inline pass)
+ =========================================================================== */
+
+/* Small variant of .btn, used for compact CTAs. */
+.btn-sm {
+ min-height: 32px;
+ padding: 0 12px;
+ font-size: 13px;
+ font-weight: var(--fw-medium);
+}
+
+/* Header right-side action group (Examples / GitHub icon). */
+.nav-cluster {
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+}
+
+/* Sidebar section group + section label (uppercase eyebrow). */
+/* Sidebar group is a native for accessible collapse without JS.
+ The summary line is the group label; the items live in .sidebar-group-items. */
+.sidebar-group {
+ margin-bottom: 16px;
+}
+.sidebar-group:last-child { margin-bottom: 0; }
+.sidebar-group[open] { margin-bottom: 20px; }
+
+/* The summary IS the group label. Strip the default marker and lay out a caret. */
+.sidebar-group-label {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 8px;
+ padding: 8px 10px 6px;
+ font-size: 12px;
+ font-weight: var(--fw-semibold);
+ color: var(--text-muted);
+ text-transform: uppercase;
+ letter-spacing: 0.06em;
+ cursor: pointer;
+ user-select: none;
+ border-radius: 8px;
+ list-style: none;
+}
+.sidebar-group-label::-webkit-details-marker { display: none; }
+.sidebar-group-label::marker { content: ''; }
+.sidebar-group-label:hover { color: var(--text); background: rgba(255,255,255,.025); }
+
+/* Match the focus ring corner to the label's own 8px radius. */
+.sidebar-group-label:focus-visible { border-radius: 8px; }
+
+.sidebar-group-caret {
+ color: var(--text-soft);
+ transform: rotate(-90deg);
+ transition: transform 180ms ease-out, color 180ms ease-out;
+ flex: none;
+}
+.sidebar-group[open] > .sidebar-group-label .sidebar-group-caret {
+ transform: rotate(0deg);
+ color: var(--text-muted);
+}
+
+/* Items inside the group fade in when the group opens. Native toggles
+ block display synchronously; the opacity transition softens the appearance.
+ A faint vertical structure-line on the left of the items signals hierarchy. */
+.sidebar-group-items {
+ display: flex;
+ flex-direction: column;
+ gap: 2px;
+ padding-top: 4px;
+ padding-left: 12px;
+ margin-left: 14px;
+ border-left: 1px solid var(--border);
+ animation: sidebar-group-fade-in 180ms ease-out;
+}
+
+/* When a link inside an open group is active, brighten the structure-line
+ segment leading to it. Implemented as a global open-group line color bump. */
+.sidebar-group[open] > .sidebar-group-items {
+ border-left-color: var(--border-strong);
+}
+
+@keyframes sidebar-group-fade-in {
+ from { opacity: 0; transform: translateY(-2px); }
+ to { opacity: 1; transform: translateY(0); }
+}
+
+@media (prefers-reduced-motion: reduce) {
+ .sidebar-group-caret { transition: none; }
+ .sidebar-group-items { animation: none; }
+}
+
+/* Prev/Next pager at the bottom of every doc page. */
+.doc-pager {
+ display: flex;
+ justify-content: space-between;
+ align-items: stretch;
+ gap: 16px;
+ margin-top: 48px;
+ padding-top: 24px;
+ border-top: 1px solid var(--border);
+}
+
+.doc-pager a {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+ padding: 14px 18px;
+ border: 1px solid var(--border);
+ border-radius: var(--radius-sm);
+ color: var(--text-muted);
+ background: rgba(255,255,255,.02);
+ border-bottom: 1px solid var(--border);
+ transition: border-color 200ms ease-out, color 200ms ease-out, background 200ms ease-out;
+}
+
+.doc-pager a:hover {
+ color: var(--text);
+ border-color: var(--border-strong);
+ background: rgba(255,255,255,.04);
+}
+
+.doc-pager a > span:first-child {
+ font-size: 12px;
+ font-weight: var(--fw-semibold);
+ color: var(--text-soft);
+ text-transform: uppercase;
+ letter-spacing: 0.06em;
+}
+
+.doc-pager a > span:last-child {
+ font-size: 15px;
+ font-weight: var(--fw-bold);
+ color: var(--text);
+}
+
+.doc-pager-next { text-align: right; align-items: flex-end; }
+.doc-pager-prev { text-align: left; align-items: flex-start; }
+
+@media (max-width: 640px) {
+ .doc-pager { flex-direction: column; }
+}
+
+/* Site footer chrome. Prisma's apps/docs footer structure:
+ brand column on the left + 4-column link grid on the right, hairline,
+ then a copyright row. Source reference:
+ prisma-docs/packages/ui/src/components/footer.tsx + data/footer.ts. */
+.site-footer {
+ margin-top: 80px;
+ border-top: 1px solid var(--border);
+ background: rgba(0, 0, 0, 0.2);
+}
+
+.site-footer-inner {
+ max-width: var(--max);
+ margin: 0 auto;
+ padding: 56px 24px 32px;
+ color: var(--text-muted);
+ font-size: 14px;
+}
+
+/* Two-region top: brand on the left, link grid on the right.
+ Below 960px the brand stacks above the grid. */
+.site-footer-top {
+ display: grid;
+ grid-template-columns: minmax(0, 320px) 1fr;
+ gap: 48px;
+ align-items: start;
+}
+
+.site-footer-brand .brand {
+ font-family: var(--font-title);
+ font-weight: var(--fw-bold);
+ font-size: 18px;
+ color: var(--text);
+ letter-spacing: -0.01em;
+ display: inline-flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.site-footer-brand .mark {
+ width: 22px;
+ height: 22px;
+ border-radius: 6px;
+ background: linear-gradient(160deg, #FB6F9D 0%, var(--primary) 100%);
+ display: inline-block;
+}
+
+.site-footer-tagline {
+ margin: 16px 0 20px;
+ font-size: 14px;
+ line-height: 1.55;
+ color: var(--text-muted);
+ max-width: 32ch;
+}
+
+.site-footer-socials {
+ display: inline-flex;
+ align-items: center;
+ gap: 4px;
+ margin-left: -8px;
+}
+
+/* The 4-column link grid. Single row on >= 640px, 2x2 below. */
+.site-footer-grid {
+ display: grid;
+ grid-template-columns: repeat(4, minmax(0, 1fr));
+ gap: 32px;
+}
+
+.site-footer-col-title {
+ margin: 0 0 16px;
+ font-family: var(--font-title);
+ font-size: 11px;
+ font-weight: var(--fw-semibold);
+ letter-spacing: 0.08em;
+ text-transform: uppercase;
+ color: var(--text);
+}
+
+.site-footer-col-list {
+ list-style: none;
+ margin: 0;
+ padding: 0;
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+}
+
+.site-footer-col-list a {
+ color: var(--text-muted);
+ font-size: 14px;
+ font-weight: var(--fw-medium);
+ text-decoration: none;
+ transition: color 160ms ease;
+ display: inline-flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.site-footer-col-list a:hover {
+ color: var(--text);
+}
+
+/* Tiny alpha-pill next to the Blackbox link. Same visual family as the
+ top-nav product-tab badge so the brand identity carries through. */
+.site-footer-badge {
+ display: inline-flex;
+ align-items: center;
+ padding: 2px 6px;
+ font-size: 9px;
+ font-weight: var(--fw-semibold);
+ letter-spacing: 0.06em;
+ text-transform: uppercase;
+ color: var(--primary-light);
+ background: var(--primary-soft);
+ border: 1px solid var(--primary-border);
+ border-radius: 999px;
+ line-height: 1;
+}
+
+.site-footer-divider {
+ height: 1px;
+ margin: 40px 0 20px;
+ background: var(--border);
+}
+
+.site-footer-bottom {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ justify-content: space-between;
+ gap: 12px;
+}
+
+.site-footer-meta {
+ margin: 0;
+ font-size: 13px;
+ color: var(--text-soft);
+}
+
+.site-footer-link--inline {
+ color: var(--text-muted);
+ text-decoration: underline;
+ text-decoration-color: var(--border-strong);
+ text-underline-offset: 3px;
+ transition: color 160ms ease, text-decoration-color 160ms ease;
+}
+
+.site-footer-link--inline:hover {
+ color: var(--primary-light);
+ text-decoration-color: var(--primary-border);
+}
+
+@media (max-width: 960px) {
+ .site-footer-top {
+ grid-template-columns: 1fr;
+ gap: 40px;
+ }
+}
+
+@media (max-width: 640px) {
+ .site-footer-inner {
+ padding: 40px 16px 28px;
+ }
+ .site-footer-grid {
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 28px;
+ }
+}
+
+/* Mobile touch target floor (ui-ux-pro-max touch-target-size, 44x44 minimum).
+ Per audit section E + Top-12 fix 6. Sidebar already overrides at 767px
+ (see .sidebar a above); matching breakpoint here for consistency. */
+@media (max-width: 767px) {
+ .btn-sm {
+ min-height: 44px;
+ padding: 0 14px;
+ }
+ .tab {
+ min-height: 44px;
+ padding: 10px 16px;
+ }
+ .icon-link {
+ width: 44px;
+ height: 44px;
+ }
+
+ /* Marketing header collapses links + dropdowns into the mobile drawer
+ toggle. The drawer panel is fixed under the topbar and scrolls. */
+ .marketing-navlinks {
+ display: none;
+ }
+ .marketing-mobile-menu {
+ display: inline-flex;
+ }
+ .marketing-mobile-menu[open] .marketing-mobile-panel {
+ display: block;
+ position: fixed;
+ top: var(--header-h);
+ right: 0;
+ left: 0;
+ z-index: var(--z-overlay);
+ max-height: calc(100dvh - var(--header-h));
+ overflow: auto;
+ padding: 16px 20px 24px;
+ background: var(--bg);
+ border-bottom: 1px solid var(--border);
+ box-shadow: var(--shadow);
+ }
+}
+
+/* ==========================================================================
+ UI/UX hardening pass (2026-06-14)
+ Six parallel opus agents reviewed cohesive component groups with the
+ ui-ux-pro-max skill. Deltas appended below so the CSS cascade naturally
+ overrides earlier definitions (last-wins). Originating scratch files:
+ .scratch/ui-ux/{site-chrome,docs-chrome,ui-primitives,mdx,islands}.css
+ ========================================================================== */
+
+/* === site-chrome === */
+/* Site chrome polish: focus rings, hover transitions, mobile touch targets,
+ footer link affordances. All changes reuse existing tokens. */
+
+/* APPEND-TO: .brand (components.css L96) */
+/* Add an explicit focus-visible radius so the global 2px outline wraps
+ cleanly around the inline-flex brand bounding box instead of clipping
+ into the mark and product slug. */
+.brand {
+ border-radius: 10px;
+}
+
+/* NEW */
+/* Match the focus ring radius to the brand's own corner so the ring
+ visually hugs the element on keyboard focus. */
+.brand:focus-visible {
+ outline-offset: 4px;
+}
+
+/* REPLACES: components.css L1123-L1131 */
+/* Icon-only header action (GitHub). Adds smooth hover transition for
+ color and background per ui-ux-pro-max duration-timing rule (200ms).
+ Global @media (prefers-reduced-motion: reduce) zeroes this transition. */
+.icon-link {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 36px;
+ height: 36px;
+ color: var(--text-muted);
+ border-radius: 8px;
+ transition: color 200ms ease, background-color 200ms ease;
+}
+
+/* APPEND-TO: .nav-action (components.css L1148) */
+/* Smooth hover transition for the Examples text action. */
+.nav-action {
+ border-radius: 6px;
+ transition: color 200ms ease;
+}
+
+/* APPEND-TO: .nav-tabs a (components.css L57) */
+/* Smooth color + underline transition when switching active product tab. */
+.nav-tabs a {
+ transition: color 200ms ease, border-bottom-color 200ms ease;
+}
+
+/* APPEND-TO: .navlinks a (implicit, components.css L131) */
+/* Smooth fade between muted and primary text colors on navlink hover. */
+.navlinks a {
+ transition: color 200ms ease;
+}
+
+/* NEW */
+/* Mobile touch target floor for header text actions and product tabs.
+ ui-ux-pro-max touch-target-size requires minimum 44x44px. The existing
+ 767px breakpoint at the bottom of components.css already handles
+ .btn-sm, .tab, and .icon-link. Extending coverage to .nav-action and
+ .nav-tabs a so every header touch target meets the floor. */
+@media (max-width: 767px) {
+ .nav-action {
+ min-height: 44px;
+ display: inline-flex;
+ align-items: center;
+ padding: 8px 10px;
+ }
+ .nav-tabs a {
+ min-height: 44px;
+ display: inline-flex;
+ align-items: center;
+ padding: 10px 0;
+ }
+}
+
+/* NEW */
+/* Footer link affordance. The Footer template renders
+ for the author name; without an explicit
+ rule it inherits the global link color (primary) and has no hover or
+ focus feedback. Mirror the navlinks pattern: muted at rest, full text
+ on hover, smooth color transition, rounded focus ring. */
+.site-footer-link {
+ color: var(--text);
+ text-decoration: underline;
+ text-decoration-color: var(--border-strong);
+ text-underline-offset: 3px;
+ border-radius: 4px;
+ transition: color 200ms ease, text-decoration-color 200ms ease;
+}
+.site-footer-link:hover {
+ color: var(--primary-light);
+ text-decoration-color: var(--primary-border);
+}
+
+/* NEW */
+/* The Footer icon-link sits in a flex row alongside two tags. The
+ site-footer-inner uses space-between, so the GitHub anchor naturally
+ anchors left. On focus, give it a slightly larger offset so the ring
+ does not collide with the surrounding text baseline. */
+.site-footer .icon-link:focus-visible {
+ outline-offset: 3px;
+}
+
+
+/* === docs-chrome === */
+/* Audit and fixes for sidebar, TOC, and prev/next pager.
+ Pairs with edits to:
+ src/components/docs/Sidebar.astro (wraps groups in