Skip to content

A fork PR whose need already landed internally is left open: make the close-with-thanks step at landing impossible to skip (missed on #19342 for two days) #19883

Description

@objectstack-fleet

Filing category: ③ maintainer-directed task.

The maintainer gave this instruction on 2026-09-23 in the PM session session_01UDXER3sdqfeVYpEWZs5mZx (the domain:spec seat 2). Verbatim:

这种pr应该写个评论直接关闭。

"这种 PR"都应该这样处理,开一个 skills 卡片

"这种 PR" means a fork PR whose need has already landed through an internal PR.

What happened

Ask (domain:skills seat)

Make the close impossible to forget. Follow the order SKILL.md gives for a failure fix: first remove the construct that allows the error, then make the right form the only spelling, and only then add a check. The seat picks the shape. Two candidates:

  • A. At the landing step. When a landing card names a fork PR it adopted, the same landing step posts the thank-you with the landing link and closes that fork PR.
  • B. In the triage sweep. Step ① already scans open PRs whose head repo ≠ base repo on every fire. Add one arm: if the fork PR's card was closed as completed by a merged PR, post the thank-you with the landing link and close the fork PR.

Also state what happens when the need is declined (the card closes not_planned). Today the text covers only the landed case.

Reading at filing

Dedupe

Queries run with search_issues on objectstack:

Filed by the domain:spec seat 2 (session_01UDXER3sdqfeVYpEWZs5mZx) on the maintainer's direct instruction. The lane domain:skills is the one the maintainer named. Not claimed.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 2
    Session: session_01A22sUB3mUWs6M36VgfijBq
    Branch: claude/issue-19883-fork-pr-close-at-landing
    Worktree: objectstack-issue-19883
    Domain: domain:skills
    Seat: domain:skills#1
    File surface: .claude/skills/pm-dispatch/references/external-contributions.md (the landed and the declined case) · .claude/skills/pm-dispatch/references/landing-operations.md (the MERGED closeout list, one line) · .claude/skills/pm-dispatch/references/triage-duties.md only if the sweep arm is the chosen reader · scripts/pm/check-half-states.mjs only for a report-only patrol row, and only with the maintainer's word quoted on the card (stop on breach; explain in the report; ⛔ SKILL.md is outside this surface — 319 / 319, and serial behind #19881 / PR #19890)
    Container & model: M — a choice between two shapes judged on the four axes; the text lands on Tier S governed references, mode:subagent, model: opus — dispatch-gates --tier --repo objectstack-ai/objectstack on the surface prints "no path-derived mandate: the surface hits none of the 3 declared glob(s) … floor sonnet · default opus · ceiling fable"
    Clause-②: no
    Thread-read: none
    Serial constraints cleared: PR #19890 (the dev of #19881, claude/lucid-turing-izrwob) is the one open PR under .claude/skills/pm-dispatch/ and touches SKILL.md + references/filing-gate.md only — disjoint from this surface; no open PR touches external-contributions.md, landing-operations.md or triage-duties.md (22 open PRs' file lists read at 2026-09-23T15:19Z); newest landing on the surface 0bc46c6 (this date); landing-operations.md sits at 101 / 101 with headroom 0, so a line added there is paid by a retired line in the same file.

    Take basis: 立卡门 ③ — the maintainer's verbatim word recorded on the card (the domain:spec seat 2's session, this date): 「这种pr应该写个评论直接关闭。」 and 「"这种 PR"都应该这样处理,开一个 skills 卡片」 — the take order's first rung. The card carries no priority:* label (a triage gap, reported in the round report, ⛔ not set by this seat). Premise re-read on origin/main at 2026-09-23T15:19Z: external-contributions.md :12 「内部 PR 落地后关闭 fork PR,附致谢与落地链接」 is the only carrier of the rule and is prose; #19342 closed at 14:42Z of this date, #19489 closed completed, PR #19534 merged 2aac821a8c — the card's readings stand. Dispatched as a subagent of this session with this comment as its only claim.


    Generated by Claude Code

  2. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    ContributorAuthor

    补定级 priority:p2 · tooling —— 维护者直接下令建的 skills 卡,⛔ 不适用「无解锁对象的 tooling 卡首触即关」

    Path: none

    Triage: lands in .claude/skills/pm-dispatch/ (the landing step, or the triage sweep's fork-PR arm, per references/external-contributions.md step ③) ⇒ domain:skills; rationale: a fork PR whose need landed internally was left open for two days with no word to its contributor, because the close-with-thanks step is prose that no landing step or sweep reads; filed on the maintainer's verbatim instruction (「这种 PR 都应该这样处理,开一个 skills 卡片」), so the p2-tooling close rule does not apply — closing it would overturn a maintainer instruction; no fork PR is waiting now (0 of 25 at filing) ⇒ p2, not p1.

    分诊席(session_01Tw7jnJinGHvoGSi8aFkhPJ),2026-09-23T15:27Z。本卡在 pm:queue 里缺 priority:*(三析取第 ④ 项)。本席读完了卡面(本卡尚无评论)。

    判定

    • 业务后果:外部贡献者的 PR,需求已经由内部 PR 落地,并且带了他的 Co-authored-by,他的 PR 却挂了两天没人理,直到维护者问起。对社区贡献者来说,这是最伤信任的一种沉默。
    • p2:现在没有等待中的 fork PR(立卡时实测,25 个开放 PR 里 0 个),本卡防的是下一次。
    • ⚠️ 关于分诊的关卡规则:triage-duties.md 规定,产品仓有 P0/P1 开着时,没有解锁对象的 p2/p3 tooling 卡首触即关。本卡是维护者直接下令建的(立卡门 ③),关掉它等于推翻维护者的指令。⇒ ⛔ 本席不关,只补定级。它在 domain:skills 队列里排在产品 P0/P1 之后,由车道按自己的节奏取。
    • 形状(A 在落地步骤里关,或 B 在分诊扫描里加一条分支)由车道选,卡面已写明;⛔ 本席不代选。别忘了卡面提的第二件事:需求被拒(not_planned)时怎么回复贡献者。

    标签:加 priority:p2、tooling;pm:queue、domain:skills 不动。


    Generated by Claude Code

  3. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 19883,
      "status": "done",
      "branch": "claude/issue-19883-fork-pr-close-at-landing",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/19895",
      "session": "session_01A22sUB3mUWs6M36VgfijBq",
      "premise_still_valid": true,
      "summary": "Shape A with a one-line B backstop, three reference files, +5 / -3, head 4a3242c. (1) external-contributions.md: the card behind a fork PR always carries a line-start `Adopts: #M` (M = the fork PR), written in the stroke that files the card or attaches the fork PR; the step-3 close becomes 'the stroke that closes the card also closes the fork PR its Adopts: line names' - completed with thanks + landing link, not_planned with thanks + the decline reason (the declined case had no text before); the comment-limit sentence is rewritten, not worked around (besides step 1's fixed comment, only review comments and the closing comment). (2) landing-operations.md section B MERGED closeout gains the fork-PR close as an item of the same action, paid by retiring old line 19 (every clause restated by the section-B heading and its 'two readings' line). (3) triage-duties.md gains the per-fire fork-PR scan with a closed-card arm, paid by retiring old line 8 (implied by the file's own header and lines 6-7). No gate, script, half-state row or ratchet added; SKILL.md untouched. Premise confirmed on origin/main dabf8d7; one dispatch reading falsified: triage-duties.md carried NO fork scan (git grep -c -i fork: exit 1 / zero hits; control external-contributions.md same tree: 8 hits, exit 0), so step 1's scan had no reader; the new triage line gives it one (bounded in-place fix, all four conditions hold, file already on the claimed surface, named in the PR body). Tier S: needs the seat's Contract review record before landing.",
      "tests": "No package touched, so no build closure and no package test owed. Union at 4a3242c (git rev-parse --short HEAD after the last commit): node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack derived 18 families from 3 paths vs merge base dabf8d795; all 18 run, exits captured before any pipe; --ran verdict: 'dispatch-gates --ran: 18 derived famil(ies) accounted for - 18 run, 0 NOT-MEASURED (a DERIVED zero - all 18 recorded an exit code and none of them is 3)'. Key verdict lines: check:pm-skill-ratchet exit 0 ('landing-operations.md is 101 lines (ceiling 101; headroom 0)', 'triage-duties.md is 120 lines (ceiling 120; headroom 0)'); check:pm-skill-id-lint exit 0 ('34 file(s) clean (pattern /#[0-9]{3,}/g)'); check:pm-governed-prose exit 0 (dispatch-named, outside the derivation); check:nul-bytes exit 0 ('no raw ASCII control bytes'); check:skill-frame-sync exit 0; check:pm-half-states exit 0 ('4912 cases pass'); check:pm-governed-merges exit 0; check:doc-formula-expressions first exit 3 PREREQUISITE NOT MET, then turbo build of @objectstack/formula + @objectstack/lint under os-verify-lock (VERDICT command-exit 0) and re-run exit 0; the other 10 derived families exit 0. Every changed line measured at 120 bytes or less. No ablation: prose-only change.",
      "gates": [
        "node scripts/check-closing-keyword-parity.mjs :: exit 0",
        "node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0",
        "node scripts/check-comment-mask-corpus.mjs :: exit 0",
        "node scripts/pm/check-harness-current.mjs --self-test :: exit 0",
        "pnpm --filter @objectstack/lint run check:doc-formula-expressions :: exit 0 (first attempt exit 3 PREREQUISITE NOT MET, cleared by the locked build)",
        "pnpm check:agent-test-spelling :: exit 0",
        "pnpm check:cross-package-test-inputs :: exit 0",
        "pnpm check:doc-authoring :: exit 0",
        "pnpm check:driver-memory-census :: exit 0",
        "pnpm check:gitlink-declared :: exit 0",
        "pnpm check:nul-bytes :: exit 0",
        "pnpm check:pm-governed-merges :: exit 0",
        "pnpm check:pm-half-states :: exit 0",
        "pnpm check:pm-skill-id-lint :: exit 0",
        "pnpm check:pm-skill-ratchet :: exit 0",
        "pnpm check:refd-timer-probe :: exit 0",
        "pnpm check:skill-frame-sync :: exit 0",
        "pnpm check:watch-hint-literal :: exit 0",
        "pnpm check:pm-governed-prose :: exit 0 (dispatch-named, outside the derivation)"
      ],
      "files_changed": [
        ".claude/skills/pm-dispatch/references/external-contributions.md (+3 / -1; 16 -> 18 lines; not in the ratchet ceiling map)",
        ".claude/skills/pm-dispatch/references/landing-operations.md (+1 / -1; 101 / 101)",
        ".claude/skills/pm-dispatch/references/triage-duties.md (+1 / -1; 120 / 120)"
      ],
      "deviations": [
        "origin/main moved e9eb2244d5 -> dabf8d7 before the worktree was cut; git diff --stat e9eb224 dabf8d7 -- .claude/skills/pm-dispatch/ is empty, so the dispatch's readings apply unchanged.",
        "Mechanism assumption 5 / 'read that line' falsified in part: triage-duties.md had no fork-scan line to read; B was therefore not optional for the declined case and step 1's reader - taken as one line, paid by a retired duplicate line.",
        "Spelling chosen `Adopts: #M` (same line-start form as the existing blocked-by directive) rather than the dispatch's example `Adopts: fork PR #N`; M avoids colliding with the fixed comment's `#N`, which names the card.",
        "Commit trailers: the model-free pair AGENTS.md prescribes (Claude-Session + Co-authored-by: Claude), not the harness reminder's model-bearing Co-Authored-By; pre-push check:commit-card-trailers green. PR footer: the AGENTS.md session-URL form.",
        "check:doc-formula-expressions needed a build of two packages the diff does not touch (its declared prerequisite); built under the verify lock, 195 s held, 1 s waited."
      ],
      "mcp_calls": "0 - no MCP GitHub tool called",
      "api_writes": "3 - all through the fleet-write relay as objectstack-fleet[bot], each one POST /repos/objectstack-ai/objectstack/dispatches: (1) pr_create -> POST /repos/objectstack-ai/objectstack/pulls (PR 19895, draft; run 35883785706 success; body read back byte-identical, 11248 bytes, one footer); (2) label-write labels_add skip-changeset -> POST /repos/objectstack-ai/objectstack/issues/19895/labels (run 35883896032 success; read back MATCHES: documentation, size/xs, skip-changeset); (3) this os-dev-report comment -> POST /repos/objectstack-ai/objectstack/issues/19883/comments. git push not counted.",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none (承接者:无) · SKILL.md phase-file index names no reader for references/external-contributions.md; after this PR both executing seats' files point at it, so no row is owed · noted in PR Acceptance notes, not filed",
        "carrier: none (承接者:无) · references/external-contributions.md is absent from the check-skill-line-ratchet CEILINGS map while the other pm-dispatch references are enumerated · noted, not filed",
        "carrier: none (承接者:无) · a fork-PR card closed as duplicate is not covered (its Adopts: line would have to move to the surviving card); 0 instances · noted, not filed",
        "carrier: none (承接者:无) · check-half-states.mjs H65 message quotes triage-duties.md with wording the file no longer carries; report-only message text · noted, not filed"
      ],
      "cleanup": "worktree /home/user/objectstack-issue-19883 removed (node_modules deleted first; git worktree remove exit 0, no --force); remote branch head 4a3242c equals the last local HEAD; no server or monitor started."
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — domain:skills seat 1 (session_01A22sUB3mUWs6M36VgfijBq, seat post #7623), 2026-09-23T15:56Z — PR #19895 (head 4a3242c3f5, draft, base main, first line Fixes #19883), report 5798000197.

    Checklist (read on GitHub): draft on main; Fixes names this card only, no closing keyword beside any other card number; Clause-②: no at line start; ## 维护者速读(草稿) present; session-URL footer; 3 changed files, all .claude/skills/pm-dispatch/references/ (+5 / −3), skip-changeset correct; check-governed-merges.mjs --pr 19895: Tier S (.claude/** ×3, 8 lines under the human-merge limb) — the ## Contract review record is rendered in-seat at tier on the PR thread (PASS); mcp_calls 0; api_writes 3 through the relay. Check-runs on the head at 2026-09-23T15:52Z: 14 success · 11 skipped · Lint & Repo Gates in progress — ready + auto-merge are armed only once it reads success and the skips read rostered.

    Spot-check readings of the seat's own: the full diff read from the branch (the Adopts: #M line-start spelling; both closing cases in step ③; the comment-set sentence rewritten; the §B closeout item; the two retired lines' clauses still stated in their own files; the triage per-fire fork scan — the seat's own origin/main grep confirms no fork scan existed there before). Executes the maintainer's word 「这种pr应该写个评论直接关闭。」 / 「"这种 PR"都应该这样处理,开一个 skills 卡片」 as a closing act with no new gate (新增门禁默认否). Deviations accepted: the assumption that a fork scan already existed was the seat's, falsified by measurement; the model-free trailer pair; the check:doc-formula-expressions prerequisite build under the verify lock.

    Out-of-scope notes (four, 承接者:无) stay on the PR's Acceptance notes, not filed. The card carries no priority:* label — a triage gap reported in the round report, ⛔ not set by this seat.

    Landing plan: Lint & Repo Gates green ⇒ check-governed-merges --pr re-read with the record ⇒ ready → auto-merge SQUASH through the CCR route, queue landing; at MERGED, Fixes closes this card and the seat strips pm:dispatched and the assignee in the same act.


    Generated by Claude Code

  5. added a commit that references this issue on Sep 28, 2026
    3230308
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