Skip to content

spec(types): group E of objectui#7759 — five runtime slots still carry a z.function() mirror the objectui#6124 sweep missed #9091

Description

@os-warren

Filed unassigned by the domain:spec@objectui PM seat, session session_01Jmxdo7bmeqCQHLSfmLVX9w, carving group E out of objectui#7759 so it can be implemented. objectui#7759's own charter is measurement-and-proposal — "this card changes no source file and opens no PR" — so the implementation lane needs its own card. ⛔ objectui#7759 stays open and unclaimed.

A ruling already exists and this is the part its sweep missed. Director batch #112 delegated exactly this to the seat: 「E 组由席位按 #6124 直接派」 — dispatch group E against objectui#6124 directly, ⛔ without spending a maintainer letter.

The ruling

objectui#6124, maintainer ruling 2026-08-30 (Q2 → A with C): replace z.function() handler mirrors with a named refusal arm. The machinery is in-tree — handlerKeyRefusal(key, disposition, label?) at packages/types/src/zod/tombstone.zod.ts:109, with HandlerKeyDisposition at :69.

Premise re-derived on origin/main before filing

reading value
handlerKeyRefusal defined tombstone.zod.ts:109
surviving z.function( in data-display.zod.ts (907 lines) 3
surviving z.function( in form.zod.ts (861 lines) 2

The control that makes this a residue and not an unswept file: handlerKeyRefusal( already appears in data-display.zod.ts and 20× in form.zod.ts. ⇒ the objectui#6124 sweep demonstrably did reach these exact files; these five are what it left behind. A file the ruling never touched would show 0.

Sites located (⛔ re-derive every address — this seat has had line numbers rot twice tonight):

  • data-display.zod.ts:157cell: z.function().optional().describe('Custom cell renderer')
  • data-display.zod.ts:314renderCellEditor: z.function().optional().describe(…)
  • form.zod.ts:175validate: z.function().optional().describe('Custom validation function')
  • form.zod.ts:186custom: z.function().optional().describe('Custom condition function')

⚠️ objectui#7759's proposal F moves FormFieldSchema::validation into this group: measured member-by-member it is not structural — FieldConstraintsSchema and FieldValidationRules agree on all seven members except validate, which is the z.function() above. On main, form.zod.ts:618 is validation: FieldConstraintsSchema.optional() and :619 is condition: FieldConditionSchema.optional() — both structural references whose referenced schema carries the function. ⭐ Decide explicitly whether fixing FieldConstraintsSchema::validate and FieldConditionSchema::custom discharges them, and say which.

⚠️ data-display.zod.ts:250 is NOT one of these

cell: retirementTombstone('RETIRED (objectui#5474) — never read by the static table; use data-table') — already retired by a different ruling, a different mechanism. ⛔ Do not touch it, and ⛔ do not confuse it with :157, which is a live z.function() on a different schema.

What is owed

  1. Re-derive the surviving z.function() population yourself, with the handlerKeyRefusal count as your firing control, and report it. ⛔ Do not trust the figures above.
  2. Convert each to a named refusal arm using the existing handlerKeyRefusal machinery. ⛔ Do not invent a second mechanism — 20 call sites in one file are the house pattern.
  3. ⭐ Each key's HandlerKeyDisposition is a judgement about what the TypeScript twin does. Read the twin per key and say what you read; ⛔ do not pick a disposition by analogy with a neighbour.
  4. A firing control per key: the refusal must be shown refusing by name, and a control key that still parses green.
  5. ⚠️ renderCellEditor's docblock says "z.function() encodes no parameter shape, so the member on DataTableSchema is the authority for it". ⛔ Check whether the refusal preserves that pointer, or whether it strips the only place the parameter shape is documented.

Clause-②: yes — this narrows the accept set on a published authoring face, which is exactly why director batch #112 put every mirror-narrowing proposal at yes. ⛔ Declared yes on that ground and on the charter tie-break, ⛔ not because a widening tell fired.

⛔ The maintainer's ordering rule governs this card

Verbatim, from the director's batch #112 note: 「我们的项目以 objectstack 协议为准,文档应该以实际实现为准。协议不正确的应该先修改协议。」 and its ordering gloss: 凡「实现或立 spec 卡退役」处,先判协议对不对;判协议不对的,spec 卡先行、本卡阻塞其上。

⇒ ⛔ Never narrow or widen a spec-declared shape locally in objectui. ⛔ Never add an author-writable key the spec does not declare. If you judge the protocol itself wrong, the deliverable is stop and say so — a spec card goes first and this card blocks on it.

Standing rules — read every line, they are not boilerplate

Identity. The card is assigned and the Claim: on it is yours; it names your branch. ⛔ Never write the assignee field. ⛔ Never post a second Claim:. If the newest Claim: names another branch, stop and report.

Container hazards.

  • /home/user/objectui is SHALLOW with a STALE origin/main. ⛔ Never git fetch, git checkout, or cut a worktree there. Clone fresh into your own scratchpad subdirectory.
  • /home/user/objectstack is a shared primary checkout — read-only.
  • ⛔ Never git stash. ⛔ Never kill a process by name. ⛔ Never mutate node_modules. ⛔ Never touch content/docs/releases/.
  • ⛔ These do NOT exist in objectui and are never a red you can wait for: scripts/pm/os-regen-merge.sh, scripts/pm/check-widening-tells.mjs, scripts/pm/check-clause2-carriers.mjs.

Measurement discipline.

  • Never write "(no output above = clean)" or any unconditional false-clean echo. Print the command and the exit code.
  • ⭐ A control is only a control if it is known to fire in the region being tested. ⚠️ Two true negatives are not a reading.
  • ⛔ A bad probe value is not a reading — a multi-line grep -F pattern is split into OR'd patterns and is one. ⛔ An empty gate section is a FAILED RUN.
  • ⛔ Never quote a bare grep -c without its exact command.
  • A claim written in the tree is a claim, not a reading — a docblock, a card body, a triage comment. Three devs refuted this seat tonight by measuring something I had quoted from in-tree prose. Refute me the same way if the measurement says so.
  • Read the stored body back after every GitHub write and report what came back.

Deliverable. Worktree → code → tests → changeset → push → draft PR carrying needs:contract-review. ⛔ Do not flip ready, ⛔ do not enqueue, ⛔ no auto-merge — landing is the seat's. Report structured JSON: PR number and head sha, every premise confirmed or refuted with exact commands, your firing controls, and CI as total / success / skipped / non-green plus whether the reported total_count equals the returned array length.


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions