fix(spec): declare allDayField on CalendarConfigSchema, the key the object-calendar prescription already names - #17877
Conversation
…iption already names
The object-calendar door refuses a flat `allDayField` and prescribes
`calendar: { startDateField, endDateField, titleField, colorField, allDayField }`,
and that block's `calendar` prop `.describe()` publishes the same five-key shape
to the generated reference docs. `CalendarConfigSchema` was a strictObject of
four keys and refused the prescribed shape by name, so an author who followed
the diagnostic verbatim on a stored view was refused a second time, by a
different schema, with a different message.
Measured which half was wrong rather than picking: the key is honoured, not
inert. At the objectui pin this repo builds against, ListView's
`collectViewFields` reads `calendar.allDayField` into the fetch projection and
its calendar branch forwards the authored block onto the object-calendar node,
where `getCalendarConfig` resolves it; objectui made it load-bearing in the
render itself. It is a field binding like its four neighbours, which is what
separates it from `defaultView` -- a UI preference that keeps its own declared
home as an object-calendar component prop and stays refused here.
Pinned in both directions: the prescribed shape is accepted at the config
schema and through the stored-view door, and the flat spelling, `defaultView`
and an unknown key are all still refused. The lead pin reads the key list out
of the prescription the runtime prints and asks the config schema to accept
each one, so a future diagnostic naming a non-member goes red on the class.
Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MkQhmuuJAVDjmeWNixwDDH
…e changeset Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MkQhmuuJAVDjmeWNixwDDH
…lendar-config-alldayfield
📓 Docs Drift Check1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them. What this run could not see
Coarse fallback — 136 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 2ea2254e8cf827a110487c4413d173c34b64376f && git checkout 2ea2254e8cf827a110487c4413d173c34b64376f
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 7cab0d8723b2be6cc5fd08c60b527a0f31b84edb 7803e3d6fd3def538d9ee33ba1609c2d3921c5de && git checkout -B drift-repro 7cab0d8723b2be6cc5fd08c60b527a0f31b84edb && git merge --no-ff 7803e3d6fd3def538d9ee33ba1609c2d3921c5de
node scripts/docs-audit/affected-docs.mjs --json 7cab0d8723b2be6cc5fd08c60b527a0f31b84edb |
|
os-contract-review ESCALATE TO MAINTAINERThe round's work holds. I tried to break it and could not: Q1, Q2 and Q4 pass, the cost-direction pins are load-bearing under ablation, and the round's correction of its own dispatch statement is itself correct. What this tier cannot supply is the authority. This change widens a published accept set and grows the published authorable surface on a Q1 — Is the widening warranted? YES. The key is honoured by a real consumer at the pin, with one scope correction.Read at
Control (the instrument could have come back empty, and did). Same command, same file, same pinned blob:
Claim 2 — is the Q2 — Is the opening exactly one key wide? YES, and the cost pins are load-bearing.Direct shape reading, not inferred from the diff. Probing
Anything else the diff lets through: nothing. Ablation A — cost direction, the "one key wide" pin. Mutation in my own worktree: add a second key (
Ablation B — cost direction, the lead class pin. Mutation: drop
⇒ five of nine cases are the cost direction, and two of them are measured load-bearing by ablation rather than asserted. Baseline at this head before any mutation: Claim 4 — is the round's correction of the dispatch statement itself correct? YES. Q3 — Does this belong on the manual floor? YES. It is the maintainer's, not this tier's.The standing floor hands the maintainer 功能新增, ADR, 协议/公开契约变化, 破坏性或难回滚动作, and its mechanical boundary test is explicit: 改动扩大接受集或公开面 ⇒ 人工;拉回已声明契约 ⇒ 代裁车道 (
⭐ And the direction itself is contested in writing, by the people who filed it, which is the signature of a ruling rather than a fix. The upstream twin objectstack#17140 — closed The counterweight, stated so the maintainer sees both: triage routed #17054 into ⇒ What I certify: the measurement. What I decline: the direction. Route this to the decision box. 维护者速读(一个问题)日历视图的「是否全天」绑定键 分歧只剩一件事:协议要不要正式收下这个键。收下,就是公开可写面多一项、发 A. 收下 —— 按本 PR 落地(schema 增一个键,文档与公开面同步,objectui#8831 转为「上游已收」)。 Q4 — Is anything owed that is missing? One small cross-repo notice. Nothing blocking.
What I did NOT measure
Tier statementThis is an in-seat at-tier review — the adjudicating subagent inherits the dispatching seat's session id, so it is ⛔ NOT an independent second seat, and it was dispatched with an explicit model parameter. Generated by Claude Code |
Contract review ADOPTED — verdict
|
| transcript | served model census |
|---|---|
this review round (a0a2a6230656bc070) |
claude-fable-5-1 ×75 — and no other model, zero turns |
control: the os-dev implementation round on this branch (aa3b8a559934912f5) |
claude-opus-5 ×109 |
CONTRACT_REVIEW_TIER read at scripts/pm/dispatch-gates.mjs:10176 → 'claude-fable-5-1'. Comparison is exact, never a family or prefix floor. ⇒ at tier. The control transcript is there so a census that returns one value everywhere cannot be mistaken for an instrument that only ever returns that value.
This PR is one of the rounds named by #17915 (contract reviews dispatched below CONTRACT_REVIEW_TIER). It is the one that was still open, so the re-run was preventive rather than post-hoc — and it earned its cost: the at-tier round found Q4, which the below-tier round missed. See the seat's disposition below.
Follow-ups from the verdict — both discharged before this adoption
- Cross-repo notice to objectui#8831 (ruling item 2, the seat's act) — posted: decision(types,plugin-calendar): objectui teaches the flat calendar field spellings as authorable; upstream Prime Directive #12 says they are read-only — reconcile objectui#8831 comment
5652138403, 2026-09-13T08:11:01Z. It names all four assertions and both stale docblocks, at line numbers this seat re-verified itself against objectuiorigin/main69aa9c017f527926ea11718c37e6583eeb18b5f1. Two corrections to the verdict's own line citations, from that re-reading: the refusal block incalendar-doc-key-set-8830.test.tsis:178-186(assertions at:181,:184,:185), not:180; and incalendar-flat-color-allday-8466.test.tsthe shape equality spans:416-421and the nested refusal:422-426. The verdict's:175and:416are exact. Neither correction changes the finding. api-surface/staleness — accepted as pre-existing and build-dependent, on the strength of the verdict's lit control (the same check exits 1 on the merge-base worktree in the same unbuilt state, with this PR absent). ⛔ No card filed from this PR.
Carriers
needs:contract-review hangs on both this PR and card #17054. The verdict returns PASS on measurement and the direction is settled by the ruling (os-tesla, card comment 5651571942), so both are being cleared now — two removals, seconds apart. A single removal would be a strip, not a clear.
⛔ The seat records, as the verdict itself asks: this round is an isolated subagent under the same seat session that dispatched the os-dev round. It is not an independent second seat.
Contract review — PR #17877, head 7803e3d6fd3
Tier self-check (first finding)
- Reading:
scripts/pm/dispatch-gates.mjs:10176→export const CONTRACT_REVIEW_TIER = 'claude-fable-5-1';(2026-09-13T07:52:56Z). Docblock at:10170: "served tier is EXACT, never a family or prefix floor". - Served model, harness-stamped in this transcript:
claude-fable-5-1. EXACT match. Nomodeldispatch parameter was taken as a reading. - Independence pair: this round is an isolated subagent under seat session
session_01MkQhmuuJAVDjmeWNixwDDH, which also dispatched theos-devround.Implemented-by: mode:subagent, branchclaude/issue-17054-calendar-config-alldayfield.Reviewed-by:the seat that adopts this verdict. Not an independent second seat — stated so the seat records it verbatim.
The prior round (5647331529, 2026-09-12T16:56Z) was read as premises only. Its findings were re-measured below; three of its cited line numbers held, one thing it missed is Q4.
Q1 — Clause ② judgment: yes is right.
Readings (07:57:01Z merge base 7c2c5aed, 07:57:04Z head 7803e3d6; tsx probe over src/ui/view.zod.ts + component.zod.ts):
mb: SHAPE_KEYS ["startDateField","endDateField","titleField","colorField"] allDayField ABSENT
head: SHAPE_KEYS ["startDateField","endDateField","titleField","colorField","allDayField"] optional? true
C2 four+allDayField mb: REFUSED unrecognized_keys ["allDayField"] → head: ACCEPTED
L2 ListView(calendar:{four+allDayField}) mb: REFUSED path ["calendar"] → head: ACCEPTED
Rule text (07:54:46Z): references/lanes/spec.md:19 「放宽接受集或扩大公开面的卡,不论多小,即条款②;收窄仍是语义面,不触条款②」; references/contract-review.md:13 「新导出符号或已发布载荷上的新键恒 yes」. Control grep zzqq_nonexistent → 0.
What widens: one key, allDayField: z.string().optional(), on CalendarConfigSchema — reachable through every published payload that embeds it (ListViewShapeSchema.calendar and the two other view shapes, generated docs rows at view.mdx:110/:947/:1344). Published: packages/spec files includes src/**/*.zod.ts and authorable-surface/ui.json gains ui/CalendarConfig:allDayField. Additive (Q3). node scripts/pm/check-clause2-carriers.mjs --pair 17877 → exit 0, both carriers agree (07:57:24Z).
Q2 — Implements the ruling, not its summary: yes, and nothing beyond it.
Ruling, os-tesla, card comment 5651571942, 2026-09-13T06:10:17Z, verbatim: maintainer 「16678 具体解释,计划用哪个字段判断经理。其他同意」 — 「其他同意」 covers this card (batch #127 item 2 = A). Execution clauses:
- "PR fix(spec): declare allDayField on CalendarConfigSchema, the key the object-calendar prescription already names #17877 is the delivery:
allDayFieldjoins thestrictObject,authorable-surface/ui.jsongains its one line,minorchangeset." — diff:view.zod.ts+28 (one key + TSDoc),ui.json+1 line,.changeset/17054-calendar-config-all-day-field.md"@objectstack/spec": minor. ✓ - "Cross-repo notice to objectui#8831 in the same round" — seat's act, not the PR's. objectui#8831 comments read 07:56:26Z: only the triage comment; notice not yet posted. Owed (see notes).
- "Nothing else moves: the flat spelling stays a runtime handoff … ⛔ not a second authorable spelling." —
component.zod.tsuntouched (diff = 7 files, none is it); probe O1 flatallDayFieldonobject-calendar: REFUSED at both mb and head, prescription text present at both. ✓
Scope the ruling does not name: 1 test file (pins, no contract effect) and 3 generated .mdx (regenerated output, Q6). No unrequested scope.
Q3 — Additivity: proven.
Probe: every input ACCEPTED at mb is ACCEPTED at head (C1, L1, O2); flips are exactly C2/L2 (REFUSED→ACCEPTED); negative controls unchanged (C3 bogusKeyXy, C4 defaultView, L3, O1). allDayField absent → C1/L1 parse identically at both. Required anywhere? No — C5 (allDayField alone) still fails on startDateField at both. One shape change worth naming: C6 allDayField: 1 refuses as invalid_type (was unrecognized_keys) — still refused, no narrowing. Ablation (08:03:52Z, under lock, merge-base worktree, test blob hash 57db78d4… identical to head blob): PR's pin file vs the mb schema → 3 failed | 6 passed (9), exactly the three acceptance cases, lead pin failing on "the prescription names allDayField, which CalendarConfigSchema refuses". Restore: 0 dirty paths.
Q4 — Blast radius: in-repo clean; ⚠ two objectui pins flip on the next spec bump — unnamed by the PR and by the prior round.
In-repo sweep (07:55:00Z, 07:56:26Z): files naming CalendarConfig outside spec src — packages/lint/src/validate-page-visualization-bindings.ts (comment only), examples/app-crm/src/views/activity.view.ts (four keys, no pin). Files naming startDateField in tests outside spec: 4 (lint/metadata-protocol) — all fixture values, no key-set/count pins. Control: colorField in corpus → 14 files; toBe(4) in spec src → 16. Liveness ledger: keyed per type, CalendarConfig rows 0, control colorField 0 — no row owed. state-counts.md regenerated → unchanged. authorable-surface.base.json untouched: correct (manual-only anchor).
objectui origin/main (69aa9c0), absent at pin 53ded82b, present on main:
packages/types/src/__tests__/calendar-doc-key-set-8830.test.ts:175expect(listed).toEqual(Object.keys(CalendarConfigSchema.shape).sort())and:180-182refused.success toBe(false)forallDayField.packages/types/src/__tests__/calendar-flat-color-allday-8466.test.ts:416Object.keys(CalendarConfigSchema.shape)).toEqual([four]),:422-423nestedallDayFieldsuccess toBe(false).
Both red the moment objectui installs a spec carrying this key (objectui main lockfile: @objectstack/spec@17.4.0). Control: list-view-spec-parity.test.ts:186 derives from the spec shape and does not flip — the PR's "nothing to do" claim covers only that file. Not a blocker here (different repo, lands on the bump), but it is the content the owed objectui#8831 notice must carry.
Q5 — Prescription: one spelling, exact match.
component.zod.ts:2918 keys list and :2921-2922 prescription literal calendar: { startDateField, endDateField, titleField, colorField, allDayField }; :2945 .describe('… allDayField? }') — optional, ships to component.mdx:312. Declared key allDayField, z.string().optional(). Spelling census in spec src excluding the PR test: allDayField ×7, no allDay/isAllDay/all_day variants (07:55:07Z).
Q6 — Generated artifacts: regenerated, not hand-edited.
Worktree at head: gen:schema (exit 0, 1534 schemas), gen:docs (exit 0, 222 files), gen:liveness-counts (exit 0) → git status --porcelain empty (07:58:52Z). check:generated: 14/15 green, api-surface/ stale. Lit control: check:api-surface on the merge-base worktree, same unbuilt state, PR absent → also exit 1 (07:59:30Z); api-surface/ carries 0 colorField (control CalendarConfigSchema 1); PR touches api-surface/ not at all. ⇒ build-dependent, pre-existing, not this PR's.
Q7 — CI, newest run per name, head 7803e3d6.
All 39 check runs completed; conclusions success or skipped. Lint & Repo Gates (job 103585518873) success, ran through its last step (check:duration-unit-keys OK at 16:58:46Z) — no first failure, no exit-3 shape, nothing unmeasured behind it. filter job: core=true (spec files) so Test Core 6/6 shards + aggregate ran on head. Duplicate names: Auto Label / Check PR Size skipped in run 24492 (16:37:56Z) — the same workflow's run 24491 (16:37:32Z, same sha) succeeded; skips are conditional jobs, not failures. PR-side CI is the affected subset — Q4 sweep covers the full-suite question for this repo.
Q8 — Prose invariants.
- TSDoc/changeset:
collectViewFieldsreadsallDayField— pinListView.tsx:1466/:1481/:1820/:1833✓; calendar branch spreads...(schema.calendar || {}):2448✓;getCalendarConfig:126-128/:137✓;.passthrough()rationaleobjectql.zod.ts:348✓;component.mdx:312✓. .describe(): "a record whose flag is true is drawn as an all-day band …; absent or false is not all-day; omit → no end date draws as all-day" — backed by objectui mainObjectCalendar.tsx:739allDay: allDayField ? Boolean(record[allDayField]) : !endDate. At the pin:555isallDay: !endDate— the drawn-output half is post-pin. Backed, correctly labelled post-pin in the TSDoc; note only.- Changeset "minor is the floor for this class" ✓ (
AGENTS.md:1040-1049; nothing removed → no ADR-0087 disposition owed).
Q9 — Changeset: owed, present, correct.
npm pack --dry-run --json (07:56:22Z, unbuilt so dist absent — irrelevant to the src glob): src/ui/view.zod.ts → 1 (positive), calendar-config-allday-prescription-17054 → 0, *.test.ts → 0 (negative), authorable-surface/ui.json → 0 (not published; docs/api-surface are). files = ["dist","json-schema","liveness","prompts","llms.txt","README.md","src/**/*.zod.ts",…].
Verdict: ACCEPT-WITH-NOTES
Follow-ups (no new file changes owed on this PR):
- Cross-repo notice to objectui#8831 (ruling item 2, seat's act, not yet posted) — must name
calendar-doc-key-set-8830.test.ts:175,:180andcalendar-flat-color-allday-8466.test.ts:416,:422as the first reds on the next@objectstack/specbump, plus the two stale docblocks. api-surface/staleness is pre-existing/build-dependent — no card from this PR.
Clause-② carriers: this round is at tier (exact) and returns PASS on measurement; direction is settled by the ruling. The carriers clear when the seat adopts this verdict verbatim and posts it (I wrote nothing to GitHub).
NOT MEASURED
- Full
pnpm --filter @objectstack/spec test(473/13443),test:repo,typecheck, repo-widelint— I ran 5 files / 720 tests + the ablation only. - Built-dist before/after table;
npm packafter build (dist half);check:dual-build-cjs-loads,check:type-check-debt. - Issue finding(spec):
OBJECT_CALENDAR_FLAT_FIELD_KEYS' prescription tells authors to writeallDayFieldinsidecalendar: {}— butCalendarConfigSchemais strict and refuses it by name #17140 body; the prior round's ablations A/B (mine was a different one); objectui test execution; any browser rendering.
Generated by Claude Code
|
Served-tier: 75/75 Verdict record in the ruled shape —
|
| field | value |
|---|---|
| Served-tier | 75/75 claude-fable-5-1 — census of the harness-stamped served-model field over every assistant turn of the reviewer's transcript, taken 2026-09-13T08:11:58Z |
CONTRACT_REVIEW_TIER |
'claude-fable-5-1', read at scripts/pm/dispatch-gates.mjs:10176 |
| comparison | EXACT — equal |
| below-tier turns | 0 |
| control | a different transcript (an os-dev round this session) read claude-opus-5 ×109 — so the probe can return non-fable, and the zero above is a reading, not a dead instrument |
| verdict | ACCEPT-WITH-NOTES |
| carriers | cleared 08:12:39Z (PR) and 08:12:41Z (card #17054) — two removals, seconds apart |
⛔ The reading is not the dispatch model parameter. ⛔ It is not a bare model-name token grepped out of the transcript body — that probe has a documented false-positive mode (objectui seat, comment 5651573578 on #17915: an adopted verdict quoted back into a later round plants a model-name token in its transcript, so the false-positive rate grows with adoption of this very discipline, biased toward falsely voiding good rulings). This census parses each transcript line as JSON, keeps only records whose type is assistant, and reads the structured message.model key — the harness stamp itself, never prose.
Generated by Claude Code
Fixes #17054
CalendarConfigSchemanow declaresallDayField, the fifth field binding on a calendar config.The two sentences, and which one was wrong
The
object-calendardoor refuses a flatallDayFieldand prescribes, verbatim from its own diagnostic:CalendarConfigSchemawas astrictObjectof exactly four keys and refused that shape by name.The round measured which half was wrong rather than picking the convenient one, and the answer is (a) — the schema was missing a key that is honoured. It is not (b): trimming the prescription would leave a shipped, honoured capability with no protocol carrier.
The evidence, read at the objectui pin this repo builds against (
.objectui-sha=53ded82bf7a494f54e344e19099dbf00854b8694, read withgit show PIN:path, not at that checkout's HEAD):packages/plugin-list/src/ListView.tsx—collectViewFieldsreadsv.allDayFieldoffschema.calendarandschema.options.calendarat two sites, feeding the$selectprojection and the$expandset. The authored nested key already changes what the server is asked for.case 'calendar':branch spreads...(schema.calendar || {})onto theobject-calendarnode, so the nested key reaches the block.packages/plugin-calendar/src/ObjectCalendar.tsx—getCalendarConfigresolves it into the calendar config.packages/app-shell/src/views/ObjectView.tsx— the dev-mode Spec Compliance warning listsallDayFieldamong the flat keys an author must move underviewDef.calendar: a third face prescribing the nested spelling.packages/types/src/zod/objectql.zod.ts— the mirror keeps.passthrough()and names this key as its reason: "the renderers grow config knobs ahead of the protocol (calendar'sallDayField, for one), and stripping them here would silently disable a shipped capability."main, the renderer makes it load-bearing:allDay: allDayField ? Boolean(record[allDayField]) : !endDate.⭐ A widening is not made acceptable by the diagnostic having promised it. This one is right because the renderer honours the key — the prescription merely happened to be the accurate half.
The countervailing reading, stated plainly. objectui
maincarries a comment declaringallDayFieldobjectui-LOCAL, in the same class as its sanctioneddefaultView, and concluding "honouringallDayFieldwidens no accept set". That is a true statement about what objectui needed in order to honour it, and it does not bind what the protocol may declare. The two keys are not the same class from this side:defaultViewis the renderer's initial view mode, a UI preference that already has a declared home as anobject-calendarcomponent prop;allDayFieldis a field binding, the same kind as its four neighbours, and it had no home at all.defaultViewstays refused on this config, pinned.A correction to the card's framing, measured
The card reads as though the prescribed shape is refused at the door that printed the prescription. It is not.
ObjectCalendarPropsSchema.calendarisz.unknown(), so the block acceptscalendar: { …, allDayField }today. The second refusal lands one door over, on stored view metadata —ListViewShapeSchema.calendarisCalendarConfigSchema— which is how calendars are actually authored in this product. The trap is real; the two doors are just not the same door. Both readings are in the before/after table.Measured against the BUILT dist, before and after
Build first and confirm both passes finished (
check-dts-emitted: 34/34 declared declaration file(s) present), then parse through the package's own./uiexport.{ objectName, allDayField }flatobject-calendarunrecognized_keyskeys=["allDayField"]calendar: { four, allDayField }object-calendar{ four, allDayField }CalendarConfigSchemaunrecognized_keyskeys=["allDayField"]calendar: { four, allDayField }ListViewSchemaunrecognized_keysatpath: ["calendar"]{ four }CalendarConfigSchema{ four, bogusKeyXy }CalendarConfigSchemaThe exact refusal texts, before:
object-calendar:Unrecognized key(s) on this \object-calendar`: `allDayField`.` followed by the prescription quoted above.Unrecognized key(s) on this calendar configuration: \allDayField`. Until these shapes were closed an unknown key was dropped silently — the view still rendered, without whatever the key was meant to configure.`After, the first is byte-identical and the second is gone — replaced by acceptance. The bogus-key control still produces that second text verbatim with
keys=["bogusKeyXy"], which is what proves the message did not change, only the membership.Pins, both directions
packages/spec/src/ui/calendar-config-allday-prescription-17054.test.ts, 9 cases. They import./view.zodand./component.zod—src/, notdist/, so no rebuild leg is needed for the ablation, and that is measured rather than assumed.Accepted: the prescribed shape at the config schema; the same shape through the stored-view door where the second refusal used to land; the same view without the key as a control.
⭐ The lead pin is written on the defect CLASS, not on one key: it reads the key list out of the
calendar: { … }shape the runtime's own prescription prints and asks the config schema to accept each name, with a floor on the extracted list so an empty extraction cannot make it vacuously true. Any future diagnostic that names a non-member goes red here, including a key nobody has thought of yet.Still refused — what the widening did NOT cost: the flat
allDayFieldonobject-calendar(one key per concept, and the refusal still carries the prescription);defaultViewon the config, so the opening is exactly one key wide; an unknown key, in the same message shape, at the config and atpath: ["calendar"]; andstartDateFieldis still required, soallDayFieldalone is not a calendar binding.Ablation
Mutation: rename the declaration to
allDayFieldAblatedinpackages/spec/src/ui/view.zod.ts. Absolute paths,trap '…' EXIT INT TERM.On-disk proof read FIRST, before the run: declaration occurrences
1 → 0, injected text0 → 1, and the file'sgit hash-objectmoving3ecc02a254265786fc29c146408479ed072ee462 → 560dc1d3299460e582e04d0a727a89600e6d23ba. The run then aborts itself if the injected text is not present exactly once.Predicted direction: RED. Observed:
3 failed | 6 passed (9), exit 1 — exactly the three acceptance pins, with the lead pin failing on its own sentence: "the prescription namesallDayField, which CalendarConfigSchema refuses". GREEN after restore:9 passed (9), exit 0.Restore proven by hash, not by an exit code:
git checkout HEAD -- ABSOLUTE_PATH(never the bare form, which reads the index), restored hash3ecc02a254265786fc29c146408479ed072ee462equal to the HEAD blob, with an empty-hash guard treating a missing read as FAILURE, andgit diff HEADempty.Changeset
.changeset/17054-calendar-config-all-day-field.md, grademinor— a published accept set widens, andminoris the floor for this class. Notskip-changeset, measured rather than assumed, withnpm pack --dry-run --jsonafter a build and controls in both directions over the packed file list (2012 files):allDayField→ 52 published files.startDateField(a sibling key that must publish) → 55.bogusKeyXy, which lives only in the new test file → 0.*.test.tsfiles publish at all.packages/specalso shipssrc/**/*.zod.tsas source and its tsup does not strip comments, so a source comment is published text: the probe phrase from the new TSDoc block appears in 23 published files. Controls were picked accordingly.Purely additive — nothing that parsed before is refused now, and no key is renamed or removed, so there is no ADR-0087 disposition to declare.
Verification
Head
7803e3d6fd.origin/mainmerged viascripts/pm/os-regen-merge.shbefore opening; main brought driver-sql and lint changes only, nopackages/spec, and no contact with PR #17796'sui/view.zod.tshunks — that PR is not addressed here and remains open.Every number below is from the final head, after the merge.
pnpm --filter @objectstack/spec test(--project local) :: exit 0 — 473 files / 13443 tests, 0 skipped.pnpm --filter @objectstack/spec test:repo(--project repo, the cross-corpus scanners) :: exit 0 — 30 files / 520 tests. ⭐ Run separately on purpose:testis not the whole suite.pnpm --filter @objectstack/spec typecheck:: exit 0 — includingcheck:test-typecheck(shrink-only ledger held).pnpm --filter @objectstack/spec check:generated:: exit 0 — all 15 generated artifacts up to date;authorable-surface/ui.jsongained exactly one line,ui/CalendarConfig:allDayField, andauthorable-surface.base.jsonwas not touched.pnpm lint(eslint . --no-inline-config, repo-wide) :: exit 0 — no narrowing claimed.node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack, re-derived on the merged head and identical to the pre-merge derivation: 106 derived, 104 run green, 2 NOT MEASURED, 0 unrun (--ranreconciliation exits 0). Exit codes captured before any pipe.pnpm check:dual-build-cjs-loadsandpnpm check:type-check-debt, both exit 3 — PREREQUISITE NOT MET. Each needs every workspace package built (turbo run build --filter='./packages/*' --filter='./packages/*/*'), which is the whole-farm run CI owns; nothing about them is answerable from a spec-only closure. This is a declared narrowing, not a skipped gate, and their verdicts are CI's.pnpm check:nul-bytes:: exit 0, plus a direct scan of all seven changed paths for the wider control-byte class — no match, grep exit 1.Clause-②: yes — this widens a published accept set, so the round's measurement agrees with the value declared at dispatch.
needs:contract-reviewrides on both carriers and this does not enqueue without an at-tier verdict on the head that lands.验收备注
Out of scope, noted and not filed — each with its carrier named:
ObjectCalendarPropsSchema.calendarisz.unknown(), so the component door validates nothing about the config it names in its own.describe(). Tightening it toCalendarConfigSchemawould narrow a published accept set and needs its own ruling; it is not a defect, it is an unbuilt door. Carrier: whoever next converges the component-door configs.ObjectCalendardocblock both state thatallDayFieldis not a spec key. Once this lands, both are stale. objectui#8831 is already the declared follow-up and triage named it, so this is not a new card. Carrier: objectui#8831.list-view-spec-paritypin listsdefaultViewas the only sanctioned local key on the calendar config; the mirror derives from the spec schema, so it picks up this key without an edit. Nothing to do, recorded so the next reader does not go looking. Carrier: objectui#8831.Generated by Claude Code