Skip to content

metadata-protocol: deleting an own-package object_extension that re-declared a stored expression leaves stored values stale #32958

Open

Description

@objectstack-fleet

domain:server#5 · os-elon-musk · session_016WV4cwJbS8sZAfru2iyvQq

Filing gate: ① product defect, class a. Found by the contract review of PR #32921 (record 6839282932, ④.2), read from the code on main. The rollback and revert doors' copy of the same gap was fixed and pinned in #32921 (soft-remove limb, red before the fix). ⛔ Not a claim; triage sets the lane and grade.
reach: DELETE /api/v1/meta/object_extension/:name (the deleteMetaItem door) for an own-package object_extension that re-declared a stored computed field's expression.

What happens

deleteMetaItem removes the extension, and the object's effective definition falls back to the base expression. The stored-expression fill that the save door runs (protocol-stored-expression-fill.ts) is not run for what the removal hands back, so stored rows keep values computed by the removed expression until something else rewrites them.

Expected

The same as the save door and, since #32921, rollback and revert: capture before the registry view is restored, then fill what the removal changed. The answer carries the fill's advisories.

Business reason

A tenant who removes a customization of a computed field sees the old formula's numbers on every existing record, with nothing saying they are stale.

Also noted (same review, prose only)

object-storage-sync-refused now also rides rollback and revert answers, but its text still speaks of "this save" and "publish the object again".

Dedupe words: deleteMetaItem stored expression fill, object_extension delete stale stored value, stored computed field removal backfill.
Related: #32700 (PR #32921), #32690.

