Skip to content

Commit d282e5a

Browse files
committed
Merge remote-tracking branch 'origin/main' into claude/sweet-ardinghelli-731802
# Conflicts: # .github/workflows/lint.yml
2 parents 0262462 + a605872 commit d282e5a

202 files changed

Lines changed: 3290 additions & 2423 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
"@objectstack/spec": patch
3+
"@objectstack/metadata": patch
4+
"@objectstack/objectql": patch
5+
---
6+
7+
**`MetadataManager.register()` / `unregister()` now announce to `subscribe()` watchers.** Both updated the registry, persisted to writable loaders and published to realtime, but never fired the watch callbacks — so `subscribe()` looked like it covered every write while silently missing all of them. Only the `saveMetaItem` path (via the repository watch stream) and the filesystem watcher ever reached a subscriber. Runtime consumers that cache metadata — notably ObjectQL's SchemaRegistry bridge, the component that decides what is queryable — went stale on every other write until the process restarted.
8+
9+
Announcing is now the **default**, so a new call site is correct without knowing this contract exists. This is a contract fix rather than a bug fix: the one live behavior change is that runtime datasource writes (`datasource-admin`) now reach the HMR SSE stream, which subscribes to every registered type. `unregisterPackage()` / `bulkUnregister()` also announce their deletes now — correct, but latent, since neither has a production caller today.
10+
11+
Bulk ingest opts out explicitly with the new `MetadataWriteOptions` (`{ notify: false }`) — boot-time filesystem priming, artifact ingest, and ObjectQL's registry bridge, each of which either runs before consumers cache anything or announces the whole batch once (as the artifact reload path does via `metadata:reloaded`). The bridge in particular MUST stay silent: it copies objects out of the SchemaRegistry, and announcing would feed them back through a handler that re-registers under `_packageId ?? 'metadata-service'`, overwriting the true package provenance of every object whose body carries no `_packageId`.
12+
13+
Additive only — `register(type, name, data)` and `unregister(type, name)` keep working unchanged.
14+
15+
Fixes #3112.

.github/workflows/ci.yml

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
outputs:
2525
docs: ${{ steps.changes.outputs.docs }}
2626
core: ${{ steps.changes.outputs.core }}
27-
skilldocs: ${{ steps.changes.outputs.skilldocs }}
27+
generated: ${{ steps.changes.outputs.generated }}
2828
steps:
2929
- name: Checkout repository
3030
uses: actions/checkout@v7
@@ -38,10 +38,30 @@ jobs:
3838
- 'content/**'
3939
- 'pnpm-lock.yaml'
4040
- '.github/workflows/ci.yml'
41-
skilldocs:
41+
# Inputs AND outputs of every generated artifact checked by the
42+
# `check-generated` job. A path missing here makes that gate dormant on
43+
# exactly the PRs that can break it, so keep the two in lockstep.
44+
generated:
45+
# check:skill-docs — catalog source is skills/*/SKILL.md; the derived
46+
# listings are skills/README.md + the reference page below. (That page
47+
# was content/docs/guides/skills.mdx until #2584 moved it; this filter
48+
# kept watching the old path, so hand-edits to the generated block went
49+
# unchecked from then until now.)
4250
- 'skills/**'
43-
- 'content/docs/guides/skills.mdx'
51+
- 'content/docs/ai/skills-reference.mdx'
4452
- 'packages/spec/scripts/build-skill-docs.ts'
53+
# check:spec-changes / check:upgrade-guide — derived from the ADR-0087
54+
# registries and the protocol version, none of which the skills paths
55+
# above cover. Both gates were dormant on spec-only PRs: a protocol bump
56+
# or a new migration could not trigger the job that verifies them.
57+
- 'packages/spec/scripts/build-spec-changes.ts'
58+
- 'packages/spec/scripts/build-upgrade-guide.ts'
59+
- 'packages/spec/src/migrations/**'
60+
- 'packages/spec/src/conversions/**'
61+
- 'packages/spec/src/kernel/protocol-version.ts'
62+
- 'packages/spec/api-surface.json'
63+
- 'packages/spec/spec-changes.json'
64+
- 'docs/protocol-upgrade-guide.md'
4565
- '.github/workflows/ci.yml'
4666
core:
4767
- 'packages/**'
@@ -354,10 +374,18 @@ jobs:
354374
- name: Build Docs
355375
run: pnpm --filter @objectstack/docs build
356376

357-
check-skill-docs:
358-
name: Check Skill Docs
377+
# Generated artifacts that are committed to the tree: regenerate, fail on drift.
378+
# Named for the class, not for skill docs alone — it has checked the ADR-0087
379+
# protocol artifacts for a while, and a name that hid them is part of why their
380+
# paths went missing from the filter above.
381+
#
382+
# The generated reference docs (content/docs/references/**) are deliberately NOT
383+
# here: they need to gate spec-only PRs, and this whole job is filter-gated, so
384+
# they live in lint.yml's required, unfiltered "TypeScript Type Check" job.
385+
check-generated:
386+
name: Check Generated Artifacts
359387
needs: filter
360-
if: needs.filter.outputs.skilldocs == 'true'
388+
if: needs.filter.outputs.generated == 'true'
361389
runs-on: ubuntu-latest
362390
permissions:
363391
contents: read

.github/workflows/lint.yml

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ jobs:
5050
- name: ESLint
5151
run: pnpm lint
5252

53+
# Raw NUL guard (#3127): one literal U+0000 byte makes grep/ripgrep treat
54+
# the whole file as binary and silently return ZERO matches — the file drops
55+
# out of code search and out of every grep-based lint, with no error saying
56+
# so. Nothing else catches it: git sniffs only the first 8000 bytes to decide
57+
# binary-ness, and protocol.ts carried its NUL at offset 147230, so it kept
58+
# diffing as ordinary text through review. That blind spot let six files
59+
# accumulate the same defect. Authors must write the unicode escape instead.
60+
- name: Raw NUL byte guard
61+
run: pnpm check:nul-bytes
62+
5363
# Docs/skills authoring guard (#2035 / ADR-0059): TS code blocks in
5464
# Markdown/MDX are not type-checked or ESLinted, so skills/ and
5565
# content/docs/ can drift back to teaching the bare `: Page = {}` literal
@@ -119,24 +129,38 @@ jobs:
119129
- name: Type check (@objectstack/spec)
120130
run: pnpm --filter @objectstack/spec exec tsc --noEmit
121131

122-
# Generated-skill gate: skills/*/references/_index.md and the objectstack-ui
123-
# react-blocks contract are generated from packages/spec/src and committed.
124-
# Nothing regenerated them in CI, so they drifted — and unlike the reference
125-
# docs these ship to third parties via `npx skills add objectstack-ai/framework`,
126-
# so the drift is served straight to consumers' agents.
132+
# Generated-docs gate: content/docs/references/** is generated from the spec
133+
# by `gen:schema && gen:docs` and committed. Nothing regenerated it in CI, so
134+
# it drifted silently — #3076 added RowCrudActionOverride to the spec and the
135+
# public reference docs never learned the type existed. Regenerates and fails
136+
# on any difference.
137+
#
138+
# Deliberately lives in this job, not in ci.yml's "Build Docs": that job is
139+
# gated on a `docs` paths-filter that does not include packages/spec/**, so it
140+
# skips exactly the spec-only PRs that cause this drift (#3076 was one). This
141+
# job has no paths filter and is a required status check, so the gate cannot go
142+
# dormant. It reads src/ + json-schema/ via tsx and needs no build, so it runs
143+
# before the workspace build and fails in ~2s.
144+
- name: Check generated reference docs are in sync with the spec
145+
run: pnpm --filter @objectstack/spec check:docs
146+
147+
# Same class, same reasoning, different surface: skills/*/references/_index.md
148+
# and the objectstack-ui react-blocks contract are generated from
149+
# packages/spec/src and committed, and nothing regenerated them either. These
150+
# ship to third parties via `npx skills add objectstack-ai/framework`, so the
151+
# drift is served straight to consumers' agents — 6 of 113 schema pointers named
152+
# files the spec had already deleted or renamed.
127153
#
128-
# Deliberately here rather than in ci.yml's `check-generated` job: that job is
129-
# paths-filtered on skills/** and the build-skill-docs.ts script, NOT on
130-
# packages/spec/src/**, so it skips exactly the spec-only PRs that cause this
131-
# drift — and it is not a required check either, so it could be merged past
132-
# even when it does run. This job has no paths filter and IS required
133-
# ("TypeScript Type Check"), so the gate can neither go dormant nor be bypassed.
154+
# Not in ci.yml's `check-generated` job for the reason above: its `generated`
155+
# filter lists specific spec paths (migrations/, conversions/, protocol-version)
156+
# but no schema dirs, so a PR touching src/data/** or src/ui/** — exactly what
157+
# drives these two artifacts — never triggers it. It is not required, either.
134158
#
135-
# Both read packages/spec/src directly via tsx and need no build (verified with
136-
# every workspace dist/ removed), so they run before the workspace build and
137-
# fail in seconds. `check:skill-refs` also fails on a SKILL_MAP entry pointing
138-
# at a file the spec no longer has — the silent skip that let the map keep
139-
# naming data/dataset.zod.ts for a year after #1620 renamed it to data/seed.zod.ts.
159+
# Both read packages/spec/src via tsx and need no build (verified with every
160+
# workspace dist/ removed), so they run before the workspace build. check:skill-refs
161+
# additionally fails on a SKILL_MAP entry naming a file the spec no longer has:
162+
# that silent skip is what let the map keep pointing at data/dataset.zod.ts for a
163+
# year after #1620 renamed it to data/seed.zod.ts.
140164
- name: Check generated skill references are in sync with the spec
141165
run: pnpm --filter @objectstack/spec check:skill-refs
142166

0 commit comments

Comments
 (0)