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
13 changes: 13 additions & 0 deletions .changeset/8903-vi-mock-override-value-shape-gate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
---

Tooling-only change. Adds `scripts/check-vi-mock-override-shape.mjs`, a third
gate over the `vi.mock` population: it compares an override's VALUE shape
against the shape the real export declares. The two existing gates judge whether
a relative specifier resolves and whether the factory inherits the real module,
and neither judges the override's value — measured, by putting the thirteen
drifted `useRecordPresence` stubs back on disk and watching both print a
byte-identical verdict line and exit 0 (objectui#8083, repaired by PR #8902).
No published package changes: the edits are the new gate, its test, a
`package.json` script alias and one `lint.yml` step, none of which any package's
`files[]` ships.
28 changes: 28 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,34 @@ jobs:
if: steps.relevant.outputs.should_run == 'true'
run: pnpm lint

# ── vi.mock override VALUE shapes (objectui#8903) ─────────────────────
# The third property of the `vi.mock` population, and the only one of the
# three that needs a parser. `check-vi-mock-specifiers.mjs` judges whether
# a relative specifier resolves; `check-vi-mock-inherit.mjs` judges whether
# the factory obtains and spreads the real module. Neither judges what the
# override is WORTH: thirteen stubs returned `{ viewers, others }` where
# the real hook returns `PresenceUser[]`, and putting them back on disk
# made both of those gates print a BYTE-IDENTICAL verdict line and exit 0
# (objectui#8083, fixed by PR #8902).
#
# Its two siblings live in `vi-mock-specifiers.yml`, which runs before any
# install so that it sees every pull request shape. This one cannot: it
# imports `typescript` to read declared return types, and
# `check-pre-install-import-graph.mjs` fails any pre-install gate that
# reaches a package — measured, by injecting the import into the sibling
# and watching that gate go from exit 0 to exit 1. So it runs here, after
# `pnpm install`.
#
# The `should_run` switch above is not a blind spot for it: the ignore list
# is Markdown plus the `content`, `docs` and `.changeset` trees, and both
# halves of what this gate compares — the override and the declared export
# — live in TypeScript files. `check-vi-mock-override-shape.test.ts` fails
# if a pattern matching a TypeScript file is ever added to that list.
- name: Check every vi.mock override matches the declared export shape
if: steps.relevant.outputs.should_run == 'true'
run: node scripts/check-vi-mock-override-shape.mjs


# ── The cross-repo closer's outcome contract (#5261) ──────────────────
# `cross-repo-issue-closer.yml` carries ~250 lines of inline
# github-script, and until this step existed it was code nobody had ever
Expand Down
15 changes: 15 additions & 0 deletions content/docs/guide/ci-cd-pipeline.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,21 @@ first, which is what stops a scanner that recognises nothing from reporting a cl
itself live under `e2e/live/ci/`
([#7692](https://github.com/objectstack-ai/objectui/issues/7692)).
- Then `pnpm lint`.
- Then `scripts/check-vi-mock-override-shape.mjs` — a `vi.mock` factory that overrides a typed
export must hand back the shape that export declares. Its two siblings run in
`vi-mock-specifiers.yml` and judge different properties of the same call sites: whether a relative
specifier resolves, and whether the factory inherits the real module. Neither judges what the
override is **worth**, and `tsc` never looks — a `vi.mock` factory is untyped, so the compiler
never compares a stub against the export's type. Measured rather than argued: thirteen
`RecordDetailView` stubs returned `{ viewers, others }` where `useRecordPresence` is declared
`PresenceUser[]`, and with all thirteen back on disk both existing gates printed a **byte-identical
verdict line and exit 0** ([#8083](https://github.com/objectstack-ai/objectui/issues/8083), repaired
by [#8902](https://github.com/objectstack-ai/objectui/pull/8902)). The failure mode is the
asymmetric one: when the stubbed contract moves, the files that stubbed it correctly go red and the
drifted ones stay green. It runs **after** the install rather than beside its siblings because it
reads declared return types with the TypeScript parser, and every pre-install gate's import graph is
held to node builtins plus local modules
([#8903](https://github.com/objectstack-ai/objectui/issues/8903)).
- Then `scripts/check-cross-repo-closer-outcome.mjs` — it extracts the ~250 lines of inline
`github-script` out of `cross-repo-issue-closer.yml` with a real parser, never a retyped copy,
runs it under doubles the way `actions/github-script` does, and pins each exit's outcome: which
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
"check:pre-install-import-graph": "node scripts/check-pre-install-import-graph.mjs",
"check:vi-mock-specifiers": "node scripts/check-vi-mock-specifiers.mjs",
"check:vi-mock-inherit": "node scripts/check-vi-mock-inherit.mjs",
"check:vi-mock-override-shape": "node scripts/check-vi-mock-override-shape.mjs",
"check:shell-escape-residue": "node scripts/check-shell-escape-residue.mjs",
"check:readme-exports": "node scripts/check-readme-exports.mjs",
"check:unreferenced-sources": "node scripts/check-unreferenced-sources.mjs",
Expand Down
Loading
Loading