Skip to content

fix(lint): 写集诊断如实描述驱动分歧,而非"静默丢弃" (#4271) #2213

fix(lint): 写集诊断如实描述驱动分歧,而非"静默丢弃" (#4271)

fix(lint): 写集诊断如实描述驱动分歧,而非"静默丢弃" (#4271) #2213

name: Spec Liveness Check
# For a metadata-driven platform the spec is the product surface — a parsed-but-
# unenforced property is a silent no-op (and, for security props, false compliance).
# This gate reads the metadata-type registry (the authorable types) and requires every
# property of a GOVERNED type to declare a liveness status with evidence in
# packages/spec/liveness/<type>.json. A new unclassified property fails the check (the
# ratchet: no new undeclared surface). See packages/spec/liveness/README.md.
#
# ADR-0054 (prove-it-runs): bound high-risk 'live' properties must carry a `proof`
# pointing to a dogfood test that declares the matching `@proof:` tag. The gate also
# triggers on packages/qa/dogfood/** so deleting/renaming a proof re-runs this check and
# the dangling reference is caught (the proof files live outside packages/spec/).
on:
pull_request:
types: [opened, synchronize, reopened]
paths:
- 'packages/spec/**'
- 'packages/qa/dogfood/**'
# The variant/doc gate reads hand-written pages, so editing one can break it
# without touching packages/spec at all.
- 'content/docs/**'
# Same for the strictness ledger — it is a doc, and editing it can break
# the gate that now holds it to the code.
- 'docs/audits/**'
permissions:
contents: read
jobs:
liveness:
name: Spec property liveness
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v7
- name: Setup Node.js
uses: actions/setup-node@v7
with:
node-version: '22'
- name: Enable Corepack
run: corepack enable
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Check spec liveness
run: pnpm --filter @objectstack/spec check:liveness
# #3896 follow-up. The liveness ledger asks whether a property does anything;
# this asks what its EMPTY value MEANS. A restriction-shaped property whose
# empty state is permissive has to be classified on purpose — omission is the
# commonest authoring error, and it must not also be the widest grant.
- name: Check empty-state semantics
run: pnpm --filter @objectstack/spec check:empty-state
# #4165 follow-up. Those two gates ask what a property does and what its empty
# value means. This asks the inverse-drift question neither covers: does a variant
# the schema declares appear in the hand-written doc at all? references/ is
# generated and cannot drift; the hand-written pages are typed by humans and do.
# apps.mdx said the nav tree had "eight item types" while the schema had nine.
- name: Check discriminated-union variants are documented
run: pnpm --filter @objectstack/spec check:variant-docs
# #4001 follow-up. The strictness ledger is the campaign's map — which
# z.object sites are authorable, wire or open. Every step reads it to pick
# the next move, and nothing kept it honest: it went stale twice in one
# week (a classification verification disproved, and a "next step" that had
# shipped months earlier). A map that drifts is worse than no map, because
# it gets followed. This holds its arithmetic and its coverage to the code.
- name: Check the strictness ledger matches the code
run: pnpm --filter @objectstack/spec check:strictness-ledger