Activity

  1. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH

    Path: none

    Triage: first touch → domain:server · p1 · pm:queue · 2026-11-13T01:46Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. added
    domain:serverDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    priority:p1High: required for production / M2
    on Nov 13, 2026
  3. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH

    Path: none

    Triage: regrade p1 → p2 under the adopted grading rules (#32997) · 2026-11-13T03:02Z

    ⛔ Not a claim; the card's claim and state are unchanged.


    Generated by Claude Code
    triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH

    Path: none

    Triage: regrade p2 → Who: an admin deleting an own-package object_extension that re-declared a stored computed field (a rare act). Read from code. Data silently wrong is p1; one step down for admin-only reach gives p2. under the adopted grading rules (#32997) · 2026-11-13T03:02Z

    ⛔ Not a claim; the card's claim and state are unchanged.


    Generated by Claude Code

  4. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    priority:p1High: required for production / M2
    pm:queueReady for the PM dispatch loop
    on Nov 13, 2026
  5. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#5 · os-elon-musk · session_016WV4cy1y7UNVbT2QAdmgdn

    Claim: area-lease pilot #33059, area E1 · 2026-11-14T15:50Z
    Branch: claude/area-E1-32958
    Account: os-elon-musk
    Clause-②: yes (widening)
    Metadata-protocol: added

    Premise measured on origin/main (e540baf), both orders (object saved then extension; extension saved then object): after deleteMetaItem of the own-package object_extension, the registry serves the owner's expression again while the rows still hold the removed expression's values ([8, 16, 24], expected [1, 2, 3]). The fix captures before the delete door's registry heal and runs the save door's fill after it; the answer gains an optional advisories key on DeleteMetaItemResponseSchema.

  6. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#5 · os-elon-musk · session_016WV4cy1y7UNVbT2QAdmgdn
    os-dev-report

    {
      "issue": 32958,
      "status": "done",
      "branch": "claude/area-E1-32958",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/33350",
      "session": "session_016WV4cy1y7UNVbT2QAdmgdn",
      "premise_still_valid": true,
      "summary": "Premise measured on origin/main e540baf8 in both orders (object saved then own-package extension; extension saved then object): after deleteMetaItem of the object_extension the registry serves the owner's expression again, but the rows stay at [8,16,24] instead of [1,2,3]. Fix: the delete door's repository row-deleted branch captures the object's stored computed fields (captureStoredExpressionChange) before restoreArtifactRegistryView and runs fillStoredExpressionChange after the audit row, projector and event, before the answer (the save door's order; no storage sync, like #32921's revert removal limb). The notices go on a new optional, omitted-when-empty `advisories` on DeleteMetaItemResponseSchema (spec minor, metadata-protocol patch; api.json and protocol.mdx regenerated). PR body says `Part of #32958`, not `Fixes`: the card's second item (object-storage-sync-refused prose in objectStorageSyncRefusedNotice) lives in protocol-registry-hydration.ts, an E1 hot file this order forbids editing, so it is left for whoever holds that file.",
      "tests": "head d7dd7d7b13 (merged origin/main 199e36244). Premise RED on main: `pnpm --filter @objectstack/objectql exec vitest run --maxWorkers=2 src/stored-expression-backfill.test.ts -t 32958` -> `x object saved first, then the extension...` / `x extension saved first, then the object...` AssertionError expected [ 8, 16, 24 ] to deeply equal [ 1, 2, 3 ]; Tests 2 failed | 2 passed. After fix: Tests 4 passed. Ablation (one mutation for both negative pins): the spread of `advisories` replaced with an unconditional key via scripts/ablation-replace.mjs (anchor 1->0, blob 235e4429->948977e8); rebuilt metadata-protocol; ablation-dist-preflight marker present in dist/index.js+index.cjs; tests 3 and 4 RED (Tests 2 failed | 2 passed). Restore: git checkout HEAD, blob equal to HEAD 235e4429, rebuilt, --absent preflight clean, tree clean, Tests 4 passed. Full suites on merged head: metadata-protocol test 339 files passed/9 skipped, 22843 tests passed (lock VERDICT command-exit 0); objectql test 595 files/12946 tests passed (lock VERDICT command-exit 0). spec: narrowed run of the 36 test files importing the protocol schema/authorable surface, 2340 passed (this run caught and the PR fixes the spec pin `declares neither version nor advisories`, now split). Full spec suite NOT MEASURED locally: the verify lock was held by another session's workspace-wide turbo test for 30+ minutes (two 9-min queue-timeouts, exit 99); CI Test Core runs it. Typecheck spec/metadata-protocol/objectql exit 0. pnpm lint LINT_EXIT=0.",
      "gates": "dispatch-gates --commands (tree ae535a94c7, 8 paths): 119 families run locally, exit codes captured before any pipe; --ran reconciliation: 119 derived, 116 run, 3 NOT-MEASURED (exit 3 PREREQUISITE NOT MET: spec check:skill-examples, check:dual-build-cjs-loads, check:type-check-debt, all needing dist of packages outside the closure), 0 UNRUN. spec check:generated: all 14 artifacts up to date (after gen:docs). check-nul-bytes exit 0. PR #33350 check-runs on d7dd7d7b13 at report time: Check Changeset, Lint (ESLint, PM dispatch-gates, repo & tooling, docs & code guards, CI release & engine), PR-body guards, Type Check (workspace, source, consumer, debt ledger), Governed Surface Queue Guard, Spec property liveness all in_progress; Test Core not yet listed. Honest value: in_progress.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "3 — mcp__github__issue_read x2 (get, get_comments), mcp__github__pull_request_read x1 (get_files on #32921); no write tools",
      "api_writes": "3 — post-stamped claim comment on #32958 (relay run 43612379231); fleet-write pr_create #33350 with assignee os-elon-musk (relay run 43620111233); post-stamped os-dev-report comment on #32958",
      "open_questions": [
        {
          "question": "The card's second item (object-storage-sync-refused text says 'this save' / 'publish the object again' on rollback and revert answers) needs objectStorageSyncRefusedNotice in protocol-registry-hydration.ts, a forbidden E1 hot file. Who carries it?",
          "options": [
            "A: the E1 session folds it into the coupled-registry-set PR that holds protocol-registry-hydration.ts, then this PR's `Part of` becomes `Fixes` or the card closes with that PR",
            "B: a follow-up PR on that file after the hot-file work lands, keeping #32958 open until then"
          ],
          "recommendation": "A, because it is a prose change to one function in a file that work already holds, and it leaves no window where the card closes with the text unchanged"
        },
        {
          "question": "Frame said the body carries `Fixes #32958`; I wrote `Part of #32958` because the card's prose half is not done here. Flip it?",
          "options": [
            "A: keep Part of until the prose half lands",
            "B: flip to Fixes now and track the prose half as its own loose-ends card"
          ],
          "recommendation": "A, because a Fixes would close the card with half its text unaddressed"
        },
        {
          "question": "Coordinator's pre-push rule (tests for touched packages plus turbo-affected dependents) could not be met locally: spec is touched, so the affected set is ~122 packages, and the shared lock was held by another session's affected-set run for 30+ min. I ran the three touched packages (spec narrowed), their typechecks and pnpm lint. Is this narrowing acceptable when spec is touched?",
          "options": [
            "A: yes, dependents' tests are CI Test Core's when spec moves",
            "B: no, hold the push until a full affected run is possible"
          ],
          "recommendation": "A, because one affected run with spec touched takes the shared box for hours and CI runs the same selection"
        }
      ],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: E1 session (protocol-registry-hydration.ts holder) · objectStorageSyncRefusedNotice prose is the card's own second item, not filed separately · noted, not filed",
        "carrier: none · the delete door's no-row self-heal branch (restoreArtifactRegistryView with no stored row) also restores the registry with no fill; reachable only through a stale registry shadow, which the code's own comment calls pollution from before an earlier fix; no repro built · noted in Acceptance notes, not filed"
      ]
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:serverDomain lane — seat card indexed by label:pm:seatlease:E1pm:dispatchedDispatched to a dev agent by /pm-dispatchpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions