Skip to content

feat(lint,cli): react-source prop validation gate (ADR-0081 Phase 2)#2482

Merged
os-zhuang merged 1 commit into
mainfrom
feat/react-prop-gate-a
Jun 30, 2026
Merged

feat(lint,cli): react-source prop validation gate (ADR-0081 Phase 2)#2482
os-zhuang merged 1 commit into
mainfrom
feat/react-prop-gate-a

Conversation

@os-zhuang

Copy link
Copy Markdown
Contributor

Phase 2 — now that the contract is spec-sourced (#2478) and the frontend is aligning to it (conformance #2480, record:* objectui #2113), use the contract to catch AI prop mistakes at os build.

validateReactPageProps parses a kind:'react' page's real JSX (TypeScript compiler) and checks each injected-block usage against REACT_BLOCKS (@objectstack/spec/ui):

  • missing required binding (e.g. <ObjectForm> with no objectName) → error
  • near-miss prop (onSuccesonSuccess, onRowClikonRowClick) → warning

Low false-positive by design: curated data props aren't flagged (only edit-distance ≤2 typos of contract props), and a spread {...props} escapes the required check. Wired into os validate.

Verified: 7 unit tests; the 5 real showcase react pages pass (no false positives); an injected onSucces typo is caught end-to-end in os validate. typescript moved to lint deps so it externalizes (lint dist 10MB→36KB; fixes a CLI 'Dynamic require of fs' ESM break).

🤖 Generated with Claude Code

validateReactPageProps parses the JSX of a kind:'react' page and checks each
injected-block usage against REACT_BLOCKS (the spec-sourced contract): missing
required binding -> error; near-miss prop (onSucces->onSuccess) -> warning.
Wired into os validate after the syntax gate. Verified: 7 unit tests; the 5 real
showcase react pages pass (no false positives); an injected onSucces typo is
caught end-to-end. typescript moved to lint deps so it externalizes (lint dist
10MB -> 36KB; fixes the CLI 'Dynamic require of fs' ESM-bundle break).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
spec Ready Ready Preview, Comment Jun 30, 2026 10:27am

Request Review

@github-actions github-actions Bot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file tests tooling size/m labels Jun 30, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 2 package(s): @objectstack/cli, @objectstack/lint.

15 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:

  • content/docs/concepts/cloud-artifact-api.mdx (via packages/cli)
  • content/docs/concepts/implementation-status.mdx (via @objectstack/cli)
  • content/docs/concepts/packages.mdx (via @objectstack/cli)
  • content/docs/getting-started/cli.mdx (via @objectstack/cli)
  • content/docs/getting-started/quick-start.mdx (via @objectstack/cli)
  • content/docs/guides/authentication.mdx (via @objectstack/cli)
  • content/docs/guides/client-sdk.mdx (via @objectstack/cli)
  • content/docs/guides/hook-bodies.mdx (via packages/cli)
  • content/docs/guides/packages.mdx (via @objectstack/cli)
  • content/docs/guides/project-scoping.mdx (via @objectstack/cli)
  • content/docs/guides/runtime-services/data-service.mdx (via packages/cli)
  • content/docs/guides/runtime-services/index.mdx (via packages/cli)
  • content/docs/guides/skills.mdx (via packages/cli)
  • content/docs/protocol/objectos/plugin-spec.mdx (via @objectstack/cli)
  • content/docs/protocol/objectos/realtime-protocol.mdx (via @objectstack/cli)

Advisory only. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs origin/main → pass the list as args.docs.

@os-zhuang
os-zhuang merged commit 5a5bf61 into main Jun 30, 2026
17 checks passed
@os-zhuang
os-zhuang deleted the feat/react-prop-gate-a branch June 30, 2026 10:30
os-zhuang added a commit that referenced this pull request Jun 30, 2026
Records the model that the spec↔contract↔conformance↔prop-gate work converged
on (now implemented + merged across framework #2478/#2480/#2482/#2484/#2485/#2488/
#2489 and objectui #2113/#2115), so future contributors don't re-litigate it:

- the spec zod schema is the protocol source of truth; the AI-facing contract is
  GENERATED from it (zero-drift), never hand-authored;
- registry inputs are the designer palette (a curated subset) — spec-only is a
  soft signal, frontend-only is the actionable one;
- React-interaction props (callbacks/controlled/binding escape-hatches) live in a
  thin overlay, not the spec; declaring a genuine binding there is how a
  frontend-only prop is closed (baseline now 0 frontend-only);
- conformance is a build-time baseline ratchet (build-console.sh, warn-only),
  not a per-PR gate — the manifest only exists at console-build time;
- authoring correctness is a hard gate at os validate (missing-required = error,
  typo = warning); and the dogfood golden page proves the chain closes.

Captures the alternatives rejected (copy props into spec / per-PR hard gate /
hand-authored contract / registry-as-source).

Co-authored-by: Jack Zhuang <277994282+os-zhuang@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
os-zhuang added a commit that referenced this pull request Jul 3, 2026
…rops (#2544)

@objectstack/lint sits on the kernel boot path, but the react-props gate
(ADR-0081 Phase 2, #2482) only runs when a kind:'react' page is actually
validated. The top-level `import ts from 'typescript'` made every boot
parse the ~9 MB compiler (~70 ms+ warm, worse on container cold starts)
and hard-crashed boot when a deployment pruned the package from the image
(cloud's Docker pruner did; worked around in cloud#728).

The compiler now loads on the first validated react-source page via a
deferred createRequire (the bundling-safe pattern from driver-sqlite-wasm's
knex-wasm-dialect); the public API stays synchronous and unchanged, and
`typescript` stays a regular dependency. If the package is missing at call
time, validation fails with an actionable error instead of killing boot.

Guarded by lazy-typescript.test.ts at three levels (structural no-eager-
import scan over src, child-process probes of both dist formats, in-process
lazy-load behavior) — verified to go red when the eager import is
reintroduced. An in-worker require.cache probe alone cannot catch it:
vitest inlines static imports through its transform.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation size/m tests tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant