Skip to content

pm/fleet-write: advisory_read holds its sender to target-write, by the maintainer's ruling, since the collaborator gate refuses every live read #29644

Closed

Description

@objectstack-fleet

domain:skills#2 · os-justin · session_01QSeKYn5CmmdShCJifm6WYj

What

advisory_read (the sealed advisory read, #29420, landed in #29536) holds the sender to senderGate: 'collaborator' in scripts/pm/fleet-write/ops.mjs. The maintainer has ruled it becomes 'target-write', the gate every other relay row keeps.

The ruling

The maintainer, in session session_01QSeKYn5CmmdShCJifm6WYj on 2026-11-02, answering the seat's question whether the read's sender gate should change from collaborator to write on the target repository, verbatim:

同意改成对仓库有写权限,立卡派发修复

This settles the open question the #29420 os-dev report left for the maintainer (comment 6584655262, open_questions[0], options A collaborator / B target-write). The ruling is B.

The measurement that prompted it (the first live reads, 2026-11-02)

  • advisory_collaborators_add for the sender landed, and its PATCH answer lists the sender among the collaborators (run 41545025429).
  • Three advisory_read strokes after it, on two advisories, were each refused at fence sender ("is not a collaborator on it"): runs 41545143476, 41545259848, 41546082963.
  • A re-sent advisory_collaborators_add on one of those advisories was a no-op: its pre-PATCH GET, under the write grant, already lists the sender (run 41546190167).
  • So the write-grant GET lists the sender in collaborating_users, and the read-grant GET the fence judges does not. Why the read-grant answer omits it is unverified (a hypothesis: the platform withholds collaborating_users from a read-only grant).
  • A sender with write on the target can already add itself to any advisory whose id it holds (ops.mjs, the sender-gate paragraph above advisory_read), so the collaborator gate excluded no one; it only blocked every live read.

Acceptance

  • advisory_read's senderGate is 'target-write'; the header prose and the row comment record the ruling verbatim, in place of "the card's recommendation" and "the maintainer rules which stands, on the pull request".
  • The relay self-tests that pin the default gate move with it; an unknown gate still fails closed.
  • After merge, one live advisory_read by a seat with write on the target opens (the seat runs it; recorded here as a run id, no advisory id).

Out of bounds

  • ⛔ The row's grant stays read. If a read under the read grant is refused once the gate is switched, that is a fork for the maintainer, never a raise to write.
  • ⛔ No advisory text, id or mechanism in the PR, the commits or the changeset.

Activity

  1. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:skills#2 · os-justin · session_01QSeKYn5CmmdShCJifm6WYj

    Claim: maintainer-directed dispatch · 2026-11-02T23:42Z
    Session: session_01QSeKYn5CmmdShCJifm6WYj
    Account: os-justin (the seat's linked user as GET /user answers it; always the card's assignee)
    Branch: claude/issue-29644-advisory-read-sender-gate
    Worktree: objectstack-issue-29644
    Domain: domain:skills
    Seat: domain:skills#2
    File surface: scripts/pm/fleet-write/ops.mjs, scripts/pm/fleet-write/execute.mjs, scripts/pm/fleet-write/validate.mjs, scripts/pm/fleet-write/dispatch.mjs (self-tests that pin the gate) (stop on breach; explain in the report)
    Container & model: S, judgment in the prose, mode:subagent, model: opus (dispatch-gates --tier: no path-derived mandate; default tier), effort: xhigh (security channel)
    Clause-②: no
    Metadata-protocol: none
    Responsibility: the relay row's senderGate value in ops.mjs | none: no other relay path reads an advisory | every fleet seat reaching an advisory read; every live read today is refused
    Thread-read: none
    Premise: holds (measured this session: runs 41545143476, 41545259848, 41546082963 refused at fence sender; run 41546190167 shows the sender persisted as a collaborator)
    Serial constraints cleared: none found — the open skills-lane PRs #29577 and #29633 touch no scripts/pm/fleet-write/ file and #29620 (the workflow comment) is closed; the other open PRs were not enumerated file by file

    Ruling carried: the maintainer's, verbatim, in the card body (session session_01QSeKYn5CmmdShCJifm6WYj). Triage: maintainer-directed, claimed before the triage audit, as on #29420.

  2. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:skills#2 · os-justin · session_01QSeKYn5CmmdShCJifm6WYj
    os-dev-report

    {
      "issue": 29644,
      "status": "done",
      "branch": "claude/issue-29644-advisory-read-sender-gate",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29656",
      "head_sha": "a8eed92854506c06d65249b2293b965aa705bd2f",
      "session": "session_01QSeKYn5CmmdShCJifm6WYj (subagent: the dispatching seat's session)",
      "premise_still_valid": true,
      "summary": "advisory_read's senderGate is now 'target-write'. The maintainer's ruling 「同意改成对仓库有写权限,立卡派发修复」 is quoted verbatim (ASCII comma, as in the card body) in the ops.mjs header paragraph and in the row comment, replacing the 'card's recommendation' and 'the maintainer rules on the pull request' text. The row's grant stays read. Keep vs. remove: I REMOVED the collaborator arm. It measured as refusing every live read, it excluded no one, and nothing outside the three edited files names it, so the startup-stage rule applies and the removal stays inside the four-file surface. ADVISORY_READ_SENDER_GATES keeps the one value, and any other value, collaborator included, fails closed. The fence no longer reads the sender, so its context and advisoryReadAction drop `sender`; no export was renamed or removed. PM zone-2 readings re-taken at base 3482f3d8: senderGate at ops.mjs:1986, the table at :1315, the header paragraph at :560 and the sender fence at :1340-1350 all held. Execute pinned the default gate at :2676-2682 and validate at :1794 and :1872-1879. FALSIFIED: dispatch.mjs pins no gate; its end-to-end read's sender is on the fixture's collaborators, so it is unchanged. The PR body labels the read-grant GET omitting collaborating_users as an UNVERIFIED hypothesis, and this PR neither tests nor depends on it. The card's post-merge live read is left to the seat.",
      "files_changed": [
        "scripts/pm/fleet-write/ops.mjs (+31/-31)",
        "scripts/pm/fleet-write/execute.mjs (+20/-17)",
        "scripts/pm/fleet-write/validate.mjs (+10/-10)"
      ],
      "tests": "Relay --self-test, before at base 3482f3d8 and after at HEAD a8eed928, each exit captured before any pipe. validate: 303 cases / 16 batteries both times. execute: 259 / 22 before, 260 / 22 after, with the advisory_read battery pin raised 17 to 18. dispatch: 315 / 27 both times. ops.mjs has no --self-test handler: it exits 0 with zero bytes because it is only an import, so it is NOT MEASURED as a self-test; validate pins its table. Executor battery: a write sender off the collaborators is now sealed for and opens byte for byte (this case was rewritten from a refusal pin). New: a triage sender is refused BEFORE the advisory GET even when listed as a collaborator (exit 4, the permission read alone). Rewritten: a made-up gate and the retired collaborator fail closed. The marker sweep now covers 20 runs instead of 19. Validator battery: the row pin is one setting with grant read; target-write reads no collaborator; any other gate is closed (retired, misspelt, a prototype key, empty, absent); a prose gate value is never echoed. One-shot ablation via scripts/ablation-replace.mjs in wrap mode, after committing the fix. Predicted directions were stated first. Leg A (senderGate back to 'collaborator'): anchor 1 to 0, blob 8bd15e59 to 46d1f81a. validate exit 1 (1/303 failed), execute exit 1 (8/260), dispatch exit 1 (4/315). Leg B (sender fence fails open): blob 8bd15e59 to 8e424259. validate exit 1 (3/303), execute exit 1 (1/260), dispatch exit 0 (315 pass, as predicted). Both legs restored with blob == HEAD 8bd15e59, git diff HEAD empty and git status clean. No *.test.* file names these scripts: git grep exit 1, against a control grep for any file naming ops.mjs that exits 0. Their suites are their own and their importers' --self-tests, all in the derived set.",
      "gates": "At HEAD a8eed928, node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 39 commands (26 pnpm, 13 node) over 3 paths, 119 changed lines. All 39 were run and all exited 0, each exit captured before any pipe and each log's own verdict line read. pnpm check:pm-dispatch-gates ran under nohup and was waited on to its exit file (EXIT=0, fast tier 1945 cases, 403.2s). --ran with exit codes: '✓ dispatch-gates --ran: 39 derived famil(ies) accounted for — 39 run, 0 NOT-MEASURED (a DERIVED zero — all 39 recorded an exit code and none of them is 3)'. Commands: check-closing-keyword-parity (+self-test), check-comment-mask-corpus, check-declaration-mirrors (+self-test), check-self-test-wired (+self-test), check-self-test-workflow-commands (+self-test), check-whole-set-label-write (+self-test), ci/plan-test-core-shards self-test, pm/bare-root-worklist self-test, and pnpm check: agent-test-spelling, bash32-floor, ci-filter-parity, cli-command-ids, cross-package-test-inputs, driver-memory-census, entry-guard, gitlink-declared, nul-bytes, parse-guard, pm-close-cards, pm-dispatch-gates, pm-fleet-write-dispatch, pm-fleet-write-execute, pm-fleet-write-validate, pm-issue-create, pm-issue-transfer, pm-label-write, pm-post-stamped, pm-record-recognisers, pm-write-pace, pnpm-filter-targets, pnpm-flag-spellings, refd-timer-probe, scripts-symbol-anchors, watch-hint-literal. PR #29656 check-runs on a8eed928 at report time: 41 total, none failed. Success: Check Changeset, Check PR Size, Dogfood Regression Gate, Governed Surface Queue Guard, PR-body guards, Test UI, filter. in_progress: Lint (CI/release/engine, ESLint, PM dispatch-gates, docs & code guards, repo & tooling, three scoped lanes), Type Check (consumer, debt ledger, source, workspace), Plan Test Core shards, Auto Label. 20 skipped. Left to CI and not run locally: the 52 artifact-roster families, the 11 wide-population families and the type-check lanes. The diff touches no TypeScript package.",
      "line_budget": "n/a — no skills/** file or line-ratcheted ledger touched. Diff +61/-58 over 3 files (119 changed lines, under the 3000 threshold).",
      "deviations": [
        "Kept/removed call (zone 3): removed the collaborator arm, with a one-line reason in the PR body. The removal reaches into the fence context (`sender` dropped from advisoryReadFenceFailures' ctx and from advisoryReadAction's parameters). That is inside the four-file surface, with no export renamed or removed, so check-platform-checklist --changed-from was not owed.",
        "dispatch.mjs is in the file surface but unedited: measured, it pins no gate.",
        "ops.mjs --self-test is a no-op (no handler), so the order's \"four relay self-tests\" are three real ones plus that no-op, reported as such.",
        "No origin/main merge before pr_create (AGENTS.md multi-agent §10 asks for one). origin/main moved 2 commits past base 3482f3d8 and neither touches scripts/pm/fleet-write/ or its imports. The full suite is left to CI per the os-dev local-verification scope.",
        "Attribution: the harness reminder asked for a model-named Co-Authored-By trailer and a different PR footer. Per AGENTS.md (which that reminder yields to), the commit carries the model-free Claude-Session / Co-authored-by pair and the PR body the session-URL footer.",
        "Writes: two git pushes, the empty-branch route probe (rule 1) and the work commit, beyond the three-write budget's one push. The probe is mandated by rule 1."
      ],
      "dogfood_battery": "n/a — no `!` in the PR title, and Clause-②: no without a (narrowing) arm",
      "mcp_calls": "0 — no MCP GitHub calls of any kind",
      "api_writes": "2 seat-side REST writes, both relay strokes, POST /repos/objectstack-ai/objectstack/dispatches. (1) pr_create, run 41550449857: the fleet executed POST /repos/objectstack-ai/objectstack/pulls (201, #29656, draft) and POST /repos/objectstack-ai/objectstack/issues/29656/labels (200, row 'labels skip-changeset'). The body read back 9760/9760 bytes identical. (2) this report comment via scripts/pm/post-stamped.mjs: POST /repos/objectstack-ai/objectstack/issues/29644/comments. Not REST: 2 git pushes.",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": []
    }
  3. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:skills#2 · os-justin · session_01QSeKYn5CmmdShCJifm6WYj

    ACCEPT → PR #29656 comment 6592025585 · head a8eed928 · ready and auto-merge enabled (relay run 41552671164) · 2026-11-03T00:25Z

  4. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:skills#2 · os-justin · session_01QSeKYn5CmmdShCJifm6WYj

    Landed · 2026-11-03T01:13Z

    reading value
    PR #29656 merged 2026-11-03T01:10Z, merge commit c3184908, through the merge queue
    live advisory_read after merge (acceptance item 3) run 41558097285, conclusion success; the sealed answer opened in this seat's process (2 parts)

    Closed as completed by the merge (Fixes); pm:dispatched removed in the next stroke.

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

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions