interfacectl is a command-line tool for managing interface contracts in the Surfaces ecosystem. It validates, compares, compiles, and enforces compliance between defined interface contracts and observed implementation artifacts across multiple surfaces.
In an interactive terminal, running bare interfacectl with no arguments opens the first-run onboarding screen. In non-interactive contexts, bare interfacectl keeps the existing help output and exit behavior so scripts and CI remain stable.
interfacectl validate is the canonical command for contract compliance. Use it to gate changes before merge or deployment. The same command can validate checked-out code only, or augment that result with browser observation through --remote-url for live target-acquisition, flow, and feedback-recovery checks. 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. For optional generator-facing authoring metadata, see docs/authoring-contracts.md.
Canonical docs for adjacent validation and generation workflows:
- docs/contract-validation.md
- docs/runtime-edge.md
- docs/ai-generator-adapter-quickstart.md
- docs/ai-generator-adapter-api.md
- docs/ai-tool-playbooks.md
- docs/generator-consumption.md
- docs/shell-boundary.md
First-run onboarding for web surfaces.
Synopsis:
interfacectl init [options]Description:
init is the primary user-facing entry point for Surfaces onboarding on web surfaces. It:
- analyzes either a local app root (
--app-root) or a live URL (--url) - classifies the surface as
marketing,application, orunknownusing platform-owned heuristics - extracts UI-system attributes across typography, color, layout, motion, icons, shell/auth primitives, sections, and copy-role signals
- decides whether to adopt an existing design system or synthesize a first draft from repeated norms
- writes four artifacts under
contracts/generated/ - validates preview artifacts before write and, in interactive mode, asks for confirmation before writing anything
Options:
| Option | Description | Default |
|---|---|---|
--url <url> |
Surface URL for remote onboarding | none |
--app-root <path> |
Local app root for source-backed onboarding | none |
--extract-mode <remote-url|local-root> |
Source mode override | inferred from inputs |
--surface <id> |
Surface identifier override | inferred from URL/path |
--surface-name <name> |
Surface display name override | derived from surface id |
--surface-kind <marketing|application|unknown> |
Confirm low-confidence classification in non-interactive flows | inferred |
--auth-profile <name> |
Replay a saved browser-session auth profile for protected remote onboarding | none |
--non-interactive |
Disable prompts | false |
--continue-on-gate |
Allow provisional output when remote onboarding resolves to a login or access-denied page | false |
--out-dir <path> |
Output directory for generated artifacts | contracts/generated |
--analysis-out <path> |
Explicit output path for <surface>.analysis.json |
derived from --out-dir |
--draft-out <path> |
Explicit output path for <surface>.design-system.draft.json |
derived from --out-dir |
--contract-out <path> |
Explicit output path for <surface>.contract.json |
derived from --out-dir |
--report-out <path> |
Explicit output path for <surface>.extraction.json |
derived from --out-dir |
Artifacts:
contracts/generated/<surface>.analysis.jsoncontracts/generated/<surface>.design-system.draft.jsoncontracts/generated/<surface>.contract.jsoncontracts/generated/<surface>.extraction.json
Notes:
- First-run output is warn-first. Findings are surfaced in the summary rather than blocking the onboarding command unless artifact generation or validation infrastructure fails.
- If surface-kind inference is low confidence, interactive mode asks for confirmation. Non-interactive mode must pass
--surface-kind. - For protected remote URLs,
--auth-profilemust point at a replay-ready profile. Interactiveinitcan capture one; non-interactive mode fails fast if the profile is missing, expired, legacy, or not replayable. - If a remote URL resolves to a login or access-denied page, interactive mode stops and offers next actions before any artifacts are written. Non-interactive mode must pass
--continue-on-gateto accept provisional output. - First-party or dogfood surfaces are not used as baselines for inference or starter recommendations.
Machine-readable first-run analysis for web surfaces.
Synopsis:
interfacectl analyze [options]Description:
analyze uses the same first-run analysis engine as init but writes only the analysis artifact. It is intended for power users and CI preparation when you want explainable classification and extraction evidence without generating the draft contract/draft-system artifacts.
Options:
| Option | Description | Default |
|---|---|---|
--url <url> |
Surface URL for remote analysis | none |
--app-root <path> |
Local app root for source-backed analysis | none |
--extract-mode <remote-url|local-root> |
Source mode override | inferred from inputs |
--surface <id> |
Surface identifier override | inferred from URL/path |
--surface-name <name> |
Surface display name override | derived from surface id |
--surface-kind <marketing|application|unknown> |
Optional classification confirmation override | inferred |
--auth-profile <name> |
Replay a saved browser-session auth profile for protected remote analysis | none |
--out <path> |
Output file path for the analysis artifact | contracts/generated/<surface>.analysis.json |
--out-dir <path> |
Output directory when --out is not supplied |
contracts/generated |
Output:
contracts/generated/<surface>.analysis.json
Manage replayable browser-session auth profiles for protected remote onboarding.
Synopsis:
interfacectl auth <subcommand> [options]Subcommands:
Launches Chromium, opens a clean browser context, waits for manual sign-in, then stores the resulting Playwright storageState as a replayable auth profile.
interfacectl auth capture --profile <name> --url <exact-host-url> [--format text|json]| Option | Description | Default |
|---|---|---|
--profile <name> |
Profile name | required |
--url <url> |
URL on the exact host to capture | required |
--format <text|json> |
Output format | text |
Notes:
- Profiles are exact-host scoped in v1. If capture ends on a different hostname, the command fails and requires a capture on that host instead.
- Replay state is stored separately from metadata.
interfacectluses keychain-first storage with encrypted local-file fallback. - Generated onboarding artifacts and CLI JSON outputs never include cookies, storage entries, or tokens.
Lists locally stored auth profiles and their replay readiness.
interfacectl auth list [--format text|json]The output includes status, replayReady, capturedAt, expiresAt, and storage mode metadata.
Validates a local auth profile. Without --url, it checks replay readiness only. With --url, it performs a real replayed navigation using the same browser observer as remote onboarding.
interfacectl auth test --profile <name> [--domain <host>] [--url <protected-url>] [--format text|json]| Option | Description | Default |
|---|---|---|
--profile <name> |
Profile name | required |
--domain <domain> |
Optional exact-host scope override | inferred from --url when present |
--url <url> |
Protected URL to validate authenticated replay against | none |
--format <text|json> |
Output format | text |
Notes:
- If
--auth-profileis explicitly supplied toinitoranalyze, interfacectl does not silently fall back to anonymous access. - Legacy v1 profiles remain listable but are not replayable; they must be re-captured.
Deletes local auth profile metadata and any stored replay state.
interfacectl auth revoke --profile <name> --domain <host>
interfacectl auth clear --allIf Chromium is not installed locally, install it with:
pnpm --filter @surfaces/interfacectl-cli exec playwright install chromiumValidates configured surfaces against a shared interface contract.
Synopsis:
interfacectl validate [options]Description: Performs comprehensive validation of surface implementations against an interface contract. This includes:
- Contract structure validation against schema
- Surface descriptor collection from codebase
- Compliance checking for fonts, colors, icon sources, layout, motion, and sections
- Authored flow, interactive-target, and async feedback/recovery validation from workspace descriptors
- Optional browser observation via
--remote-urlfor live target metrics, flow markers, and async-state / recovery markers - Generation of structured validation reports
Options:
| Option | Description | Default |
|---|---|---|
--contract <path> |
Path to the contract JSON file | contracts/surfaces.web.contract.json or SURFACES_CONTRACT env var |
--schema <path> |
Optional path to the contract schema JSON file | Bundled schema |
--config <path> |
Path to interfacectl config JSON file | interfacectl.config.json |
--root <path> |
Project root directory | Current working directory or SURFACES_ROOT env var |
--workspace-root <path> |
Workspace root directory (alias for --root) |
Current working directory |
--surface <id...> |
Limit validation to specified surface identifiers | All surfaces |
--remote-url <url> |
Augment validation with browser-observed target, flow, and async-state metrics from the provided URL | none |
--format <text|json> |
Output format | text |
--json |
Emit JSON output (shortcut for --format json) |
false |
--out <path> |
Write output to file instead of stdout | stdout |
--exit-codes <v1|v2> |
Exit code version (default: v1, use v2 for new contract) | v1 |
Exit Codes:
v1 (legacy, default):
0: All surfaces comply with the contract1: Contract violations detected2: Configuration or contract loading error
v2 (new contract, opt-in via --exit-codes v2 or INTERFACECTL_EXIT_CODES=v2):
0: All surfaces comply with the contract10: E0 - Artifact invalid (config/contract load failures, schema parse errors, internal errors)20: E1 - Token policy violation (font/color/icon/motion not allowed)30: E2 - Interface contract violation (layout/section violations)
Note: v1 internal errors use exit code 2. v2 unifies all E0 conditions to exit code 10. Use --exit-codes v2 to opt into the new exit code contract. A deprecation warning is printed in v1 mode when violations occur.
Violation Types Detected:
surface.unknown: Surface ID not found in contractdescriptor.missing: Surface descriptor not found in codebasedescriptor.unused: Surface defined in contract but no descriptor founddescriptor.flows.missing: Contract-declared flow is not authored or discoverable in the checked-out surfacesection.missing: Required section missing from surfacesection.unexpected: Unknown section in surfacefont.disallowed: Font not allowed by contractcolor.disallowed: Color not allowed by contracticon.source-disallowed: Icon source library not allowed by contractlayout.width-exceeded: Layout width exceeds contract maximumlayout.width-undetermined: Layout width cannot be determinedlayout.container-missing: Required container missing from layoutmotion.duration: Motion duration not allowed by contractmotion.timing: Motion timing function not allowed by contracttarget.hit-area-too-small: Browser-observed control is smaller than the contract minimumtarget.gap-too-tight: Browser-observed controls are spaced too closelytarget.edge-inset-too-small: Browser-observed control sits too close to the viewport edgetarget.destructive-too-close: Browser-observed destructive control is too close to a non-destructive neighbortarget.unobservable: Runtime observation cannot deterministically measure the required control setflow.required.missing: Required flow wrapper is missingflow.steps.min: Observed flow does not meet the declared minimum step countflow.steps.required: Required flow step marker is missingflow.transition.required: Required flow transition marker is missingflow.terminal.invalid: Terminal step still exposes an outgoing transitionflow.unobservable: Runtime observation cannot see the declared flow markersfeedback.state-missing: Required async state is missing or unmarkedfeedback.recovery-action-missing: Required recovery affordance is missing from the observed async statefeedback.pending-action-not-blocked: Pending submit action remains interactive while work is in flightfeedback.last-good-content-missing: Required preserved content is missing from the failing async statefeedback.unobservable: Runtime observation cannot see the declared async-state markers
Output Format (JSON):
{
"contractPath": "string",
"contractVersion": "string | null",
"summary": {
"errors": "number",
"warnings": "number"
},
"findings": [
{
"code": "string",
"severity": "error | warning",
"category": "E0 | E1 | E2",
"surface": "string",
"message": "string",
"expected": "unknown",
"found": "unknown",
"location": "string"
}
]
}When --remote-url is supplied, the JSON shape is unchanged. The findings array may include browser-observed target.*, flow.*, and feedback.* codes alongside workspace-discovered findings.
Compares a contract against observed artifacts and generates a detailed diff.
Synopsis:
interfacectl diff [options]Description: Performs a structural comparison between the contract definition and observed surface descriptors. Generates a comprehensive diff showing additions, removals, modifications, and renames. Includes drift risk detection and normalization support.
Options:
| Option | Description | Default |
|---|---|---|
--contract <path> |
Path to the contract JSON file | contracts/surfaces.web.contract.json or SURFACES_CONTRACT env var |
--schema <path> |
Optional path to the contract schema JSON file | Bundled schema |
--config <path> |
Path to interfacectl config JSON file | interfacectl.config.json |
--root <path> |
Project root directory | Current working directory or SURFACES_ROOT env var |
--workspace-root <path> |
Workspace root directory (alias for --root) |
Current working directory |
--surface <id...> |
Limit diff to specified surface identifiers | All surfaces |
--format <text|json> |
Output format | text |
--json |
Emit JSON output (shortcut for --format json) |
false |
--out <path> |
Write output to file instead of stdout | stdout |
--no-normalize |
Disable normalization (for debugging) | Normalization enabled |
--rename-threshold <0-1> |
Rename detection threshold (0.0-1.0) | 0.8 |
--policy <path> |
Optional policy path (for policy metadata in output) | None |
--exit-codes <v1|v2> |
Exit code version (default: v1, use v2 for new contract) | v1 |
Exit Codes:
v1 (legacy, default):
0: No differences found1: Differences detected (any severity)2: Configuration or contract loading error3: Internal error (preserved from existing behavior)
v2 (new contract, opt-in via --exit-codes v2 or INTERFACECTL_EXIT_CODES=v2):
0: No differences found10: E0 - Artifact invalid (config/contract load failures, schema parse errors, internal errors)30: E2 - Blocking drift (error or warning entries detected)40: E3 - Non-blocking drift (all entries are info severity after policy overrides)
Note: E3 (non-blocking drift) only exists in v2 and requires policy-driven severity downgrades to info. v1 always exits 1 if any entries exist, regardless of severity. A deprecation warning is printed in v1 mode when diffs exist.
Diff Entry Types:
added: Path exists in observed but not in contractremoved: Path exists in contract but not in observedmodified: Path exists in both but values differrenamed: Path was renamed (detected via similarity threshold)
Severity Levels:
error: Critical violation requiring immediate attentionwarning: Non-critical issue that may indicate driftinfo: Informational difference
Includes traceability fields.
Drift Risks Detected:
diff-noise: Formatting-only or reorder-only changes filteredsemantic-ambiguity: Diff entries lack rule/clause referencesenforcement-overreach: Semantic changes attempted in autofixes (only mechanical changes allowed)policy-drift: Policy fingerprint validation failedcontract-evolution: Contract changes should be diffableobserved-instability: Observed descriptors fail validation before diffingrename-inflation: Excessive rename detection (threshold too low)output-schema-drift: Output schema version mismatchseverity-inflation: Policy has excessive error severity overrideslocal-ci-mismatch: Repro command missing from output
Output Format (JSON):
{
"schemaVersion": "1.0.0",
"tool": {
"name": "interfacectl",
"version": "string"
},
"policy": {
"version": "string",
"fingerprint": "string"
},
"contract": {
"path": "string",
"version": "string"
},
"observed": {
"root": "string"
},
"normalization": {
"enabled": "boolean",
"reorderedPaths": ["string"],
"strippedPaths": ["string"]
},
"summary": {
"totalChanges": "number",
"byType": {
"added": "number",
"removed": "number",
"modified": "number",
"renamed": "number"
},
"bySeverity": {
"error": "number",
"warning": "number",
"info": "number"
}
},
"entries": [
{
"path": "string",
"type": "added | removed | modified | renamed",
"severity": "error | warning | info",
"surfaceId": "string",
"contractValue": "unknown",
"observedValue": "unknown",
"rule": "string",
"stableId": "string",
"contractRef": { "path": "string", "surfaceId": "string", "sectionId": "string", "constraintId": "string" },
"ruleRef": { "id": "string", "version": "string" },
"rename": {
"fromPath": "string",
"toPath": "string",
"confidence": "number"
}
}
],
"driftRisks": [
{
"category": "string",
"severity": "error | warning | info",
"message": "string",
"relatedPaths": ["string"]
}
],
"repro": {
"command": "string"
}
}Enforces policy on interface contract using configurable enforcement modes.
Synopsis:
interfacectl enforce [options]Description: Applies enforcement policies to interface contracts through three modes:
- fail: Runs a structural diff and exits with an error code when differences exceed the policy threshold
- fix: Applies safe, mechanical fixes based on policy rules
- pr: Generates patches for review (unified diff or JSON patch format)
Options:
| Option | Description | Default |
|---|---|---|
--mode <fail|fix|pr> |
Enforcement mode | fail |
--strict |
Alias for --mode fail (strict enforcement) |
false |
--policy <path> |
Policy JSON path | Default policy |
--contract <path> |
Contract path | SURFACES_CONTRACT env var or default |
--root <path> |
Workspace root | SURFACES_ROOT env var or current directory |
--config <path> |
Config path | interfacectl.config.json |
--surface <id...> |
Filter surfaces | All surfaces |
--dry-run |
For fix mode, show what would change without applying | false |
--format <text|json> |
Output format | text |
--json |
Emit JSON output (shortcut for --format json) |
false |
--out <path> |
Output file path | stdout |
--exit-codes <v1|v2> |
Exit code version (default: v1, use v2 for new contract) | v1 |
Enforcement Modes:
-
fail (default):
- Runs a structural diff between the contract and observed descriptors
- Exits with an error code if differences exceed the policy threshold
- Does not modify files
- Suitable for CI when you want policy-based blocking on diff severity
-
fix:
- Automatically applies safe fixes matching autofix rules
- Only applies mechanical, non-semantic changes
- Respects safety levels and rule patterns
- Can run in
--dry-runmode to preview changes
Includes traceability fields.
- pr:
- Generates patch files for review
- Supports unified diff or JSON patch formats
- Does not modify files directly
- Suitable for automated PR generation
Exit Codes:
v1 (legacy, default):
0: Enforcement passed (no violations or fixes applied successfully)1: Violations remaining or enforcement failed2: Configuration or policy loading error
v2 (new contract, opt-in via --exit-codes v2 or INTERFACECTL_EXIT_CODES=v2):
0: Enforcement passed (no violations or fixes applied successfully)10: E0 - Artifact invalid (config/policy load failures, internal errors)30: E2 - Differences exceed policy threshold (does not distinguish E1 vs E2 for exit codes)
Note: enforce does not distinguish E1 (token policy) vs E2 (interface contract) violations for exit codes - both return 30 in v2. However, JSON findings still carry category: "E1" or category: "E2" so downstream tools can see what happened. A deprecation warning is printed in v1 mode when violations exist.
Output Format (JSON):
{
"schemaVersion": "1.0.0",
"mode": "fail | fix | pr",
"policy": {
"version": "string",
"fingerprint": "string"
},
"applied": [
{
"ruleId": "string",
"path": "string",
"oldValue": "unknown",
"newValue": "unknown",
"confidence": "number",
"stableId": "string",
"contractRef": { "path": "string", "surfaceId": "string", "sectionId": "string", "constraintId": "string" },
"ruleRef": { "id": "string", "version": "string" }
}
],
"skipped": [
{
"ruleId": "string",
"path": "string",
"oldValue": "unknown",
"newValue": "unknown",
"confidence": "number",
"stableId": "string",
"contractRef": { "path": "string", "surfaceId": "string", "sectionId": "string", "constraintId": "string" },
"ruleRef": { "id": "string", "version": "string" }
}
],
"errors": [
{
"ruleId": "string",
"path": "string",
"message": "string",
"stableId": "string",
"ruleRef": { "id": "string", "version": "string" }
}
]
}Produces a deterministic directory bundle from a contract for generation-time and runtime consumption. The bundle is readable, composable, and diffable. This is a build artifact, not an enforcement engine.
Synopsis:
interfacectl compile --contract <path> --out <dir> [--schema <path>] [--format json]Description:
- Loads and validates the contract structure using the same validator as
validate. - Writes a bundle directory at
--outwith stable key ordering and deterministic JSON. - Emits generation slices, runtime slices, and repair guidance keyed to canonical finding codes when the contract declares those capabilities.
- Writes files atomically (temp then rename) where possible to avoid partial bundles.
- Exits non-zero on invalid contract or write failure.
Options:
| Option | Description |
|---|---|
--contract <path> |
Path to the contract JSON file (required) |
--out <dir> |
Output directory for the bundle (required) |
--schema <path> |
Optional path to the contract schema JSON file |
--format <format> |
Output format (e.g. json) |
Exit Codes:
0: Bundle written successfully1: Invalid contract (schema validation failed), missing file, or write failure
Bundle structure
The output directory contains:
| Path | Description |
|---|---|
manifest.json |
Bundle manifest with version, contract id/version, tool info, inputs, and file hashes |
contract/normalized.json |
Normalized full contract kept for traceability and downstream validation |
surfaces/<surfaceId>/generation.json |
Surface entrypoint for generators and adapter consumers |
surfaces/<surfaceId>/sections.json |
Surface-local section slices and anatomy references |
surfaces/<surfaceId>/components.json |
Shared component catalog referenced by sections |
surfaces/<surfaceId>/constraints.json |
Cross-cutting contract-authoritative constraints for the surface |
surfaces/<surfaceId>/runtime.json |
Runtime-ready structure, contexts, policy severities, flow summaries, target-acquisition policy, and feedback-recovery policy |
surfaces/<surfaceId>/repair-map.json |
Deterministic repair actions keyed by canonical finding codes |
surfaces/<surfaceId>/authoring.json |
Optional authoring hints when the surface declares them |
Manifest fields
| Field | Description |
|---|---|
bundleVersion |
Format version for this bundle (e.g. "2.0") |
contractId |
From the contract |
contractVersion |
From the contract (version field) |
schemaVersion |
Schema bundle identifier used by the CLI (e.g. surfaces.web.contract@1) |
tool |
{ name: "interfacectl", version: "<version>" } |
inputs |
{ contractPath: string, schemaPath: string or null } |
files |
Array of { path, sha256 } for all bundle files except manifest.json, sorted lexicographically by path. Hashes are SHA-256 hex strings. |
No timestamps are included in the manifest so that bundles remain deterministic.
Resolves one compiled surface bundle into a single, agent-ready JSON payload for local workspace agents.
Synopsis:
interfacectl prepare-generation --bundle-root <dir> --surface <id> [--out <path>]Description:
- Loads a compiled generation bundle and validates that the requested surface exists.
- Resolves
generation.json,sections.json,components.json,constraints.json,repair-map.json, optionalauthoring.json, andcontract/normalized.json. - Emits one deterministic JSON document with summary text, checklist items, resolved generation guidance, sections, components, constraints, repairs, provenance, and source file paths.
- The resolved
repairMapmay include canonicalflow.*,target.*, andfeedback.*finding codes when the compiled contract declares those policy families. - Uses evidence refs only; it does not inline extracted observation payloads.
Options:
| Option | Description |
|---|---|
--bundle-root <dir> |
Path to the compiled generation bundle directory (required) |
--surface <id> |
Surface identifier to resolve from the bundle (required) |
--out <path> |
Optional output file path. When provided, the command writes the JSON payload to disk and suppresses the full stdout payload |
Exit Codes:
0: Prepared payload written successfully10: Invalid input, missing bundle files, unsupported bundle version, or unreadable compiled contract1: Unexpected internal error
Output shape
The generated JSON document includes:
| Field | Description |
|---|---|
surface |
{ surfaceId, displayName, type } |
bundle |
{ root, version, manifestPath, sourcePaths } |
contract |
{ id, version, normalizedPath } |
summary |
Human-readable text plus checklist/focus items and top repair priorities |
generation |
Resolved boundary, structure, layout, visual, and guidance objects |
sections |
Resolved section list for the target surface |
components |
Resolved component catalog for the target surface |
constraints |
Cross-cutting contract-authoritative constraints |
repairMap |
Deterministic repair actions keyed by canonical finding codes |
authoring |
Optional authoring hints when present in the source bundle |
evidenceRefs |
Evidence refs only; no inline extracted payloads |
Resolves one compiled surface bundle into a single, adapter-ready JSON payload for runtime consumers.
Synopsis:
interfacectl prepare-runtime --bundle-root <dir> --surface <id> [--out <path>]Description:
- Loads a compiled bundle and validates that the requested surface includes
runtime.json. - Resolves runtime structure, governance, mutation-envelope policy, contextual rules, target-acquisition policy, feedback-recovery policy, and flow summaries from the compiled bundle.
- Emits one deterministic JSON document with runtime checklist items, bundle and contract provenance, source paths, and evidence refs.
- Reuses the same canonical finding families that surface in
validate --remote-url; consumer adapters may wrap the data, but they should not redefine rule meaning.
Options:
| Option | Description |
|---|---|
--bundle-root <dir> |
Path to the compiled bundle directory (required) |
--surface <id> |
Surface identifier to resolve from the bundle (required) |
--out <path> |
Optional output file path. When provided, the command writes the JSON payload to disk and suppresses the full stdout payload |
Exit Codes:
0: Prepared runtime payload written successfully10: Invalid input, missing bundle files, missingruntime.json, unsupported bundle version, or unreadable compiled contract1: Unexpected internal error
Output shape
The generated JSON document includes:
| Field | Description |
|---|---|
surface |
{ surfaceId, displayName, type } |
bundle |
{ root, version, manifestPath, sourcePaths } |
contract |
{ id, version, normalizedPath } |
summary |
Human-readable runtime checklist including required sections, mutation mode, strict categories, contexts, target-acquisition thresholds, feedback-recovery requirements, and flow coverage |
governance |
Resolved governance payload for the surface |
runtime |
Resolved runtime structure, contexts, interaction policy, mutation envelope, and policy severities |
evidenceRefs |
Evidence refs only; no inline extracted observation payloads |
Creates a tracked local-agent session from an already compiled bundle. The command copies the bundle into a session-local directory, prepares the canonical agent payload once, and writes session.json.
Synopsis:
interfacectl init-generation-session --bundle-root <dir> --surface <id> --workspace-root <path> [--tool <codex|cursor>] [--guidance-mode <prepared|unguided>] [--brief-file <path>] [--session <id>] [--artifacts-root <path>]Description:
- Requires a compiled bundle and does not call
compileimplicitly. - Defaults session artifacts to
<workspaceRoot>/artifacts/generation-sessions/<surfaceId>/<sessionId>/. - Writes
bundle/, optionalprepared-input.json, andsession.json. --guidance-mode preparedis the guided contract-aware arm.--guidance-mode unguidedintentionally withholds the prepared payload from the generator while still freezing the same bundle for later validation.--brief-filefreezes the implementation brief into the session so later benchmark comparisons can prove both sessions used the same task.- Canonical session schema lives at
packages/interfacectl-cli/schemas/generation-session.schema.json.
Exit Codes:
0: Session created successfully10: Invalid input, unreadable bundle, duplicate session, or unreadable workspace root1: Unexpected internal error
Records one operator-reviewed attempt for a tracked session.
Synopsis:
interfacectl record-generation-attempt --session-dir <path> --assessment-file <path>Description:
- Loads
session.jsonfrom the provided session directory. - Validates the workspace against the frozen session bundle.
- Requires a rubric assessment with
structure,components,boundary,visual,responsiveness,notes, and optionaltouchedFiles. - Writes:
attempts/<nnn>.validate.jsonattempts/<nnn>.assessment.jsonattempts/<nnn>.metadata.json
- Emits a canonical
generationrun intocontracts/generated/contract-runs.jsonand rebuildscontract-lineage.json. - Canonical assessment schema lives at
packages/interfacectl-cli/schemas/generation-assessment.schema.json.
Exit Codes:
0: Attempt recorded successfully10: Invalid input, missing session, invalid assessment payload, or unreadable files1: Unexpected internal error
Records an explicit human review for one warn attempt.
Synopsis:
interfacectl review-generation-attempt --session-dir <path> --attempt <number> --review-file <path>Description:
- Loads the validate payload for the selected attempt and requires that the attempt status is
warn. - Requires a review file with
status,findingCodes, andrationale. - When
status=accepted, the reviewed finding-code set must cover every remaining finding on the attempt. - Writes
attempts/<nnn>.review.json. - Canonical review schema lives at
packages/interfacectl-cli/schemas/generation-attempt-review.schema.json.
Exit Codes:
0: Review recorded successfully10: Invalid input, missing session/attempt, invalid review coverage, or unreadable files1: Unexpected internal error
Summarizes recorded attempts for one session.
Synopsis:
interfacectl summarize-generation-session --session-dir <path>Description:
- Aggregates attempt count, first pass attempt, first acceptable attempt, latest status, latest outcome, recurring finding codes, recurring repair codes, latest assessment, and the latest review when present.
- Writes
summary.jsonandsummary.md. - Canonical summary schema lives at
packages/interfacectl-cli/schemas/generation-session-summary.schema.json.
Exit Codes:
0: Latest outcome ispassoraccepted-warn30: Latest outcome iswarnorblock10: Missing session or attempts, or invalid artifacts1: Unexpected internal error
Compares two tracked generation sessions for the same implementation brief.
Synopsis:
interfacectl compare-generation-sessions --baseline-session-dir <path> --guided-session-dir <path> [--out-dir <path>]Description:
- Requires both sessions to target the same surface, use the same tool, and freeze the same brief file.
- Works with any valid guidance-strategy pair; the output records each session’s concrete strategy.
- Computes first-attempt finding deltas, attempts-to-acceptable-outcome delta, rubric deltas, and goal checks.
- Writes
comparison.jsonandcomparison.md. - Canonical schema lives at
packages/interfacectl-cli/schemas/generation-session-comparison.schema.json.
Exit Codes:
0: Comparison artifacts written successfully10: Invalid session pairing, mismatched brief, or unreadable artifacts1: Unexpected internal error
Generates evidence-backed contract-refinement suggestions from a guided session without mutating the contract.
Synopsis:
interfacectl suggest-contract-deltas --session-dir <path> [--out <path>]Description:
- Requires a guided
preparedsession. - Uses the session repair map, repeated finding patterns, and latest validate evidence to propose contract paths for review.
- Emits deterministic suggestion JSON and markdown.
- Suggestions start as
status=proposed. - Canonical schema lives at
packages/interfacectl-cli/schemas/contract-delta-suggestions.schema.json.
Exit Codes:
0: Suggestion artifacts written successfully10: Invalid session state or unreadable artifacts1: Unexpected internal error
Applies human accept/reject decisions to suggestion artifacts without mutating the canonical contract.
Synopsis:
interfacectl review-contract-delta-suggestions --suggestions <path> --review-file <path> [--out <path>]Description:
- Loads an existing suggestion artifact.
- Applies review decisions keyed by
suggestionId. - Preserves undecided suggestions as
proposed. - Rewrites markdown alongside the updated JSON output.
Exit Codes:
0: Suggestion review recorded successfully10: Invalid decisions or unreadable files1: Unexpected internal error
Aggregates one or more comparison artifacts and reviewed suggestion sets into one benchmark report.
Synopsis:
interfacectl summarize-generation-benchmark --comparisons <path[,path...]> [--suggestions <path[,path...]>] [--out-dir <path>]Description:
- Summarizes whether the compared candidate sessions reduced first-attempt blocking findings, reached acceptable outcomes no later, and improved rubric dimensions.
- Aggregates accepted/rejected/proposed suggestion counts across surfaces.
- Writes
benchmark-report.jsonandbenchmark-report.md. - Canonical schema lives at
packages/interfacectl-cli/schemas/generation-benchmark-report.schema.json.
Exit Codes:
0: Benchmark report written successfully10: Missing comparison inputs or unreadable artifacts1: Unexpected internal error
Writes one canonical run record into contracts/generated/contract-runs.json and rebuilds contract-lineage.json.
Synopsis:
interfacectl emit-run-artifact --workspace-root <path> --surface <id> --source <bootstrap|generation|ci|runtime> --status <pass|warn|fail|unknown> [--contract <path>] [--extraction-path <path>] [--report-path <path>] [--finding-codes <csv>] [--workspace-id <id>] [--idempotency-key <key>] [--created-at <timestamp>] [--run-id <id>]Description:
- Creates
contract-runs.jsonandcontract-lineage.jsonif they do not yet exist. - Uses canonical schema files:
packages/interfacectl-cli/schemas/contract-runs.schema.jsonpackages/interfacectl-cli/schemas/contract-lineage.schema.json
- Dedupes by
(workspaceId, runId)and(workspaceId, idempotencyKey)when provided.
Exit Codes:
0: Run artifact emitted successfully10: Invalid input
Extracts a deterministic contract artifact from a Next.js app by analyzing app code. Extraction only — no enforcement, no network calls. Output is schema-valid; extracted-only fields live under x_extracted.
Synopsis:
interfacectl generate-contract --app-root <path> --surface <id> [--out <path>] [--report-out <path>] [--schema <path>]Description:
- Scans the app directory for routes (app router), layout shell (
app/layout.tsxorapp/(shell)/layout.tsx),@surfaces/uicomponent imports, and/authroutes. - Seeds
color.allowedValuesfrom observed descriptors and seedssurfaces[*].iconsfor web surfaces withpolicy: "warn"plus discovered icon source libraries. - Seeds
surfaces[*].layout.chromePolicyconservatively when portable chrome markers are present and deterministic:.contract-containerforlayout-container- top-level
data-contract-sectionfortop-level-section - optional
data-contract="page-container"forpage-container - legacy
data-contract-containerremains supported for compatibility
- Writes a contract JSON (default
contracts/generated/<surfaceId>.contract.json) and an extraction report (defaultcontracts/generated/<surfaceId>.extraction.json). - Validates the generated contract against the schema before writing. Running the command twice produces identical output (stable key order, no timestamps).
Options:
| Option | Description | Default |
|---|---|---|
--app-root <path> |
Path to the Next.js app root (directory containing app/) |
(required) |
--surface <id> |
Surface identifier (e.g. surfaces-web) |
(required) |
--out <path> |
Output path for contract JSON | contracts/generated/<surfaceId>.contract.json |
--report-out <path> |
Output path for extraction report | contracts/generated/<surfaceId>.extraction.json |
--schema <path> |
Optional path to the contract schema JSON file | Bundled schema |
Exit Codes:
0: Contract and report written successfully1: Schema validation failed for generated contract
Phase 0 scope: Routes, hasShell, designSystemComponents (from @surfaces/ui), authAware. Other fields use placeholders, conservative defaults, or descriptor seeding; the report lists warnings for omitted or ambiguous extraction.
Phase 0 guardrails: No Babel or heavy AST. Uses filesystem + regex for determinism, debuggability, and minimal deps. See docs/plans/phase-0-extraction-guardrails.md for extraction limits and when AST tooling may be added.
Fails if the contract’s Phase 0 expectations (surfaces[].phase0) conflict with extracted reality. Use after generate-contract to gate policy vs. code.
Synopsis:
interfacectl validate-extracted --contract <path> --extracted <path> [--surface <id>] [--format text|json] [--out <path>] [--exit-codes v1|v2]Contract shape (policy only; no x_ in policy):*
Optional per-surface block surfaces[].phase0:
authPosture:"public"|"auth-aware"|"auth-first"requiresShell: booleanexpectsAuthRoutes: booleanexpectsDesignSystem: boolean
Extracted input: (1) Extraction report: { surfaceId, extracted: { routes, hasShell, designSystemComponents, authAware } }. (2) Generated contract with x_extracted; use --surface <id> when surfaceId cannot be inferred.
Validation rules:
Auth posture: auth-first ⇒ authAware true and all four auth routes; auth-aware ⇒ authAware true. Shell: requiresShell true and hasShell false ⇒ mismatch. Auth routes: when expectsAuthRoutes true, requires /auth/login, /auth/callback, /auth/session, /auth/logout. Design system: expectsDesignSystem true and empty designSystemComponents ⇒ mismatch.
Findings: Deterministic order (surfaceId, then code). Codes: phase0.authPosture.mismatch, phase0.authRoutes.missing, phase0.shell.mismatch, phase0.designSystem.missing. Category E2 for mismatches, E0 for load/parse errors.
Exit codes (v2):
0: Success (no phase0 block or no mismatches).10: E0 (load/parse/schema or internal error).30: E2 (one or more mismatches).
Diff and enforce JSON output include optional traceability fields for correlation and debugging. These fields are additive and optional; existing consumers should keep working.
- stableId: Deterministic correlation id (64-bit). Use for deduplication and change tracking within a repo or CI workflow. NOT a globally unique identifier. For cross-repo or large-fleet indexing, consider extending to 128 bits in a future phase.
- contractRef: Reference to contract structure when deterministically derivable. Fields:
path(JSON pointer style),surfaceId,sectionId,constraintId.contractRef.pathis omitted when the mapping is ambiguous or the node does not exist in the contract (e.g. surface-missing). - ruleRef:
id(and optionalversion) of the rule that produced the entry.
Maps surface IDs to their root directories in the codebase.
Format:
{
"surfaceRoots": {
"surface-id": "path/to/surface/root",
"another-surface": "apps/another-app"
}
}Environment Variables:
SURFACES_ROOT: Default workspace root directorySURFACES_CONTRACT: Default contract file pathSURFACES_CONFIG: Default config file pathINTERFACECTL_EXIT_CODES: Exit code version (v1orv2, default:v1)
Enforcement policies define:
- Autofix rules: Patterns and conditions for automatic fixes
- Mode configurations: Behavior for fail/fix/pr modes
- Severity thresholds: Minimum severity to trigger enforcement
- Safety levels: Controls for what types of changes are allowed
- Fingerprint: Cryptographic hash for policy integrity verification
- Schema validation against JSON Schema
- Structural validation of contract format
- Surface descriptor discovery and parsing
- Multi-surface compliance checking
- Optional browser observation for target acquisition, task flows, and async feedback / recovery states
- Structural comparison between contract and implementation
- Normalization to handle formatting differences
- Rename detection via similarity thresholds
- Drift risk identification and reporting
- Rule-based autofix system
- Safety level enforcement (only mechanical changes)
- Confidence scoring for applied fixes
- Patch generation for review workflows
- Text: Human-readable colored output with structured sections
- JSON: Machine-readable structured data with full details
- Multiple surfaces in single contract
- Per-surface filtering and validation
- Surface-specific root directory mapping
- Cross-surface compliance checking
Use validate with v2 exit codes for contract compliance in CI:
interfacectl validate --root . --contract ./contracts/ui.contract.json --format json --exit-codes v2Or set the environment variable: INTERFACECTL_EXIT_CODES=v2.
To block on structural diff severity in addition to validate:
interfacectl enforce --mode failinterfacectl enforce --mode fix --dry-run
interfacectl enforce --mode fixinterfacectl enforce --mode pr --format json --out fix-patch.jsonAll commands provide structured error reporting:
- Clear error messages with context
- Exit codes for programmatic handling
- JSON error output for machine parsing
- Detailed validation error listings
When using --exit-codes v2 or INTERFACECTL_EXIT_CODES=v2:
validate v2: 0 / 10 / 20 / 30
0: Fully compliant10: E0 - Artifact invalid20: E1 - Token policy violation30: E2 - Interface contract violation
diff v2: 0 / 10 / 30 / 40
0: No diffs found10: E0 - Artifact invalid30: E2 - Blocking drift (error/warning entries)40: E3 - Non-blocking drift (all entries are info)
enforce v2: 0 / 10 / 30
0: Enforcement passed (no violations or fixes applied successfully)10: E0 - Artifact invalid30: E2 - Differences exceed policy threshold (does not distinguish E1 vs E2 for exit codes)
Note on v1 internal errors: v1 internal errors may be 2 or 3 depending on command (diff uses 3 if it currently does); v2 unifies to 10.
Category Field: The category field in JSON findings is stable and versioned with the output schema. It is always present (not optional) and not best-effort. Categories: E0 (artifact invalid), E1 (token policy), E2 (interface contract), E3 (drift non-blocking, diff v2 only).
Compatibility: v1 (default) behavior is preserved. Use --exit-codes v2 to opt into the new exit code contract. Deprecation warnings are printed in v1 mode when violations occur. The default will change to v2 in a future major release.
- Contract schema documentation
- Policy file format specification
- Surface descriptor format documentation