Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion API.md
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,11 @@ interfacectl generate-contract --app-root <path> --surface <id> [--out <path>] [
**Description:**
- Scans the app directory for routes (app router), layout shell (`app/layout.tsx` or `app/(shell)/layout.tsx`), `@surfaces/ui` component imports, and `/auth` routes.
- Seeds `color.allowedValues` from observed descriptors and seeds `surfaces[*].icons` for web surfaces with `policy: "warn"` plus discovered icon source libraries.
- Seeds `surfaces[*].layout.chromePolicy` conservatively when portable chrome markers are present and deterministic:
- `.contract-container` for `layout-container`
- top-level `data-contract-section` for `top-level-section`
- optional `data-contract="page-container"` for `page-container`
- legacy `data-contract-container` remains supported for compatibility
- Writes a contract JSON (default `contracts/generated/<surfaceId>.contract.json`) and an extraction report (default `contracts/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).

Expand All @@ -440,7 +445,7 @@ interfacectl generate-contract --app-root <path> --surface <id> [--out <path>] [
- `0`: Contract and report written successfully
- `1`: Schema validation failed for generated contract

**Phase 0 scope:** Routes, hasShell, designSystemComponents (from `@surfaces/ui`), authAware. Other fields use placeholders or defaults; the report lists warnings for any omitted extraction.
**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](docs/plans/phase-0-extraction-guardrails.md) for extraction limits and when AST tooling may be added.

Expand Down
12 changes: 12 additions & 0 deletions docs/contract-baseline.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ Optional surface layout fields:
- `layout.requiredContainers` (array of strings)
- `layout.pageFrame` (when present, enforced by validator)
- `layout.pageFrame.containerMinWidthPx` (optional): exact deterministic min-width check in px for `[data-contract="page-container"]`.
- `layout.chromePolicy` (when present, enforced by validator)
- Shared `generate-contract` can seed this conservatively from portable contract markers.

### Portable chrome extraction

Portable chrome extraction is opt-in and deterministic. Shared `interfacectl` only observes actual elements carrying contract-aware markers; it does not infer wrapper intent from generic DOM structure.

- Use `.contract-container` on governed layout containers. This is the recommended portable `layout-container` signal.
- Use top-level `data-contract-section="<id>"` wrappers for governed sections. Nested sections do not count toward chrome extraction.
- Use `data-contract="page-container"` only when the repo wants explicit page-frame semantics. It remains optional.
- `data-contract-container` remains supported for backward compatibility, but `.contract-container` is the recommended path for new adopters.
- Dynamic radius/shadow values, unresolved custom properties, and runtime-only expressions are treated as ambiguous and will suppress generated `chromePolicy` seeding.

Optional per-surface icon policy (web surfaces):

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions packages/interfacectl-cli/dist/commands/generate-contract.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { writeFile, mkdir, readFile } from "node:fs/promises";
import { extractContractFromNextApp, stableStringify, } from "@surfaces/interfacectl-extractor";
import { getBundledContractSchema, validateContractStructure, } from "@surfaces/interfacectl-validator";
import { seedColorPolicyFromObservedDescriptors } from "../utils/color-policy-seeding.js";
import { seedChromePolicyDefaults } from "../utils/chrome-policy-seeding.js";
import { seedChromePolicyFromObservedDescriptors } from "../utils/chrome-policy-seeding.js";
import { seedIconPolicyFromObservedDescriptors } from "../utils/icon-policy-seeding.js";
const DEFAULT_OUT_DIR = "contracts/generated";
export async function runGenerateContractCommand(options) {
Expand Down Expand Up @@ -35,7 +35,10 @@ export async function runGenerateContractCommand(options) {
surfaceId,
contract: seeded.contract,
});
const chromeSeeded = await seedChromePolicyDefaults({
const chromeSeeded = await seedChromePolicyFromObservedDescriptors({
workspaceRoot: cwd,
appRoot,
surfaceId,
contract: iconSeeded.contract,
});
const contract = chromeSeeded.contract;
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading