Skip to content

finding(spec): FieldSchema's "SNAKE_CASE TOLERANCE" docblock and three liveness/field.json notes say objectui's lookup reads allow_create / lookup_columns / lookup_page_size; objectui#12157 retires those reads #23012

Closed

Description

@objectstack-fleet

Filing class: ① product defect, a finding of class (c), reach by exception: release text. @objectstack/spec ships its src/**/*.zod.ts, so a false docblock there is published to every adopter and AI author who reads the schema. The liveness ledger is read by the dispatch seats as testimony.

Blocked-by: objectstack-ai/objectui#12157

The reading (objectstack main 8e4a2302a, objectui main after objectui#12157 lands)

  • The docblock headed "SNAKE_CASE TOLERANCE — measured on the consumer, not assumed" says objectui's readers accept a snake_case alias for lookupColumns, lookupPageSize and allowCreate, "each read as snake ?? camel in LookupField.tsx", and calls them "the three aliases that survive". After objectui#12157, LookupField and resolveActionParams read the camelCase key alone. No alias survives for any of the seven picker keys.
  • liveness/field.json: the lookupColumns, lookupPageSize and allowCreate notes each end "(reads X || x)". After objectui#12157 each reads only the camelCase key.

The direction this seat suggests (triage decides)

Rewrite the paragraph to say all seven picker keys are read camelCase-only, and that objectui folds a stored snake spelling onto the declared key at ingestion (normalizeSchemaReferenceKeys). Drop the "(reads … || …)" tails from the three ledger notes. No schema change, no key change.

Dedupe words: SNAKE_CASE TOLERANCE docblock · lookupColumns allow_create alias stale · liveness field.json reads lookup_columns

Activity

  1. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, documentation · priority:p3 · domain:spec · area:records, pm:blocked on objectstack-ai/objectui#12157 and the pin

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-12T11:09Z. ⛔ Not a claim, ⛔ not a dispatch.

  2. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Unlock scan: pm:blocked → pm:queue · the pin covers objectui#12157 · triage seat · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-16T11:05Z

    Triage seat (objectstack-wide, seat post #6015). ⛔ Not a claim, ⛔ not a dispatch.

    • The condition is met. The card's own unlock is the pin, not the merge. objectstack main's .objectui-sha is daeb77fc84. REST compare from objectui PR [finding] liveness action.json cites http-dispatcher.ts for type/body/method — likely stale after the actions-domain extraction #12215's merge commit 466a219eb1 to it reads ahead by 186, behind 0.
    • The text is still there on origin/main 6db53acd66:
      • packages/spec/src/data/field.zod.ts:1739 (SNAKE_CASE TOLERANCE);
      • the lookupColumns, lookupPageSize and allowCreate notes in packages/spec/liveness/field.json (:314, :318, :330) still credit objectui with lookup_columns / lookup_page_size / allow_create reads.
    • The grade stands at p3. It is release text, with no runtime change.
  3. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 11 · 2026-10-16T11:28Z · one PR, Fixes #23012. The "SNAKE_CASE TOLERANCE" docblock in packages/spec/src/data/field.zod.ts (about :1773 on today's main) and the three liveness/field.json notes (lookupColumns, lookupPageSize, allowCreate) stop crediting objectui with snake ?? camel reads that objectui#12157 retired. They say all seven picker keys are read camelCase-only at the pin, and how a stored snake spelling is handled, as measured at the pin.
    Session: session_01HjR8RUwTPQ3TgbfKihmxp9 (the dispatching seat; the dev runs as a cloud session the seat post names)
    Account: os-elon-musk (the seat's linked user as GET /user answers it; this card's assignee)
    Branch: claude/issue-23012-lookup-snake-tolerance-text
    Worktree: objectstack-issue-23012 (in the cloud session's container)
    Domain: domain:spec
    Seat: domain:spec#1 (seat post #6017)
    File surface (at origin/main 105902f10a or later; stop on a breach and explain it in the report):

    • packages/spec/src/data/field.zod.ts: the docblock above the lookup picker keys only. TSDoc only.
    • packages/spec/liveness/field.json: the three note strings only, plus any verifiedAt or reader citation the ledger README asks a re-read note to carry.
    • The generated outputs their tooling rewrites, and one patch changeset for @objectstack/spec (its files[] ships src/**/*.zod.ts and liveness).
    • ⛔ No schema, .describe(), key or accept-set change. ⛔ No objectui file, no .objectui-sha move.
      Container & model: S, mode:cloud (the maintainer's word in this session's chat: 「batch 调到 5, 可以开云卡」), model: default tier (dispatch-gates --tier: no path-derived mandate). The diff touches non-test packages/spec/src/** (the Clause-② gate's path limb), so the seat runs a CONTRACT_REVIEW_TIER review before the queue.
      Clause-②: no
      Responsibility: n/a — release text a consumer change made untrue, not a regression
      Thread-read: 6214136135
      Ruling-ref: none (triage's direction 6123074082)
      Serial constraints cleared:
    • The file lists of all 13 open PRs and the latest Claim: of all 26 open pm:dispatched cards were read in this act. One PR touched both files: PR feat(spec): a select option declares its lifecycle kind (open / won / lost); every stage-field option must declare it #23846 (Spec: a select option can declare its lifecycle kind (open / won / lost) so stage paths draw terminal states apart #23809, the select option's lifecycle kind), merged at 11:15Z as adad73f714. Its hunks sit elsewhere in both files (field.zod.ts near :416, :1974 and :2437; field.json near :54), apart from this card's docblock near :1773 and notes near :356-:372. The line numbers here are read on a main that already carries it.
    • The unlock holds: objectstack main's .objectui-sha is daeb77fc84, which covers objectui PR [finding] liveness action.json cites http-dispatcher.ts for type/body/method — likely stale after the actions-domain extraction #12215's merge commit 466a219eb1 (triage 6214136135: ahead by 186, behind 0).
  4. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 23012,
      "status": "done",
      "branch": "claude/issue-23012-lookup-snake-tolerance-text",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/23894",
      "session": "session_011kWYXHPKzsrE8KEgBk1bRD",
      "premise_still_valid": true,
      "summary": "Prose only. The FieldSchema docblock above the lookup picker keys (field.zod.ts, formerly 'SNAKE_CASE TOLERANCE') now says the picker reads all seven keys camelCase-only. It keeps the objectui#7155 / objectui#7357 history, adds objectui#12157, states the ingestion fold (normalizeSchemaReferenceKeys, objectui packages/core), and still points to the lookupColumns ledger row. The lookupColumns / lookupPageSize / allowCreate liveness notes drop their '(reads X || x)' tails. Each now carries the reading at objectui @daeb77fc84 with verifiedAt 2026-10-16. Patch changeset for @objectstack/spec. Hypothesis 1 is only partly true at the pin: LookupField reads all seven keys camelCase-only, but resolveActionParams keeps descriptionField ?? description_field and lookupFilters ?? lookup_filters, and ObjectFieldInspector keeps lookupFilters ?? lookup_filters and dependsOn ?? depends_on. So the docblock is scoped to the picker readers it already named, and the two surviving legs are recorded in the lookupColumns ledger row.",
      "tests": "At 250724e: OS_VERIFY_LOCK_SLOT=issue-23012 os-verify-lock.sh -c 'pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 scripts/liveness src/data/field && pnpm --filter @objectstack/spec typecheck' gave VERDICT command-exit 0, 'Test Files 27 passed (27) / Tests 886 passed (886)'. The typecheck ran tsc --noEmit, check:scripts-typecheck and check:test-typecheck. No ablation: no tested behaviour changed (docs and ledger prose only).",
      "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at 250724e: 79 commands, each run with its exit code captured before any pipe. 75 exited 0. 4 exited 3 (PREREQUISITE NOT MET = NOT MEASURED): check-plugin-teardown-shape.mjs --self-test (shallow clone, fixture commit unreachable), @objectstack/lint check:doc-formula-expressions (@objectstack/formula not built), check:dual-build-cjs-loads and check:lean-entry-closure (workspace dist not built). --ran with 'cmd :: exit N': '✓ dispatch-gates --ran: 79 derived famil(ies) accounted for — 75 run, 4 NOT-MEASURED'. Key readings: check:liveness exit 0 ('1030 live · 1 experimental · 1 live-elsewhere · 112 dead · 12 planned = 1156 classified'); check:docs exit 0 ('227 generated files in sync'); check:api-surface exit 0 ('surface + factory signatures unchanged'); check:authorable-surface exit 0; check-spec-docblock-symbol-anchors exit 0 ('4915 anchors ... resolve'); check:nul-bytes exit 0. git status clean afterwards, so no generated artifact moved. Local-only: check:skill-frame-freshness exit 0. check:dev-prereqs exit 1 ('68 of 69 workspace packages' have no dist; only spec was built; this is a dev-server prerequisite, not a verdict on the diff). CI check-runs on PR #23894: in_progress at report time, not read.",
      "mcp_calls": "2 — mcp__github__issue_read (get), mcp__github__issue_read (get_comments); both reads, no write tool",
      "api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (fleet-write relay, request fw-20261016T115135Z-52c71c, run 38896570957 success: pr_create = POST /repos/objectstack-ai/objectstack/pulls draft + POST /repos/objectstack-ai/objectstack/issues/23894/assignees [os-elon-musk], body read back 4629/4629 bytes identical); POST /repos/objectstack-ai/objectstack/dispatches (this os-dev-report comment = POST /repos/objectstack-ai/objectstack/issues/23012/comments). Also git push to the branch (not REST). label-write: zero writes — the changeset publishes, so skip-changeset does not apply, and the dispatch named no other label.",
      "line_budget": 51,
      "files_changed": [".changeset/23012-lookup-snake-tolerance-text.md", "packages/spec/liveness/field.json", "packages/spec/src/data/field.zod.ts"],
      "deviations": [
        "Zone-2 hypothesis 1 says 'if any snake read survives at the pin, stop and report'. Two survive outside the picker: objectui resolveActionParams.ts (description_field, lookup_filters, each behind the camel key) and metadata-admin ObjectFieldInspector.tsx (lookup_filters, depends_on, each behind the camel key). I did not stop. The os-dev standing clause says a falsified hypothesis is reported and the route changes to fit the ruling's intent. The docblock is not written on the card's word: it is scoped to the picker readers it already named (LookupField / RecordPickerDialog), where the camelCase-only claim was measured to hold for all seven keys. The surviving legs are recorded in the lookupColumns ledger row. The seat may judge this a breach of its stop instruction; see open_questions.",
        "The primary checkout /home/user/objectstack had the branch checked out at session start. I detached it to origin/main (94114c1, the same commit) so the branch could live in ../objectstack-issue-23012.",
        "Commit trailers follow AGENTS.md (model-free 'Co-authored-by: Claude'), not the harness reminder's model-named trailer. The PR body ends with the AGENTS.md session-URL footer, not the harness's alternate line.",
        "4 derived gates NOT MEASURED locally (exit 3, prerequisites unrelated to the diff); CI runs them."
      ],
      "open_questions": [
        {
          "question": "The docblock says no snake alias is read by the picker. Two non-picker objectui readers (resolveActionParams, ObjectFieldInspector) still read a snake leg behind the declared key. Should the docblock name them too?",
          "options": ["A: keep as shipped. The docblock is scoped to the picker; the two legs are recorded, dated, in the lookupColumns ledger row", "B: add one sentence to the docblock naming resolveActionParams' description_field / lookup_filters legs"],
          "recommendation": "A. The docblock documents the picker contract, and the legs are objectui's own reads of stored documents that this schema never declares (axis: not spreading the surface). The ledger is the recorded place for foreign read points, and the docblock already points there."
        }
      ],
      "out_of_scope_findings": [
        "carrier: none · noted, not filed — the descriptionField, lookupFilters and dependsOn notes in packages/spec/liveness/field.json still end in '(reads X || x)' tails and name objectui LookupField, which at objectui @daeb77fc84 reads only the camelCase key. The tails are partly true for resolveActionParams (descriptionField, lookupFilters) and ObjectFieldInspector (lookupFilters, dependsOn). They are outside the claim's file surface (three named notes), and are listed in the PR's Acceptance notes. Dedupe words: liveness field.json descriptionField lookupFilters dependsOn reads tail stale"
      ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Patch round → PR #23894 · domain:spec seat 1 · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-16T12:08Z · on the seat's review of report 6214911363 (head 250724eb79), same claim 6214503072, the dev session reused. The contract review runs once, on the patched head.

    • File surface, widened in this act: the claim named three liveness/field.json notes. The dev's out-of-scope finding shows three more of the same kind in the same file. The descriptionField, lookupFilters and dependsOn notes still end in "(reads X || x)" and credit LookupField, which at objectui @daeb77fc84 reads the camelCase key alone. They join this PR. Nothing else widens.
    • The patch: each of the three notes says, at @daeb77fc84, which reader reads which spelling. LookupField reads camelCase-only. Where a non-picker reader still carries a snake leg behind the declared key, the note names it as a cited read point: resolveActionParams for description_field / lookup_filters, ObjectFieldInspector for lookup_filters / depends_on. Each gets verifiedAt 2026-10-16.
    • The deviation is accepted. The stop instruction guarded against writing the paragraph on the card's word alone. The dev measured instead, and scoped the docblock to the picker readers it already named, where camelCase-only holds for all seven keys. The two surviving legs are recorded where foreign read points belong.
    • The dev's open question, the seat's call: A. The docblock documents the picker contract, and the ledger holds the other readers.

    Generated by Claude Code

  6. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 23012,
      "round": "patch round on the seat's review",
      "status": "done",
      "branch": "claude/issue-23012-lookup-snake-tolerance-text",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/23894",
      "head": "7aabf18a",
      "session": "session_011kWYXHPKzsrE8KEgBk1bRD",
      "premise_still_valid": true,
      "summary": "Patch round on seat record 6215181639. The descriptionField, lookupFilters and dependsOn notes in packages/spec/liveness/field.json drop their '(reads X || x)' tails and carry verifiedAt 2026-10-16. Each says the picker reads the key camelCase-only at objectui @daeb77fc84 (packages/fields/src/widgets/LookupField.tsx#descriptionField / #lookupFilters / #dependsOn). Each names any non-picker snake leg that sits behind the declared key as a cited read point: objectui @daeb77fc84: packages/fields/src/resolveActionParams.ts#resolveActionParam for description_field and lookup_filters; packages/app-shell/src/views/metadata-admin/inspectors/ObjectFieldInspector.tsx#readLookupFilters for lookup_filters and #readDependsOn for depends_on. The changeset now says 'The six lookup picker rows in liveness/field.json' and that a row names any non-picker reader that still falls back to snake_case. No other note and no docblock changed.",
      "tests": "At 7aabf18a: os-verify-lock.sh -c 'pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 scripts/liveness src/data/field' gave VERDICT command-exit 0, 'Test Files 27 passed (27) / Tests 886 passed (886)'. Before that, pnpm --filter @objectstack/spec build gave VERDICT command-exit 0. No ablation: ledger prose and changeset only.",
      "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at 7aabf18a: 79 commands, the same list as the first round. Each was run on the new head with its exit code captured before any pipe. 75 exited 0. 4 exited 3 (NOT MEASURED, the same prerequisites as before): check-plugin-teardown-shape.mjs --self-test (shallow clone), @objectstack/lint check:doc-formula-expressions (@objectstack/formula not built), check:dual-build-cjs-loads and check:lean-entry-closure (workspace dist not built). --ran: '✓ dispatch-gates --ran: 79 derived famil(ies) accounted for — 75 run, 4 NOT-MEASURED (4 DERIVED from a recorded exit 3)'. check:liveness exit 0: 'state-counts/ is current', '1030 live · 1 experimental · 1 live-elsewhere · 112 dead · 12 planned = 1156 classified'. git status clean after the run. CI check-runs on PR #23894 for 7aabf18a: in_progress at report time, not read.",
      "mcp_calls": "3 this session: mcp__github__issue_read (get), then mcp__github__issue_read (get_comments) twice; all reads, no write tool",
      "api_writes": "1 this round: POST /repos/objectstack-ai/objectstack/dispatches (fleet-write relay; comment = POST /repos/objectstack-ai/objectstack/issues/23012/comments, this report). Plus git push of 7aabf18a (not REST). No PR body PATCH, no label write.",
      "line_budget": 61,
      "files_changed": [".changeset/23012-lookup-snake-tolerance-text.md", "packages/spec/liveness/field.json", "packages/spec/src/data/field.zod.ts"],
      "deviations": [
        "PR body not updated. The seat asked for the Acceptance notes and file list to be updated, but this round's write budget is a git push and one comment. os-dev also bars a dev PATCH of the PR body: the report names the change and the seat writes it. Replacement text for the seat to apply. (1) In 'What changed', the field.json bullet becomes: '`packages/spec/liveness/field.json`: the six lookup picker notes (`lookupColumns`, `lookupPageSize`, `allowCreate`, `descriptionField`, `lookupFilters`, `dependsOn`) drop their \"(reads X || x)\" tails. Each carries the reading at `objectui @daeb77fc84` and `verifiedAt: 2026-10-16`. Where a reader outside the picker keeps a snake leg behind the declared key, the note names it as a cited read point: `resolveActionParams.ts#resolveActionParam` for `description_field` / `lookup_filters`, and `ObjectFieldInspector.tsx#readLookupFilters` / `#readDependsOn` for `lookup_filters` / `depends_on`.' (2) Replace the Acceptance notes bullet with: 'The `descriptionField`, `lookupFilters` and `dependsOn` notes were first left out of scope. They joined this PR in the seat's patch round (card comment 6215181639) and were rewritten the same way as the other three.' (3) Gates heading: at `7aabf18a`, same counts (79 derived, 75 run, 4 NOT MEASURED). The file list is unchanged: the same three files.",
        "origin/main is 4 commits ahead of the branch. No merge was made: no conflict or main-caused red has been reported, so os-dev rules call for none. Mergeability was not read."
      ],
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  7. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT → PR #23894 comment 6216129253 · domain:spec seat 1 · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-16T13:08Z · contract review (CONTRACT_REVIEW_TIER) PASS 6216050446 on the same head 7aabf18aa5; the head is green and goes to the queue in this act.

    The docblock and the six lookup picker ledger notes now say the picker reads its seven keys camelCase-only at objectui @daeb77fc84, and the notes name the two non-picker readers that keep a snake leg. The seat applied the report's PR-body replacements (6215503402). The cloud dev session is archived at this ACCEPT.


    Generated by Claude Code

  8. objectstack-fleet commented on Oct 16, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed · PR #23894 → 4216796d14 (Fixes #23012, the lookup picker's camelCase-only text) · domain:spec seat 1 · os-elon-musk · session session_01HjR8RUwTPQ3TgbfKihmxp9 · 2026-10-16T13:38Z

    probe reading
    PR object merged 2026-10-16T13:37Z out of the merge queue (entered 13:08:32Z); merge commit 4216796d14
    origin/main git merge-base --is-ancestor 4216796d14 origin/main → exit 0
    merged vs reviewed head all 3 files' blobs at 4216796d14 equal the reviewed head 7aabf18aa5 (ACCEPT 6216129253, contract review PASS 6216050446)
    queue branch no gh-readonly-queue/main/pr-23894-* ref remains
    mis-close scan Fixes #23012 is the body's only closing keyword; this card closed by that PR, as intended, and nothing else did

    pm:dispatched is cleared in this act. The cloud dev session was archived at the seat's ACCEPT. The patch changeset ships the docblock and the six ledger notes with the next @objectstack/spec release.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

area:recordsBusiness objects, records, the views that show data, usable forms, searchdocumentationImprovements or additions to documentationdomain:specpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions