From aeaed584abeedc89b3dcf9878456af1ccf1ca84d Mon Sep 17 00:00:00 2001 From: Mike Long Date: Thu, 12 Mar 2026 16:41:23 -0700 Subject: [PATCH] docs: canonicalize generator and validation docs --- API.md | 10 ++ README.md | 13 +++ docs/ai-generator-adapter-api.md | 130 ++++++++++++++++++++++++ docs/ai-generator-adapter-quickstart.md | 68 +++++++++++++ docs/ai-tool-playbooks.md | 75 ++++++++++++++ docs/contract-validation.md | 91 +++++++++++++++++ docs/generation-boundaries.md | 5 + docs/generator-consumption.md | 94 +++++++++++++++++ docs/shell-boundary.md | 52 ++++++++++ 9 files changed, 538 insertions(+) create mode 100644 docs/ai-generator-adapter-api.md create mode 100644 docs/ai-generator-adapter-quickstart.md create mode 100644 docs/ai-tool-playbooks.md create mode 100644 docs/contract-validation.md create mode 100644 docs/generator-consumption.md create mode 100644 docs/shell-boundary.md diff --git a/API.md b/API.md index e86f301..776b75f 100644 --- a/API.md +++ b/API.md @@ -10,6 +10,16 @@ In an interactive terminal, running bare `interfacectl` with no arguments opens `interfacectl validate` is the canonical command for contract compliance. Use it to gate changes before merge or deployment. For deterministic, category-based exit codes, use `--exit-codes v2` or set `INTERFACECTL_EXIT_CODES=v2`. The command `enforce --mode fail` runs a structural diff and applies a policy threshold. It is optional and useful when you want to block on diff severity separately from compliance. For the minimal contract format and where contract semantics live in the repo, see [docs/contract-baseline.md](docs/contract-baseline.md). For optional generator-facing authoring metadata, see [docs/authoring-contracts.md](docs/authoring-contracts.md). +Canonical docs for adjacent validation and generation workflows: + +- [docs/contract-validation.md](docs/contract-validation.md) +- [docs/runtime-edge.md](docs/runtime-edge.md) +- [docs/ai-generator-adapter-quickstart.md](docs/ai-generator-adapter-quickstart.md) +- [docs/ai-generator-adapter-api.md](docs/ai-generator-adapter-api.md) +- [docs/ai-tool-playbooks.md](docs/ai-tool-playbooks.md) +- [docs/generator-consumption.md](docs/generator-consumption.md) +- [docs/shell-boundary.md](docs/shell-boundary.md) + ## Commands ### `init` diff --git a/README.md b/README.md index 86a3422..fb90ae2 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,19 @@ interfacectl init --url https://app.example.com --surface customer-app --auth-pr `interfacectl` replays the saved browser session in Chromium, analyzes the rendered authenticated page, and keeps auth state out of generated artifacts. +## Canonical docs + +Reusable platform semantics live in `interfacectl`: + +- [API reference](API.md) +- [Contract validation reference](docs/contract-validation.md) +- [Runtime (edge) enforcement guide](docs/runtime-edge.md) +- [AI Generator Adapter Quick Start](docs/ai-generator-adapter-quickstart.md) +- [AI Generator Adapter API](docs/ai-generator-adapter-api.md) +- [AI Tool Playbooks](docs/ai-tool-playbooks.md) +- [Generator-Aware Contract Consumption](docs/generator-consumption.md) +- [Shell Boundary Semantics](docs/shell-boundary.md) + ## Commands Overview The CLI provides two first-run commands, browser-session auth helpers, and the validation and enforcement commands: diff --git a/docs/ai-generator-adapter-api.md b/docs/ai-generator-adapter-api.md new file mode 100644 index 0000000..ac677ae --- /dev/null +++ b/docs/ai-generator-adapter-api.md @@ -0,0 +1,130 @@ +# AI Generator Adapter API + +This page defines the canonical request/response semantics for generator adapters built around `interfacectl` validation. + +Consumer repos may materialize this contract as JSON Schema, typed interfaces, CLI wrappers, or HTTP endpoints, but they should not change the meaning of the fields or the `pass|warn|block` verdict model. + +## Request contract + +```json +{ + "requestId": "uuid", + "tool": "codex|cursor|lovable|figma-make", + "surfaceId": "reference-target-web", + "mode": "workspace|descriptor", + "workspaceRoot": "/absolute/path/optional", + "descriptor": [ + { + "surfaceId": "reference-target-web", + "primitives": [], + "colors": [], + "icons": [{ "value": "@heroicons/react/24/outline", "source": "generated.tsx" }] + } + ], + "contractPath": "/absolute/path/optional", + "provenance": { + "sessionId": "string", + "userId": "string", + "timestamp": "ISO-8601" + } +} +``` + +Field notes: + +- `requestId` is caller-supplied when available and otherwise may be generated by the consumer. +- `tool` identifies the caller for provenance and debugging; it does not change policy meaning. +- `surfaceId` selects the governed surface within the target contract. +- `mode=workspace` requires `workspaceRoot`. +- `mode=descriptor` requires `descriptor`. +- `contractPath` is an optional consumer override for contract resolution. +- `provenance` is optional but recommended for auditability. + +Descriptor entries commonly include: + +- `primitives`: emitted shell/surface roles with counts and sources +- `colors`: observed generated color values and sources +- `icons`: observed icon import sources and sources +- additional additive fields supplied by the consumer's extraction pipeline + +## Response contract + +```json +{ + "requestId": "uuid", + "status": "pass|warn|block", + "surfaceId": "reference-target-web", + "contract": { + "id": "surfaces.web", + "version": "0.1.0" + }, + "coverage": { + "generationGuard": true, + "fullValidate": true, + "shellBoundaryEvaluated": true, + "colorPolicyEvaluated": true, + "iconPolicyEvaluated": true + }, + "findings": [ + { + "code": "color.disallowed|icon.source-disallowed|shell-owned-primitive-emitted|...", + "severity": "error|warning", + "policy": "strict|warn|off", + "message": "human-readable", + "location": { + "file": "path", + "line": 0 + }, + "evidence": {} + } + ], + "timings": { + "totalMs": 0 + }, + "provenance": { + "sessionId": "string", + "userId": "string", + "timestamp": "ISO-8601", + "evaluatedAt": "ISO-8601" + } +} +``` + +Field notes: + +- `status` is the canonical verdict. +- `coverage.generationGuard` is `true` when generation-time guard checks ran. +- `coverage.fullValidate` is `true` only when a full validation pass ran. +- Category-specific coverage flags state whether that policy area was actually evaluated for this request. +- `findings` carry the structured remediation payload that tools should feed back into generation. +- `timings` and `provenance` are additive operational metadata. + +## Status semantics + +- `block`: at least one strict/error finding exists. +- `warn`: findings exist, but none are blocking. +- `pass`: no findings exist. + +Consumers must preserve these semantics even if they map the result onto repo-local HTTP status codes, CLI exit codes, or in-product publish gates. + +## Transport guidance + +This contract is transport-agnostic. + +- CLI wrappers may emit JSON and map `block` to a non-zero exit code. +- HTTP wrappers may map `block` to `422` or another non-success status. +- Editor or MCP wrappers may return the payload directly. + +Transport choices are local. Verdict and finding meaning are canonical. + +## Versioning policy + +- Additive fields are backward compatible. +- Breaking request/response changes require coordinated updates across canonical docs and consumer wrappers. +- Consumers may add transport metadata, but they should not rename or reinterpret the canonical verdict fields. + +## Related docs + +- [AI Generator Adapter Quick Start](./ai-generator-adapter-quickstart.md) +- [AI Tool Playbooks](./ai-tool-playbooks.md) +- [Generator-Aware Contract Consumption](./generator-consumption.md) diff --git a/docs/ai-generator-adapter-quickstart.md b/docs/ai-generator-adapter-quickstart.md new file mode 100644 index 0000000..3803bff --- /dev/null +++ b/docs/ai-generator-adapter-quickstart.md @@ -0,0 +1,68 @@ +# AI Generator Adapter Quick Start + +Use this flow when a generator authors or modifies UI and you want immediate contract feedback at `Generation time`. + +## Purpose + +The generator adapter loop gives tools a stable verdict contract: + +- `pass` +- `warn` +- `block` + +The adapter is not a separate policy system. It translates generator output into the same contract-aware feedback loop that `interfacectl validate` uses for authoritative compliance checks. + +## Integration flow + +1. Load the target contract and surface id. +2. Choose execution mode: + - `descriptor` for hosted builders or tools without a full checkout + - `workspace` for local agents or CI jobs with a checkout +3. Convert generated output into a descriptor or point the adapter at the workspace. +4. Run generation guard checks so shell-boundary violations and other generation-time findings surface immediately. +5. In `workspace` mode, run full `interfacectl validate` and treat that result as the authoritative promotion gate. +6. Feed structured findings back into the generator and regenerate until the result is `pass` or an accepted `warn`. + +## Mode guidance + +### `descriptor` + +Use `descriptor` mode for tools such as Lovable, Figma Make, or other hosted builders that do not operate inside a repo checkout. + +- Always evaluate shell-boundary signals. +- Evaluate any additional parity checks that the consumer repo enables for descriptor-mode rollout. +- Never treat descriptor-only success as the final shipping gate. + +### `workspace` + +Use `workspace` mode for tools such as Codex, Cursor, Claude Code, or any local generator that can inspect the real repo state. + +- Run generation guard checks first for fast feedback. +- Run full `interfacectl validate` before promotion or merge. +- Prefer deterministic exit-code modes in CI so generated changes can be blocked cleanly. + +## Adapter outputs + +Every adapter wrapper should return: + +- `requestId` +- `status` +- `findings` +- `coverage` +- `contract` metadata +- `timings` +- `provenance` + +See [AI Generator Adapter API](./ai-generator-adapter-api.md) for the canonical request/response contract. + +## Consumer wiring + +Consumer repos may expose the adapter through wrapper commands, HTTP endpoints, editor tasks, or MCP tools. Those entrypoints are repo-local concerns. They should preserve the canonical verdict semantics documented here and in the adapter API. + +## Related docs + +- [AI Generator Adapter API](./ai-generator-adapter-api.md) +- [AI Tool Playbooks](./ai-tool-playbooks.md) +- [Generator-Aware Contract Consumption](./generator-consumption.md) +- [Shell Boundary Semantics](./shell-boundary.md) +- [Generation Boundaries Guide](./generation-boundaries.md) diff --git a/docs/ai-tool-playbooks.md b/docs/ai-tool-playbooks.md new file mode 100644 index 0000000..6577d79 --- /dev/null +++ b/docs/ai-tool-playbooks.md @@ -0,0 +1,75 @@ +# AI Tool Playbooks + +This page shows how generators should use the same contract and verdict loop across local agents, IDE coders, hosted builders, and template engines. + +## Shared model + +All tools should follow the same pattern: + +1. Load the target contract and surface id before generation. +2. Constrain generation with the contract instead of treating validation as a post-hoc lint step. +3. Validate generated output through an adapter or a workspace validation flow. +4. Feed structured findings back into the generator context and regenerate when needed. +5. Keep `interfacectl validate` as the final CI/CD gate. + +The transport can change. The contract semantics do not. + +## Agentic coders + +Examples: Codex, Cursor, Claude Code, repo-local codegen workflows. + +Recommended flow: + +1. Read the contract and identify the target surface. +2. Generate directly in the repo or a checked-out workspace. +3. Run `workspace` mode or `interfacectl validate`. +4. Treat `block` as a hard stop. +5. Feed findings back into the next generation attempt. + +These tools benefit most from the full workspace path because they can validate against the actual repo state before code lands. + +## Hosted builders + +Examples: Lovable, Figma Make, or other tools that produce UI outside the repo. + +Recommended flow: + +1. Map generated output into a descriptor. +2. Submit the descriptor to an adapter wrapper. +3. Surface the returned findings in-product. +4. Gate export or publish on `block` whenever the host allows it. +5. Keep a CI fallback that runs workspace validation before merge or deploy. + +Hosted tools usually start with `descriptor` mode and rely on a later workspace gate for authoritative promotion. + +## Template engines and scaffolds + +Examples: internal generators, boilerplate scaffolds, CMS-to-code exporters. + +Recommended flow: + +1. Use the contract as an input spec for allowed structure, layout, color, icon, motion, and shell boundary rules. +2. Emit provenance in generated output. +3. Produce descriptors or run workspace validation as part of generation. +4. Fail the generation job when a blocking finding is returned. + +## What can vary by tool + +- how the contract is injected into prompts or generation config +- whether the tool uses `descriptor` or `workspace` mode first +- how findings are surfaced back to the user +- whether publish/export can be blocked in-product or only in CI + +## What must stay stable + +- contract semantics +- shell-boundary meaning +- `pass|warn|block` verdict meaning +- the use of CI/CD validation as the final shipping gate + +## Related docs + +- [AI Generator Adapter Quick Start](./ai-generator-adapter-quickstart.md) +- [AI Generator Adapter API](./ai-generator-adapter-api.md) +- [Generator-Aware Contract Consumption](./generator-consumption.md) +- [Shell Boundary Semantics](./shell-boundary.md) diff --git a/docs/contract-validation.md b/docs/contract-validation.md new file mode 100644 index 0000000..beff404 --- /dev/null +++ b/docs/contract-validation.md @@ -0,0 +1,91 @@ +# Contract Validation Reference + +This page defines the canonical validation semantics around `interfacectl validate` and related contract-compliance commands. + +Consumer repos may add wrapper commands, default contract paths, CI artifact locations, or adapter transports. Those are local concerns. Validation meaning stays here. + +## Canonical validation commands + +### `interfacectl validate` + +Use `validate` as the authoritative contract-compliance gate for checked-out code. + +`validate`: + +- loads the contract and bundled schema +- collects static descriptors from the workspace +- evaluates compliance for structure, sections, layout, fonts, colors, icons, and motion +- returns structured findings and an exit code + +Use `--format json --out ` when you want a machine-readable artifact for CI or downstream tooling. + +### `interfacectl validate-extracted` + +Use `validate-extracted` when you need to compare declared policy in the contract with extracted Phase 0 reality from a generated report or extraction artifact. + +This is a focused expert command. It complements `validate`; it does not replace it. + +### `interfacectl enforce --mode fail` + +Use `enforce --mode fail` only when you want an additional policy threshold on top of diff severity. + +It is not the canonical compliance command. The canonical compliance command is still `validate`. + +## Exit-code guidance + +For deterministic automation, prefer `--exit-codes v2`. + +- `0`: validation succeeded +- `10`: artifact/config/schema/internal failure +- `20`: token-policy violation +- `30`: interface-contract violation + +Legacy `v1` exit codes remain available for compatibility, but new CI and generator flows should prefer `v2`. + +## Validation at different lifecycle points + +### `Generation time` + +Generators and adapter wrappers may provide earlier feedback loops, but they are still downstream of the same contract semantics. + +- `descriptor` mode is useful for hosted tools or partial outputs. +- `workspace` mode is useful for local agents and CI checks. +- only a full workspace `validate` pass is the authoritative promotion gate for checked-out code + +### `CI/CD time` + +CI should run `validate` directly or run a wrapper that ends in `validate`. + +Use JSON output for uploaded artifacts, dashboards, or audit trails. The artifact path itself is consumer-local. + +### `Runtime (edge)` + +Runtime consumers should read compiled or derived policy artifacts. They do not redefine validation semantics. See [Runtime (Edge) Enforcement Guide](./runtime-edge.md). + +## Output semantics + +Structured validation output should preserve: + +- contract identity and version +- surface identity +- findings with stable codes, severity, and evidence +- enough metadata for downstream tooling to explain or audit the decision + +Transport details such as HTTP status codes, repo-local file names, or dashboard field names are consumer-local and should not reinterpret the meaning of findings or exit codes. + +## Repo-local concerns that stay outside this doc + +These belong in consumer repos, not here: + +- wrapper commands such as `pnpm validate:*` +- default contract file locations +- CI artifact upload paths +- published quick-start pages +- generator-host-specific rollout switches + +## Related docs + +- [API reference](../API.md) +- [Contract baseline](./contract-baseline.md) +- [Runtime (Edge) Enforcement Guide](./runtime-edge.md) +- [AI Generator Adapter Quick Start](./ai-generator-adapter-quickstart.md) diff --git a/docs/generation-boundaries.md b/docs/generation-boundaries.md index f64e273..a2a4d39 100644 --- a/docs/generation-boundaries.md +++ b/docs/generation-boundaries.md @@ -46,3 +46,8 @@ Goal: prevent generators from emitting shell-owned primitives (e.g., navigation) ## Notes - If both `mustNotEmit` and `shell.owns` are absent, the checker is a no-op for that surface. - Role naming: use the canonical role string `navigation` for nav bars; if you introduce aliases, normalize them before writing the descriptor. + +## Related docs +- [Shell Boundary Semantics](./shell-boundary.md) +- [AI Generator Adapter Quick Start](./ai-generator-adapter-quickstart.md) +- [Generator-Aware Contract Consumption](./generator-consumption.md) diff --git a/docs/generator-consumption.md b/docs/generator-consumption.md new file mode 100644 index 0000000..f9af6c5 --- /dev/null +++ b/docs/generator-consumption.md @@ -0,0 +1,94 @@ +# Generator-Aware Contract Consumption + +This document defines how generators should consume interface contracts to improve generation accuracy before code lands and to correct output when it drifts. + +## Use the contract twice + +Generators should use the contract in two loops: + +1. **Before generation** to constrain structure, layout, tokens, and boundaries. +2. **After generation** to evaluate the produced output and feed structured findings back into the next attempt. + +Using only the second loop turns the contract into a post-hoc blocker. Using both loops makes it an authoring aid. + +## Contract fields that matter at generation time + +### Boundary and ownership + +- `shell.owns` +- `shell.contentSlot` +- `surface.mustNotEmit` + +These fields define what the generator must leave to the shell and where the surface-owned content is allowed to live. + +### Structure and composition + +- `sections[*].id` +- `sections[*].intent` +- `surfaces[*].requiredSections` +- `surfaces[*].layout.landingPattern` +- `surfaces[*].flows` + +These fields tell the generator which sections must exist, what order or grouping rules apply, and which flows or steps are required. + +### Layout constraints + +- `surfaces[*].layout.maxContentWidth` +- `surfaces[*].layout.requiredContainers` +- `surfaces[*].layout.pageFrame` +- `surfaces[*].layout.chromePolicy` +- `marketingProfiles.layout` + +These fields constrain page width, container shape, frame rules, and shared marketing layout expectations. + +### Visual system constraints + +- `color.policy` +- `color.allowedValues` +- `surfaces[*].icons.policy` +- `surfaces[*].icons.allowedSources` +- `constraints.motion.allowedDurationsMs` +- `constraints.motion.allowedTimingFunctions` +- `marketingProfiles.typography` +- `surfaces[*].marketingTypographyProfile` +- `surfaces[*].marketingTypographyPolicy` + +These fields constrain the palette, icon sources, motion behavior, and shared typography/layout profiles. + +## Generator workflow + +1. Load the contract and narrow to the target surface. +2. Convert contract fields into prompt instructions, generation config, or locked UI regions. +3. Generate only inside the surface-owned boundary. +4. Emit provenance such as `surfaceId`, `contractId`, and `contract version`. +5. Convert the result into a descriptor or validate directly against the workspace. +6. Feed structured findings back into the next generation attempt. + +## Findings are generation input + +Generators should not treat findings as human-only diagnostics. + +- `shell-owned-primitive-emitted` means the next attempt must stay inside the surface boundary. +- `color.disallowed` means the next attempt must restrict itself to the allowlist. +- `icon.source-disallowed` means the next attempt must pick an allowed icon library. +- layout, landing-pattern, typography, and flow findings should be translated into concrete repair instructions for the next attempt. + +## Provenance expectations + +Generated output should carry enough provenance for later inspection: + +- `surfaceId` +- `contractId` +- `contract version` + +Embedding patterns vary by consumer, but the goal is consistent traceability from generated output back to the contract that shaped it. + +## Limits of the current contract + +The current contract is strongest at correctness constraints and boundary enforcement. Consumer repos may add richer authoring metadata for higher-fidelity first-pass generation, but generators should treat the canonical contract fields above as the minimum interoperable source of truth. + +## Related docs + +- [AI Generator Adapter Quick Start](./ai-generator-adapter-quickstart.md) +- [AI Generator Adapter API](./ai-generator-adapter-api.md) +- [Shell Boundary Semantics](./shell-boundary.md) diff --git a/docs/shell-boundary.md b/docs/shell-boundary.md new file mode 100644 index 0000000..38b7ff8 --- /dev/null +++ b/docs/shell-boundary.md @@ -0,0 +1,52 @@ +# Shell Boundary Semantics + +This page defines the generator-facing shell ownership rules that prevent surface code from emitting shell-owned primitives. + +The normative checker behavior remains in [Generation Boundaries Guide](./generation-boundaries.md). This page explains how generators should consume the same semantics. + +## Canonical signals + +- `contract.shell.owns`: global shell-owned primitives +- `surface.mustNotEmit`: per-surface override for banned primitives +- `shell.contentSlot`: the place where surface-owned content is expected to mount +- descriptor `primitives`: emitted roles, counts, and sources for generated output + +If `surface.mustNotEmit` is missing, generators should fall back to `contract.shell.owns`. + +## Required generator behavior + +1. Load the contract. +2. Compute `banList = surface.mustNotEmit || contract.shell?.owns || []`. +3. Generate only inside the surface-owned content slot or boundary. +4. Convert generated output into descriptor primitives. +5. Fail fast with `shell-owned-primitive-emitted` if any banned primitive is emitted. + +## Tool patterns + +### Figma Make and other frame-based builders + +- lock or reserve shell-owned frames +- expose only the content slot for generation +- emit descriptor primitives for anything the builder still creates + +### Agentic coders and template engines + +- ban shell-owned imports or components from generated output +- keep shell/layout files out of the writable scope for the surface change +- run generation guard checks before code is committed or promoted + +### Hosted descriptor-first tools + +- normalize generated output into descriptor primitives +- treat shell-boundary findings as hard generation-time stops +- keep a workspace validation fallback in CI/CD + +## Why this matters + +The shell boundary is the earliest reliable place to prevent duplicate navigation, duplicate auth wrappers, and other chrome re-emission failures. Generators should use it as a generation-time constraint, not only as a later validation failure. + +## Related docs + +- [Generation Boundaries Guide](./generation-boundaries.md) +- [AI Generator Adapter Quick Start](./ai-generator-adapter-quickstart.md) +- [Generator-Aware Contract Consumption](./generator-consumption.md)