Skip to content

spec: rename allowOrgOverride to an environment-overlay key with an ADR-0087 load-time conversion (ADR-0131 C5's spec half, split from #15206 per #22007 ruling C) #22340

Closed

Description

@objectstack-fleet

Ruled: 6073921182 · letters Q1 A · Q2 A · 2026-10-09T03:53Z

Filed by the triage seat (objectstack-wide, seat post #6015, session_01AavokzJ5DndAwitDXvKy4U), answering #15206's retriage (option A). ⛔ Not a claim.

Part of #15194 (ADR-0131 execution tree). The direction is ruled: #22007, letter C (6028809298), as written into #15206's scope by triage's note 6037959748. This card is that scope's spec half, split out because a new published key is a Clause-②: yes widening, which is spec-lane work wherever it lands (execution-duties.md:101; dispatch-gates: "a hit outside those lanes is spec-lane work and moves there").

Scope (as ruled)

  • The rename. allowOrgOverride (packages/spec/src/kernel/metadata-plugin.zod.ts, about :267 on main, today "Allow per-org overlay writes via runtime metadata API") becomes a key that says what it will then mean: may an environment overlay this packaged item. ⛔ The new name is fixed by this card's contract review, not here.
  • The conversion. An ADR-0087 D2 load-time conversion, so a manifest naming the old key still loads unchanged.
  • No overlay is lost. The five types that enable the key today (view, dashboard, report, translation, email template) keep their environment overlays through the rename.
  • Generated baselines and docs follow the rename.
  • ⛔ Not taken (ruled): a second key with the organization one frozen at false (A), or the old name with a new meaning (B).

Not this card (it stays on #15206, domain:engine)

The narrowings, which stay in their lane and owe one contract-tier review:

  • the sys_metadata family goes tenant-less;
  • an organization-scoped metadata write is refused;
  • managed content is sealed;
  • the per-organization overlay path behind isOverlayAllowed is deleted;
  • sys_view_definition retires.

#15206 uses the key under its current name. The deletion does not depend on the key's name, so the two cards land in either order or in parallel. The engine seat states the seam at its claim.

Acceptance

  • Pins: a manifest with the old key loads and converts to the new one. Each of the five types keeps its environment overlay. The generated baselines name the new key.
  • Clause-②: yes; the contract-review tier is owed.

Activity

  1. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 (stage 0 of this card: measure first, no code, no PR) · 2026-10-08T21:20Z
    Session: session_01DhTqaEHqPVSVnAkjG3jywn
    Account: os-sales (the seat's linked user as GET /user answers it; the card's assignee from this act)
    Branch: claude/issue-22340-stage-0 (stage 0 writes no code; each later stage names its own branch on this card)
    Worktree: objectstack-issue-22340
    Domain: domain:spec
    Seat: domain:spec#2 (seat post #18549)
    File surface (at origin/main 54c3ce10c or later): stage 0 writes no file and opens no PR. The report is the deliverable. It contains:


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 22340,
      "status": "done",
      "branch": "claude/issue-22340-stage-0",
      "pr": null,
      "session": "session_01DhTqaEHqPVSVnAkjG3jywn (subagent of the PM session; identity = the branch named in claim 6069288725)",
      "premise_still_valid": true,
      "summary": "Stage 0 measured on origin/main 54c3ce10c (worktree ../objectstack-issue-22340, read-only, no install, no build; main moved to b7e01fbbd during the run, one commit, 0 diff lines name the key). The direction (rename, ruling C) stands, but the ruled mechanism does not: no manifest, stack, plugin config or stored row can carry a type-registry entry (contributes.kinds is a closed shape, config.additionalTypes is a tombstone, DEFAULT_METADATA_TYPE_REGISTRY is a TypeScript literal that no production code parses), so an ADR-0087 D2 conversion would have no seam; the recorded precedent for renaming a non-stack key is a retiredKey() tombstone + a retired-keys entry + a D3 semantic entry, with no D2 entry (HotReloadConfig.debounceDelay). The rename also reaches a published wire field the card does not name, GET /meta/types entries[].allowOrgOverride (protocol.zod.ts:210), which objectui reads at the pin in 11 source files as Studio's write gate for every packaged item of the five types, through its own optional field type, so by reading neither the Console Pin Gate nor api-surface/authorable-surface would see a missed sibling. Census: 176 files / 765 hits. 46 source hits (14 files) and 120 test hits (32 files) sit in the per-organization path that #15206 S3-S5 delete, so the rename should land after #15206 S5; before S3/S4 a key with an environment name would still decide organization-scoped writes. The rename's declaration is Clause-② yes (narrowing), not yes (widening). Report and translation have no environment-overlay pin today.",
      "census": {
        "base": "origin/main 54c3ce10c (54c3ce10ce8cf89290b67813c34d1f10dbab6938). Re-read at b7e01fbbd (#22342, test titles only): git diff 54c3ce10c b7e01fbbd names the key on 0 lines.",
        "command_and_controls": "git grep -n allowOrgOverride 54c3ce10c = 765 lines in 176 files (the claim's 176 files and 60 hits in protocol.ts both reproduce). Pathspec proof: ':(glob)packages/**/src/**' key 113 files, controls DEFAULT_METADATA_TYPE_REGISTRY 95 and isOverlayAllowed 13; the plain pathspec 'packages/**/src' answers 0 for the key AND 0 for the control (vacuous, no glob magic). ':(glob)**/*.test.ts' key 80, control 'describe(' 4824. ':(glob)content/docs/**' key 14, control ADR-0005 12.",
        "method": "Every hit line was read and classed by what it governs or describes; comments are classed with the code they annotate. Three source files split by line (protocol.ts 19 a / 41 b, spec api/protocol.zod.ts 1 a / 3 b, runtime domains/meta.ts 3 a / 1 b). Counts are path:hits (path:class-hits/file-hits for a split file).",
        "class_totals": "(a) per-organization path: 46 hits, 14 files (11 wholly + 3 split). (b) environment-overlay permission that survives: 75 hits, 19 files (16 wholly + 3 split). (c) declaration 47/1, docs 64/23, generated 16/8, ADR-0087 ledger prose 4/4, tooling 28/3, history (CHANGELOG 147/10 + pending changesets 3/2) 150/12, governed 48/15. (d) tests: pinning (a) 120 hits / 32 files, pinning (b) 156 / 46, mixed 11 / 2. Sum 765.",
        "a_per_org_path": {
          "files": "packages/metadata-protocol/src/protocol.ts:19/60, packages/spec/src/api/protocol.zod.ts:1/4, packages/runtime/src/domains/meta.ts:3/4, packages/metadata-core/src/meta-write-capability.ts:1, packages/metadata-core/src/meta-write-org-scope.ts:6, packages/plugins/plugin-email/src/bootstrap-declared-email-templates.ts:1, packages/rest/src/meta-item-read-gate.ts:1, packages/rest/src/rest-route-ledger.ts:1, packages/rest/src/rest-server.ts:5, packages/runtime/src/domains/mcp.ts:1, packages/runtime/src/domains/packages.ts:3, packages/runtime/src/route-ledger.ts:1, packages/services/service-automation/src/sys-flow-credential.object.ts:1, packages/spec/src/security/capabilities.ts:2",
          "by_15206_stage": "S3 (doors): meta-write-org-scope.ts 6 (ORG_OVERRIDABLE_TYPES :96-100 reads the flag; declaresOrgOverride feeds organizationIdForMetaWrite :141 and organizationIdForMetaRead :189), meta-write-capability.ts 1, spec security/capabilities.ts 2 (manage_org_presentation :47/:62), rest meta-item-read-gate.ts 1, rest-route-ledger.ts 1, rest-server.ts 5, runtime domains/meta.ts 3, runtime route-ledger.ts 1, plugin-email bootstrap-declared-email-templates.ts 1 = 21. S4 (protocol writes): protocol.ts orgScopedWriteRefusal TSDoc and sentence :16136/:16140/:16168/:16215 (its exemption is :16210 'if (this.isOverlayAllowed(type)) return null'), resolveMetaItemOrgScope note :7144, applyRegistryWriteThrough note :19222, duplicatePackage note :24793; runtime domains/packages.ts 3, domains/mcp.ts 1, service-automation sys-flow-credential.object.ts 1, spec api/protocol.zod.ts:676 (SaveMetaItem organizationId describe) = 13. S5 (reads): protocol.ts :8927, :10064, :10145, :10719, :10778, :11537, :11544, :14732 (organization read-gate notes) and reportUnhydratableOrgScopedRows :27457/:27498/:27554 (reads the flag)/:27640 (sentence) = 12."
        },
        "b_environment_overlay_permission": {
          "files": "packages/metadata-protocol/src/protocol.ts:41/60, packages/spec/src/api/protocol.zod.ts:3/4, packages/runtime/src/domains/meta.ts:1/4, examples/app-showcase/src/coverage.ts:1, packages/lint/src/validate-ai-agent-authoring.ts:1, packages/metadata-core/src/contract-suite.ts:1, packages/metadata-core/src/types.ts:1, packages/metadata-protocol/src/package-writability.ts:1, packages/metadata-protocol/src/sys-metadata-repository.ts:13, packages/objectql/src/engine.ts:1, packages/platform-objects/src/audit/sys-job.object.ts:1, packages/plugins/plugin-security/src/object-posture-gate.ts:1, packages/plugins/plugin-security/src/permission-set-overlay-discard.ts:1, packages/plugins/plugin-security/src/permission-set-projection.ts:2, packages/plugins/plugin-security/src/security-plugin.ts:2, packages/spec/src/kernel/index.ts:1, packages/spec/src/kernel/metadata-create-seeds.ts:1, packages/spec/src/kernel/metadata-type-schemas.ts:1, packages/spec/src/system/email-template.zod.ts:1",
          "code_reads": "protocol.ts:15845 (OVERLAY_ALLOWED_TYPES, read by isOverlayAllowed :15976, whose callers are refusePackagedBaseOverride :17171, refusePackagedBaseRemoval :17278, saveMetaItem :20172, migrateStoredMetadata :21644, historyMetaItem :21830, publish/promote :22266, rollbackMetaItem :26075, deleteMetaItem :26619/:26722, and orgScopedWriteRefusal :16210 which S4 deletes); sys-metadata-repository.ts:316 (its own OVERLAY_ALLOWED_TYPES, read by assertAllowed :1789/:1849); protocol.ts getMetaTypes :7883/:7884/:7953 (the wire field and its env-hatch elevation).",
          "author_facing_strings": "protocol.ts :16099 and :16118 (code-only refusals), :17247 (package-door sentence 'has not opted into per-org overlay writes (allowOrgOverride=false)'), :21650 (migrate-stored reason); sys-metadata-repository.ts :1854, :1855, :1975, :1983. All name the key and survive into the rename."
        },
        "c_declaration_docs_history_governed": {
          "declaration": "packages/spec/src/kernel/metadata-plugin.zod.ts:47 (key :267, TSDoc :253-266, 28 registry rows, the customizationPolicies tombstone prescription :513-520 that ships on 17.x and names the key, and about 15 rationale comments).",
          "docs": "packages/spec/liveness/README.md:2, packages/spec/liveness/capability.json:1, packages/spec/liveness/job.json:1, docs/qa/platform-checklist/areas/studio-authoring.json:18, content/docs/concepts/metadata-lifecycle.mdx:8, docs/qa/platform-checklist/areas/platform-core.json:5, docs/qa/platform-checklist/areas/ai.json:3, content/docs/plugins/adding-a-metadata-type.mdx:3, docs/qa/platform-checklist/areas/records-forms.json:2, docs/qa/platform-checklist/areas/integration-system.json:2, docs/qa/platform-checklist/areas/automation.json:2, docs/qa/platform-checklist/FOLLOW-UPS.md:2, docs/audits/2026-06-ask-build-agent-development-assessment.md:2, content/docs/permissions/capabilities.mdx:2, content/docs/kernel/contracts/metadata-service.mdx:2, content/docs/ai/agents.mdx:2, docs/qa/platform-checklist/RUNNER.md:1, content/docs/protocol/objectui/concept.mdx:1, content/docs/permissions/authorization.mdx:1, content/docs/deployment/environment-variables.mdx:1, content/docs/automation/jobs.mdx:1, content/docs/api/metadata-api.mdx:1, content/docs/api/declarative-endpoints.mdx:1",
          "generated": "packages/spec/src/migrations/registry.ts:4, packages/spec/authorable-defaults/kernel.json:1, packages/spec/authorable-surface.base.json:1, packages/spec/authorable-surface/kernel.json:1, content/docs/references/api/protocol.mdx:3, content/docs/references/kernel/metadata-plugin.mdx:3, content/docs/references/system/email-template.mdx:1, docs/protocol-upgrade-guide.md:2",
          "adr_0087_ledger_prose": "packages/spec/src/migrations/entries/retired-keys/18.kernel__MetadataPluginConfig__customizationPolicies.ts:1, packages/spec/src/migrations/entries/semantic/17.api-runtime-create-withdrawn.ts:1, packages/spec/src/migrations/entries/semantic/17.field-runtime-create-withdrawn.ts:1, packages/spec/src/migrations/entries/semantic/18.metadata-customization-protocol-retired.ts:1. The two 17.* entries describe the shipped v17 refusal body and stay; the two 18.* entries are unreleased (spec latest 17.7.0, pre mode 'next') and present the key as the live mechanism.",
          "tooling": "scripts/check-overlay-whitelist-table.mjs:26, scripts/adr-anchors/packages__spec__src__kernel__metadata-plugin.zod.ts.json:1, scripts/adr-anchors/packages__plugins__plugin-security__src__permission-set-projection.ts.json:1",
          "history_never_edited": ".changeset/22203-position-package-door.md:1, .changeset/22220-package-door-before-gates.md:2, packages/metadata-protocol/CHANGELOG.md:58, packages/spec/CHANGELOG.md:33, packages/runtime/CHANGELOG.md:15, packages/rest/CHANGELOG.md:13, packages/objectql/CHANGELOG.md:10, packages/plugins/plugin-security/CHANGELOG.md:5, packages/lint/CHANGELOG.md:5, packages/metadata-core/CHANGELOG.md:4, packages/platform-objects/CHANGELOG.md:3, packages/metadata/CHANGELOG.md:1. The two .changeset files are other PRs' pending release inputs.",
          "governed": "docs/adr/0005-metadata-customization-overlay.md:12, docs/adr/0010-metadata-protection-model.md:9, docs/adr/0094-sys-permission-set-pure-projection.md:5, docs/adr/0070-package-first-authoring.md:5, docs/adr/0029-kernel-object-ownership-and-platform-objects-decomposition.md:4, docs/adr/0126-packaged-metadata-customization-model.md:2, docs/adr/0086-authz-metadata-config-boundary-and-cross-package-composition.md:2, docs/adr/0046-package-docs-as-metadata.md:2, skills/objectstack-ai/SKILL.md:1, docs/adr/0131-total-organization-ownership-no-null-organization-id.md:1, docs/adr/0109-ai-tool-authoring-model.md:1, docs/adr/0063-two-kernel-agents-skills-are-the-extension-primitive.md:1, docs/adr/0027-metadata-authoring-lifecycle.md:1, docs/adr/0015-external-datasource-federation.md:1, AGENTS.md:1",
          "governed_lines_a_carrier_must_change": "AGENTS.md:190-192 (Prime Directive #7: 'Org overlay opt-in lives only in allowOrgOverride on DEFAULT_METADATA_TYPE_REGISTRY', false twice once #15206 and this card land); skills/objectstack-ai/SKILL.md:347 (published skill, 'allowOrgOverride:false' on agent); docs/adr/0005 :47 and :68 (normative current-state sentences; the file already carries the v5.0 rename note at :3 as the shape for a top note); docs/adr/0010 :19, :94, :119-122 (the L1 type-level knob). The remaining ADR hits (0015, 0027, 0029, 0046, 0063, 0070, 0086, 0094, 0109, 0126, 0131) record decisions under the name of their time and need no rewrite; 0029:386 carries an ungated '#allowOrgOverride' symbol anchor. .claude/** has 0 hits."
        },
        "d_tests": {
          "pins_a": "packages/metadata-core/src/meta-write-capability.test.ts:4, packages/metadata-core/src/meta-write-org-scope.test.ts:2, packages/metadata-protocol/src/get-meta-item-cached-etag-scope.test.ts:8, packages/metadata-protocol/src/get-meta-item-layered-org-read-gate.test.ts:4, packages/metadata-protocol/src/get-meta-item-org-read-gate.test.ts:4, packages/metadata-protocol/src/get-meta-items-org-read-gate.test.ts:3, packages/metadata-protocol/src/protocol-publish-drafts-advisories.test.ts:1, packages/metadata-protocol/src/protocol-publish-drafts-org-scope.test.ts:3, packages/metadata-protocol/src/protocol-publish-drafts-package-scope.test.ts:1, packages/metadata-protocol/src/protocol.lock-org-axis-agree.test.ts:1, packages/metadata-protocol/src/protocol.metadata-store-outage.test.ts:1, packages/metadata-protocol/src/protocol.org-scoped-cold-boot-audit-live-registry.test.ts:1, packages/metadata-protocol/src/protocol.org-scoped-cold-boot-audit.test.ts:6, packages/metadata-protocol/src/protocol.org-scoped-write-refused.test.ts:9, packages/metadata-protocol/src/protocol.publish-item-draft-org-scope.test.ts:2, packages/objectql/src/overlay-precedence.test.ts:16, packages/objectql/src/protocol-meta.test.ts:10, packages/objectql/src/protocol-org-overlay-registry-gate.test.ts:2, packages/objectql/src/publish-meta-response-conformance.test.ts:2, packages/objectql/src/publish-package-drafts-response-conformance.test.ts:1, packages/rest/src/meta-item-save-capability-gate.test.ts:1, packages/rest/src/meta-publish-package-scope.test.ts:1, packages/rest/src/meta-write-door-capability-enumeration.test.ts:2, packages/rest/src/rest-server-meta-cached-etag-door-scope.test.ts:2, packages/rest/src/rest-server-meta-history-diff-org-scope.test.ts:4, packages/rest/src/rest-server-meta-org-scope-url-spelling.test.ts:2, packages/rest/src/rest-server-meta-read-org-scope.test.ts:7, packages/rest/src/rest-server-meta-write-org-scope.test.ts:4, packages/runtime/src/domains/meta-save-capability-gate.test.ts:2, packages/runtime/src/domains/packages-seed-apply-org-scope.test.ts:3, packages/runtime/src/meta-write-org-scope.test.ts:10, packages/runtime/src/package-duplicate-adopt-org-scope.integration.test.ts:1",
          "pins_a_by_15206_stage": "S3 14 files / 45 hits (the core and runtime meta-write-org-scope tests, the capability-gate and door tests in rest and runtime, the rest org-scope read/write/history/etag/url-spelling suites, packages-seed-apply and package-duplicate-adopt); S4 9 files / 45 (protocol.org-scoped-write-refused, the identity pin, :550 lists exactly the five; publish-item-draft and publish-drafts org/package scope and advisories; objectql overlay-precedence, protocol-meta, publish-meta and publish-package-drafts conformance); S5 9 files / 30 (the four get-meta-item(s) read-gate suites incl. cached-etag, lock-org-axis-agree, metadata-store-outage, both cold-boot audits, objectql protocol-org-overlay-registry-gate).",
          "pins_b": "packages/metadata-protocol/src/protocol.adr0005-org-override-rollback.test.ts:9, packages/metadata-protocol/src/protocol.capability-write-door.test.ts:1, packages/metadata-protocol/src/protocol.code-only-types.test.ts:5, packages/metadata-protocol/src/protocol.delete-receipt-wording.test.ts:7, packages/metadata-protocol/src/protocol.delete-rewrap-envelope.test.ts:4, packages/metadata-protocol/src/protocol.destructive-gate-reachable-types.test.ts:1, packages/metadata-protocol/src/protocol.diff-dead-history-read.test.ts:1, packages/metadata-protocol/src/protocol.driver-text-disclosure.test.ts:3, packages/metadata-protocol/src/protocol.legacy-overlay-delete.test.ts:10, packages/metadata-protocol/src/protocol.marked-refusal-classification.test.ts:1, packages/metadata-protocol/src/protocol.package-door-before-gates.test.ts:3, packages/metadata-protocol/src/protocol.packaged-base-refusal.test.ts:2, packages/metadata-protocol/src/protocol.read-lock-flags-write-door.test.ts:2, packages/metadata-protocol/src/protocol.read-verb-canonical-fold.test.ts:3, packages/metadata-protocol/src/protocol.recovery-doors-emit-mutation.test.ts:1, packages/metadata-protocol/src/protocol.runtime-gate-stored-universe.test.ts:1, packages/metadata-protocol/src/protocol.save-receipt-wording.test.ts:6, packages/metadata-protocol/src/protocol.stored-migration.test.ts:2, packages/metadata-protocol/src/protocol.unrecognised-meta-type.test.ts:1, packages/metadata-protocol/src/sys-metadata-repository.contract.test.ts:3, packages/metadata-protocol/src/sys-metadata-repository.package-writability.test.ts:14, packages/objectql/src/engine-security-catalog-package-door.test.ts:9, packages/objectql/src/meta-object-search-companion-roundtrip.test.ts:1, packages/objectql/src/protocol-commit-history.test.ts:7, packages/objectql/src/protocol-delete-object-registry-heal.test.ts:1, packages/objectql/src/protocol-meta-effective-schema.test.ts:1, packages/objectql/src/protocol-meta-types-rich.test.ts:11, packages/objectql/src/protocol-object-overlay-layer.test.ts:2, packages/objectql/src/protocol-publish-canonical-fold.test.ts:1, packages/objectql/src/protocol-registry-shadow.test.ts:2, packages/objectql/src/protocol-writepath-object-ownership.test.ts:1, packages/objectql/src/sys-metadata-repository.test.ts:4, packages/platform-objects/src/audit/sys-job.global-unique.test.ts:5, packages/plugins/plugin-security/src/packaged-permission-set-restore-leg.test.ts:1, packages/plugins/plugin-security/src/permission-set-projection.test.ts:3, packages/qa/dogfood/test/showcase-permission-projection.dogfood.test.ts:3, packages/qa/dogfood/test/two-doors-permission.dogfood.test.ts:3, packages/rest/src/rest-meta-packaged-flow-refusal.test.ts:1, packages/runtime/src/meta-field-overlay-lock.test.ts:4, packages/runtime/src/meta-overlay-read-your-writes.test.ts:2, packages/spec/src/data/picklist.test.ts:1, packages/spec/src/kernel/capability-metadata-kind.test.ts:3, packages/spec/src/kernel/metadata-create-seeds.test.ts:2, packages/spec/src/kernel/metadata-customization-retirement.test.ts:1, packages/spec/src/kernel/metadata-type-api-registration.test.ts:4, packages/spec/src/kernel/metadata-type-field-registration.test.ts:3",
          "mixed": "packages/metadata-protocol/src/protocol.flow-org-override-closed.test.ts:9, packages/objectql/src/save-meta-response-conformance.test.ts:2 (flow-org-override-closed pins flow's flag false (b) and its organization-scoped refusal (a); save-meta-response-conformance :239 code-only (b), :309 organization-scoped refusal (a)).",
          "message_text_pins": "Tests that assert a runtime sentence naming the key: (b) protocol.delete-rewrap-envelope.test.ts:343, protocol.legacy-overlay-delete.test.ts:428, protocol.packaged-base-refusal.test.ts:150, sys-metadata-repository.package-writability.test.ts:1350, objectql protocol-commit-history.test.ts:667 and :865, plugin-security packaged-permission-set-restore-leg.test.ts:211 and permission-set-projection.test.ts:156, rest rest-meta-packaged-flow-refusal.test.ts:117, spec metadata-customization-retirement.test.ts:58 (regex on the 17.x tombstone prescription); (a) protocol.org-scoped-write-refused.test.ts:421."
        },
        "sibling_repos": "objectui at the .objectui-sha pin a58626c88 (commit fetched into the shared objectui object store; no checkout moved): 57 files / 154 hits = 11 source files / 49 hits (metadata-admin useMetadata.ts:77 declares its own optional 'allowOrgOverride?: boolean'; registry.ts 3, ResourceEditPage.tsx 12, PermissionMatrixEditor.tsx 17, DirectoryPage.tsx 3, ResourceListPage.tsx 3, PageShell.tsx 1, StudioHomePage.tsx 1, EmbeddedItemEditor.tsx 1, previews/PicklistPreview.tsx 1, i18n.ts 5 user-visible strings naming the key) + 43 test files / 95 + 3 CHANGELOG / 10. cloud: NOT MEASURED, reason: this session's GitHub proxy is repository-scoped (search/code answers 403) and no cloud checkout exists here."
      },
      "five_types": {
        "verified": "DEFAULT_METADATA_TYPE_REGISTRY parsed from source at 54c3ce10c: 28 entries; the flag is true on exactly view (metadata-plugin.zod.ts:855), dashboard (:857), report (:863), translation (:1070), email_template (:1071). supportsOverlay true with the flag false: page, app, dataset, book, permission, position, tool, skill. The card's list holds.",
        "write_path_all_five": "REST PUT /meta/:type/:name rest-server.ts:7050-7052 then p.saveMetaItem :7307; dispatcher runtime/src/domains/meta.ts:1287 then saveMetaItem :1464. protocol.ts saveMetaItem :20023: type gate :20172 (isOverlayAllowed :15976, OVERLAY_ALLOWED_TYPES :15842-15851, the flag read at :15845, OS_METADATA_WRITABLE hatch envWritableTypes :15865), package door :20317 into refusePackagedBaseOverride :17168 (:17171), then repo.put :21129 into SysMetadataRepository.assertAllowed sys-metadata-repository.ts:1781 (:1789, set at :314-317, flag read at :316). Reset/remove: deleteMetaItem :26576 (:26619, :26722).",
        "read_path_all_five": "No served read consults the flag; the read keys on supportsOverlay (mergesOverlayAtRead :15969). getMetaItem :10046 via findServedOverlayRow :9976 and servedOverlayRowCandidates :2032; getMetaItems :8851 via mergePackageAwareOverlay :2160 (:9120); getMetaItemLayered :10647. A server-side rename therefore cannot hide a stored overlay; the loss risks are the two write-side derivations and the Studio gate.",
        "studio_gate_all_five": "GET /meta/types: protocol.ts getMetaTypes :7830 emits the flag (:7883-7886, synthesized :7953), typed by spec api/protocol.zod.ts:210 (GetMetaTypesResponseSchema :202) and by @objectstack/client meta.getTypes (client/src/index.ts:1754, :7629). objectui pin a58626c88 ResourceEditPage.tsx:1357-1359 and :1775-1778: canWriteByType for an artifact-backed item is !!entry.allowOrgOverride. With the wire renamed and objectui unchanged, every packaged item of the five types opens read-only in Studio: the overlay is lost at the authoring door, silently.",
        "view": "Flag :855. Pins of an environment overlay of a packaged item: runtime/src/meta-field-overlay-lock.test.ts:552 (dispatcher PUT, 200, row stored), metadata-protocol/src/protocol.packaged-base-refusal.test.ts:94 (package-door verdict null for save and delete), metadata-protocol/src/sys-metadata-repository.package-writability.test.ts:325 (repository put lands); served read: qa/dogfood view-container-cross-package-default.dogfood.test.ts:113 (names no key); wire: objectql/src/protocol-meta-types-rich.test.ts:91.",
        "dashboard": "Flag :857. Pin: runtime/src/meta-field-overlay-lock.test.ts:563 (dispatcher PUT over the packaged system_overview, 200, row stored). No served-read or wire pin found.",
        "report": "Flag :863. NO pin of an environment overlay of a packaged report found. Its only pins are organization-scoped, class (a): objectql/src/overlay-precedence.test.ts:154 (organizationId org_alpha, not a packaged item) and the five-type identity pin protocol.org-scoped-write-refused.test.ts:550; #15206 S4 flips both.",
        "translation": "Flag :1070. Extra reader: core/src/fallbacks/authored-translation-sync.ts:115 readAuthoredTranslationLayer (sys_metadata type translation, every organization, :126) into the i18n authored layer; it reads no flag. NO pin of an environment overlay of a packaged translation found; only the (a) identity pin :550.",
        "email_template": "Flag :1071. Extra reader: plugin-email/src/email-plugin.ts:1325 readEffectiveTemplate (getMetaItem :1335, projected into sys_email_template); bootstrap-declared-email-templates.ts readDeclared reads the Default-Organization layer (class a, #15206 S3). Pin: objectql/src/engine-security-catalog-package-door.test.ts:262 (saveMetaItem over a packaged template on both topologies, row stored). The served-read dogfood email-template-overlay-survives-boot.dogfood.test.ts is organization-scoped by construction (orgContext: true) and names no key.",
        "search_method": "Test files naming the type literal AND an artifact marker (_packageId, getArtifactItem, packaged) AND a write (saveMetaItem, PUT), each read; plus dogfood 'PUT /meta/TYPE' scans. 'None found' is that search's reading, not a proof of absence."
      },
      "conversion": {
        "entry_points": "None carries a registry entry. (1) The type registry: MetadataTypeRegistryEntryBaseSchema metadata-plugin.zod.ts:207-267; its only writer is the TypeScript literal DEFAULT_METADATA_TYPE_REGISTRY :714 typed MetadataTypeRegistryEntryParsed[] (never parsed), installed by setTypeRegistry at packages/metadata/src/plugin.ts:411; MetadataTypeRegistryEntrySchema has 0 non-test parse sites. (2) Plugin manifest: contributes.kinds[] is a closed strictObject of id, globs (tombstone) and description (kernel/manifest.zod.ts:696-715), so the key would be an unrecognized key. (3) MetadataPluginConfig.additionalTypes is a retiredKey tombstone (:561) since 17. (4) defineStack / stack.zod.ts: no type-registry collection. (5) Stored rows: no sys_metadata type stores registry entries. The key only leaves the platform, on GET /meta/types.",
        "precedent": "conversions/registry.ts has no entry that renames a key on a registry or config entry; every rename walks a stack (objectCompactLayoutRename :225, stackRolesToPositions :264; manifestPermissionsStringListRemoved :8961 reaches stack.manifest and packages[].manifest). The non-stack rename precedent is in migrations: retired-keys/18.kernel__HotReloadConfig__debounceDelay.ts quotes 'Tombstoned with `retiredKey()`: `HotReloadConfigSchema` is not `.strict()`, so a bare deletion would silently strip the key ... No D2 conversion: not a stack collection member, not a stored row' (schema shape: debounceDelayMs plugin-lifecycle-advanced.zod.ts:380 beside 'debounceDelay: retiredKey(...)' :384; D3 entry kernel-health-check-and-hot-reload-durations-unit-in-key). The same registry's retired-keys/18.kernel__MetadataPluginConfig__additionalTypes.ts quotes 'Registered here but NOT in `src/conversions/registry.ts` ... a MetadataConversion here would be a transform with no seam that ever runs.' The converse, retired-keys/18.api__ApiEndpoint__cacheTtl.ts, gets a D2 entry only because 'apis: is a stack collection'.",
        "d2_reading": "A D2 conversion for this key would be a declared transform the loader never applies. The acceptance pin 'a manifest with the old key loads and converts to the new one' cannot be written: no manifest can carry the key. See open question 1.",
        "baselines_that_change": "packages/spec/authorable-surface/kernel.json:347 (gen:schema; the old path becomes ' [RETIRED]' under a tombstone), authorable-defaults/kernel.json:70 (the '= false' fingerprint), src/migrations/registry.ts (generated barrel, new retired-key + D3 entries), spec-changes.json and docs/protocol-upgrade-guide.md (gen:spec-changes, gen:upgrade-guide), content/docs/references/kernel/metadata-plugin.mdx:271, references/api/protocol.mdx:1422/:1428 (wire field), references/system/email-template.mdx:15 (TSDoc of system/email-template.zod.ts:16).",
        "baselines_that_do_not_change": "Measured by grep, the property name is absent from: api-surface/ (export names only: MetadataTypeRegistryEntry*, GetMetaTypesResponse*), export-origins/, json-schema.manifest/kernel.json (schema ids), declaration-map/, api-surface-signatures.json (define* factory hashes; none takes a registry entry), dropped-refinements.baseline.json (sites carry no key), liveness/ (no ledger row for kernel/MetadataTypeRegistryEntry; 3 prose notes only). authorable-surface/api.json tracks GetMetaTypesResponse:entries and :types only, so the wire rename is invisible to every spec gate except the regenerated reference page.",
        "not_written_by_the_rename_pr": "authorable-surface.base.json:4262: only gen:authorable-surface-base writes it; the deletion gate needs the RETIRED_KEYS_BY_MAJOR registration instead (packages/spec/scripts/build-schemas.ts :805-813, :954-961).",
        "gates_reached": "check:authorable-surface (live to absent refused without a retired-key registration), check:overlay-whitelist-table (scripts/check-overlay-whitelist-table.mjs COL_FLAG :255 reads the registry column and the table header content/docs/concepts/metadata-lifecycle.mdx:109; legs 1-3 plus its self-test fixtures), check:platform-checklist (anchors 'metadata-plugin.zod.ts#allowOrgOverride' at docs/qa/platform-checklist/areas/platform-core.json:492 and studio-authoring.json:1257; a tombstone keeps the word at line start, so those stale anchors would still resolve), check:docs, check:spec-changes, check:upgrade-guide, check:adr-0087-registration."
      },
      "name_candidates": [
        {
          "name": "allowEnvironmentOverlay",
          "reads_at_call_sites": "Row: { type: 'report', supportsOverlay: true, allowEnvironmentOverlay: true, allowRuntimeCreate: true }. Derivation: if (!entry.allowEnvironmentOverlay) continue. Sentence: 'the type does not allow environment overlays (allowEnvironmentOverlay=false)'. objectui: isArtifactItem ? !!entry.allowEnvironmentOverlay : ...",
          "collisions": "Exact (git grep -w, whole tree): 0. Near: supportsOverlay on the same entry (the read-path capability; the intended pair); overlayScope 'env' (api/protocol.zod.ts:537, the same scope vocabulary); capabilities.overlay on MetadataPluginConfig (metadata-plugin.zod.ts:672, a plugin capability); the retired persistence.overlayWritable (kernel/metadata-loader.zod.ts:193). Confusable: the wire entry's overrideSource 'env' and OS_METADATA_WRITABLE use 'env' for an environment VARIABLE.",
          "four_axes": "Business need (measured): writers are DEFAULT_METADATA_TYPE_REGISTRY, test fixtures and the getMetaTypes synthesis only; readers are two write-gate derivations, the wire field and 11 objectui source files. That holds for every candidate, so this axis does not separate them. Long-term: names the scope in the canonical ADR-0006 spelling and the mechanism noun ADR-0005 and supportsOverlay use; stays unambiguous if a per-organization axis returns (ADR-0131 D6 retires it 'for now'). AI error: the capability/permission pair (supportsOverlay vs allowEnvironmentOverlay) states the #6960 distinction in the names; the env-variable reading is the residual risk. Startup: one rename, no new capability."
        },
        {
          "name": "allowEnvironmentOverride",
          "reads_at_call_sites": "Row: { type: 'view', supportsOverlay: true, allowEnvironmentOverride: true }. Sentence: '(allowEnvironmentOverride=false)'. Wire entry: { allowEnvironmentOverride: true, overrideSource: 'env' }.",
          "collisions": "Exact: 0. Near: overrideSource 'registry'|'env' on the same /meta/types entry (api/protocol.zod.ts:216), where 'env' means OS_METADATA_WRITABLE; the code NOT_OVERRIDABLE and the write intent override-artifact (metadata-core/src/types.ts:158) share the stem; configOverrides (system/app-install.zod.ts:113) is unrelated.",
          "four_axes": "Business need: as above. Long-term: the smallest edit from the old name, but it keeps the override/overlay split (ADR-0005 and supportsOverlay say overlay). AI error: the most guessable old-to-new mapping; the strongest misreading of the three, since 'environment override' beside overrideSource 'env' reads as 'overridden by an environment variable'. Startup: one rename."
        },
        {
          "name": "allowPackagedOverlay",
          "reads_at_call_sites": "Row: { type: 'translation', supportsOverlay: true, allowPackagedOverlay: true }. Sentence: 'the type does not allow overlays of packaged items (allowPackagedOverlay=false)'. objectui: isArtifactItem ? !!entry.allowPackagedOverlay : ...",
          "collisions": "Exact: 0 ('packagedOverlay' appears once, in prose). Near: ADR-0126's 'packaged base' vocabulary (29 hits in packages/spec/src) reads as intended; but 'packaged overlay' also reads as an overlay that ships in a package (ADR-0070 package-first authoring; overlay rows carry the package_id of the package they customize).",
          "four_axes": "Business need: as above. Long-term: names the object (the artifact-backed item that the override-artifact intent gates) and drops the scope; if a per-organization axis returns, one scope-less key would again govern two scopes, the shape ruling C closed. AI error: free of the env-variable clash; open to the 'overlay from a package' misreading. Startup: one rename."
        }
      ],
      "name_candidates_excluded": "overlayWritable (a retired key's name on MetadataManagerConfig.persistence, metadata-loader.zod.ts:193; a live key sharing a tombstone's name confuses both prescriptions); allowOverlay / overlayable (scope- and object-less, beside capabilities.overlay). The choice is the contract review's; no pick is made here.",
      "stage_plan": [
        {
          "stage": "S0",
          "what": "This measurement. No file, no PR.",
          "clause_2": "n/a"
        },
        {
          "stage": "S1",
          "what": "Environment-overlay pins for the five types, tests only, under the current key name.",
          "files": "One new test file in packages/objectql/src on the real SchemaRegistry + protocol, both topologies (engine-security-catalog-package-door.test.ts is the harness model); optionally a dispatcher case in packages/runtime/src. Per type: PUT env-wide (no organization) over a packaged item is accepted, the row is stored with organization_id NULL, GET serves the overlay body, /meta/types advertises the flag true; identity: the true set is exactly the five.",
          "clause_2": "no (tests only; nothing in any package's files[] moves).",
          "serial": "Independent of every open PR and of #15206; must not pass organizationId so S3/S4 leave it standing. Reverse verification: commit, then flip report's flag to false, its case goes red; restore.",
          "why_now": "Report and translation have no environment-overlay pin, and #15206 S3/S4 rewrite the write doors all five pass through (organizationIdForMetaWrite, orgScopedWriteRefusal). Landing before S3 makes 'no overlay is lost' checkable during #15206, not only after it.",
          "estimate": "S"
        },
        {
          "stage": "S2",
          "what": "The rename: new key, retiredKey() tombstone on the old one, retired-keys + D3 entries (no D2 entry, per open question 1), the wire field renamed with objectui in the same landing (open question 2).",
          "files": "spec: kernel/metadata-plugin.zod.ts (key :267 + TSDoc, 28 rows, comments, the customizationPolicies prescription :513-520), api/protocol.zod.ts :210/:216/:1667, system/email-template.zod.ts:16, kernel/index.ts:31, kernel/metadata-create-seeds.ts:141, kernel/metadata-type-schemas.ts:142, new migrations/entries/retired-keys/18.kernel__MetadataTypeRegistryEntry__allowOrgOverride.ts and a semantic 18.* entry, the two unreleased 18.* prose entries, regenerated registry.ts / authorable-surface/kernel.json / authorable-defaults/kernel.json / spec-changes.json / protocol-upgrade-guide.md / 3 reference pages, 6 spec tests. Runtime: protocol.ts (the 41 class-(b) lines; code :15845, :7883/:7884/:7953; sentences :16099/:16118/:17247/:21650), sys-metadata-repository.ts (13), package-writability.ts, metadata-core types.ts/contract-suite.ts, runtime domains/meta.ts:967, objectql engine.ts, plugin-security (4 files, comments), platform-objects sys-job.object.ts, lint validate-ai-agent-authoring.ts, examples/app-showcase coverage.ts. Tooling: check-overlay-whitelist-table.mjs (+ self-test), 2 adr-anchors. Docs: 11 content/docs pages, 8 docs/qa/platform-checklist files (re-point both '#allowOrgOverride' anchors explicitly), 3 liveness notes. Tests: the 46 class-(b) files + residue of the 2 mixed; the 10 message-text pins move with their sentences. Cross-repo: an objectui PR (11 source + about 43 test files at the pin) and, in this PR, the .objectui-sha bump with the regenerated SDUI manifest.",
          "clause_2": "yes (narrowing): widens (a new authorable key and wire field), narrows (the authorable key and the GetMetaTypesResponse field are retired). BREAKING; changeset carries FROM allowOrgOverride TO NEW_KEY on MetadataTypeRegistryEntry and GET /meta/types entries, and 'adr-0087: registered' naming the two new ids. Contract-tier review owed (dispatch-gates --tier: no path mandate; clause-② suspect on both spec paths).",
          "serial_vs_15206": "After #15206 S5 (hence after S2-S4). S1 (sys_view_definition): only the migrations barrel, regenerate. S2 (seal): rewrites refusePackagedBaseOverride/Removal :17168-17290 and the repository hatch :370, the same sentence (:17247) and repository messages (:1854-1983) this stage renames. S3: deletes ORG_OVERRIDABLE_TYPES (a flag reader), the manage_org_presentation arm and capability, door threading, 14 test files. S4: deletes the :16210 exemption, the :16215 sentence and the identity pin, 9 test files. S5: removes the :27554 flag read and 9 read-gate test files.",
          "serial_vs_open_prs": "#22215 (PROTOCOL_VERSION 18; spec-changes.json, protocol-upgrade-guide.md): land after it and regenerate. #22323 (protocol.ts :22697-22778, sys-metadata-repository.ts :81-1379, api/protocol.zod.ts :1781-1800, references/api/protocol.mdx): textually disjoint from this stage's hunks, regenerate the reference page. #22322 (references/api/protocol.mdx) and #22315 (migrations/registry.ts + an 18.* semantic entry): regenerate. #22352, #22351, #22354, #22353, #22347, #22341, #22339, #22327, #22268: no file in common. #21988 (Version Packages): CHANGELOGs only, never edited here (its file list read to page 1 of 2).",
          "pins": "The five S1 cases flip to the new key and gain the served-read leg; a tombstone pin (parse of the old key is refused with a prescription naming the new key, code + path); /meta/types carries the new key true for the five and no old key; check:overlay-whitelist-table self-test on the new column. Reverse verification: flip one of the five to false, its case red.",
          "estimate": "L (about 110 files with the objectui companion; changed lines well under 5,000)"
        },
        {
          "stage": "S3",
          "what": "Governed text, Tier H, its own PR after S2 merges; fold #15206 S7 (ADR-0005 note) into it if both are cut.",
          "files": "AGENTS.md:190-192, skills/objectstack-ai/SKILL.md:347, docs/adr/0005 (top note in the shape of its :3 v5.0 note, plus :47/:68), optionally docs/adr/0010 status note.",
          "clause_2": "no. dispatch-gates --tier on this surface: MANDATORY claude-fable-5-1 (skills/**, no one-line exemption). skills line budget: one-line in-place edits, report whole-file and whole-catalog line counts.",
          "estimate": "S"
        }
      ],
      "order_recommendation": "S1 now; S2 after #15206 S5 merges; S3 after S2. Measured reasons: (1) wasted work: 166 of the 408 code and test hits (46 source hits in 14 files, 120 test hits in 32 files) are in code #15206 S3-S5 delete or rewrite. (2) Meaning: until S4, orgScopedWriteRefusal exempts organization-scoped writes of exactly the flag's types (protocol.ts:16210); until S3, organizationIdForMetaWrite/Read thread the organization only for them (meta-write-org-scope.ts:99, :141, :189); until S5, reportUnhydratableOrgScopedRows treats their organization rows as legitimate (:27554). A key renamed to an environment name before then still governs organization scope, ruling C's rejected B shape inverted. (3) Conflict: S3-S5 are L-sized PRs over protocol.ts, rest-server.ts, runtime meta.ts and the same test files. The card's 'either order or in parallel' holds for the DELETION (it never needs the new name), not for the rename.",
      "falsified_premises": [
        "F1 'An ADR-0087 D2 load-time conversion, so a manifest naming the old key still loads unchanged' / acceptance 'a manifest with the old key loads and converts': no manifest, stack, plugin config or stored row can carry a type-registry entry (conversion.entry_points), so a D2 entry has no seam. The recorded non-stack precedent is tombstone + retired-key + D3 (conversion.precedent). The ruling's intent, that no author hand-edits anything, holds vacuously: no author can write the key today.",
        "F2 'Clause-②: yes' (card) / 'yes (widening: a new published key ...)' (claim): the rename also retires an authorable key and a published wire field, so by the arm table in scripts/pm/clause2-line.mjs, where yes (narrowing) is 'a diff that widens one surface and narrows another', it is yes (narrowing), BREAKING, with a FROM/TO migration and a registered ADR-0087 disposition.",
        "F3 Scope 'generated baselines and docs follow' is incomplete: the rename also reaches GET /meta/types entries[].allowOrgOverride (spec api/protocol.zod.ts:210, @objectstack/client meta.getTypes) and objectui at the pin (11 source files, Studio's write gate for packaged items of the five types), runtime sentences naming the key (8 sites, pinned at 9 test sites in 8 files), two gates (check:overlay-whitelist-table reads the column name in code and in the docs table; check:platform-checklist resolves two symbol anchors), and the 17.x customizationPolicies tombstone prescription.",
        "F4 'The two cards land in either order or in parallel': true for #15206's deletion; for this card's rename, landing before #15206 S5 renames 166 hits of code S3-S5 delete and ships an environment-named key that still decides organization scope (order_recommendation).",
        "F5 'No overlay is lost' pins: today only view, dashboard and email_template have a pin of an environment overlay of a packaged item; report and translation have none, and their organization-scoped pins are #15206 S4's to flip (five_types).",
        "Confirmed, not falsified: the five types (28 entries, exactly five true); the key at metadata-plugin.zod.ts:267 with describe 'Allow per-org overlay writes via runtime metadata API'; the claim's 176 files and 60 protocol.ts hits; #15206 uses the key under its current name and its deletion does not depend on the name; isOverlayAllowed has no organization branch of its own (it is :15976; the per-organization path is orgScopedWriteRefusal :16203-16231 and the door helpers)."
      ],
      "open_questions": [
        {
          "question": "Q1. The ruled 'ADR-0087 D2 load-time conversion' has no seam (F1). What carries the old key's prescription instead?",
          "options": [
            "A. retiredKey() tombstone on MetadataTypeRegistryEntryBaseSchema + retired-keys entry 18.kernel__MetadataTypeRegistryEntry__allowOrgOverride + a D3 semantic entry; no D2 entry (the HotReloadConfig.debounceDelay and MetadataPluginConfig.additionalTypes precedents). Cost: two ledger files and a tombstone pin.",
            "B. Register a D2 conversion anyway to meet the ruling's letter. Cost: a conversion entry no loader ever applies; the precedent text calls it 'a transform with no seam that ever runs'.",
            "C. Plain rename with no tombstone and no ledger entry. Refused mechanically: check:authorable-surface rejects live-to-absent without a retired-key registration, and AGENTS.md requires a tombstone for a removed authorable key."
          ],
          "recommendation": "A. Business need: measured, zero manifests or stored rows can name the key, so no author needs a load-time rewrite; the readers that matter are TypeScript code and wire consumers, which the compiler and the tombstone reach. Long-term: two recorded precedents of the same shape. AI error: the tombstone refuses the old key loudly at parse and compile with the new name in the prescription; B declares a capability the runtime never exercises (declared is not enforced). Startup: no window, no dead ledger row. This replaces the ruling's mechanism, not its direction, so it needs triage or the contract review to record it."
        },
        {
          "question": "Q2. The /meta/types wire field (GetMetaTypesResponseSchema entries[].allowOrgOverride) is the same key's projection and objectui's Studio write gate. How does it move?",
          "options": [
            "A. Rename it in S2, in one landing with an objectui PR that reads the new key and the .objectui-sha bump (+ SDUI manifest regeneration). Cost: a cross-repo landing; the objectui PR merges just before S2 so objectui main does not run long against the old server.",
            "B. Keep the wire name allowOrgOverride for now and rename only the authoring key. Cost: the wire keeps a key that says 'organization' and governs environments, read by Studio and by AI clients of /meta/types.",
            "C. Emit both names for one release. Cost: a dual-spelling window and a consumer-side fallback in objectui."
          ],
          "recommendation": "A. Business need: objectui is the measured reader (11 source files at the pin; every packaged item of the five types). Long-term: one name end to end. AI error: B is ruling C's rejected B shape on the wire; and objectui's own optional field type means neither the Console Pin Gate nor api-surface would see a missed objectui side, so the same landing is the only safe form. Startup: C is a dual-spelling window, which this stage of the company does not take without named external users; none measured (cloud NOT MEASURED)."
        }
      ],
      "out_of_scope_findings": [
        "class: b (stated contract) · reach: NOT MEASURED, no public-door run · sys-metadata-repository.ts:362-363 states both write gates 'must consult the same elevated set', but the repository reads readEnvWithDeprecation('OS_METADATA_WRITABLE', []) (:370) while protocol.ts:15867 also honours the legacy OBJECTSTACK_METADATA_WRITABLE; by reading, with only the legacy variable set /meta/types advertises the type writable and the protocol gates pass, while the repository's assertAllowed would refuse the write. objectui PageShell.tsx:110 and useMetadata.ts:87 name the legacy variable to users · dedupe words: OS_METADATA_WRITABLE, OBJECTSTACK_METADATA_WRITABLE, envWritableMetadataTypes, readEnvWithDeprecation · carrier: #15206 S2 (the seal stage edits both hatch readers); noted, not filed",
        "The key's TSDoc (metadata-plugin.zod.ts:262-265) says only view and dashboard opt in and names 'not_overridable' in lower case; five opt in and the code is NOT_OVERRIDABLE · carrier: S2 of this card (it rewrites that TSDoc); noted, not filed",
        "The 17.x customizationPolicies tombstone prescription (metadata-plugin.zod.ts:513-520), the unreleased 18.metadata-customization-protocol-retired entry and kernel/index.ts:31 direct authors to 'ADR-0005's org-scoped overlay (opt-in via allowOrgOverride)', false twice once #15206 and this card land; pinned by metadata-customization-retirement.test.ts:58 · carrier: S2 of this card; noted, not filed",
        "qa/dogfood email-template-overlay-survives-boot.dogfood.test.ts pins the email-template overlay as organization-scoped by construction (orgContext: true); after #15206 S3 the save lands env-wide · carrier: #15206 S3; noted, not filed",
        "A tombstone keeps 'allowOrgOverride' at line start in metadata-plugin.zod.ts, so the two checklist anchors naming metadata-plugin.zod.ts#allowOrgOverride would keep resolving to the tombstone with check:platform-checklist green; docs/adr/0029:386 holds a third, ungated · carrier: S2 (re-point the checklist anchors) and S3 (ADR) of this card; noted, not filed"
      ],
      "tests": "No build and no test ran; stage 0 writes no file. Read-only probes in ../objectstack-issue-22340 at 54c3ce10c, git status --porcelain empty throughout: (1) git grep census with glob pathspecs and controls (census.command_and_controls); every hit line read and classed. (2) Registry entries parsed from source with a node one-liner (28 entries, five true). (3) objectui at the pin: git fetch of a58626c88 into the shared objectui object store, then git grep at that commit (no checkout change). (4) node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --tier on the S2 and S3 surfaces (no path mandate for S2, clause-② suspect on spec paths; MANDATORY fable for S3). (5) npm view @objectstack/spec dist-tags: latest 17.7.0, so 18.* entries are unreleased. (6) REST reads: card #22340 + 1 comment, #15206 + 11 comments incl. report 6067752061, #22007 + ruling 6028809298, open-PR list (14) and each PR's file list, PRs 22338/22331/22319 state, the 22323 patch hunks.",
      "mcp_calls": "0 — no MCP tool called",
      "api_writes": "1 — POST /repos/objectstack-ai/objectstack/issues/22340/comments (this os-dev-report, through scripts/pm/post-stamped.mjs and the fleet-write relay)",
      "gates": "not applicable — stage 0 writes no file. Derived: none (dispatch-gates without paths: 'this branch changes nothing against origin/main ... nothing to derive'). Run: none. Exit codes: none. --ran verdict line: not run.",
      "line_budget": "0 changed lines against merge base 54c3ce10c (git diff --stat empty); governed paths touched: 0.",
      "deviations": [
        "Did not push the empty branch (os-dev rule 1). The dispatch forbids any push in stage 0 and no edit happened, so neither the landing marker nor the write-route probe had anything to mark; os-dev says the role file prevails on conflict, so this is flagged for the seat rather than chosen silently.",
        "No pnpm install in the worktree: no edit, build or test.",
        "Classification reads each hit line by what it governs; three source files are split by line and two test files are mixed (census.method).",
        "objectui was measured at the .objectui-sha pin a58626c88, not at objectui main; cloud NOT MEASURED (repository-scoped proxy).",
        "origin/main moved to b7e01fbbd during the run (shared refs); the census stays anchored to 54c3ce10c and the one new commit names the key on 0 lines.",
        "The worktree ../objectstack-issue-22340 is removed after this report (clean, never pushed)."
      ],
      "files_changed": []
    }

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat review of #22340 stage 0: census accepted. Order set by the seat; the conversion mechanism goes back to the decision box (its ruled premise is falsified). Stage S1 is claimed

    domain:spec seat 2 (#18549) · os-sales · session session_01DhTqaEHqPVSVnAkjG3jywn · 2026-10-08T21:51Z · holder of claim 6069288725. This amends that claim. ⛔ Not a new claim.

    The stage-0 report is on this card (os-dev-report, measured at 54c3ce10c; b7e01fbbd names the key on 0 lines). The seat checked the method: the census uses glob pathspecs with non-vacuous controls, and every hit line was read and classed. The seat accepts it.

    Accepted readings:

    Set by the seat (ordering and dependency, not a product question):

    Back to the decision box: the ruling's mechanism. Ruling C (6028809298, #22007) prescribes "an ADR-0087 D2 load-time conversion so an existing manifest naming the old key still loads unchanged". Measured (F1), no manifest, stack, plugin config or stored row can carry a type-registry entry:

    • contributes.kinds is a closed shape;
    • additionalTypes is a tombstone;
    • the registry is a TypeScript literal that nothing parses.

    So a D2 conversion has no seam. A premise of the ruling is falsified, which is the case that returns to the box; the seat does not swap the mechanism itself. The sub-question the ruling did not cover, the wire field (Q2), is put in the same act. The four-axis analysis (Chinese) is the next comment. The state moves to needs-user-decision when S1 lands.

    S1 claim amendment:

    • Branch claude/issue-22340-s1-env-overlay-pins, worktree objectstack-issue-22340-s1.
    • File surface: one new test file in packages/objectql/src on the real SchemaRegistry and protocol, both topologies (harness model: engine-security-catalog-package-door.test.ts), plus optionally one dispatcher case in packages/runtime/src. No source file.
    • Clause-②: no (tests only). No changeset if the repo's rules exempt a test-only diff. Cross-lane on [PM seat] domain:engine — 🟢 sunhaolin #6367 (packages/objectql, packages/runtime tests).

    Noted, not filed (each with its carrier):


    Generated by Claude Code

  4. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    待维护者裁决:#22340 —— 改名 allowOrgOverride 时,「旧键照常加载」靠什么兑现;/meta/types 返回里的同名字段是否一起改

    domain:spec seat 2 (#18549) · os-sales · session session_01DhTqaEHqPVSVnAkjG3jywn · 2026-10-08T21:53Z · 认领 6069288725 的持有席。依据:阶段 0 报告(本卡 os-dev-report,54c3ce10c 实测)与本席复核 6069745527。

    一句话问题: 你在 #22007 裁的 C 是给这个键改名,并用「加载期转换」让旧写法照常加载。实测发现,没有任何作者能在 manifest 或配置里写这个键,所以那道转换没有地方可以生效。另外,这个键还以同名字段出现在 Studio 读取的接口返回里,原裁决没有提到它。

    背景(实测):

    • 这个键只写在平台自己的类型注册表里。注册表是一段 TypeScript 字面量,没有生产代码去解析它。
    • 插件 manifest 的 contributes.kinds 是封闭结构,写这个键会被拒;MetadataPluginConfig.additionalTypes 已经是墓碑;stack 里没有类型注册表集合;存储行里也不存注册表条目。
    • 仓里有同类改名的先例:HotReloadConfig.debounceDelay、MetadataPluginConfig.additionalTypes。做法是旧键留墓碑(retiredKey(),解析时响亮拒绝,并提示新名字),加一条 retired-keys 记录和一条 D3 语义记录,不加 D2 转换。先例原文:"a MetadataConversion here would be a transform with no seam that ever runs"。
    • GET /meta/types 的 entries[].allowOrgOverride(api/protocol.zod.ts:210)是同一个键投影到接口上的字段。objectui 在当前 pin 上有 11 个源文件读它,用来决定 Studio 能不能编辑这五类已打包条目。objectui 用的是自己定义的可选字段类型,所以服务端改了名、objectui 没跟上时,没有任何门禁会报错。结果是这五类条目在 Studio 里静默变成只读。

    Governing text:

    协议声明: 不改协议,只是落实已裁的改名方向。被证伪的是裁决中「旧 manifest 要靠转换」这一条前提。

    前提(附复验方式):

    • P1:注册表条目没有可被作者写入的入口 —— git grep -n "MetadataTypeRegistryEntrySchema" -- ':(glob)packages/**/src/**' ':!*.test.ts',非测试的解析点为 0。
    • P2:objectui 在 pin 上读这个字段 —— 在 objectui 的 .objectui-sha 提交上 git grep -n allowOrgOverride -- 'packages/**/src/**',命中 11 个源文件。

    Q1:旧键的提示由什么承载

    选项 做什么 客户/作者能感知到的后果
    A 墓碑 + D3(推荐) 新键上线,旧键留墓碑,解析时响亮拒绝并给出新名字;加 retired-keys 与 D3 语义记录,不加 D2 今天没有作者能写这个键,所以没有人需要被自动改写;平台代码和接口消费方由编译器和墓碑拦住
    B 照裁决原文加 D2 另外登记一个 D2 转换 账本里多一条永远不会执行的转换,等于声明了一个运行时不兑现的能力
    C 直接改名,不留墓碑 — 会被机械拒绝:check:authorable-surface 不允许没有退役登记的删除,AGENTS.md 也要求墓碑

    Q2:/meta/types 的同名字段

    选项 做什么 后果
    A 一起改名(推荐) S2 改服务端字段,同一次落地配一个 objectui PR 改读新名字,并升级 .objectui-sha 从注册表到 Studio 用同一个名字;代价是一次跨仓协同落地
    B 接口保留旧名 只改作者侧的键 接口上留下一个写着「组织」、实际管「环境」的字段,Studio 和读 /meta/types 的 AI 客户端都会读错。这正是裁决 C 已经否掉的 B 形态,只是换到了接口上
    C 新旧两个名字同时发一个版本 — 双拼写过渡期,objectui 还要写回退逻辑。没有具名外部用户的证据,按「过渡也从紧」不荐

    业务含义直译:

    • Q1-A ≈「门牌换了,旧门牌钉一块『已搬到 X』的牌子」。Q1-B ≈「再装一台永远不会有人按的转接电话」。
    • Q2-A ≈「店名和招牌同一天一起换」。Q2-B ≈「新店名开张,门口招牌还挂旧名」。

    四轴论证:

    • 长远合理性: Q1-A 与仓里两条同形先例一致,账本里不留死记录。Q2-A 从头到尾只有一个名字。
    • 实际业务拉动: 写这个键的只有平台自己;读它的是两处写门推导、一个接口字段,以及 objectui 的 11 个源文件。所以 Q1 没有作者需要迁移,Q2 有一个实测的真实消费方(Studio)。
    • 防 AI 犯错(出错时谁看到什么):
      • Q1-A:旧键在解析和编译时响亮报错,并给出新名字;Q1-B 声明了一个不会执行的转换。
      • Q2-B / Q2-C:AI 读接口时会把「org」理解成组织。Q2 漏改 objectui 时是静默只读,所以必须同一次落地。
    • 创业阶段不扩散: Q1-A 不新增任何长期维护面;Q2-C 是双拼写窗口,不荐。

    os-decision-facets

    推荐:Q1 选 A,Q2 选 A。 只看①选 A / A;②③④ 是否翻转:否(④ 只影响落地形式:Q2-A 要求 objectui PR 与 S2 同一次落地)。回退项:Q1 无(B、C 都不成立);Q2 回退到 C 需要具名的外部用户证据。

    置信缺口: cloud 仓有没有读 /meta/types 的 allowOrgOverride,未实测(本会话的 GitHub 代理按仓限定)。objectui 只测了 pin 上的提交,没测它的 main。

    裁后执行:

    状态: S1 落地后,本卡转入 needs-user-decision。请在本卡回两个字母,例如「Q1 A,Q2 A」。


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 22340,
      "status": "done",
      "branch": "claude/issue-22340-s1-env-overlay-pins",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/22363",
      "session": "session_01DhTqaEHqPVSVnAkjG3jywn (subagent of the PM session; identity = the S1 branch named by the seat amendment 6069745527, verified against the newest Claim: 6069288725, which names stage 0's branch; no second claim posted)",
      "premise_still_valid": true,
      "summary": "S1 landed as one new test file, packages/objectql/src/environment-overlay-five-types.test.ts (tests only, no source file). It runs on the real ObjectQL engine, SchemaRegistry and ObjectStackProtocolImplementation on both topologies, and no organizationId reaches any call. For each of view, dashboard, report, translation and email_template it pins three things. (1) saveMetaItem over the packaged item is accepted, stores exactly one row with organization_id NULL, and the read serves the written body. (2) A stored env-wide row put straight into the store is what getMetaItem serves, with a control that the read serves the packaged item before the row exists. (3) getMetaTypes advertises allowOrgOverride true with overrideSource registry, with OS_METADATA_WRITABLE cleared. One more case pins the identity: the flag is true on exactly these five. On origin/main 1cb0edb82, all five env-wide overlays are accepted on both topologies, so no stop condition fired. Two of the dispatch's premises were measured and corrected; neither changes the stage. (a) The served read getMetaItem keys on neither the flag nor supportsOverlay. Its only skip is declinesStoredRow (shipped flows and code datasources), and supportsOverlay's sole protocol reader, mergesOverlayAtRead, is called only by the delete door. So the pin claims only that the read consults no flag, and the ablation shows it. (b) No in-repo producer puts a packaged translation into the SchemaRegistry, so the translation case registers its packaged item through registerItem(type, item, 'name', packageId), the entry isArtifactBacked reads. Existing pins are listed per type in the file header and the PR body. No runtime dispatcher case was added: for an env-wide write the dispatcher reads the flag nowhere.",
      "tests": "All runs at head db89d66f0. New file: pnpm --filter @objectstack/objectql exec vitest run --project local src/environment-overlay-five-types.test.ts gives 26 passed (26): 1 identity, 2 topologies x 5 types x write/read = 20, 5 wire. Package: pnpm --filter @objectstack/objectql exec vitest run --project local --maxWorkers=2 gives Test Files 388 passed (388), Tests 7633 passed (7633). Typecheck: pnpm --filter @objectstack/objectql run typecheck exits 0, with 'check:test-typecheck: OK ... 40 file(s) / 234 error(s) / 65 pinned signature(s) held'; the new file is unledgered, so it compiles with zero errors. ABLATION, report flag true to false in DEFAULT_METADATA_TYPE_REGISTRY via scripts/ablation-replace.mjs: anchor x1 to x0, replacement x0 to x1, blob 47f68e76cb5c to 01bfde907a81. @objectstack/spec was rebuilt (exit 0), and ablation-dist-preflight found the marker in 4 built files: dist/kernel/index.js, dist/kernel/index.mjs, dist/browser/kernel/index.js, dist/browser/kernel/index.mjs. Predicted before running: 4 red / 22 green, with report's read cases staying green. Measured 'Tests 4 failed | 22 passed (26)', exactly the predicted four. Identity received [dashboard, email_template, translation, view]. Report write on both topologies received refused { code NOT_OVERRIDABLE, status 403 }. Report wire received allowOrgOverride false, overrideSource registry. RESTORE: by the tool, blob == HEAD 47f68e76cb5c, git diff HEAD empty. Spec was rebuilt (exit 0), ablation-dist-preflight --absent reported the marker absent from all 232 built files and the whole tree clean, and the re-run gave 26 passed (26). Lint, a declared narrowing: eslint --no-inline-config --format json on the one file reports 1 file, 0 errors, 0 warnings. The file is in eslint's population (--print-config returns a config with 5 rules for it). The invariance holds because type-aware linting is not enabled (no parserOptions.project, no typed rules; eslint.config.mjs states the same), so a new file cannot change another file's result. Changeset measurement: objectql was built (exit 0). The test file's fixture strings appear 0 times in files[] (dist, README.md, CHANGELOG.md), against a positive control of registerMetadataCollections in 6 dist files.",
      "mcp_calls": "0 (no MCP tool used)",
      "api_writes": "3 from this session, all POST /repos/objectstack-ai/objectstack/dispatches (the fleet-write relay). The relay executed 4 writes as objectstack-fleet[bot]: (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls, giving #22363 draft, with the read-back reporting 9933 bytes sent and 9933 stored, identical; (2) labels_add, POST /repos/objectstack-ai/objectstack/issues/22363/labels [skip-changeset]; (3) assign, POST /repos/objectstack-ai/objectstack/issues/22363/assignees [os-sales]; (4) this os-dev-report comment, POST /repos/objectstack-ai/objectstack/issues/22340/comments via post-stamped.mjs. Separately, 2 git pushes of the branch (the empty branch probe and db89d66f0), which are not REST writes. The card's assignee was not written.",
      "gates": {
        "derived": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, with no paths, at db89d66f0. Change set: 1 path vs merge base 1cb0edb82. 56 commands, byte-identical after sort to the dispatch file g22340s1.txt (derived at b7e01fbbd), so nothing was added.",
        "run": "56 run, unlocked and in the foreground (nohup plus a tail --pid wait), at head db89d66f0. 55 exit 0. pnpm check:dual-build-cjs-loads exit 3: PREREQUISITE NOT MET, 65 packages have no dist. It needs every workspace package built and is NOT MEASURED; the diff adds a test file that no build emits (measured, 0 hits in objectql dist), and CI builds the workspace.",
        "notable_exit_0": "check:nul-bytes 'OK (scanned 10343 text file(s) ... no raw ASCII control bytes)'; check:engine-double-contract 'OK — 990 pinned, 129 in the DEBT ledger, 3 exempt'; check:objectql-double-limit '... none new'; check:test-source-alias OK; check:driver-memory-census OK; check:type-check-debt OK; check-issue-citations '0 file(s) read' (test files are a DEFERRED surface of that gate).",
        "ran_verdict": "✓ dispatch-gates --ran: 56 derived famil(ies) accounted for — 55 run, 1 NOT-MEASURED (1 DERIVED from a recorded exit 3).",
        "ci_at_report": "in_progress (12 of 30 check runs completed at report time, none failed; Check Changeset skipped by the skip-changeset label). CI convergence is the PM's."
      },
      "line_budget": "+359 / -0 in 1 file vs merge base 1cb0edb82 (dispatch-gates: 359 changed lines, under the 5000 human-merge threshold). Governed paths touched: 0.",
      "deviations": [
        "Read leg: the dispatch said the served read keys on supportsOverlay, not on the flag. Measured: getMetaItem consults neither, so the pin asserts only that the read consults no flag. The ablation shows this: report's read cases stay green while its write and wire cases go red.",
        "Translation: no stack collection carries a packaged translation, so its packaged item is registered through SchemaRegistry.registerItem(type, item, 'name', packageId) instead of the manifest; the other four go through the manifest's own stack collections.",
        "The read leg seeds the env-wide row directly into the store, with the shape the repository writes: type, name, organization_id null, package_id null, metadata as JSON, state active, version 1. This asks the read alone, with no write door in front of it. The write leg also reads back through the protocol, which ties what the door stores to what the read serves.",
        "organization_id is asserted as (row.organization_id ?? null) toBeNull. It is NULL today, and the form stays standing if #15206 makes the family tenant-less and drops the column.",
        "email_template's packaged save on both topologies already exists as the control in engine-security-catalog-package-door.test.ts. Here it is the first step of a round trip that goes on to read the stored row's organization, the served body and the wire flag, so it is not a duplicate single-fact case. No other existing pin was restated.",
        "Commit trailers use AGENTS.md's model-free pair (Claude-Session plus Co-authored-by: Claude). The harness reminder's model-named Co-Authored-By trailer was not used because the pre-push hook refuses a model identifier; the PR footer uses AGENTS.md's session-URL form.",
        "check:dual-build-cjs-loads is NOT MEASURED (exit 3, prerequisite: a whole-workspace build)."
      ],
      "files_changed": [
        "packages/objectql/src/environment-overlay-five-types.test.ts"
      ],
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: #22340 S2 contract review (the domain:spec seat) · noted, not filed · No in-repo producer puts a packaged translation into the SchemaRegistry. This is a reading of four seams at 1cb0edb82, not a boot measurement: METADATA_ARRAY_KEYS in objectql/src/engine.ts and ARTIFACT_FIELD_TO_TYPE in metadata/src/plugin.ts carry no translations collection; MetadataPlugin._loadFromFileSystem stamps _packageId but registers into MetadataManager's own map; ObjectQLPlugin.loadMetadataFromService copies only object, view, app, flow and hook. So isArtifactBacked is false for every translation, and an env-wide translation write is admitted by allowRuntimeCreate, not by the flag. The flag's live effect on translation is the per-organization path (#15206) and the Studio wire gate, which bears on what 'no overlay is lost' means for translation in S2 · dedupe words: translation packaged artifact, isArtifactBacked translation, translations METADATA_ARRAY_KEYS",
        "carrier: #22340 S2 (the domain:spec seat) · noted, not filed · Stage 0's reading 'the read keys on supportsOverlay (mergesOverlayAtRead)' does not hold for getMetaItem. That read serves any stored active row unless declinesStoredRow holds, and mergesOverlayAtRead is called only by refusePackagedBaseRemoval, the delete door. The rename still cannot hide a stored overlay from this read: it consults no flag, as pinned and as the ablation shows · dedupe words: mergesOverlayAtRead, supportsOverlay served read, declinesStoredRow",
        "Governed text: none made false by this diff (AGENTS.md:190-192, skills/objectstack-ai/SKILL.md:347 and ADR-0005 are S3's, unchanged)."
      ]
    }

    Generated by Claude Code

  6. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    Seat review of #22340 S1, PR #22363 at db89d66f0: ACCEPT. Lands when green; the card then moves to needs-user-decision (6069763011)

    domain:spec seat 2 (#18549) · os-sales · session session_01DhTqaEHqPVSVnAkjG3jywn · 2026-10-08T22:44Z · holder of claim 6069288725 (S1 per 6069745527).

    The report is on this card. The PR adds one test file and touches no source file: packages/objectql/src/environment-overlay-five-types.test.ts, +359.

    • What it pins. For each of view, dashboard, report, translation and email_template, on both topologies, with no organizationId reaching any call:

      • an env-wide saveMetaItem over the packaged item is accepted and stores one row with organization_id NULL, and the read serves the written body;
      • a stored env-wide row is what getMetaItem serves (with a before-row control);
      • getMetaTypes advertises the flag true from registry, with OS_METADATA_WRITABLE cleared.

      The identity case pins that exactly these five carry the flag. 26 tests pass.

    • Ablation (report's flag true → false, spec dist rebuilt, marker proven in 4 built files): 4 failed | 22 passed, exactly the predicted four.

      • The identity case drops report.
      • Report's write is refused with 403 NOT_OVERRIDABLE on both topologies.
      • Report's wire field reads false.
      • Report's read cases stay green, because the read consults no flag.

      It was restored to the HEAD blob, with the dist clean (marker absent from all 232 files).

    • Level: test-only, skip-changeset (0 fixture hits in objectql's files[]), Clause-②: no. No contract review is owed. 55 / 56 derived gates ran; check:dual-build-cjs-loads is NOT MEASURED (a whole-workspace build).

    Two stage-0 readings corrected by measurement, recorded for S2 and the decision. Neither changes S1.

    Next: every check green → landing (Part of #22340) → needs-user-decision.


    Generated by Claude Code

  7. 49 remaining items

  8. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 (#22340 S3 — the governed-text half of the allowOrgOverride → allowEnvironmentOverlay rename, routed to this lane by triage 6121122315) · 2026-10-12T09:10Z
    Session: session_01CinRQcE6T8SvMbhH8D3NhS
    Account: huangyiirene (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-22340-s3-governed-text-rename
    Worktree: objectstack-issue-22340
    Domain: domain:skills
    Seat: domain:skills#1
    File surface: AGENTS.md (rule 7, line 191 on origin/main 74c4b3435, edited in place), skills/objectstack-ai/SKILL.md (line 347, in place; published catalog, token ratchet), docs/adr/0005-metadata-customization-overlay.md and docs/adr/0010-metadata-protection-model.md (a header amendment note each plus an Amended by entry naming ADR-0131; history lines untouched) (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: ceiling — this run's --tier on the four paths printed 「Model tier — MANDATORY: … (derived from the file surface, not recalled)」 for skills/objectstack-ai/SKILL.mdunder clause ① (the 2026-09-10 ruling 「必须 fable的还包括对外发布的skills」); the ceiling is CONTRACT_REVIEW_TIER; no one-line exit exists forskills/**Clause-②: no — S3 changes governed text only (AGENTS.md, one published skill line, two ADR headers); the published-surface widening of this card (the new key and the renamed wire field) landed in S2, PR #22874, under its own contract review PASS6118257575Responsibility:n/a — not a defect card(the governed-text half of a ruled rename) Thread-read: 6121122315 Ruling-ref:6073921182 (batch #297 item 1, Q1 A · Q2 A, maintainer 「同意」; fetched in this act) on the direction of #22007 letter C (6028809298); the S3 shape is triage's routing 6121122315(header amendment notes, in-place edits of the two normative lines, no residue) Resume-from: none (S3 starts frommain; S2 is e23eccb) Serial constraints cleared: AGENTS.md is shared with #22998 (os-zhuang, in flight; its claim names the merge-queue required-set paragraph and the gates section, not rule 7) — region-disjoint, so parallel under the four-point discipline: merge mainbefore the PR opens and again after that sibling lands; no otherpm:dispatched claim names these four files (claim threads grepped 2026-10-12T09:10Z: #22991, #15953, #15213 hit only in prose); none of the open PRs changes them (files lists read); #22978 (pm:blocked) will later touch other ADRs, not 0005/0010; newest touches 7873a05(AGENTS.md, 2026-10-11) andbf515e7(the skill, 2026-10-11), both merged Delivery shape:Part of #22340 (S3), ⛔ not Fixes — cloud's two test helpers (6109343061` item 5) stay on the card for a seat that reaches cloud


    Generated by Claude Code

  9. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 22340,
      "status": "done",
      "branch": "claude/issue-22340-s3-governed-text-rename",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/23011",
      "session": "session_01CinRQcE6T8SvMbhH8D3NhS",
      "premise_still_valid": true,
      "summary": "S3 of the allowOrgOverride → allowEnvironmentOverlay rename — governed text only — is in draft PR #23011 (head 7362ce1 = 5963d2cf6 merged with origin/main 6a7eca686; 5 files, +18/−4). AGENTS.md rule 7 and skills/objectstack-ai/SKILL.md:347 name the new key in place at the same line count (AGENTS.md 1109 lines under its 1116 ceiling, unchanged; the skill 5540 → 5541 tokens under its 6806 ceiling, no deletion needed). ADR-0005 and ADR-0010 each gain a 'Protocol 18 update (2026-10-12, ADR-0131 C5, #22340)' blockquote note at the top, written in ADR-0005's own v5.0-note voice and copied verbatim to ADR-0010, plus an Amended-by entry naming ADR-0131 C5 / D6 (ADR-0010's header block gains the line); their 12 + 9 history lines naming the old key are untouched. A '@objectstack/skills': patch changeset carries the published skill line (the package is in the fixed group; pre mode next; precedent PR #22846). Premises held on origin/main 74c4b3435 with one count corrected: ADR-0005 has 12 matching lines, not 13. #22998 had not landed at the merge and main touched none of the four files. Tier H: draft only, maintainer speed-read section in the body, no ready flip, no label write; the claim 6121201470 names this branch and no second claim was posted.",
      "tests": "No package source touched, so no package test or typecheck is owed and no ablation applies (no mechanism changed). node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 53 commands (41 at claim time; the changeset path adds the changeset families), each run with its exit captured before any pipe, and --ran on the 7362ce1 record answered '✓ dispatch-gates --ran: 53 derived famil(ies) accounted for — 51 run, 2 NOT-MEASURED (2 DERIVED from a recorded exit 3)'. Verdict lines at 7362ce1: '✓ check-skill-line-ratchet: AGENTS.md is 1109 lines (ceiling 1116; headroom 7).' · '✓ check-skill-line-ratchet: AGENTS.md: widest table row is 768 bytes (pin 768; headroom 0).' · '✓ check-skills-token-ratchet: skills/objectstack-ai/SKILL.md is 5541 tokens (ceiling 6806; headroom 1265).' (5540 / 1266 before) · '✓ check-skill-id-lint: 34 file(s) clean (pattern /#[0-9]{3,}/g).' · 'check-skill-identifier-liveness OK — Leg 1: 457 citation(s) over 53 published file(s) checked against 126987 implementation word tokens (0 ledgered exemption(s)); Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s).' · '✅ check-adr-symbol-anchors: 2319 anchors across 142 records resolve — 439 symbol (412 declaration, 27 literal), 1853 file-level, 27 cross-repo, 6 exempt, 18 continuation.' (the notes anchor packages/spec/src/kernel/metadata-plugin.zod.ts#allowEnvironmentOverlay, accepted as a declaration site) · '✅ check-adr-links: 730 relative link destination(s) under docs/adr/ resolve' · 'check-adr-anchors: OK (68 anchored file(s) … 44050 citation(s) across 5831 file(s) resolve …)' · '✓ check-governed-prose: 2 instruction surface(s) name all 6 registered governed surfaces … and claim no others.' · 'check-nul-bytes: OK (scanned 11012 text file(s) … no raw ASCII control bytes).' · '✓ No empty-frontmatter changeset introduced by this diff (1 declaring changeset(s) added).' · '✓ This diff introduces no major bump.' · '✅ Skill docs in sync' · '✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 473 files / 1388 TS blocks judged clean by @objectstack/formula.' (measured after building @objectstack/formula + @objectstack/lint with their closure under scripts/pm/os-verify-lock.sh: 'VERDICT command-exit 0 · held the lock 115s · waited 121s'). NOT MEASURED, declared: pnpm check:dual-build-cjs-loads and pnpm check:lean-entry-closure exited 3 PREREQUISITE NOT MET — they load every workspace package's built entry points (107 without dist) / objectql's dist; the diff changes no file any package build reads (no packages/** source, manifest or tsconfig; the skills package build is a byte copy that emits no entry point), so the repo-wide build they need is CI's run. check:dts-closure ('4 built package(s) swept - 46/46') and check:sourcemap-no-sources-content ('4 built package(s) swept - 58 map(s)') exited 0 as partial sweeps over the four built packages, not closure readings. pnpm lint is CI's: the diff has no lintable file. PR body read back after the create: 13012 bytes sent, 13012 stored, footer intact, draft true, assignee huangyiirene.",
      "mcp_calls": "0 — no MCP GitHub calls. The card and its 28 comments were read with a single-card REST read (gh api …/issues/22340 and …/issues/22340/comments); the PR was read back the same way.",
      "api_writes": "2 relay strokes through scripts/pm/with-fleet.sh --via dispatch (repository_dispatch to the board, executed as objectstack-fleet[bot]): ① pr_create → POST /repos/objectstack-ai/objectstack/pulls (draft) + POST /repos/objectstack-ai/objectstack/issues/23011/assignees (huangyiirene) — run 38231650601, body stored byte-identical; ② comment → POST /repos/objectstack-ai/objectstack/issues/22340/comments (this report). Also 3 git pushes to the branch (not REST). No label write: a changeset is owed, so no skip-changeset; no PATCH of any body; no ready flip.",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: the next PR that edits scripts/adr-anchors/packages__spec__src__kernel__metadata-plugin.zod.ts.json · its invariant prose cites docs/adr/0005-metadata-customization-overlay.md:53-64 (the whitelist table), which the two-line note at the top of ADR-0005 moves to lines 55–66; no gate reads that range (check:adr-anchors verifies ADR ids and decision letters; check:adr-symbol-anchors sweeps docs/adr/**, not scripts/adr-anchors/**), and the file is outside this PR's governed-only surface · noted in the PR's Acceptance notes, not filed",
        "carrier: none (a history line of the class triage left as written) · docs/adr/0063 line 135, the §2 checklist the skill line cites, still spells allowOrgOverride:false; the skill cites the decision, not the spelling · noted, not filed"
      ]
    }

    Report written 2026-10-12T09:44Z; final head 7362ce1; PR #23011 draft, Tier H.


    Generated by Claude Code

  10. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT (S3) — PR #23011 (head 7362ce1, 5 files +18/−4, draft, Tier H: AGENTS.md + skills/** + docs/adr/**) · reviewed 2026-10-12T09:50Z by session_01CinRQcE6T8SvMbhH8D3NhS (skills seat 1).

    Checklist, verified on GitHub against the diff, not against the report:

    • PR form: draft, base main, first line Part of #22340 (S3) — ⛔ no closing keyword anywhere (the card stays open); Clause-②: no on line 2; PR assignee = the card's; ## 维护者速读(草稿) present; session-URL footer; two commits (the change, then the merge of main before the PR opened; skills(ci): two-speed CI — fast set on PR and merge-queue runs, full battery hourly on main and before a release, main-red stops the lane, four required contexts plus the guard, timing gates report-only, test budgets not deletions #22998 had not landed, and main touched none of the four files).
    • Scope: exactly the four governed files the claim declared plus the owed @objectstack/skills patch changeset; no residue, no fence, no code.
    • The four edits read in the diff: rule 7 in place (same line count, no number); the skill line in place (5541 / 6806 tokens); the two ADR notes in ADR-0005's own amendment voice with Amended by entries, history lines untouched (12 + 9 old-key lines stay).
    • Gates on 7362ce1: 53 derived, --ran 51 run + 2 NOT-MEASURED (repo-wide build prerequisites, CI's); ratchets (AGENTS.md 1109/1116 and the 768-byte row pin; the skill's tokens), id-lint 34 clean, skill-identifier-liveness (457 citations / 53 files), adr-symbol-anchors (2319 anchors resolve, the note's anchor accepted as a declaration site), adr-links, adr-anchors, governed-prose, nul-bytes, the changeset guards, check:doc-formula-expressions after its prerequisite build — all green. Check-runs at review: 19 success / 3 skipped / 8 in progress, 0 red.
    • Contract review (governed text face, in seat at CONTRACT_REVIEW_TIER): PASS, recorded on the PR.

    What remains on this card after S3 lands: cloud's two test helpers (6109343061 item 5: packages/service-ai-studio/src/__tests__/write-door.ts:58, metadata-tools.test.ts:305, deriving the locked-type set from the renamed field) — a seat that reaches cloud files them. When PR #23011 merges, this seat writes the Release: line, returns the card to pm:queue with pm:retriage asking triage to route that residue (cloud lane), and clears the assignee.

    Landing: Tier H. needs-user-decision on the PR, the 速读终稿 posted there, review requested from os-zhuang and hotlong. After an authorized APPROVED review the seat lands it through the queue — noting that AGENTS.md is itself an agent-instruction file, so the seat's landing stroke may meet the same [Self-Modification] classifier refusal PR #22997 met; if it does, the landing is the approver's hand and the seat says so on the card.


    Generated by Claude Code

  11. added
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    and removed on Oct 12, 2026
  12. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Release: session_01CinRQcE6T8SvMbhH8D3NhS (skills seat 1, huangyiirene) · cause: partial landing — S3 merged as Part of, the remainder is outside this lane's reach · destination: pm:queue + pm:retriage (route the residue to a seat that reaches the cloud repository) · 2026-10-12T11:34Z

    Landed: PR #23011 → e4a770d6b (squash). The governed-text half of the allowOrgOverride → allowEnvironmentOverlay rename is on main: AGENTS.md rule 7 names the key S2 landed; skills/objectstack-ai/SKILL.md:347 teaches the spelling the runtime accepts; ADR-0005 and ADR-0010 carry a header amendment note each and an Amended by entry naming ADR-0131 C5 / D6; the @objectstack/skills patch changeset rides. Content read on origin/main after the merge. Landed by an authorized APPROVED review (os-zhuang) and the merge queue.

    Remainder, per the dispatch and the ACCEPT 6121838081: the two test-helper files in the cloud repository still spell the old key — work no seat of this lane can reach from objectstack or objectui. Retriage asked: name the lane and seat that holds the cloud repository (or confirm the residue is tracked there and close this card as completed on S1–S3). No branch to resume from: S3's branch claude/issue-22340-s3-governed-text-rename is fully merged; the next claimant starts the residue from zero in its own repository.

    Same act: pm:dispatched → pm:queue + pm:retriage, assignee cleared.


    Generated by Claude Code

  13. objectstack-fleet commented on Oct 12, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage answers pm:retriage 6123458126: closed completed on S1–S3. The cloud residue rides cloud's v18 pin move, recorded on objectstack-ai/cloud#2709

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-12T12:58Z. ⛔ Not a claim, ⛔ not a dispatch. Thread-read: 6121838081, 6123458126.

  14. removed
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    on Oct 12, 2026
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

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions