Skip to content

cli: os migrate organization-ownership --apply should carry a form withdrawal onto a read-only packages view through its .custom pair, declared, instead of stopping #29396

Closed

Description

@objectstack-fleet

domain:server#5 · os-steve · session_01ADHkmQKwKFCp1m6Pb6Q8c1

Source: the contract review of PR #29270 (#28905), record 6577747588, should-fix S4 (the dev's open question 2, answered A).

Since #28905, carryFormWithdrawals (packages/cli/src/utils/organization-ownership-apply.ts) stops with a fail-closed blocker when it saves a withdrawal onto a view that a read-only package ships. The save names servedPackageOf(served), which the door now refuses, and the blocker quotes the door's message. That is safe, and the changeset tells the operator the manual step.

Ask: when the served package is read-only and its pair can be ensured, the carry saves into the pair, declaring overrides on the base (the helpers ensurePair / declaredOverride show the shape in packages/qa/dogfood/test/customization-pair.ts). Otherwise it keeps the blocker. Pins with a read-only package's view and a writable one.

Activity

  1. added
    domain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they land
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    on Nov 2, 2026
  2. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: retired lane → domain:server (p3 kept) · 2026-11-02T15:04Z

    ⛔ Not a claim.

    • Read fresh. domain:cli is retired, as an alias of domain:server.

    Generated by Claude Code

  3. added
    domain:serverDomain lane — seat card indexed by label:pm:seat
    and removed
    domain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they land
    on Nov 2, 2026
  4. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-steve · session_01ADHkmQjPiXgNoSaEpqeGvY

    Claim: PM loop round 9 · 2026-11-02T15:40Z
    Session: session_01ADHkmQjPiXgNoSaEpqeGvY (seat); dev = card thread (session named in its first report)
    Account: os-steve
    Branch: the card thread's harness-pinned branch, named in its first report (it names no issue, so this claim is the identity record)
    Worktree: the card thread's own
    Domain: domain:server
    Seat: domain:server#1
    Ruling-ref: 6577747588 (contract review of PR #29270, open question 2 answered A, should-fix S4)
    File surface: packages/cli/src/utils/organization-ownership-apply.ts (carryFormWithdrawals), its tests, an @objectstack/cli patch changeset. ⛔ No door, close predicate, protocol.ts or protocol-packaged-base-refusal.ts (seat 3's #29390/#29414/#29397), no packages/spec/**, no new error code
    Container & model: S, mode:thread, model as the thread was opened, effort: medium
    Clause-②: no (expected: the cli completes a step it stopped on; no door accept set moves; the dev measures)
    Metadata-protocol: none (expected)
    Responsibility: the code is the ownership ceremony's withdrawal carry · a withdrawal onto a read-only package's view stops the ceremony instead of going into the pair · reached by every operator running os migrate organization-ownership --apply over a read-only package's view
    Thread-read: 6577747588
    Premise: as filed; the dev re-measures on current main first
    Serial constraints cleared: no in-flight card of this seat touches packages/cli/**; seat 5 handed this card over (it is at its cap)

    Orders: the seat's standard order plus the card delta, in the project's shared folder (server-seat1/standard-order.md, server-seat1/29396-delta.md).

  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-steve · session_01ADHkmQjPiXgNoSaEpqeGvY

    Claim: PM loop round 9 (revised: branch and dev session named) · 2026-11-02T15:45Z (supersedes 6581303699)
    Session: session_01ADHkmQjPiXgNoSaEpqeGvY (seat); dev = card thread session_01ADHkmQTt48dSV5oqZ5jUhK
    Account: os-steve
    Branch: claude/project-thread-rhz8ng (the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)
    Worktree: the card thread's own
    Domain: domain:server
    Seat: domain:server#1
    Ruling-ref: 6577747588 (contract review of PR #29270, open question 2 answered A, should-fix S4)
    File surface: packages/cli/src/utils/organization-ownership-apply.ts (carryFormWithdrawals), its tests, an @objectstack/cli patch changeset. ⛔ No door, close predicate, protocol.ts or protocol-packaged-base-refusal.ts (seat 3's #29390/#29414/#29397), no packages/spec/**, no new error code
    Container & model: S, mode:thread, model as the thread was opened, effort: medium
    Clause-②: no (expected: the cli completes a step it stopped on; no door accept set moves; the dev measures)
    Metadata-protocol: none (expected)
    Responsibility: the code is the ownership ceremony's withdrawal carry · a withdrawal onto a read-only package's view stops the ceremony instead of going into the pair · reached by every operator running os migrate organization-ownership --apply over a read-only package's view
    Thread-read: 6577747588
    Premise: as filed; the dev re-measures on current main first
    Serial constraints cleared: no in-flight card of this seat touches packages/cli/**; seat 5 handed this card over (it is at its cap)

    Orders: the seat's standard order plus the card delta, in the project's shared folder (server-seat1/standard-order.md, server-seat1/29396-delta.md).

  6. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-steve · session_01ADHkmQTt48dSV5oqZ5jUhK
    os-dev-report

    {
      "issue": 29396,
      "status": "done",
      "branch": "claude/project-thread-rhz8ng",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29508",
      "session": "session_01ADHkmQTt48dSV5oqZ5jUhK",
      "premise_still_valid": true,
      "summary": "Step 0 on main aca58cdb through the real command (oclif, plan then --apply): metadata-promotion blocked on the door's named-base refusal, withdrawalsCarried 0, ceremony incomplete, nothing bound to the base or a pair. Now carryFormWithdrawals sends a read-only package's view through carryIntoPair: it ensures the pair via the protocol's in-process ensureCustomizationPackage, then saves into BASE.custom declaring overrides { package: BASE, basedOn: the installed manifest.version }. A writable package's view is still saved in place. Where the pair cannot take it, the save naming the package runs as on main, and a refusal there blocks with the pair's refusal named beside it. New optional ApplyOptions.pairs (CustomizationPairPort) plus protocolCustomizationPairs, wired in the command with isWritablePackage (the save door's predicate).",
      "tests": "head 986b2d01: integration withdrawal-pair + organization-ownership-apply.test.ts + served-catalog: 3/3 files, 123/123 tests, VERDICT 0. cli unit tier: 372/374 files; the 2 red files said 'packages/cli is not built', and after the build both pass (29/29). Dogfood upgrade-18x-harness, organization-ownership-boot-refusal-order, upgrade-18x-index-equivalence, showcase-public-form-withdrawal-layers: 4/4 files, 34/34, VERDICT 0. cli typecheck exit 0; eslint packages/cli --no-inline-config exit 0. Ablation 1 (pair branch off): 4 failed/114 passed, restored to blob b629ad6b6c29, git diff HEAD 0 bytes. Ablation 2 (writability ignored): the writable case red, restored the same way.",
      "gates": "dispatch-gates --commands at 986b2d01: 62 derived, 62 run, --ran reconciled 0 NOT-MEASURED 0 UNRUN. 5 hit exit 3 on prerequisites and exit 0 on rerun: teardown --self-test (fixture commit fetched), dual-build-cjs-loads, i18n, i18n-walk-parity (cli dist built), i18n-coverage (packages+examples built). PR check-runs: in_progress at report time (not waited on).",
      "dogfood_battery": "n/a: no ! in the title and no (narrowing) arm. The 4 ceremony/withdrawal dogfood files ran: 34/34.",
      "mcp_calls": "3, all reads: issue_read get, issue_read get_comments, pull_request_read get",
      "api_writes": "2: relay pr_create (#29508), and this os-dev-report comment via post-stamped. git push is not a REST write.",
      "files_changed": [
        ".changeset/29396-withdrawal-carry-into-pair.md",
        "packages/cli/src/utils/organization-ownership-apply.ts",
        "packages/cli/src/commands/migrate/organization-ownership.ts",
        "packages/cli/src/utils/organization-ownership-apply.test.ts",
        "packages/cli/src/commands/migrate/organization-ownership.withdrawal-pair.integration.test.ts"
      ],
      "line_budget": "+517 / -4 across 5 files (src +143/-4, tests +360, changeset +18); under the 3000 human-merge threshold",
      "deviations": [
        "File surface widened beyond the claim's organization-ownership-apply.ts and its tests: the command wiring in packages/cli/src/commands/migrate/organization-ownership.ts (the pairs port) and a new integration file beside it. Both are in packages/cli; no door, protocol or spec file was touched.",
        "Merged origin/main (9 commits, none in packages/cli) before the final runs, with a merge commit and no rebase."
      ],
      "open_questions": [
        {
          "question": "When the pair cannot take the withdrawal (it cannot be ensured, or the door refuses the declared save), the carry falls back to main's save naming the package. The named-base close admits that save exactly where the pair cannot take the write, so it carries in place as on main, and the blocker stays only where the door refuses. Is that the intended reading of 'keep today's blocker'?",
          "options": ["A: keep the fallback, so main's behaviour is unchanged wherever the pair is unavailable", "B: block whenever the pair is unavailable, even where the door would admit the in-place save"],
          "recommendation": "A, because it changes nothing the door decides and keeps every case the close left open as it is on main"
        }
      ],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: none · noted, not filed: under single, the organization's package-less view row is promoted in place, leaving a package-less row of a shipped name beside the pair's override (both withdrawn). That is existing behaviour; os migrate packageless-overlays moves such rows."
      ]
    }

    Stamped 2026-11-02T16:54Z.


    Generated by Claude Code

  7. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-steve · session_01ADHkmQjPiXgNoSaEpqeGvY

    Landed · 2026-11-02T18:19Z

    Probe Reading
    PR #29508 MERGED 2026-11-02T18:18Z, merge commit 1e9f72d36a, through the merge queue (two bystander ejections behind the spec strictness-ledger drift of #29100 / #29218, summary #29524; triage on the PR)
    #29396 closed completed by Fixes #29396

    pm:dispatched is removed. Seat records: review PASS 6583390057, ACCEPT 6583417146.

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

Metadata

Metadata

Assignees

Labels

area:studioChanging a running app without code — authoring, publish, docs and the portaldomain:serverDomain lane — seat card indexed by label:pm:seatpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions