Skip to content

feat(spec): declare style on ListMapConfigSchema and point object-map.map back at it - #18904

Merged
os-elon-musk merged 2 commits into
mainfrom
claude/issue-18406-listmap-style-key
Sep 18, 2026
Merged

os-elon-musk merged 2 commits into
mainfrom
claude/issue-18406-listmap-style-key

Conversation

@os-elon-musk

Copy link
Copy Markdown
Collaborator

Fixes #18406

Clause-②: yes (widening) — the published accept set grows by exactly one key, ui/ListMapConfig:style. Changeset: @objectstack/spec minor.

Director decision batch #153 item 4, letter 1 (ruling comment 5724940537 on #18406, maintainer 「其他同意」). ⛔ Not mapStyle (letter 2 declined: "a second spelling the renderer would have to learn"). ⛔ No alias (letter 3 declined: "an alias is a permanent obligation for a key nobody has written yet").

The defect, measured

ListMapConfigSchema is a strictObject and style was the one member of the map renderer's own documented config surface it omitted, so ListMapConfigSchema.safeParse({ style: 'https://tiles.example/style.json' }) answered success: false and a map style could not be declared through the spec's list-view face at all.

Measured at the .objectui-sha pin 53ded82bf7a494f54e344e19099dbf00854b8694:

Reading Where
ObjectMapConfigSchema declares eight keys, style among them packages/types/src/zod/objectql.zod.ts:562, the style row at :570
getMapConfig reads `schema.mapStyle
the authored block is validated against that schema packages/plugin-map/src/ObjectMap.tsx:373
objectui's own docs publish style inside the block content/docs/plugins/plugin-map.mdx:131 (that path is objectui's, and the spec docblock's parenthetical is scoped to objectui — verified present at the pin, so the citation is sound)
FLAT_MAP_CONFIG_KEYS is that shape MINUS style packages/plugin-list/src/ListView.tsx:40-67

So the divergence was against the documented surface the spec docblock itself cites, not merely against code.

⚠️ Line numbers were re-derived from the tree. The card and the ruling both cite view.zod.ts:1631 for ListMapConfigSchema; on this branch's base it is at :1754.

The change, file by file

packages/spec/src/ui/view.zod.ts

  • ListMapConfigSchema (:1754) gains style, an optional string, after center. The describe names it the map style URL, records that the component-level mapStyle is read FIRST and wins when both are present, and says it is not the inline CSS style record a component node carries.
  • The docblock's strictness paragraph (:1746-1752) gains a purely ADDITIVE correction. strictObject stays and the rationale for closing the block is untouched — the ruling does not fault strictness. What is recorded is that the paragraph's parity claim was one key SHORT, which key it was, and the pin it was measured at.

packages/spec/src/ui/component.zod.ts

  • map (:3272) stops being z.unknown() and becomes ListMapConfigSchema.optional(), spelled exactly as the sibling gantt door is. ListMapConfigSchema joins the ./view.zod import on line 4. The registration 'object-map': ObjectMapPropsSchema (:3735) is unchanged.
  • The "VALUE posture for map" paragraph is rewritten: it was the record of WHY the door had to stay open, and that reason is now discharged.
  • The flat-guidance docblock gains "minus that same style" plus the reason style is subtracted on both sides — flattened to the top level it collides with BaseSchema.style, the node's inline CSS record, which is why the renderer stopped reading a top-level style as a map style at all (objectui#5017) and why the prescription routes it to mapStyle.
  • mapStyle is untouched. It is the component-level spelling, read first, and is not a member of the config block.

packages/spec/src/ui/component.test.ts — PR #18403's negative pins, inverted (:3534-3540)

  • ListMapConfigSchema.safeParse({ style: ... }).success flips false → true.
  • The door's acceptance of a map block carrying style stays true, now through the spec's own schema rather than through an open value.
  • ⭐ A third assertion is added, because the two above would pass just as well against the z.unknown() they replaced: an authored map block carrying styl is refused, and the refusal is asserted to land AT map with styl echoed in the issue's keys.
  • The flat-key-set equality (:3507-3509) now derives by SUBTRACTION — the config block's shape minus style — rather than by hand-listing, so a newly declared config key still lands in that assertion.

packages/spec/src/ui/view.test.ts

  • The documented-surface test carries eight keys instead of seven, and asserts the parse OUTPUT equals the input, so a declaration that silently dropped a member could not satisfy it.
  • A new pin takes the card's repro as its subject: style accepted alone, the node-level object form of style refused, and both styl and mapStyle still refused — style did not open the block.

Generated (regenerated, never hand-edited)

  • packages/spec/authorable-surface/ui.json gains exactly one line, ui/ListMapConfig:style. Written by pnpm --filter @objectstack/spec build.
  • content/docs/references/ui/view.mdx and content/docs/references/ui/component.mdx via gen:docs. In the component reference the object-map.map row changes from any to the block's real shape and a nested-shape table for it appears — the retraction of z.unknown() made visible in the published reference.
  • authorable-surface.base.json is deliberately NOT touched; only gen:authorable-surface-base writes it.

Of the 15 generated artefacts, check:generated proved exactly one stale (content/docs/references/**) and --fix regenerated only that one. After the origin/main merge and a full rebuild, all 15 report up to date with a clean tree.

Reverse verification

Ablation (PLANT mode, scripts/ablation-replace.mjs). The style row was renamed to styleAblated18406, so the key is no longer declared under the name the pins assert. On-disk evidence: anchor count 1 → 0, planted marker 0 → 1, blob 1c83516951e3 → d256ada1f791. Restore proved by blob equal to HEAD, git diff HEAD empty, and a WHOLE-TREE git status --porcelain empty.

  • Source leg — RED, as predicted. 4 of 782 tests fail, and they are exactly the four this PR authors or modifies; 778 pass. So the new pins are discriminating, not vacuously true.
  • Build leg — an independent third witness. gen:schema's authorable-key ratchet also reds under the ablation and names ui/ListMapConfig:style as having "disappeared from the contract" while the committed baseline still records it. That is mechanical confirmation that the key really landed in the tracked contract.
  • Dist leg — NOT MEASURED, and declared so. Because the ablated build failed at gen:schema, no ablated dist/ was ever produced. The temporary type probe consequently read the PRE-mutation artefact and exited 0 — precisely the false green scripts/ablation-dist-preflight.mjs exists to catch, and it caught it, reporting the marker ABSENT from dist/. That green is discarded, not recorded as a pass.

Cross-package type reverse verification, supplied separately because the dist leg above could not supply it. A temporary probe inside packages/lint resolves @objectstack/spec/ui through the package exports, i.e. the BUILT declarations, so its verdict is a function of build state:

  • Positive leg, exit 0 — style is assignable on the config block, AND a ts-expect-error directive on an undeclared member inside map is USED, which is only true if the door really narrowed away from unknown.
  • Negative leg, exit 2 — both halves fail as required, and each would have COMPILED against the pre-change declarations. The compiler names bogus as not existing in the block type and prints that type inline with its style member, and it reports the stale expectation-of-refusal as an unused directive. A cached declaration file cannot produce either error.

Both probe files were deleted; the tree is clean.

Gates

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands derived 107 command families from the real change set (8 paths, including the generated artefacts and tests). All 107 were run, each exit code captured BEFORE any pipe and written to a file, and --ran FILE reconciles to 107 derived / 107 run / 0 NOT-MEASURED / 0 UNRUN — a DERIVED zero, since every line carries its code and none of them is 3.

Eight families first returned a non-zero that was NOT a finding and are green after their prerequisite was met: five reported PREREQUISITE NOT MET for build state (cleared by a full pnpm build), one needed the MANIFEST value CI supplies and was then run in CI's exact spelling, and one — check-plugin-teardown-shape.mjs --self-test — refused because its fixture commit is unreachable in a shallow clone, cleared by a targeted git fetch origin 621a4876... rather than an unshallow.

⛔ Not read as clearance: 13 of the roster families run only the checker's own --self-test, 49 declare a tracked-file roster whose silence is a fact about a list, 11 declare a population too wide to place, and 6 CI jobs scheduled by these paths run steps no local command covers. Those are CI's.

Lint and tests

Both readings taken at 0af4dfc76, the final commit.

  • pnpm lint = eslint . --no-inline-config, run repo-wide rather than narrowed: exit 0, 6853 files inspected (counted from --format json), 0 errors, 0 warnings, 75s. For the record, the config never enables type-aware linting for any file — no parserOptions.project and no typed rules — which eslint.config.mjs:326-336 states with its own positive control, so this diff could not move an untouched file's verdict either way.
  • pnpm --filter @objectstack/spec test — 488 files, 14128 tests, all passing.
  • pnpm --filter @objectstack/spec typecheck — green, test layer included.
  • check:generated — all 15 artefacts up to date.

Verify-lock readings, for the lane's baseline: acquisitions waited 0s / 5s / 0s / 4m05s / 1m18s / 0s, and the full pnpm build held the lock 4m56s.

Acceptance notes

Observed, in scope of nothing here, and ⛔ not filed by this seat.

  1. The docblock clause "so an extra key here would be dropped there" is measurably false at the pin, and it is the clause immediately beside the one this PR corrects. ObjectMapConfigSchema is a plain z.object, not strict, so a safeParse of a block carrying an extra key SUCCEEDS; getMapConfig uses that result only to decide whether to emit a console.warn; and ObjectMap.tsx:378 returns a spread of the authored block, so the extra key is carried through rather than dropped. An undeclared key inside map is therefore neither flagged nor dropped by the renderer — the opposite of what the clause asserts. Left untouched deliberately: the ruling's facts reach the style key and objectui's read of it, and they do not reach this mechanism claim, so correcting it would widen the diff past what the ruling authorises. Passed to the seat for filing-class judgement rather than filed.

  2. The retraction did not need to reach into PR feat(spec)!: every engine-evaluated expression slot requires a non-blank source #18638's hunk regions. Its view.zod.ts hunks start at old lines 53 / 2241 / 2771 / 2978 and its component.zod.ts hunks at 6 / 738 / 1591 / 1601; this PR's regions are view.zod.ts:1727-1766 and component.zod.ts:4, 3163-3175, 3210-3218, 3272-3273. The origin/main merge brought only content/docs/deployment/validating-metadata.mdx and scripts/gen-sdui-manifest-node.mjs, neither of which overlaps.

维护者速读(草稿)

改了什么

地图视图配置块 ListMapConfigSchema 新增一个可选键 style —— 地图底图样式的 URL。同时把组件契约里 object-map 的 map 属性重新指回这个块(上一个 PR 因为这个键缺失,被迫把它放成了"任意值")。就一个键,没有别名,没有第二种拼写。

为什么改

渲染器一直在读这个键,规格却一直不声明它。后果是:作者在平台的权威声明面上根本无法声明地图样式 —— 写 style 被严格校验拒掉,写 mapStyle 规格也不认。代价已经付过一次:为了绕开这个拒收,上一个 PR 把一个组件属性的值契约整个放开成了"任意值",于是那个位置的拼写错误不再有人拦。这次两件事一起收回。

键名取 style 而不是 mapStyle,因为 Mapbox 与 MapLibre 这个行业本来就叫 style,也是渲染器在配置块里实际读的名字。

风险与代价(含回滚)

  • 接受集只扩大,不缩小:原先能通过的元数据,现在全部照旧通过。
  • 一处收紧:object-map 的 map 值从"任意值"变回真正的块契约,所以块内的拼写错误现在会被明确拒收并指名。这正是本次要恢复的保护,但它确实是一个行为变化 —— 如果线上有依赖"任意值"往 map 里塞非契约键的写法,会在这里被拒。仓内扫描未发现这类写法。
  • 不涉及 objectui 仓:objectui 那边教人写 mapStyle 的开发警告,由另一张 domain:ui 卡单独修,本 PR 不碰。
  • 回滚:单次 revert 即可。没有数据迁移,没有退役键,没有 ADR-0087 转换,没有墓碑。

席位意见

你要做的

本 PR 是 Clause-②: yes(公开接受集扩大),按流程需要合约层评审后才可落地;评审席位与载体标签不由本席位挂摘。除评审外无需人工动作 —— 本地门禁已全绿,生成产物已按机制重生成。


Generated by Claude Code

…t-map.map` back at it

`ListMapConfigSchema` is a `strictObject` and `style` was the one member of the
map renderer's own documented config surface it omitted, so a strict parse
refused the map style URL the renderer reads and an author could not declare a
map style through the spec's list-view face at all.

Measured at the `.objectui-sha` pin `53ded82b`: objectui's
`ObjectMapConfigSchema` (`packages/types/src/zod/objectql.zod.ts:562`) declares
all eight keys, `getMapConfig` reads `schema.mapStyle || schema.map?.style`
(`packages/plugin-map/src/ObjectMap.tsx:365`), and objectui's own
`content/docs/plugins/plugin-map.mdx:131` documents `style` inside the block.

In the same stroke the `object-map` component door stops being `z.unknown()`:
that posture existed only because pointing it at a schema missing `style` would
have refused a value the renderer honours. The two assertions that recorded the
divergence are inverted, and the flat-key-set equality now subtracts `style`
explicitly — flattened to the top level it collides with `BaseSchema.style`, the
node's inline CSS record, which is why objectui's own `FLAT_MAP_CONFIG_KEYS`
subtracts it too.

⛔ Not `mapStyle`, and no alias: one name, the one the renderer reads.

Claude-Session: https://claude.ai/code/session_019srGWGCBBCBHqcDoRZpQRh
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation protocol:ui tests tooling labels Sep 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

This PR changes 1 package(s): @objectstack/spec, touching 2 documentable anchor(s). ⚠️ 1 changed file(s) yielded no anchor (packages/spec/authorable-surface/ui.json), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files.

⛔ 1 release-owned page(s) name something this change touched. These are read-only:

  • content/docs/releases/v17/17-1.mdx (via ListMapConfigSchema (symbol, a top-level const))

content/docs/releases/ is RELEASE-OWNED (AGENTS.md "Documentation Guardrails"): release
notes are written centrally at release time, and a code PR that edits them is the exact PR
that guardrail exists to stop. They are still audited — read-only. If one of them is actually
wrong, file an issue or open a dedicated docs-only PR; do not edit it here.

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/spec/authorable-surface/ui.json) — pages documenting those are invisible to this run
  • the SDK route bridge reached 60 of 215 client-bound route-ledger rows — the other 155 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 155: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 100 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.

Coarse fallback — 136 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 84ba4a847600dbecb55fcd2e31322ada19496f58 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 8b7f4ae2aec11968444f8524842a0b1e8b4c34aa — the merge of head 0af4dfc76ed5ab0a1994296554e7f44d102cfe0f into base 84ba4a847600dbecb55fcd2e31322ada19496f58, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 8b7f4ae2aec11968444f8524842a0b1e8b4c34aa && git checkout 8b7f4ae2aec11968444f8524842a0b1e8b4c34aa
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 84ba4a847600dbecb55fcd2e31322ada19496f58 0af4dfc76ed5ab0a1994296554e7f44d102cfe0f && git checkout -B drift-repro 84ba4a847600dbecb55fcd2e31322ada19496f58 && git merge --no-ff 0af4dfc76ed5ab0a1994296554e7f44d102cfe0f

node scripts/docs-audit/affected-docs.mjs --json 84ba4a847600dbecb55fcd2e31322ada19496f58

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

Advisory only, and a precision-first one (#9192): a page is listed because it names a
symbol, wire route or SDK method this diff touched — not because it mentions a changed
package. Each row says which anchor put it there, so a wrong row is reportable rather than
merely annoying. To re-verify, run the docs-accuracy-audit workflow scoped to these files:
node scripts/docs-audit/affected-docs.mjs 84ba4a847600dbecb55fcd2e31322ada19496f58 → pass the list as
args.docs, on the commit named under Which tree this was computed on.

@os-elon-musk
os-elon-musk marked this pull request as ready for review September 18, 2026 05:26
@os-elon-musk
os-elon-musk added this pull request to the merge queue Sep 18, 2026
Merged via the queue into main with commit 1aa5026 Sep 18, 2026
44 checks passed
@os-elon-musk
os-elon-musk deleted the claude/issue-18406-listmap-style-key branch September 18, 2026 06:04
akarma-synetal pushed a commit to akarma-synetal/framework that referenced this pull request Sep 28, 2026
… NavigationModeSchema modes (objectstack-ai#19675)

Part of objectstack-ai#18459 (item N2)

> ⚠️ **Closing keyword corrected by the seat from `Fixes` to `Part
of`.** Card objectstack-ai#18459 carries FOUR items. N1 is measured DEAD on main (PR
objectstack-ai#18904 replaced the enumerating describe with a pointer at
`ListViewSchema.map`, whose schema declares every key `.optional()`),
and **N2 is what this PR lands**. ⛔ **N3 and N4 are NOT fixed** — both
were re-measured at the live pin and deliberately left on the card, N3
with fresh numbers that supersede the card's own stale proposals. A
`Fixes` would have closed the card on merge and destroyed both. The seat
releases the card back to the queue on landing with a `Release:` naming
what landed and what remains.

Clause-②: no

## Summary

The card carried **two shipped imprecisions**. Re-measured at the LIVE
objectui pin
`87af769e9a3ee28ace099fdd653d3ebd79fe82e2` before anything was changed,
**one is dead and
one survives** — and the surviving one is wider than the card scoped it.

This PR fixes the surviving one. The falsification of the other is
recorded below rather
than acted on.

## Zone 2 — what the re-measurement found

### N1 (lat/lng pair marked required) — FALSIFIED, already fixed. No
change here.

At PR objectstack-ai#18403 the `object-map` `map` row read:

`'Map field config, the author face: { latitudeField, longitudeField,
locationField?, titleField?, descriptionField?, zoom?, center?, style?
}. Taken WHOLE when present ...'`

— the enumeration the card objected to. Commit `1aa5026e30` (PR objectstack-ai#18904,
"declare `style` on
`ListMapConfigSchema` and point `object-map.map` back at it") **deleted
that enumeration**.
On `main` today the row reads `'Map field config, the author face — the
same block
ListViewSchema.map declares ...'`, and the generated reference renders
the TYPE from
`ListMapConfigSchema` itself:

`| **map** | { latitudeField?: string; longitudeField?: string;
locationField?: string; titleField?: string; … } | optional | ...`

Every key optional, no required pair claimed. The statement the card
called false no longer
exists in the source or in the shipped reference.

Reproduce: `git log -S "Map field config, the author face: {
latitudeField" -- packages/spec/src/ui/component.zod.ts`
returns exactly two commits, `a3d4c59d69` (added, PR objectstack-ai#18403) and
`1aa5026e30` (removed, PR objectstack-ai#18904).

### N2 (navigation list omits `new_window`) — CONFIRMED, and it is four
rows, not three.

At the live pin, `object-grid`, `object-map`, `object-gantt` and
`object-tree` each hand
`schema.navigation` straight into the shared `useNavigationOverlay` hook
(`ObjectGrid.tsx:2321`, `ObjectMap.tsx:1041`, `ObjectGantt.tsx:1680`,
`ObjectTree.tsx:891`).
That hook binds its own mode union to this package's
`NavigationModeSchema` — its docblock
says so in as many words, *"the seven modes this hook switches on are
exactly the seven the
exported union publishes"*, held by a parity test on that side — and its
click router carries
a `new_window` branch that delegates to `onNavigate` and otherwise falls
through to a
`window.open`. `object-gantt` implements that action itself as well.

The four `.describe()` strings listed six of the seven (no
`new_window`), except `object-grid`
— the row the other three were copied from — which listed five (no
`popover` either). All four
doors are `z.unknown()`, so that sentence is the entire published
account of the shape, and
the reference page renders the type beside it as `any`.

### N3 (two comment citations in `component.test.ts`) — NOT fixed here,
and the card's own correction is stale.

Both citations still exist (`component.test.ts:3649` `label (:1849)`,
`:3750`
`ObjectGantt.tsx:501`). But they are HISTORICAL citations anchored to
the retired pin
`53ded82b`, and the corrections the card proposes (`:1871`, `:500`) were
measured at that
same retired pin. At the live pin the true positions are **`:503`** for
the
`GanttConfigSchema.safeParse` and **`:2181`** for the label resolution —
so applying the
card's numbers would replace one unverifiable pair with another.
`component.test.ts` is also
outside this dispatch's declared file surface. Left for the card.

### N4 (historical pin-citation spelling) — unchanged, measured.

`check:objectui-pin-citations --list` on this head: **48 historical / 29
asserting / 7
assertion** entries. **30 historical citations still name the retired
`53ded82b`**, ten of
them in `component.zod.ts`, including the three headers this card is
about
(`component.zod.ts:3561` map, `:3715` gantt, `:3906` tree). The gate
permits the historical
form by design, so nothing is violated and nothing reds — those anchors
simply are not
re-checked on a pin bump, which is exactly what the card recorded. N3's
re-measurement above
shows the drift is real and not hypothetical. Converting them is a
re-measurement job, not a
spelling change, and is left for the card.

## The change

Four `.describe()` strings, plus the reference page regenerated from
them with
`pnpm --filter @objectstack/spec check:generated --fix` (never by hand):

- `ObjectGridPropsSchema.navigation`
- `ObjectMapPropsSchema.navigation`
- `ObjectGanttPropsSchema.navigation`
- `ObjectTreePropsSchema.navigation`

Each now lists `page | drawer | modal | split | popover | new_window |
none` and names
`NavigationModeSchema` as the source of that list, so the next member
added to the enum has a
named edge into these rows instead of four independently drifting lists.

**Why `object-grid` is in scope.** The card names it as the precedent
the other three copied
and says "fixing it means fixing the family, not just these three rows".
It is the same defect
class, in the same file, in the same gate family, adds no verification
surface, and understates
by two rather than one. Correcting three while leaving the source of the
pattern intact would
leave the family in the state that produced the defect.

No accept set moves: the doors stay `z.unknown()`.

## Changeset — measured, not pattern-matched

`patch` on `@objectstack/spec`. The changed bytes ARE published bytes:

- `packages/spec/package.json` `files[]` contains `src/**/*.zod.ts`, so
  `src/ui/component.zod.ts` ships verbatim in the tarball.
- The compiled strings ship in `dist/ui/index.js` and
`dist/ui/index.mjs`.
- `npm pack --dry-run --json` in `packages/spec` lists all three of
those paths among its
2030 entries. `@objectstack/spec` is `private: false` at `17.4.0` — a
released package.
- Controls: a positive control (an untouched describe from the same
rows) is found in the same
dist files; a negative control (a string present nowhere) is found in
none.

So `skip-changeset` would have been wrong here, and no changeset would
have been wrong too.

## Verification

Head `55dd769453`. `origin/main` merged in at `f2101d0492` via
`scripts/pm/os-regen-merge.sh`
before the final measurements; all 15 spec generated artifacts
re-checked clean after it.

- `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack
--commands` derived
**102 families** from the actual changed paths. All 102 run, exit codes
captured to a file
BEFORE any pipe, reconciled with `--ran`: **102 run, 0 NOT MEASURED, 0
UNRUN**.
- The single non-zero is `pnpm --filter @objectstack/spec run
check:react-declaration-parity`
in its bare spelling, which exits 1 by design with no `MANIFEST`. Run as
CI runs it —
`MANIFEST="$PWD/sdui.manifest.json" ... --baseline
react-declaration-parity.baseline.json --strict`
— it exits **0**, with no new declaration divergence vs the accepted
baseline.
- `pnpm --filter @objectstack/spec test` — **512 files, 14953 passed, 1
todo**.
- `pnpm --filter @objectstack/spec typecheck` — exit 0 (`tsc --noEmit`,
`check:scripts-typecheck`,
  `check:test-typecheck`).
- `pnpm lint` (`eslint . --no-inline-config`, the whole repo, not
narrowed) — exit 0.
- `pnpm --filter @objectstack/spec check:generated` — all 15 artifacts
up to date.
- Every heavy run went through `scripts/pm/os-verify-lock.sh`; verdicts
read from its
  `VERDICT command-exit` line.

## Acceptance notes

Observed while measuring, deliberately NOT changed here and not filed:

1. **These four describes account for `mode` only.**
`useNavigationOverlay` also reads `size`,
`openNewTab` and `preventNavigation`, and the TYPED sibling rows
(`object-kanban`,
`object-calendar`, the list-view entry) name all four members. On a
`z.unknown()` door the
describe is the whole account, so naming one member of four understates
the block — a
separate imprecision from the one this card carries. Carrier: the next
PR touching these
rows, or a decision to point these four doors at
`NavigationConfigSchema` the way their
   typed siblings already do.
2. **A stale comment in the sibling repo.**
`plugin-tree/src/ObjectTree.tsx` at the live pin
states "measured on the installed spec: `navigation` is declared on
exactly one
`ComponentPropsMap` entry, `object-grid`". It is now declared on
several. A comment in
   another repository with no contract behind it. Carrier: objectui.
3. N3 and N4 above remain open on the card, with fresh measurements
recorded there.


---
_Generated by [Claude Code](https://claude.ai/code)_

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:ui size/m tests tooling

Projects

None yet

2 participants