Repository navigation
docs(pm): rest-channel names the fleet-write relay as the channel to the App identity - #19770
Conversation
The App identity `objectstack-fleet[bot]` is reached through the `fleet-write` relay: the four write tools and `with-fleet.sh --via auto` share one selector that takes `dispatch` only under the cloud discriminator, a session id derived from the container (with `OS_FLEET_SESSION` as the override, never a command prefix) and a relay that is live on main (file present and Actions state active). The dispatch carries the session token; the run executes on the runner with a per-run App token narrowed to the target repo; the closed op list is `scripts/pm/fleet-write/ops.mjs`; reads stay direct; an over-cap body goes direct for that write with one printed line; a failed run and an UNCONFIRMED outcome are read, never retried. Nine lines are retired to pay the file's ceiling in place, each one restated elsewhere: the closed-gate 403 shape and the probe rule (platform-readings quota rows), the two identity-bound rate-limit rows (platform-readings quota rows), the label-write recipe (SKILL.md), the Content-Type 415 rule (platform-readings), the MCP update_pull_request ban (settings deny list and the ccr rows above it), the MCP search fallback (platform-readings degradation ladder) and the try-the-action queue reading (platform-readings queue section). Claude-Session: https://claude.ai/code/session_01XPUwWGnmky4PXPofNsf2w7 Co-authored-by: Claude <noreply@anthropic.com>
Contract reviewServed-tier: ① Derived judgmentsRendered in-seat by the director seat (summon #27,
② VerdictPASS. Lands through the queue after ACCEPT on the card; Generated by Claude Code |
Contract reviewRecord of record for this head, re-posted with the Served-tier: ① Derived judgmentsRendered in-seat by the director seat (summon #27,
② VerdictReviewed-by: VERDICT: PASS — lands through the queue after ACCEPT on the card; Generated by Claude Code |
Part of #19739
Clause-②: no
What changed
One file,
.claude/skills/pm-dispatch/references/rest-channel.md, section 〈通道边界〉: one paragraph of nine rule lines stating how the App identity is reached.objectstack-fleet[bot]is reached through thefleet-writerelay; the four write tools (post-stamped,label-write,issue-create,close-cards) andwith-fleet.sh --via autoshare one selector.dispatchonly when three conditions hold —CCR_AGENT_PROXY_ENABLED=1, a session id, a live relay — otherwisedirect, with one printed line.CLAUDE_CODE_REMOTE_SESSION_ID;OS_FLEET_SESSIONoverrides it for local checkouts and tests only.mainAND its Actions stateactive; the maintainer disabling it in the Actions UI turns the whole fleet back todirect.scripts/pm/fleet-write/ops.mjs; reads stay direct.post-stampedbody over 60,000 bytes takesdirectfor that one write, with one printed line, as the seat's own user.post-stamped/close-cards4,label-write/issue-create5) and UNCONFIRMED (6) are read, ⛔ never retried.Spellings are taken from the #19755 branch
claude/issue-19755-fleet-write-derive-sessionat 6470e4e (PR #19760):sessionSourceinscripts/pm/fleet-write/dispatch.mjs,CONTAINER_SESSION_ENVinops.mjs,relayLive's Actions-state read, thewith-fleet.sh --via autoparagraph, andsizeRoute/MAX_BODY_BYTESinpost-stamped.mjs. Everything else is read frommainat 544767d (.github/workflows/fleet-write.yml:repositories:= the validated target,permission-issues: write,permission-pull-requests: write,permission-metadata: read).One correction to the card's item 3 wording. The failed-run exit is not
4fleet-wide. Each tool books it in its own register on that branch:post-stamped4 (EXIT_NOT_STORED, viarelayExitFor),close-cards4 (EXIT_HALF_WRITE, and the same 4 for an unconfirmed close),label-writeandissue-create5 (exitForResult→EXIT_PLATFORM_REFUSAL). UNCONFIRMED is 6 in every tool that takes the relay. The paragraph states the registers as they are on that branch; the rule — read, never retry — is the same in all four.Line budget — ceiling 82, headroom 0, paid in place (+9 / −9)
Nine lines are retired. Each is a restatement; the line that keeps the rule is named beside it (line numbers on
mainat 544767d).rest-channel.mdline)gh, MCP and git fineplatform-readings.md108 (the 403 shape), 114–115 (git first, MCP third), 142 (noghin the container)platform-readings.md107, 127platform-readings.md122, 125GET /uservs the refused id)platform-readings.md125 (theGET /usertest), 96 (one identity inside a seat)label-write.mjs(four steps, read-back)SKILL.md394;os-dev.md304; the tool's own headerContent-Type: application/json; the 415 and its discriminantplatform-readings.md119–120update_pull_request; ready/draft and auto-merge take the ccr routes.claude/settings.jsondeny list;SKILL.md610; the ccr rows at 48 and 52 of this filesearch_issuesplatform-readings.md115, 211platform-readings.md9; rows 73–75 of this file keep the three criteriaNo line was re-wrapped; every line is ≤ 120 bytes (
check:pm-skill-ratchetgreen on the head).Landing order
⛔ This PR lands only after #19755 (PR #19760) merges: the paragraph states what that PR makes true (the container-derived session, the Actions-state half of the liveness read, the size route). Not enqueued by this dispatch. Tier S (
.claude/**),CONTRACT_REVIEW_TIER— the director seat renders the## Contract reviewof record.skip-changeset: nothing published from any released package; this dispatch forbids label writes, so the label is the seat's to apply.Verification
Gates derived by
node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commandson the edited tree at 9f49c33; each run alone, exit captured before any pipe (cmd > log 2>&1; ec=$?).node scripts/check-closing-keyword-parity.mjsnode scripts/check-closing-keyword-parity.mjs --self-testnode scripts/check-comment-mask-corpus.mjsnode scripts/pm/check-harness-current.mjs --self-testpnpm --filter @objectstack/lint run check:doc-formula-expressionspnpm check:agent-test-spellingpnpm check:cross-package-test-inputspnpm check:doc-authoringpnpm check:driver-memory-censuspnpm check:gitlink-declaredpnpm check:nul-bytespnpm check:pm-governed-mergespnpm check:pm-skill-id-lintpnpm check:pm-skill-ratchetpnpm check:refd-timer-probepnpm check:skill-frame-syncpnpm check:watch-hint-literalAlso run on this tree, named by the dispatch and not in the derived list:
pnpm check:skill-frame-freshnessexit 0 ·pnpm check:pm-governed-proseexit 0.--ranreconciliation: ✓ dispatch-gates --ran: 17 derived famil(ies) accounted for — 17 run, 0 NOT-MEASURED (a DERIVED zero — all 17 recorded an exit code and none of them is 3).Acceptance notes
scripts/pm/with-fleet.sh --read -- truein this cloud container (a probe of the direct path before opening the PRs): the mintPOST /app/installations/{id}/access_tokensis refused by the egress proxy (HTTP 403 "not permitted through this proxy"),classifyHttpread that 403 asratelimit, andwrite-pacewrote a 30-minute STOP MARKER for the App token's key (f665bb8f6447). A proxy path refusal is not a back-off signal; the marker blocks nothing this session writes (the session token's keyf07d7417ce88carries no marker), but it would block a seat that can mint. Reported on the card for the seat to file; not fixed here (scripts/pm/**, outside this diff).#19755 remains open; its PR fix(pm): fleet-write derives the seat session from the container; the workflow’s Actions state is the kill switch; size-routed direct for post-stamped #19760 is the head this text was read from. If that branch changes the reason text, exit registers or the cap before it merges, this paragraph is re-read against the merged text before the contract review.Generated by Claude Code