You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Browse filesBrowse the repository at this point in the historyBrowse files
authored
fix(spec,metadata): three self-descriptions re-anchored to a verifiable source of truth (#7024) (#7032)
Sweep card #7024 — every member is a self-description that stopped being
answerable to reality, and each fix re-anchors it to something checkable.
#6242 — eight enumerations of the stack-collection set, none answerable to
`stack.zod.ts`. New `pnpm check:stack-collection-maps` derives the set from
`ObjectStackDefinitionSchema` and reconciles all eight against it in both
directions; every deviation is a waiver row carrying its reason, and a stale
waiver fails like a stale ledger row. Writing it found a seventh site the
hand-audit missed (`APP_CATEGORY_KEYS`) and a divergence between ObjectQL's two
copies that neither list shows alone. One code change: `ARTIFACT_FIELD_TO_TYPE`
no longer aims the seed collection (`data:`) at the analytics kind
(`'dataset'`) — a provably inert entry pointed at the wrong kind.
#4837 — the ledger counted "a consumer read site exists" as `live` evidence,
which misses producer-less dead keys (`Seed.env`). Adds the `producer` field
(resolved like `evidence`, so a call-site claim cannot rot), the criterion in
liveness/README.md, and a `--producer-gap` worklist. Six entries re-verified by
hand; `seed.env` restamped with both sides cited.
#4895 — adds `evidenceScope` (`in-repo` | `cross-repo`), and re-verifies the
#4667 retirement batch cross-repo against objectui @c2fd1223: all six keys
confirmed, no counter-example. The two surviving tombstone rows carry the scope
and the pinned commit.
⛔ Zero acceptance-face changes: authorable-surface.base.json is untouched, and
the three drift rows that sit on acceptance faces are recorded as waivers rather
than fixed.
Claude-Session: https://claude.ai/code/session_01Y3ydyJV9reKBgoez8LAoqY
Co-authored-by: os-zhuang <zhuangjianguo@steedos.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
fix(metadata,repo): every enumeration of the stack-collection set is now answerable to `stack.zod.ts`, and the artifact map stops aiming `data:` at the analytics kind (#6242)
6
+
7
+
`ObjectStackDefinitionSchema` decides which collections a stack may declare — 32
8
+
of them today. **Seven** other places re-enumerate that same set by hand (eight
9
+
enumerations in all, because ObjectQL declares its list twice), and nothing
10
+
compared any of them to the schema or to each other:
"producer":"packages/metadata-protocol/src/seed-loader.ts:174 — load() resolves the comparison environment itself (resolveEnvConfig), rather than trusting a caller to pass it"
183
+
}
184
+
```
185
+
186
+
`producer` resolves through **the same resolver as `evidence`** — repo-rooted
187
+
paths must exist or CI fails; cross-repo paths are attributed and counted. A
188
+
call-site claim nothing can falsify is precisely what this field exists to
189
+
remove, so it does not get a weaker standard than the pointer it completes.
190
+
191
+
Which entries need one. The risk is highest for **optional config with a
192
+
default**: those always "have a value" in the type system and can still be
193
+
`undefined` at runtime.
194
+
195
+
| Shape | Needs `producer`? |
196
+
|---|---|
197
+
| The consumer reads the authored value directly (`hook.priority` orders hooks) | no — the author IS the producer |
198
+
| The consumer compares the authored value against something a caller supplies (`seed.env`) |**yes** — cite who supplies it |
199
+
| The consumer reads it out of an options/config object built elsewhere (`job.timeout`) |**yes** — cite the threading site |
200
+
| The property is `dead`| no — there is nothing to produce |
201
+
202
+
Absence never fails CI (most of the ledger predates the field, and back-filling
203
+
guesses is the sin this records). `pnpm check:liveness --producer-gap` prints
204
+
every `live` entry citing a consumer only — an upper bound on the debt, to be
205
+
triaged with the table above rather than read as a defect list. A **malformed**
206
+
value does fail.
207
+
208
+
### `evidenceScope` — how wide the last look actually was (#4895)
209
+
210
+
Four measured verdicts were reached by searching **this repo only**, and
211
+
published as though they covered every consumer:
212
+
213
+
| # | Verdict | What the search missed |
214
+
|---|---|---|
215
+
| 1 |`app.homePageId` tombstoned "no shell ever read it" | objectui's `AppContent.resolveLandingRoute()` had been reading it all along (corrected in #4709) |
216
+
| 2 |`flow.nodes.children.position` marked live, "designer canvas layout" | the designer wrote its own `ui:{x,y}` and **nothing** read `position` — a false *live*, the opposite direction |
217
+
| 3 |`HttpMethod` reported unused | the scan matched only `import … from`|
218
+
| 4 |`Notification` / `NotificationConfig` removed on "zero importers" | objectui re-exported them with `export … from`, and the real consumers imported from `@object-ui/types` — **two hops**, so even a scan covering `export … from` misses it while it matches on the spec specifier |
219
+
220
+
Case 4 is the one that decides the method: **no amount of text or specifier
221
+
matching is sufficient**. A negative cross-repo claim has to follow the resolved
222
+
symbol graph through re-export chains, or it is a guess with a citation. Every
223
+
barrel package adds a blind spot, and the renderer repo is all barrels.
224
+
225
+
`evidenceScope` records what was actually done, as data:
226
+
227
+
| Value | Means |
228
+
|---|---|
229
+
|`in-repo`| the call graph was closed inside this repo only |
230
+
|`cross-repo`| a named foreign realm was walked too — say **which**, in the evidence, and **pin the commit** (`objectui @c2fd1223`): `action.undoable`'s reader line numbers drifted 28 lines in one day (#3714) |
231
+
232
+
Absent = scope undeclared, a worklist row rather than a failure; the field is
233
+
younger than nearly every entry. A value outside the vocabulary FAILS, the same
234
+
asymmetry as `verifiedAt` — a value the parser cannot read would silently exempt
235
+
that entry from every future sweep.
236
+
237
+
⚠️ Neither `cross-repo` value in the tree today covers **`cloud`**: the closed
238
+
runtime is not reachable from an open-source checkout, so a `cross-repo` claim
239
+
means "the realms named in the evidence", never "everywhere".
240
+
146
241
### ⚠️ An authoring/preview renderer is NOT a runtime consumer
147
242
148
243
`live` means **authoring the property changes runtime behaviour**. A Studio
@@ -522,10 +617,15 @@ over-share.
522
617
silently. Same "pure + unit-tested" reasoning as `orphans.mts`, for the same reason.
523
618
-`../scripts/liveness/check-empty-state.mts` — the empty-state gate (above);
524
619
`empty-state-registry.mts` is its source of truth.
620
+
-`../scripts/liveness/producer.mts` — the `producer` / `evidenceScope` fold
621
+
(#4837 / #4895). Pure + unit-tested for the same reason as `orphans.mts`: on
622
+
the shipped ledgers these checks are almost entirely quiet, so a green gate
623
+
proves nothing about whether they can fire.
525
624
526
625
```bash
527
626
pnpm --filter @objectstack/spec check:liveness # run the gate
528
627
tsx packages/spec/scripts/liveness/check-liveness.mts --dump field # inventory a type (seeding aid)
628
+
tsx packages/spec/scripts/liveness/check-liveness.mts --producer-gap # live entries citing a consumer only
529
629
```
530
630
531
631
CI: `.github/workflows/spec-liveness-check.yml` runs on PRs touching `packages/spec/**`.
0 commit comments