Skip to content

registry: an unshipped bundle member overlay wears the bundle artifact envelope, so isCodeArtifactBody reads it as packaged code; measure every reader and fix the graft at its root #23074

Closed

Description

@objectstack-fleet

Filing gate ①, class (a), to measure: an unshipped bundle member's overlay is classified as packaged code. reach: measured once by PR #23070's showcase dogfood, which routed around it in one reader only. An environment overlay of a member the package does not ship (for example a zh-CN email_template beside a shipped en-US) is hydrated wearing the bundle's artifact envelope (_packageId / _provenance, grafted by mergeArtifactProtection). isCodeArtifactBody then reads it as packaged code, and removeOverlayEntry refused to remove it. PR #23070 lifts that member's runtime shadow at the level of the NAME in removeRuntimeShadow. That works around the misclassification, but the root cause is still there.

Filed by domain:engine seat 2 (#20966) · os-steve · session_01ADzJtzYTLUfgrRZHxkagkX · 2026-10-12T16:54Z, at PR #23070's ACCEPT (#22877 stage 2, ruling 6116165299 letter A). It comes from the dev's report 6127796890 and the contract records 6128093700 and 6128724141. ⛔ Not a claim. Lane and grade are triage's.

Wanted

  • Measure every reader of isCodeArtifactBody (and of the grafted envelope) for a non-shipped member's overlay: locks, editable / deletable decorations, reset, the protection gate.
  • Fix the graft at its root, so the envelope is stamped only onto the member the package ships. Then decide whether removeRuntimeShadow's name-level test can return to member level.
  • Pins: an unshipped member's overlay is not packaged code at any of those readers. CONTROL: the shipped member's artifact protection is unchanged.

Dedupe: this is new with PR #23070.

Activity

  1. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, bug · priority:p2 · domain:engine · area:i18n, into pm:queue. The envelope is stamped only on the member the package ships

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

    • Why p2: an environment's own overlay of a member the package does not ship reads as packaged code. So it can be refused at removal, which PR feat(metadata-protocol): one language of an email template is addressed by name — the by-name /meta doors accept a bundle member selector (#22877, stage 2) #23070 worked around for one reader, and it picks up the locks and decorations of shipped code. The misclassification is in the stricter direction, so it is not a security loosening.
    • Direction, the card's own:
      1. Measure every reader of isCodeArtifactBody and of the grafted envelope for an unshipped member's overlay: locks, editable / deletable, reset, and the protection gate.
      2. Fix the graft in mergeArtifactProtection, so it stamps only the shipped member.
      3. Then decide whether removeRuntimeShadow's name-level lift can return to member level.
      • Pins: an unshipped member's overlay is not packaged code at any measured reader. CONTROL: the shipped member's protection is unchanged.
    • Triage: lands in the registry's artifact-protection graft (domain:engine); rationale: the root, not a second workaround.
  2. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 · 2026-10-12T18:14Z
    Session: session_01ADzJtzYTLUfgrRZHxkagkX
    Account: os-steve (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-23074-member-envelope
    Worktree: objectstack-issue-23074
    Domain: domain:engine
    Seat: domain:engine#2 (seat post #20966); the lane's only seated PM
    Triage-ref: 6129705694 (the envelope is stamped only on the member the package ships; the root, not a second workaround)
    File surface (read on origin/main 7f2f081e8a; stop on a breach and explain it in the report). ⛔ Classes, positions and functions only, in every artefact.

  3. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 23074,
    "status": "done",
    "branch": "claude/issue-23074-member-envelope",
    "pr": "#23094",
    "session": "session_01ADzJtzYTLUfgrRZHxkagkX (the dispatching PM's; this is a subagent run)",
    "premise_still_valid": true,
    "summary": "Premise reproduced on origin/main 62ce45d (one spec-only commit past the dispatch's 7f2f081). An unshipped acme.digest zh-CN overlay, after a restart, was registered with _packageId com.acme.mail / _packageVersion 1.0.0 / _provenance package (isCodeArtifactBody true). getArtifactItem(member zh-CN) answered the overlay itself as the package's zh-CN artifact. GET ?member=zh-CN and the list (served and execution) served it under provenance package, and removeOverlayEntry refused it. Root fix in metadata-protocol: mergeArtifactProtection takes the type and grafts an artifact only onto a body of the same bundle member (itemDiscriminator via bundleMemberOf). Its four call sites pass the type, and the three that can serve a member (hydrateOverlayIntoRegistry, getMetaItem, readFlattenedMetaItems) look the artifact up at the body's own member, so the shipped non-canonical member keeps its envelope. removeRuntimeShadow returns to member level for a named member: measured sound only together with the graft fix (ablation A3 reds #22877's door case), and confirmed at the showcase dogfood door. Lock (name-level, one item-lock resolution) and resettable/reset receipt (isArtifactBacked by name) are deliberately unchanged and recorded in the PR.",
    "tests": "All at 5d156f7, through os-verify-lock, each read from its VERDICT command-exit 0 line. (1) New block [#23074] in packages/objectql/src/environment-overlay-email-locale-restart.test.ts: 10 cases, each CONTROL its own case (hydration, ?member= read, list served+execution, reset, a member-ignoring registry, and a non-discriminated translation with a differing locale). File total 29/29. (2) registry-i18n-bundle-key.test.ts: the unshipped name-level lift case now pins the member-level decline plus the retirement. Call-site ledgers updated. (3) metadata-protocol typecheck exit 0; objectql typecheck exit 0 (check:test-typecheck held 40 files / 234 errors / 65 signatures). metadata-protocol vitest: 228 files passed, 3 skipped, 28203 tests. objectql --project local: 408/408 files, 7984 tests; --project repo: 1/1, 5 tests. (4) Real door: dogfood email-template-two-locales-survive-boot.dogfood.test.ts 4/4 on the fixed dist (showcase, SQLite, real sendTemplate). (5) Ablation, from committed state with scripts/ablation-replace.mjs under a trap restore. Each metadata-protocol leg was rebuilt and dist-preflighted; the DTS step fails TS6133 on the guard-deleting legs, while ESM and CJS are emitted and the preflight proves the consumed ESM carries the mutation. A3 (unconditional graft back): 6 red (5 unshipped + #22877's no-artifact door case), all 23 others green, every CONTROL included. A1 (guard only): only the member-ignoring-registry case red. A2 (member lookups only): exactly the 4 shipped-member CONTROLs red. A4 (removeRuntimeShadow name-level, src): only the unshipped reset case red. Each restore was proven by blob == HEAD and an empty git diff HEAD, then rebuilt and preflighted present. Final run 29/29. One earlier A3 run is VOID: an unlocked check:type-check-debt full build rewrote metadata-protocol dist mid-leg; the preflight caught it and the leg was redone alone. (6) eslint --no-inline-config --format json on the 6 changed TS files: 6 files, 0 errors, 0 warnings, none ignored. eslint.config.mjs enables no type-aware linting, so untouched-file verdicts are invariant.",
    "mcp_calls": "0",
    "api_writes": "2 relay strokes (POST /repos/objectstack-ai/objectstack/dispatches, executed as objectstack-fleet[bot]): (1) pr_create = POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos//issues/23094/assignees [os-steve]; (2) this os-dev-report comment = POST /repos//issues/23074/comments via scripts/pm/post-stamped.mjs. git push x6 (not REST). Zero label writes, as the dispatch ordered.",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: none (noted in PR #23094 Acceptance notes, not filed) - for a bundle member the package does not ship, GET ?member= reads resettable: true and DELETE ?member= answers reset: true / 'reset to artifact default' (both from isArtifactBacked(type, name), by name), while GET ?member=zh-CN is 404 after the reset; at send time the zh-CN sends do fall back to the package's en-US wording, so the receipt is true at the send door and not at the by-name read. #22877 pinned reset: true for this case deliberately. Dedupe words: email_template resettable unshipped member, reset receipt bundle member, isArtifactBacked member"
    ],
    "gates": "Derived union node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 5d156f7: 69 commands (the dispatch's 58, all included, plus 11 changeset families this diff adds), 69 exit 0, exit codes captured before any pipe. --ran reconciliation: 69 derived, 69 run, 0 NOT-MEASURED, 0 UNRUN. check:dual-build-cjs-loads and check:type-check-debt measured after a full turbo build of ./packages/* (72 tasks) at that head. A first battery overlapped the ablation windows and was discarded. CI on the PR head: in_progress (15 completed, 22 in progress at the one read).",
    "line_budget": "7 files, +305 / -30 = 335 changed lines (under the 3000 human-merge threshold). No skills/** or governed surface touched.",
    "deviations": [
    "Base: the worktree was cut from origin/main 62ce45d, not 7f2f081 (one spec/ui-only commit apart, none of this card's files). origin/main a22e67b was merged later (5d156f7); the incoming commits touch none of this diff's files.",
    "Conflict named: the dispatch lists git push under 'through the scripts/pm/ relay'. The role file says git push is not a REST write and does not go through the relay, so it was a plain git push.",
    "Commit trailers: the harness reminder asked for a Co-Authored-By trailer naming the model. AGENTS.md requires the model-free pair, so the first commit was amended to the model-free form before its first push; nothing with a model id was ever pushed. The PR body footer uses AGENTS.md's session-URL form, not the reminder's form.",
    "Hunks beyond mergeArtifactProtection / call sites / removeRuntimeShadow: two new module-private helpers in protocol.ts (bundleMemberOf), the two call-site ledger tests (protocol.lookup-artifact-item-call-sites.test.ts, protocol.register-item-call-sites.test.ts) and registry-i18n-bundle-key.test.ts. All are within the claim's surface ('tests beside the code'). migrateStoredMetadata is untouched.",
    "Worktree removed after the PR opened (rm -rf node_modules, then git worktree remove, with no --force needed). A patch round needs a fresh worktree from origin/claude/issue-23074-member-envelope at 5d156f7."
    ],
    "files_changed": [
    ".changeset/23074-member-envelope.md",
    "packages/metadata-protocol/src/protocol.ts",
    "packages/metadata-protocol/src/protocol.lookup-artifact-item-call-sites.test.ts",
    "packages/metadata-protocol/src/protocol.register-item-call-sites.test.ts",
    "packages/objectql/src/registry.ts",
    "packages/objectql/src/registry-i18n-bundle-key.test.ts",
    "packages/objectql/src/environment-overlay-email-locale-restart.test.ts"
    ]
    }


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    ✅ ACCEPT: PR #23094 at 5d156f7044 · domain:engine seat 2 · session_01ADzJtzYTLUfgrRZHxkagkX · 2026-10-12T21:40Z

    Basis:

    • triage 6129705694 binds the direction;
    • claim 6129978918;
    • report 6132131059.

    Everything below was checked on GitHub, not taken from the report. Classes, positions and functions only.

    • Form:
      • draft to main, assignee os-steve;
      • line 1 Fixes #23074, the only closing keyword;
      • line 2 Clause-②: no.
    • Scope:
      • 7 files, +305 / −30, none governed (check-governed-merges: clean);
      • no packages/spec source, so no contract surface, and the seat read the diff itself;
      • nothing under content/docs/releases/.
    • Fix, read in the diff:
      • mergeArtifactProtection now takes the type, and grafts an artifact only onto a body of the same bundle member (a new module-private bundleMemberOf, which reads itemDiscriminator);
      • its four call sites pass the type;
      • the three that can serve a member look up the artifact at the body's own member, so a shipped non-canonical member keeps its envelope;
      • removeRuntimeShadow returns to member level for a named member.
    • Evidence:
    • CI on 5d156f7044: 40 check runs, none failed.
    • Acceptance notes:

    Landing: prechecks pass:

    • every check is green;
    • merge-tree is clean against origin/main;
    • not governed;
    • 335 lines.

    The PR is readied and armed through the relay in this act.

  5. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #23094 → abf86554c9 · domain:engine seat 2 · session_01ADzJtzYTLUfgrRZHxkagkX · 2026-10-12T22:09Z

    • Merge: the merge queue merged PR fix(metadata-protocol): the artifact envelope is stamped only on the bundle member the package ships (#23074) #23094 at 2026-10-12T22:09Z as abf86554c90922bfbe66567644645f825045c23e, with one parent, d0f1c5bfb9. The ACCEPT is on this card, from the seat's own diff read (no contract surface).
    • On main at that commit: the squash carries the accepted change exactly. Every file has hunks identical to the accepted head.
    • What main now holds: mergeArtifactProtection grafts a package artifact only onto a body of the same bundle member. An environment's overlay of a member the package does not ship is no longer read as packaged code, and a shipped non-canonical member keeps its envelope. removeRuntimeShadow lifts one member's shadow by member.
    • Card: closed completed by the PR's Fixes #23074. pm:dispatched comes off in this act.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:i18nThe customer's own language, across UI, metadata and notificationsbugSomething isn't workingdomain:enginepriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions