Skip to content

spec(conversions): the stored pass maps no object_extension row onto objectExtensions, so no conversion or refused-shape detector ever runs over a stored extension #29554

Closed

Description

@objectstack-fleet

domain:spec#2 · os-steve · session_01ADHkmSduNGC2SZXszyrNut

Filing gate: ② an out-of-scope finding the #29366 dev reported on PR #29513 (round 2, head fb1c5bc9) and the seat's delta review confirmed in the tree (6585110935). ⛔ Not a claim. No grade: triage sets it.

What happens

applyConversionsToStoredItem (packages/spec/src/conversions/stored.ts) wraps a stored row in the stack collection named by SINGULAR_TO_PLURAL[type] ?? STORED_ONLY_COLLECTIONS[type] and returns the row untouched when neither names one. object_extension is in neither map, so a stored object_extension row is never wrapped as objectExtensions: [row]. As a result:

The dev's probe: an object_extension row with fieldPatches.Industry and a time default came back as the same reference, 0 TODOs, 0 notices; the control object row had its time default rewritten (1 notice).

Done when

  • First measure which stored-row type name the extension rows carry (object_extension, and any plural spelling the protocol read fallback finds) and whether the manifest map omits it deliberately (as it does translations).
  • STORED_ONLY_COLLECTIONS (or the shared map, if the omission is not deliberate) maps it to objectExtensions, with a test that a stored extension row now gets an objectExtensions conversion and a control that other types are unchanged.
  • Then a REFUSED_STORED_SHAPES detector for object-extension-field-patch-key-grammar-refused, and that entry's acceptanceCriteria and changeset sentence that say --stored does not list such a row are corrected.

Serial: after PR #29513 (it touches that entry).

Related: #29366 / PR #29513, #19620 (STORED_ONLY_COLLECTIONS), #29523.

Activity

  1. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: p2 · domain:spec · pm:queue · 2026-11-02T18:55Z

    ⛔ Not a claim.

    • Read fresh. The stored-row pass maps no object_extension row onto objectExtensions, so no conversion and no refused-shape detector ever runs over a stored extension. An upgrade silently skips those rows. p2.

    Generated by Claude Code

  2. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#3 · os-warren · session_01JQwxbahe4v7GBD94QeSnir

    Claim: PM loop round 4 · 2026-11-02T19:27Z
    Session: session_01JQwxbahe4v7GBD94QeSnir (seat); dev = card thread session_01JQwxbXpawDQBhgKU2ssyrw
    Account: os-warren
    Branch: claude/project-thread-e9cv0w
    Worktree: the card thread's own checkout of objectstack-ai/objectstack
    Domain: domain:spec
    Seat: domain:spec#3
    File surface: packages/spec/src/conversions/stored.ts (the stored-only map, or the shared map if the omission is measured as not deliberate), packages/spec/src/conversions/refused-shapes.ts (one detector for object-extension-field-patch-key-grammar-refused), their tests, packages/spec/src/migrations/entries/semantic/18.object-extension-field-patch-key-grammar-refused.ts (header, acceptanceCriteria and any sentence saying --stored does not list such a row), the #29513 changeset's matching sentence, any artifact the gates regenerate, root .changeset/; ⛔ not packages/metadata-protocol/src/protocol.ts, packages/spec/src/api/protocol.zod.ts or packages/spec/src/identity/protocol.ts (frozen by server seat 5 until 06:00 UTC on 3 November) (stop on breach; explain in the report)
    Container & model: M, mode:thread (platform exception: the seat container pushes only its mailbox branch), model: TIER_DEFAULT (build; --tier at ff827bcf: packages/spec/src/** clause-② SUSPECT hint), reviewed at CONTRACT_REVIEW_TIER (migration entry text + stored detector), effort: high
    Clause-②: no (no accept set moves; the stored pass and the --stored listing widen) — the dev measures and corrects if wrong
    Metadata-protocol: none
    Responsibility: n/a — out-of-scope finding of PR #29513 (delta review 6585110935)
    Thread-read: 6585608827
    Premise: holds (read on origin/main ff827bcf: STORED_ONLY_COLLECTIONS at stored.ts ~L63 maps only translation / translations; the entry ~L11-14 and ~L40-42 says --stored does not list such a row)
    Serial constraints cleared: PR #29513 merged 19:07Z; no open PR touches these files, read over every open PR this patrol. Spec seat 5's #29541 will also add a detector to refused-shapes.ts: additive, seat 5 lands after this PR (agreed in thread). #29523 (same seat) is held serial behind this card.


    Generated by Claude Code

  3. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#3 · os-warren · session_01JQwxbXpawDQBhgKU2ssyrw
    os-dev-report

    {
     "issue": 29554,
     "status": "done",
     "branch": "claude/project-thread-e9cv0w",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/29589",
     "session": "session_01JQwxbXpawDQBhgKU2ssyrw",
     "premise_still_valid": true,
     "summary": "Premise held on origin/main ff827bcf: applyConversionsToStoredItem returned a stored object_extension row by reference with 0 notices and 0 TODOs, while the control object row got a time-default-utc-suffix-dropped notice. Measured: object_extension is the only stored spelling (the save door folds object_extensions and objectExtensions to it; the read fallback finds no other; migrateStoredMetadata skips a non-canonical stored type before reading the body), and the manifest map's omission of objectExtensions is deliberate (check:stack-collection-maps waiver: extensions merge into their target, not named items). So STORED_ONLY_COLLECTIONS maps object_extension to objectExtensions beside translation; one REFUSED_STORED_SHAPES detector for object-extension-field-patch-key-grammar-refused, appended last, whose predicate is ObjectExtensionSchema.safeParse keeping each invalid_key issue at fieldPatches.KEY; the entry header, acceptanceCriteria and the #29366 changeset sentence now say --stored lists such a row. patch changeset added. No protocol.ts file touched.",
     "tests": "pnpm --filter @objectstack/spec exec vitest run src/conversions/stored.test.ts src/conversions/refused-shapes.test.ts: Test Files 2 passed, Tests 110 passed. vitest run src/conversions src/migrations: 28 files, 981 tests passed. Spec typecheck exit 0. Ablation 1 (scripts/ablation-replace.mjs deleting the object_extension map line, committed first): 3 failed / 107 passed, restored, blob e26e3a1e equals HEAD, git diff HEAD empty. Ablation 2 (deleting the detector from REFUSED_STORED_SHAPES): 3 failed / 84 passed, restored, blob d205cc7d equals HEAD. End-to-end probe (throwaway copy of the protocol.stored-migration.test.ts harness on the built objectql closure, not committed): an extension with only fieldPatches.Industry reads skipped with 1 TODO at objectExtensions[0].fieldPatches.Industry; with a Z-suffixed time default too it previews pending with both lines and fails on apply at the save door; a packaged extension with only the time default on opens_at__c is rewritten and stored as 12:00.",
     "gates": "At head 91fbde28 (branch merged with origin/main dbca3ef0). dispatch-gates --commands --repo objectstack-ai/objectstack: 81 derived; --ran reconciliation 81 accounted, 80 run, 1 NOT MEASURED, 0 unrun. All exit 0 except: node scripts/check-empty-changeset.mjs --base origin/main exit 1 (deliberate correction of the pending #29366 changeset, red by design until a person confirms); pnpm check:dual-build-cjs-loads exit 3 NOT MEASURED (needs every package built; CI Lint and Repo Gates runs it). check-plugin-teardown-shape --self-test exit 3 on the shallow clone, exit 0 after fetching its pinned fixture commit; check:lean-entry-closure exit 3, exit 0 after the objectql closure build. Extra, outside the derivation, all exit 0: check:stack-collection-maps, spec check:meta-url-spelling, spec typecheck, spec vitest src/conversions src/migrations. CI check-runs: in_progress at report time.",
     "dogfood_battery": "n/a: no ! in the PR title and no (narrowing) arm",
     "mcp_calls": "0",
     "api_writes": "3: git push of claude/project-thread-e9cv0w (2 pushes, not REST); relay pr_create (fleet-write run 41518249483) opening PR 29589; this os-dev-report comment via post-stamped.mjs on issue 29554",
     "open_questions": [
      {
       "question": "The deliberate correction of the pending changeset .changeset/29366-field-patches-key-grammar.md reds check-empty-changeset by design. Keep it?",
       "options": [
        "A keep the corrected sentence and have a person confirm it on the PR, as the gate prescribes",
        "B restore the base sentence and let only this PR's changeset say the row is listed"
       ],
       "recommendation": "A, because the order and the card ask for the correction and B ships a false sentence next to a true one in the same release notes"
      }
     ],
     "security_findings": "none",
     "out_of_scope_findings": [
      "carrier: none · noted, not filed: the missing-direction waiver reason in scripts/check-stack-collection-maps.mjs still says objectExtensions has no singular metadata-type name, though ADR-0146 D10 added object_extension; the waiver stays right, only its reason text is dated (wording)"
     ],
     "deviations": "Clause-② line copied from the Claim without its trailing instruction to the dev (measured: no accept set moves, Metadata-protocol none holds). Commit trailer is the model-free pair the pre-push hook requires. The branch carries one merge of origin/main (stale dispatch-gates engine files). Platform PR body footer and attribution lines kept as the harness requires.",
     "body_amendments": "none"
    }
  4. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#3 · os-warren · session_01JQwxbahe4v7GBD94QeSnir

    Landed · 2026-11-03T01:13Z

    Reading Value
    PR #29589 MERGED 2026-11-03 01:10:22Z via merge queue, merge commit 57958aab on main
    Card #29554 closed completed by Fixes #29554; no other closing keyword in the body

    State change: pm:dispatched removed from #29554 (a stay-behind tail of the stood-down seat). Delivered: a stored object_extension row is read as an objectExtensions entry, so conversions replay over it, and os migrate meta --stored lists each fieldPatches key no field name can be; the pending #29366 changeset sentence was corrected on Warren's written confirmation (PR comment 6591818192). Unblocked: #29523 (was serial behind this PR, still pm:queue), spec seat 5's #29541, and server card #29596.


    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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions