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

vercelBot commented Jun 30, 2026

Copy link
Copy Markdown

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

ProjectDeploymentActionsUpdated (UTC)
specReadyReadyPreview, CommentJun 30, 2026 10:27am

Request Review

@github-actionsgithub-actionsBot 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 mainJun 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>
@github-actionsgithub-actionsBot mentioned this pull request Jul 14, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependenciesPull requests that update a dependency filedocumentationImprovements or additions to documentationsize/mteststooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@os-zhuang