Repository navigation
docs(agents,pm-dispatch): a draft conversion drops only an unqueued PR's auto-merge; a queued governed pull-back goes to the maintainer - #20854
Conversation
…nd routes a queued PR to the maintainer WIP: first of the three AGENTS.md sentences rewritten. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTZmMfzVzjNvyaLyQ8mHvg
…to-merge; a queued pull-back goes to the maintainer The "State on your PR" paragraph and multi-agent section 7 stop saying a draft conversion drops queue membership; pm-dispatch SKILL.md's queued pull-back line asks the maintainer for a manual removal at once, since no seat act is measured to dequeue a PR. Co-authored-by: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01KTZmMfzVzjNvyaLyQ8mHvg
Contract reviewServed-tier: Reviewed read-only: card #20847 (body + comments 5910732998 / 5911100852 / 5911443452), PR #20854 body, file list and net diff, PR #20845 diff, the #20695 / #6732 / #20797 timelines, the head's check-runs, and the repository at Net diff at the head. Check-runs on the head ( ① Derived judgmentsPrime Directive #14,
"State on your PR", Multi-agent §7,
The dequeue-act measurement — the relay half verified at the code; the sentence is an honest statement. The cross-file citation and sequencing. At Pins — right, measured at the head. Survivor grep at the head ( ② Semver level
③ Boundary flags
This PR is Tier H ( Implemented-by: VERDICT: PASS |
…that decided it (objectstack-ai#20866) Part of objectstack-ai#20596 Clause-②: no ## What changed This is the seventeenth stage of the `domain:services` lane of the dead-citation sweep. It covers `packages/services/service-job/src/**` and nothing else. By the seat's claim (`5911377566`), it is the next of the two single-site packages left in the lane, taken one package per stage. Later stages cover the other packages, so this PR says `Part of` and the card stays open. Every comment or docblock site in scope that cited a tracker number answering 404 has been rewritten in ruling C+D's form C (comment 5749154545 on objectstack-ai#19123), by the method of stages 1 to 16 (the latest is PR objectstack-ai#20850, landed as `40d6c5fbd`, the base here). That is **2 sites on 2 lines in 2 files, covering 1 number**: - `src/never-fires.fixture.ts:30`, the census's one site in this package at the base (a docblock); - `src/db-job-adapter.timeout.test.ts:55`, a test-comment site the census defers, found by the supplementary reading below and rewritten too, as stages 1 to 15 did. No test string, source string or gate-invisible spelling in this package carries a dead number, so these two sites are the whole population. Both rewritten lines now cite the commit in this repository that decided what they describe: **1 commit sha**. No ADR or ruling record records that decision (see the per-number table), so ruling C's commit rung applies. No number was dropped. Only comments changed. Each file keeps its line count (2 lines out, 2 in), so no line citation into either file moves. No code token moves (see the guard below). **No citation number is added**: the only tracker number on the added lines is the live `objectstack-ai#8628`, which already stood on its line. **No changeset.** Neither rewritten line reaches `dist`, and `dist` is byte-identical with and without the rewrite (see Changeset below), so this PR takes `skip-changeset`. ## Census: `service-job`, before and after **Instrument (A1).** The gate's own `node scripts/check-issue-citations.mjs --census --json`, read-only and unchanged. The count below is its `allocated-but-absent` findings under `packages/services/service-job/`. Each run counts as a reading only because its board frontier equals the newest issue or pull-request number, read by a separate request just before and just after the run. | reading | tree | board | whole-repo `allocated-but-absent` | service-job sites | lines | files | numbers | |---|---|---|---|---|---|---|---| | before | base `40d6c5fbd`, run 2026-09-30T12:36:32Z to 12:40:56Z | enumerated, 187 pages, frontier objectstack-ai#20855 (newest objectstack-ai#20854 before; objectstack-ai#20855 after, an issue opened 12:40:06Z inside the run, so the frontier equals the newest at the run's end) | 745 | **1** | 1 | 1 | 1 | | after | head `6ac866f86`, run 12:46:10Z to 12:49:55Z | enumerated, 187 pages, frontier objectstack-ai#20856 (newest objectstack-ai#20856 before and after) | 744 | **0** | 0 | 0 | 0 | The whole-repo drop is 1, and the finding sets of the two runs differ by exactly one row, `never-fires.fixture.ts:30 objectstack-ai#8748`, removed; none was added. The `resolves` tally is 33,221 in both runs, and `resolves-as-pull-request` (1,985) and `cross-repo-unjudged` (1,018) did not move either. Neither run was truncated or discarded: both enumerations read 187 pages at the newest frontier. The seat's census counted 1 here at `6bff748b`, and the base agrees: `6bff748b` is an ancestor of the base, and no commit between them touches this package's `src`. **Supplementary instrument, the whole scope.** The census does not read test files or strings. So a second reading runs the gate's own exported `extractCitations` (whole-file and comment-prose projections) and `namesThisRepository` over every `.ts` file under `service-job/src` (18 files). It takes its verdicts from the before census's own board reading rather than from a second enumeration: a number is dead when that census reported it `allocated-but-absent`, and alive when the gate's own census-scope extraction (`collectCitations`) judged it and the census did not report it. 4 numbers are covered by neither, because they stand only in test files. Each was read on its own through the read-only tools, and each answers as an issue: `objectstack-ai#8628`, `objectstack-ai#9611`, `objectstack-ai#9631` and `objectstack-ai#9633`. The probe's control: `objectstack-ai#8748` answers 404 on the issues endpoint and on the pull-request endpoint. | reading | citations | dead | src comment | test comment | src string | test string | |---|---|---|---|---|---|---| | before, `40d6c5fbd` | 95 | **2** | 1 | 1 | 0 | 0 | | after, `6ac866f86` | 93 | **0** | 0 | 0 | 0 | 0 | Its src-comment column equals the census's 1, which is the control on the second instrument. The 93 live citations are the same in both readings (81 by the census's judgement, 12 by the single reads), none is cross-repo, none is unjudged, and the drop of 2 citations is exactly the two rewritten sites. A third, raw reading (every `#` followed by 2 to 6 digits, whatever surrounds it) finds 95 occurrences before and 93 after, the same drop of 2, and no token beyond the gate's grammar. ## Per-number table Sites and files count every dead occurrence in scope at the base (comments and strings, tests included). | number | sites / files | rewritten / left | anchor: what it decided | |---|---|---|---| | `objectstack-ai#8748` | 2/2 | 2/0 | `226cb71d5` (PR objectstack-ai#8774): every exact-count case in this package moves onto the inert `NEVER_FIRES` cron fixture (`'0 0 30 2 *'`, February 30th, which never occurs), and the fixture moves out of the timeout suite into the shared `never-fires.fixture.ts`. Its message records the measurement `:30` describes: only `Date` faked, the registration placed 2/5/10/15 ms before the expression's instant, one extra handler run per case under the firing spellings, and two of the three no longer reproducing at a 2 ms lead. That is what `:30` says, and what `:55`'s 「now shared with the sibling job suites rather than spelled a second time here」 says. Its subject names `objectstack-ai#8748`, and its own diff names it on 2 added lines; `git blame` puts both rewritten lines in this commit | The sha matches exactly one commit (`git rev-parse --disambiguate`, count 1) and is an ancestor of the base (`merge-base --is-ancestor`, exit 0; reverse leg, base against the anchor, exit 1; control legs exit 0: `7246d631d`, 5,451 commits behind the base, and the repository's root commit `1598cabe4`, 15,209 behind, against the anchor's 5,436; the history is complete, `--is-shallow-repository` false, 15,210 commits at the base). `objectstack-ai#8748` answers 404 on the issues endpoint and on the pull-request endpoint, read one by one. No ADR, `scripts/adr-anchors/` file or ruling record names `objectstack-ai#8748`, PR objectstack-ai#8774, `NEVER_FIRES`, `never-fires`, February 30th or an inert cron (`git grep` over `docs/adr` and `scripts/adr-anchors`: 0 hits), so ruling C's first rung is empty. The repository's other `objectstack-ai#8748` tokens are `objectui#8748`, a cross-repo reference the gate never judges. ## Wordings to check - **`never-fires.fixture.ts:30`, tag swap in place.** 「Measured (objectstack-ai#8748) by faking ONLY `Date`」 became 「Measured (commit 226cb71) by faking ONLY `Date`」. The form is the one `packages/lint/src/lint-flow-patterns.ts:1468` already carries on `main` (「Measured (commit 8ed9c54)」). - **`db-job-adapter.timeout.test.ts:55`, tag swap in place.** 「(objectstack-ai#8628, objectstack-ai#8748)」 became 「(objectstack-ai#8628, commit 226cb71)」. The live `objectstack-ai#8628` stays: it is the report of the wall-clock flake, whose own change, `7246d631d` (PR objectstack-ai#8750), first made this suite's cron unable to self-fire. The form is the one stages 7 and 9 landed (for example `(objectstack-ai#5928, commit 69787f0)` in `plugin-audit`). - Neither line was reflowed, so each is 11 characters longer than before (70 to 81, and 72 to 83), a little past its block's wrap. `eslint.config.mjs` declares no line-length rule, and reflowing would have moved neighbouring lines. ## Sites left - **In `src`: none.** No test title, assertion message, operator log string, runtime refusal, quoted maintainer ruling or generated file in this package carries a dead number. - **Outside `src`, listed and left, not edited in this stage:** - The release-owned `CHANGELOG.md` names the dead `objectstack-ai#13112` on 1 line (`:705`; 404 on the issue and pull-request endpoints). Its other 27 numbers are live: 19 by the census's judgement, and by single reads `objectstack-ai#18715`, `objectstack-ai#14619`, `objectstack-ai#9517`, `objectstack-ai#1893`, `objectstack-ai#9611`, `objectstack-ai#9631` and `objectstack-ai#9633` as issues and `objectstack-ai#9546` as a pull request. - `vitest.config.ts` names the live `objectstack-ai#10374`. - `README.md`, `package.json` and `tsconfig.json` name none. ## Mechanical guard: no code token moves The guard compares, base `40d6c5fbd` against head, over both touched `.ts` files: - **Reading 1**, the TypeScript parser's leaf nodes (a `forEachChild` walk, so comments are trivia and JSDoc nodes are never visited). String and template literals are therefore read in full. - **Reading 2**, the full token stream in parser context (a `getChildren` walk, so punctuation and keywords are included; JSDoc nodes skipped). Results: - Real run at the head `6ac866f86`: 755 base leaf tokens, **0 files with a token change** on either reading (exit 0). - Comment control (「croner resolves Feb 29 forward」 to 「croner rolls Feb 29 forward」): 0 files changed, as expected (exit 0). - Positive control, a code identifier renamed (`expression: NEVER_FIRES }` to `expression: NEVER_FIRESX }`): DIFFER on the identifier in both readings (exit 1). - Positive control, a string literal changed (`'0 0 30 2 *'` to `'0 0 31 2 *'`): DIFFER on the string literal in both readings (exit 1). - Positive control in the second file, a numeric literal changed (`TIMEOUT_MS = 20` to `21`): DIFFER on the literal in both readings (exit 1). Every mutation went through `scripts/ablation-replace.mjs` (wrap mode) under a shell trap that restores by absolute path, and each landed (anchor 1 to 0, blob changed). Each restore was proven byte-identical to the HEAD blobs (`1fd5e1b3f612`, `ce37b1050c78`), with `git diff HEAD` empty and a clean tree afterwards. ## Changeset: none (`skip-changeset`) `files[]` is `dist`, `README.md` and `CHANGELOG.md`, and the package is not private. `never-fires.fixture.ts` is a test-only support module (nothing in `src/index.ts` re-exports it, and the tsup entry is `src/index.ts` alone), and the other touched file is a test. Measured on the built package (A3), after `pnpm --filter '@objectstack/service-job...' build` at `6ac866f86`, where the package's own `tsup` ran and cleaned its output folder: - Neither rewritten line appears in any `dist` file (0 in all 6, source maps included). Nor do the old number, `objectstack-ai#8628`, the anchor sha, the neighbouring lines `:28`, `:31`, `:54` and `:56`, `NEVER_FIRES`, the `'0 0 30 2 *'` expression, or a never-written negative phrase. - Positive controls, text that does ship: `CronJobAdapter` (45 hits), `DbJobAdapter` (73) and `sys_job_run` (52) across the entries, and two docblock lines of the `DbJobAdapter` class JSDoc in `db-job-adapter.ts` (「`{@link DbJobAdapterOptions.recordRuns}` is `false`, the on/off switch for」 and the `recordRuns` gating line below it), each in `index.d.ts` and `index.d.cts`. - **Byte identity.** The package was rebuilt with the base text put back in both files (through nested `scripts/ablation-replace.mjs` legs, with each file proven equal to its base blob, `919a2e444f23` and `eb00f6eb1978`, during the leg), and again after the proven restore. The sha256 of all 6 `dist` files is identical in all three builds: JS entries, declaration files and source maps. So nothing this PR rewrites is published, and a changeset would announce a change no consumer can observe. No `.changeset/*` file is added or touched. ## Gates (head `6ac866f86`) - **Citation judging, as CI runs it:** `node scripts/check-issue-citations.mjs` exits 0 (「no issue citations added against 40d6c5f」). `pnpm check:issue-citations` exits 0 (self-test, 114 cases, 8 batteries). - **Doc authoring:** `pnpm check:doc-authoring` exits 0 (the sibling-package prose-id baseline holds, no growth). - **Derived gates:** `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` at `6ac866f86` (change set derived from git: 2 paths against the merge base `40d6c5fbd`) derived 54 commands, all among the dispatch list's 63. - All 63 of the dispatch list ran, each with its exit code captured before any pipe, and all 63 exit 0; none exited 3. - `--ran`, fed each command with its exit code, reports 54 derived, 54 run, 0 NOT MEASURED (a derived zero), 0 unrun, and exits 0. Of the other 9, it classifies 7 as pending-changeset families and 2 as outside this derivation. - A full `turbo run build` over `./packages/*` and `./packages/*/*` ran first under the shared verify lock (71 of 71 tasks), so no gate hit an unbuilt workspace. - **Roster families the derivation lists outside its commands** (their rosters sit in a directory this diff touches): `pnpm check:authz-resolver`, `pnpm check:error-code-casing` and `pnpm check:filter-alias-parity`, plus `node scripts/check-changeset-fixed.mjs`, which the dispatch named. Each exits 0. - **Tests and typecheck, under the verify lock, at `6ac866f86`:** - `pnpm --filter @objectstack/service-job test`: 11 files pass and 117 tests pass, which is every tracked test file under `src/`. - `pnpm --filter @objectstack/service-job typecheck` exits 0, and `tsc --noEmit --listFiles` puts both touched files in the program (the config includes `src` and excludes no test file). - **Lint, as a proven narrowing:** eslint with inline config disabled, over the 2 touched `.ts` files, gives 2 files, 0 errors and 0 warnings (its `--format json` output). Both files are in eslint's own population (not reported ignored; `dist/index.js`, the control, reads ignored). `eslint.config.mjs` never enables type-aware linting (no `parserOptions.project`, as its own lines 327-328 state), so a comment edit here cannot move the verdict on any untouched file. The repo-wide `pnpm lint` is CI's run. - **Control bytes:** `pnpm check:nul-bytes` exits 0, and a raw scan of the changed files for control bytes finds none. ## Acceptance notes - **The gate-invisible spellings, grepped as the claim asked** (objectstack-ai#20636, including the `clause #N` position). At the base and at the head, `#N-word`, `#A/#B`, `option #N`, `clause #N` and URL-spelled links are each on 0 lines, so the claim's 0 / 0 / 0 / 0 / 0 hold. The one prefix-joined token, `pre-objectstack-ai#6617` in a test title of `db-job-adapter.degraded-outcome.test.ts`, is inside the gate's grammar and names a live number. - **Wording only:** 「the card」 / 「this card」 stands on 4 comment lines in 3 files under `service-job/src`. It carries no number, neither instrument sees it, and this diff removes no antecedent. - **Outside-`src` residue.** `CHANGELOG.md:705` names the dead `objectstack-ai#13112`; the file is release-owned and is left. - **The census instrument did not truncate in this stage.** Both enumerations read 187 pages at the newest frontier. - **Base.** The branch is on `main` at `40d6c5fbd`. `main` has since moved two commits (to `660a9b247`). Neither touches `packages/services/service-job`, `scripts/check-issue-citations.mjs`, `scripts/pm/dispatch-gates.mjs` or `.changeset/config.json`, so no merge was taken; the merge queue rebuilds on the merged generation. The one derivation input that moved is `scripts/doc-authoring-prose-id.baseline.json`, where the second commit removed only `packages/objectql` entries; this package has no entry there before or after, so the merged tree cannot move that gate's verdict on this diff. --- _Generated by [Claude Code](https://claude.ai/code/session_01XY5uCwTjZj7884yYtyur4H)_ Co-authored-by: Claude <noreply@anthropic.com>
Fixes #20847
Clause-②: no
What changes
Four sentences stop saying that a draft conversion, or draft plus an auto-merge disable, removes a PR from the merge queue. Each keeps the half that holds: on an unqueued PR, the conversion drops auto-merge. Prime Directive 14 now names the one removal act that is measured, the maintainer's manual removal, and says why a seat cannot do it.
AGENTS.mdPrime Directive 14, "Already armed or queued" (was:285-:287, now:285-:288)origin/main.platform-readings.md, queue membership), so ask the maintainer at once to remove a queued PR by hand — then confirm from the remote that it is in neither the queue nororigin/main.AGENTS.md"State on your PR" (:428-:429→:429-:430)AGENTS.mdmulti-agent §7 (:532-:533→:533-:534).claude/skills/pm-dispatch/SKILL.md:202Every clause that still holds is kept: "Draft is no barrier by itself — the barrier is this directive", "confirm from the remote that it is in neither the queue nor
origin/main", "ready first, arm second", and the positive-probe reading of a dequeue. The rule text citesplatform-readings.mdand restates no reading. The readings themselves are in PR #20845 (issue #20764).The grep.
AGENTS.mdand every file under.claude/**were searched for other copies of the claim:queue membership, draft next to queue or auto-merge, 转 draft, 出队, 踢队, dequeue, evict. The four sites above are all of them.references/platform-readings.md:41-:43is PR #20845's, and this PR leaves it alone.lanes/cli.md:17only points at that file.Is there a seat act that removes a queued PR? (the claim's measurement)
Every step was read-only. ⛔ No mutation was called and no PR was dequeued.
POST https://api.github.com/graphqlwithquery { __type(name: "Mutation") { fields { name description } } }. It returned 403 from this session's egress, with the message "GitHub GraphQL is not available from Claude Code sessions". The same message lists the pull-request routes the egress does serve:ccr/auto_merge(PUT/DELETE),ccr/ready_for_reviewandccr/convert_to_draft. None of them dequeues.octokit/graphql-schemaschema.graphqlonmain, fetched 2026-09-30T12:18Z (1,223,842 bytes, sha256 prefix3c62d0526d133cee). It declaresdequeuePullRequest(input: DequeuePullRequestInput!)with the description "Remove a pull request from the merge queue." Its input isid: ID!, the pull request id.github/rest-api-description,api.github.com.json(info version 1.1.4,main), no path containsqueue. The word "dequeue" appears only in thepull_request.dequeuedwebhook schemas.github/docsonmain(data/reusables/pull_requests/merge-queue-removal-reasons.md). The list has four entries: CI failure, timeout, "User requesting a removal via the API or merge queue interface", and a branch-protection failure. Neither a draft conversion nor a close is on it. The how-to page (merging-a-pull-request-with-a-merge-queue.md) removes a PR through the web page's Remove from queue button and says the CLI cannot do it.scripts/pm/fleet-write/ops.mjsat05a7547c9has 15 ops: comment, comment_edit, labels_add, labels_remove, assign, unassign, issue_patch, issue_create, pr_create, pr_request_reviewers, pr_ready, pr_draft, automerge_enable, automerge_disable and transfer.ALLOWED_MUTATIONShas five entries, anddequeuePullRequestis not one of them.⇒ No dequeue act is measured to be available to a seat. The platform documents one (the GraphQL mutation), but neither this session's egress nor the relay can reach it. So the rule sends a queued pull-back to the maintainer and says why. The triage direction on the card reserves the next step for the triage seat: whether to file a tooling child for a relay dequeue op. That would be a new relay capability.
Coordination with PR #20845
The new rule cites the queue-membership section of
platform-readings.md. Atorigin/main(05a7547c9), line:42of that section still carries the old reading, and PR #20845 rewrites:41-:43. Until #20845 lands, the rule and line:42disagree. #20845 should land first, or with this PR. The citation names a file section, not a PR, so it is correct once both have landed, whatever the order.Line budget
AGENTS.md: 1107 → 1108 lines, against a ceiling of 1116 (headroom 9 → 8). The +1 is all in Prime Directive 14. The new sentence adds the maintainer route and the reason for it, and it needs four lines where the old one took three. The other twoAGENTS.mdsentences are net 0.pm-dispatch/SKILL.md: 319 → 319 lines (ceiling 319, headroom 0). Line:202is edited in place and goes from 107 to 116 bytes.SKILL.md).check:pm-skill-ratchetreports no over-length line and leaves the table-row pins unchanged (768 and 342).Deviations from the dispatch
SKILL.md:202drops two parts. They are the clause 「ref 缺席只旁证」 and the 「才读到本条」 of the trigger. The 120-byte cap left 13 bytes of room on the line, and the maintainer route with its reason needs about 50. The dropped clause is kept inplatform-readings.md:44(「ref 缺席只作旁证,⛔ 永不承载结论」), and the positive-probe half of the line stays.AGENTS.mdis net +1, not ≤ 0. None of the three sentences frees a whole line by deleting content. Freeing one would need a re-wrap of text this PR does not otherwise change. The pin is not exceeded.Acceptance notes
scripts/pm/check-governed-queue-guard.mjsmakes the same claim in both of its refusal texts, at:1451-:1452and:1911-:1912(at05a7547c9): "take the pull request out of the queue: convert it back to DRAFT (disarming auto-merge alone does NOT dequeue it)". Parking the PR in draft after the guard's red is still useful: an armed PR re-enters the queue, and a draft cannot be armed. The part in parentheses is the falsified premise. This is reported to the seat so it can join the card's family. No card is filed.issue_patchwithstate: closed. A code comment in.github/workflows/cross-repo-issue-closer.yml:399-:401says that closing drops queue membership. GitHub's list of removal reasons does not name it, and I know of no reading of it in this repo. It was not attempted..claude/**andAGENTS.mdare not in any package'sfiles[], so this PR publishes nothing.skip-changesetis for the seat to apply.AGENTS.md). The PR stays a draft until an authorized approval.Verification (head
b095ba02e)node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands, with no paths, derived 22 commands for this change set (2 paths against merge base05a7547c9). All 22 exited 0:check-closing-keyword-parity, plus its--self-test;check-comment-mask-corpus;check-governed-queue-guard --self-testandcheck-harness-current --self-test;@objectstack/lint check:doc-formula-expressions, run after building@objectstack/lintand its dependency closure underos-verify-lock.sh(VERDICT command-exit 0);check:family:agent-test-spelling,cross-package-test-inputs,doc-authoring,docs-audit-scope,driver-memory-census,gitlink-declared,nul-bytes,pm-expected-skips,pm-governed-merges,pm-governed-prose,pm-skill-id-lint,pm-skill-ratchet,refd-timer-probe,required-contexts,skill-frame-syncandwatch-hint-literal.pnpm check:pm-settings-deny-rosterwas also run, because its roster lives under.claude. It exited 0.--ranreconciliation read "22 derived, 22 run, 0 NOT-MEASURED, 0 UNRUN". All 22 commands recorded an exit code.check:pm-skill-ratchet: "AGENTS.md is 1108 lines (ceiling 1116; headroom 8)" and "pm-dispatch/SKILL.md is 319 lines (ceiling 319; headroom 0)".check:pm-skill-id-lint: "34 file(s) clean".check:pm-governed-prose: "2 instruction surface(s) name all 6 registered governed surfaces".check-required-contexts --verify-required-set, which reads the workflow event and so runs only in CI;维护者速读(草稿)
AGENTS.md三句、pm-dispatch/SKILL.md一行。旧文说「转 draft 会把 PR 踢出合并队列」,现在都不再这么说。改后:转 draft 只在未入队时掉 auto-merge。已入队的受管 PR 要撤回时,两手照做,并立即请你手动出队。dequeuePullRequest,但本会话出口拒绝 GraphQL(403),中继也没有这个 op。所以规则暂时把已入队的撤回交给你手动出队。要不要给中继加出队 op,属于新能力,由分诊决定是否立子卡。子卡立了,你会看到裁决请求。Generated by Claude Code