chore: rename residual framework→objectstack dir/pin references #9436
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Lint & Type Check | |
| on: | |
| push: | |
| branches: | |
| - main | |
| pull_request: | |
| branches: | |
| - main | |
| jobs: | |
| lint: | |
| name: ESLint | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v7 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: "20" | |
| - name: Enable Corepack | |
| run: corepack enable | |
| - name: Get pnpm store directory | |
| shell: bash | |
| run: | | |
| echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV | |
| - name: Setup pnpm cache | |
| uses: actions/cache@v6 | |
| with: | |
| path: ${{ env.STORE_PATH }} | |
| key: ${{ runner.os }}-pnpm-store-v3-${{ hashFiles('**/pnpm-lock.yaml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pnpm-store-v3- | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| # Enforces the no-restricted-imports guard against @objectstack/spec root | |
| # namespace imports (the dormant rule was never run in CI). Syntactic | |
| # only, so no build step needed. | |
| - name: ESLint | |
| run: pnpm lint | |
| # Raw NUL guard (#3127): one literal U+0000 byte makes grep/ripgrep treat | |
| # the whole file as binary and silently return ZERO matches — the file drops | |
| # out of code search and out of every grep-based lint, with no error saying | |
| # so. Nothing else catches it: git sniffs only the first 8000 bytes to decide | |
| # binary-ness, and protocol.ts carried its NUL at offset 147230, so it kept | |
| # diffing as ordinary text through review. That blind spot let six files | |
| # accumulate the same defect. Authors must write the unicode escape instead. | |
| - name: Raw NUL byte guard | |
| run: pnpm check:nul-bytes | |
| # Docs/skills authoring guard (#2035 / ADR-0059): TS code blocks in | |
| # Markdown/MDX are not type-checked or ESLinted, so skills/ and | |
| # content/docs/ can drift back to teaching the bare `: Page = {}` literal | |
| # while the examples (which ARE linted) stay clean. This fails on any bare | |
| # metadata literal for the 16 factory domains in a doc code block. | |
| - name: Doc/skill authoring guard | |
| run: pnpm check:doc-authoring | |
| # ADR-0090 D3 vocabulary ratchet: "role" is reserved-forbidden in docs | |
| # and skills. Existing occurrences are frozen in the baseline (better-auth | |
| # boundary, ARIA samples, educational mentions); NEW occurrences fail. | |
| # Improvements ratchet the baseline down via --update. | |
| - name: Reserved-word ("role") docs ratchet | |
| run: pnpm check:role-word | |
| # #3280/#3290 org-identifier guard: `organizationId` is the blessed | |
| # developer-facing name for the caller's active org in hook/action bodies; | |
| # the `session.tenantId` alias was REMOVED in v11 (#3290). Keeps our own | |
| # reference code (examples/, apps/, AND packages/) — which authors and AIs | |
| # copy from — off the removed name. Hard-fail (surfaces carry zero | |
| # occurrences today); tests, comments, skills/ and docs/ are excluded, and | |
| # driver-layer `execCtx.tenantId` is never matched. | |
| - name: Org-identifier authoring guard | |
| run: pnpm check:org-identifier | |
| # Authorization resolution must stay single-sourced (resolveAuthzContext, | |
| # @objectstack/core). Guards against a duplicate resolver copy drifting on a | |
| # security path (the REST-vs-dispatcher sys_user_role drift) and against an | |
| # entry point silently dropping the delegation. | |
| - name: Single authz resolver guard | |
| run: pnpm check:authz-resolver | |
| # Release-notes drift guard: the platform is one version-locked train, so | |
| # every released @objectstack/spec major must have a curated, navigable | |
| # release page at content/docs/releases/v<major>.mdx. Catches the gap that | |
| # let v10–v14 ship with no page while spec was already at 14.x. | |
| - name: Release-notes drift guard | |
| run: pnpm check:release-notes | |
| typecheck: | |
| name: TypeScript Type Check | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v7 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: '20' | |
| - name: Enable Corepack | |
| run: corepack enable | |
| - name: Verify pnpm version | |
| run: pnpm --version | |
| - name: Get pnpm store directory | |
| shell: bash | |
| run: | | |
| echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV | |
| - name: Setup pnpm cache | |
| uses: actions/cache@v6 | |
| with: | |
| path: ${{ env.STORE_PATH }} | |
| key: ${{ runner.os }}-pnpm-store-v3-${{ hashFiles('**/pnpm-lock.yaml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pnpm-store-v3- | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| - name: Type check (@objectstack/spec) | |
| run: pnpm --filter @objectstack/spec exec tsc --noEmit | |
| # Generated-docs gate: content/docs/references/** is generated from the spec | |
| # by `gen:schema && gen:docs` and committed. Nothing regenerated it in CI, so | |
| # it drifted silently — #3076 added RowCrudActionOverride to the spec and the | |
| # public reference docs never learned the type existed. Regenerates and fails | |
| # on any difference. | |
| # | |
| # Deliberately lives in this job, not in ci.yml's "Build Docs": that job is | |
| # gated on a `docs` paths-filter that does not include packages/spec/**, so it | |
| # skips exactly the spec-only PRs that cause this drift (#3076 was one). This | |
| # job has no paths filter and is a required status check, so the gate cannot go | |
| # dormant. It reads src/ + json-schema/ via tsx and needs no build, so it runs | |
| # before the workspace build and fails in ~2s. | |
| - name: Check generated reference docs are in sync with the spec | |
| run: pnpm --filter @objectstack/spec check:docs | |
| # Same class, same reasoning, different surface: skills/*/references/_index.md | |
| # and the objectstack-ui react-blocks contract are generated from | |
| # packages/spec/src and committed, and nothing regenerated them either. These | |
| # ship to third parties via `npx skills add objectstack-ai/objectstack`, so the | |
| # drift is served straight to consumers' agents — 6 of 113 schema pointers named | |
| # files the spec had already deleted or renamed. | |
| # | |
| # Not in ci.yml's `check-generated` job for the reason above: its `generated` | |
| # filter lists specific spec paths (migrations/, conversions/, protocol-version) | |
| # but no schema dirs, so a PR touching src/data/** or src/ui/** — exactly what | |
| # drives these two artifacts — never triggers it. It is not required, either. | |
| # | |
| # Both read packages/spec/src via tsx and need no build (verified with every | |
| # workspace dist/ removed), so they run before the workspace build. check:skill-refs | |
| # additionally fails on a SKILL_MAP entry naming a file the spec no longer has: | |
| # that silent skip is what let the map keep pointing at data/dataset.zod.ts for a | |
| # year after #1620 renamed it to data/seed.zod.ts. | |
| - name: Check generated skill references are in sync with the spec | |
| run: pnpm --filter @objectstack/spec check:skill-refs | |
| - name: Check the react-blocks contract is in sync with the spec | |
| run: pnpm --filter @objectstack/spec check:react-blocks | |
| # Example apps are AI-authoring reference templates; a red typecheck is a | |
| # bad signal to copy from. tsup transpiles them without a full typecheck, | |
| # so build alone will not catch type drift — typecheck them explicitly. | |
| # They import from built workspace packages, so the packages must be built | |
| # first for cross-package type resolution to succeed. The examples' | |
| # dependency closure is requested EXPLICITLY (`./examples/*^...` = deps | |
| # of the examples, not the examples themselves): the bare `./packages/*` | |
| # glob only matches direct children, and the connector packages the | |
| # showcase imports were previously built only by accident — through | |
| # dogfood's dependency chain, which broke when dogfood moved to | |
| # packages/qa/ (#3037). | |
| - name: Build workspace packages | |
| run: pnpm exec turbo run build --filter='./packages/*' --filter='./examples/*^...' | |
| - name: Type check example apps | |
| run: pnpm --filter './examples/*' run typecheck | |
| # Backward-compatibility gate: a frozen third-party-style consumer | |
| # (#2035). Unlike the examples it must NOT be migrated to accommodate a | |
| # spec change — a red typecheck here means the spec dropped/narrowed an | |
| # export a published-spec third party already uses. See the package README. | |
| - name: Type check downstream consumer contract | |
| run: pnpm --filter @objectstack/downstream-contract run typecheck | |
| # Public API-surface gate (#2035): the spec package IS the third-party API. | |
| # A removed/renamed export silently breaks every consumer pinned to a | |
| # published release. This diffs the built export surface against the | |
| # committed snapshot; intentional changes regenerate it via | |
| # `pnpm --filter @objectstack/spec gen:api-surface`. Runs after the build | |
| # step above (reads the built dist). | |
| - name: Check @objectstack/spec public API surface | |
| run: pnpm --filter @objectstack/spec run check:api-surface | |
| # Anti-drift for the skill EXAMPLES, not just the skill reference indexes | |
| # (#3094). The TypeScript in skills/ is the first thing an AI copies when | |
| # authoring metadata, yet nothing type-checked it — so it rotted silently | |
| # (`ObjectSchema`/`Data`/`Field` imported from the wrong entry point, a | |
| # `defineStack` key that no longer exists). Each block tagged with an | |
| # `<!-- os:check -->` comment is extracted and run through `tsc --noEmit` | |
| # against the built `@objectstack/spec` declarations — the exact surface a | |
| # consumer's import resolves to — so a renamed export or tightened union | |
| # fails here instead of in a third party's editor. Reads the built dist, | |
| # so it runs after the build step alongside the other consumer gates. | |
| - name: Check skills TypeScript examples compile | |
| run: pnpm --filter @objectstack/spec run check:skill-examples |