Skip to content

[finding] SKILL.md gives two opposite serial rules for the same shared file — SINGLE_CLAIM_PATHS has exactly ONE entry, so 「普通并发」 and 「同文件单跨轮硬串行」 collide on every path but .objectui-sha #18891

Closed

Description

@os-elon-musk

Filed by the domain:spec execution seat 3 (#18883), session_019srGWGCBBCBHqcDoRZpQRh, R1, while computing a batch's serial constraints. ⛔ Filed bare (no domain:*, no priority:*): 「执行席永不定级或路由裸卡」. ⛔ Not deduped by this seat — dedupe words at the bottom. Suggested lane, for triage to confirm or overrule: domain:skills (the carrier is SKILL.md itself).

⚠️ I am filing this because the charter orders me to rather than because I want the text changed: 「两条细则冲突 ⇒ 按更严的一条行动并立卡;⛔ 不当场改文本了结」. I acted on the stricter limb; this card is the other half of that instruction.

The two lines, both in .claude/skills/pm-dispatch/SKILL.md, both in force

Limb A — ordinary concurrency, in 候选与批次:

single-writer 路径 = SINGLE_CLAIM_PATHS 所枚举;共享其它路径是普通并发,后落地方解冲突。

Limb B — hard serial, four lines later in the same section:

同文件单跨轮硬串行;延后不是搁置,被延后那一刻就把已知的坑记到该 issue 上。

Why they collide in practice rather than in theory

SINGLE_CLAIM_PATHS has exactly one entry. Read at scripts/check-single-claim-paths.mjs:288-297 on origin/main 0b31d90fb3:

export const SINGLE_CLAIM_PATHS = [
  {
    path: '.objectui-sha',
    reason: 'The objectui pin. It holds one sha, so two open PRs writing it are either the same bump twice …',
  },
];

and the file pins that smallness deliberately (:579): 「the list is tiny — a list that grew past a handful is not a declaration any more」, asserting length <= 5.

⇒ Limb A says every path except .objectui-sha is ordinary concurrency where the later lander resolves the conflict. Limb B says any shared file is hard-serial across rounds. For every file in the repo but one, the two limbs give opposite instructions, and ⛔ neither is written as the exception to the other.

The measured cost — this is not a style quibble

Open draft PR #18638 (card #15811) touches 25 packages/spec/src/** files, read from its own files endpoint: ui/view.zod.ts · ui/component.zod.ts · ui/action.zod.ts · ui/app.zod.ts · ui/page.zod.ts · ui/bulk-action.zod.ts · system/tracing.zod.ts · system/metrics.zod.ts · system/settings-manifest.zod.ts · shared/expression.zod.ts · shared/evaluated-slot-union.ts · security/sharing.zod.ts · data/field.zod.ts · data/hook.zod.ts · data/object.zod.ts · data/validation.zod.ts · kernel/plugin-security-advanced.zod.ts · kernel/plugin-versioning.zod.ts · migrations/registry.ts and their tests.

That PR is parked on a ruling no execution seat may make (fact 3 in #18640's decision box, per seat 1's post). So:

  • under limb B, one parked PR freezes a large share of this lane's dispatchable surface for as long as the decision box holds it;
  • under limb A, it freezes nothing and the later lander merges.

⇒ The same board, read through two lines of one document, yields two very different queues. And the divergence scales with how long a card sits in the decision box, which is exactly when a lane can least afford it.

⭐ Corroboration that this is live, not hypothetical: both sibling seats are currently operating limb B. Seat 1 (#6017) records #17518 as 「FROZEN until #18752 merges — same-file serial」, and seat 2 (#18549) keeps a 「席 1 / 他席持有面 —— ⛔ 不派入」 block listing whole files as unavailable. ⛔ Neither is misreading the charter; each picked a limb.

What this seat did, so the record is not silent

I acted on limb B (the stricter), with the charter's own escape hatch: 「认领申报文件面到区域级,拿不准就串行」. For #18406 I measured #18638's hunk starts in both shared files (view.zod.ts old lines 53 / 2241 / 2771 / 2978; component.zod.ts old lines 6 / 738 / 1591 / 1601; 12 changed lines each) against my own regions (:1754 and :3186-3400/:3735) and declared region-level disjointness in the claim. ⇒ region-level declaration is what let a p1 ruled card move at all under limb B. ⛔ I did not rely on limb A.

What is NOT being asked

⛔ I am not proposing which limb wins — that is a charter judgment for the skills seat, and picking it here would be the 「当场改文本了结」 the rule forbids. ⛔ I am also not asserting either limb is wrong.

⚠️ For whoever grades this: the cheap-looking fix — 「limb A means text-mergeability, limb B means dispatch discipline」 — does not dissolve it, because limb A names a consequence (「后落地方解冲突」) that only makes sense if the later PR is allowed to exist, which is precisely what limb B forbids.

查重词

SINGLE_CLAIM_PATHS · 同文件单跨轮硬串行 · 普通并发 后落地方解冲突 · 热文件串行队 · region-level file surface


Generated by Claude Code

Activity

  1. hotlong commented on Sep 18, 2026

    @hotlong
    Contributor

    Ruling: batch #157 item 2 · letter 甲 (SKILL.md:441 「同文件单跨轮硬串行」 is narrowed to the REGION: hard serial across rounds applies only where the claimed file surfaces overlap at region level; the same file in different regions is ordinary concurrency and the later lander resolves the conflict; :437 is unchanged, and a PR parked in the decision box holds only the regions it declared) · maintainer 「其他同意」 2026-09-18T08:10Z

    Director seat, summon #24, session_01Wj1HUjzyeiBQ8atRf1ZhaL. Presented in detail with the recommendation 甲; the maintainer agreed. Facts (this card; triage 5725445532): SINGLE_CLAIM_PATHS has one entry (.objectui-sha, pinned small at check-single-claim-paths.mjs:579), so for every other file :437 (「共享其它路径是普通并发,后落地方解冲突」) and :441 (「同文件单跨轮硬串行」) give opposite instructions. Measured cost: PR #18638 (25 packages/spec/src/** files) parked in the decision box froze a large share of the spec lane under :441; all three spec seats operate limb B and moved a p1 card only through the existing escape hatch 「认领申报文件面到区域级,拿不准就串行」. Mainstream practice: two PRs on one file are ordinary, the later one rebases; what is genuinely serialised is the same region.

    Ruling — 甲

    • SKILL.md:441 becomes: 同区域(认领申报的文件面重叠)单跨轮硬串行;同文件不同区域是普通并发,后落地方解冲突。 The 「延后不是搁置…」 half of the line stays. :437 is unchanged; SINGLE_CLAIM_PATHS stays the only whole-file single-writer set.
    • A claim declares its file surface to region level (the existing rule); a PR parked on a ruling or in the decision box holds only the regions its claim declared, never the whole file. Overlap that the claimant cannot judge is still serial (「拿不准就串行」).
    • references/core-rules.md gets the twin in the same PR if it carries the line (SKILL.md:44); ⛔ no new script, no gate: region overlap is judged by the claimant from the two claims' declared surfaces, as today.
    • ⛔ 乙 (all shared paths hard-serial) makes one parked PR freeze every file it touched; ⛔ 丙 (delete :441) leaves no serial discipline where an AI resolving a real overlap can silently drop the other side's change.

    Four-facet reading: ① one line narrower, a special case removed; ② the spec lane's throughput on 100+ cards is the direct beneficiary; ③ region-level declaration is closed and readable in the claim; ④ no mechanism added.

    Execution

    needs-user-decision → pm:queue; domain:skills, p2 stay. One-line governed change ⇒ draft PR, the approver lands it; may ride the same skills round as #18773 / #18829 / #18862 if the seat batches them.


    Generated by Claude Code

  2. self-assigned this
    on Sep 20, 2026
  3. os-steve commented on Sep 20, 2026

    @os-steve
    Collaborator

    Claim: PM loop round 1 (skills seat 2 at #19287 — R1, fable-first: maintainer direct dispatch)
    Session: session_017ETYWqMQD4qMtZzAGovWNi
    Branch: claude/issue-18891-region-level-serial
    Worktree: objectstack-issue-18891
    Domain: domain:skills
    Seat: domain:skills#2
    File surface: .claude/skills/pm-dispatch/SKILL.md :441 IN PLACE (at 4efb988: 「同文件单跨轮硬串行;延后不是搁置,被延后那一刻就把已知的坑记到该 issue 上。」 → the ruling's wording with the 「延后不是搁置…」 half kept; net 0 on 813 / 813) and .claude/skills/pm-dispatch/references/core-rules.md :105 IN PLACE (its twin 「同批独立性按文件面不相交判,⛔ 不按包;同文件硬串行,冲突交合并队列仲裁 ⛔ 不手排。」 → the region wording; net 0 on 151 / 151); :437 unchanged; ⛔ no script, no gate, no other line of either file (seat 1's SKILL.md regions :485–:486 / :608 / :362 / :99 / 候选与批次 ordering, and this seat's :128 / :214 / :242 / :496, are other cards).
    Container & model: S in size, S in judgment, mode:subagent, CONTRACT_REVIEW_TIER — dispatch-gates --tier --repo objectstack-ai/objectstack .claude/skills/pm-dispatch/SKILL.md at 4efb988: the PM dispatch skill MAIN file is MANDATORY (clause ①); the one-line exit is not taken — the wording is the ruling's, but the twin's fold and the ratchet payment are a judgment on protocol text, and the maintainer's 「后续优先派需要fable 的任务」 orders this tier for exactly this class.
    Clause-②: no
    Thread-read: 5727164406
    Ruling-ref: 5727164406 — director seat, batch #157 item 2, letter 甲, maintainer 「其他同意」 2026-09-18T08:10Z; the new :441, verbatim from the ruling: 「同区域(认领申报的文件面重叠)单跨轮硬串行;同文件不同区域是普通并发,后落地方解冲突。」, with 「The 「延后不是搁置…」 half of the line stays. :437 is unchanged; SINGLE_CLAIM_PATHS stays the only whole-file single-writer set.」 and 「references/core-rules.md gets the twin in the same PR if it carries the line」 — it does, at :105. Prior rulings read: 串行,并发,同文件,single_claim_paths,区域 → 0 hits; none; thread: 1 ruling(s) (5727164406). Maintainer direct dispatch in this seat's session, verbatim: 「后续优先派需要fable 的任务」 (2026-09-20) — this card is the first take under that order.
    Serial constraints cleared: 0 of 31 open PRs touch .claude/skills/pm-dispatch/SKILL.md (PRs — hunk ranges read this act, none at :441) and 0 touch references/core-rules.md (every open PR's file list enumerated at 2026-09-20T10:38Z; positive control on the same enumeration: scripts/pm/dispatch-gates.mjs 2); git ls-remote --heads origin | grep issue-18891 → 0 heads; no in-flight claim of either seat declares :441 or core-rules :105; H17 index (anchor #9857 swept 2026-09-20T07:48Z): 0 rendered rows name either file.

    Net-line budget (a PM figure, ⛔ not the dev's to raise): net 0 in both files (813 / 813 · 151 / 151 at 4efb988). Label on the PR: skip-changeset (.claude/** is not published).


    Generated by Claude Code

  4. os-steve commented on Sep 20, 2026

    @os-steve
    Collaborator

    os-dev-report

    {
      "issue": 18891,
      "status": "done",
      "branch": "claude/issue-18891-region-level-serial",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/19317",
      "session": "session_017ETYWqMQD4qMtZzAGovWNi",
      "premise_still_valid": true,
      "summary": "Verified on origin/main 801415a that SKILL.md :437 and :441 still carry the two opposite serial rules and core-rules :105 the twin; the newest Claim: (5749281451) names my branch. Landed ruling 甲 as the minimal rendering: SKILL.md :441 同文件→同区域 (107 B→107 B, the 「延后不是搁置…」 half byte-verbatim, :437 untouched) and core-rules :105 同文件硬串行→同区域硬串行 (119 B→119 B); net 0 in both files (813/813, 151/151), no script, no gate. The ruling's own :441 sentence is 123 B alone and 198 B with the deferral half, against the ratchet's MAX_LINE_BYTES=120 and a headroom-0 ceiling — measured red on the real gate in one-line (R1) and two-line (R2, R3) forms, no neighbour has slack, no provable duplicate exists to retire — so the 「同文件不同区域是普通并发,后落地方解冲突」 clause is delegated to :437 (which states it for every non-single-writer path) and the 区域 definition to :449 / :278 / seat-post-protocol :20; the alternative (ceiling raise 813→814 under the ratchet's maintainer exit, precedent e872ef4) is stated in the PR body for the seat. Draft PR #19317, Tier S, skip-changeset applied and read back.",
      "tests": "Union derived on head 5676515 by `node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack` (no paths; 2 committed / 0 wt / 0 untracked vs merge base 801415a): 20 commands, identical to the dispatch lead; `--ran` with exit codes: 20 derived / 20 run / 0 NOT-MEASURED / 0 UNRUN. Exits (captured before any pipe): check:pm-skill-ratchet 0 (SKILL.md 813 lines ceiling 813 headroom 0; core-rules 151/151) · check:pm-skill-id-lint 0 (27 files clean) · check:pm-governed-prose 0 · check:skill-frame-sync 0 · check:skill-frame-freshness 0 [extra] · check:pm-governed-merges 0 · check:pm-expected-skips 0 · check:pm-half-states 0 · check:doc-authoring 0 · check:nul-bytes 0 (9034 files, no control bytes) · check:agent-test-spelling 0 · check:cross-package-test-inputs 0 · check:driver-memory-census 0 · check:refd-timer-probe 0 · check:watch-hint-literal 0 · check:pm-settings-deny-roster 0 [extra, roster under .claude] · `pnpm --filter @objectstack/lint run check:doc-formula-expressions` 3 then 0 (first run PREREQUISITE NOT MET: formula/lint not built, nothing measured; built via `turbo run build --filter=@objectstack/formula --filter=@objectstack/lint` under os-verify-lock.sh, VERDICT command-exit 0, 4/4 cached; rerun 58 self-test cases + 22/9/14 examples clean) · check-closing-keyword-parity 0 · its --self-test 0 · check-comment-mask-corpus 0 (6920 files, 0 disagree) · check-governed-queue-guard --self-test 0 · check-harness-current --self-test 0 · `check-governed-merges.mjs --test` both paths 3 = GOVERNED Tier S (expected) · `dispatch-gates --tier` MANDATORY at CONTRACT_REVIEW_TIER. Ratchet readings on candidate texts (each restored to the HEAD blob, hash-verified): R0 baseline exit 0; R1 ruling+deferral one line (198 B) exit 1 'L441 (198B) over the 120-byte budget'; R2 ruling (123 B)/deferral two lines exit 1 'L441 (123B)' + '814 lines; ceiling 813'; R3 异区域 (120 B)/deferral two lines exit 1 '814 lines; ceiling 813'; R4 core-rules twin (119 B) exit 0. Control-char scan of both edited files: no hits. No ablation owed (prose only). Nothing declared to CI beyond the roster/wide/pending families dispatch-gates itself lists as outside the derived total.",
      "mcp_calls": "0 — no MCP GitHub tool used (reads and writes all via curl + GITHUB_TOKEN or label-write.mjs)",
      "api_writes": "3 REST writes + 2 git pushes — POST /repos/objectstack-ai/objectstack/pulls (1, draft #19317, HTTP 201); POST /repos/objectstack-ai/objectstack/issues/19317/labels (1, via scripts/pm/label-write.mjs, HTTP 200, read-back matches: size/xs, skip-changeset); POST /repos/objectstack-ai/objectstack/issues/18891/comments (1, this os-dev-report); git push (empty-branch probe, exit 0) and git push (commit 5676515, exit 0)",
      "files_changed": [
        ".claude/skills/pm-dispatch/SKILL.md (:441 only)",
        ".claude/skills/pm-dispatch/references/core-rules.md (:105 only)"
      ],
      "lines": {
        "SKILL.md:441": {
          "before": "- 同文件单跨轮硬串行;延后不是搁置,被延后那一刻就把已知的坑记到该 issue 上。",
          "before_bytes": 107,
          "after": "- 同区域单跨轮硬串行;延后不是搁置,被延后那一刻就把已知的坑记到该 issue 上。",
          "after_bytes": 107
        },
        "core-rules.md:105": {
          "before": "- 同批独立性按文件面不相交判,⛔ 不按包;同文件硬串行,冲突交合并队列仲裁 ⛔ 不手排。",
          "before_bytes": 119,
          "after": "- 同批独立性按文件面不相交判,⛔ 不按包;同区域硬串行,冲突交合并队列仲裁 ⛔ 不手排。",
          "after_bytes": 119
        },
        "net_lines": {
          "SKILL.md": "813 → 813 (net 0)",
          "core-rules.md": "151 → 151 (net 0)"
        },
        "union_head": "5676515 (base 801415a; origin/main moved +1 to e3b3cdd, metadata-protocol, touching neither file nor the ratchet — no merge performed)"
      },
      "deviations": [
        "Rendering differs from the ruling's verbatim :441 sentence: 「同区域(认领申报的文件面重叠)单跨轮硬串行;同文件不同区域是普通并发,后落地方解冲突。」 is 123 B (198 B with the deferral half the ruling keeps) against MAX_LINE_BYTES=120 and ceiling 813 headroom 0 — unlandable without a script edit both the ruling and the dispatch refuse; landed the one-word narrowing 同文件→同区域 and delegated the concurrency clause to :437. Named in the PR body with the alternative (ceiling raise 813→814, precedent e872ef4) for the seat.",
        "Mechanism assumption 3 refuted in two parts: the 120-byte cap is MAX_LINE_BYTES in scripts/pm/check-skill-line-ratchet.mjs (check:pm-skill-ratchet), not check:pm-governed-prose (which pins governed-surface enumerations); and the suggested-route texts measure 198 B (:441) and 152 B (core-rules :105) — neither fits; the ruling sentence alone (123 B) does not fit either. Assumptions 1, 2, 4 held.",
        "No provable duplicate line exists to retire (bigram-Jaccard scan of 627 SKILL.md bullets: top pairs J 0.59–0.35 are distinct pointer lines); the split-and-retire fallback was therefore not available.",
        "Two gates run beyond the derived 20: check:pm-settings-deny-roster (derivation flags it as a roster under .claude) and check:skill-frame-freshness (assumption 4 names it); both exit 0.",
        "check:doc-formula-expressions first exited 3 (PREREQUISITE NOT MET, not a measurement); the prescribed build ran under the verify lock and the rerun is exit 0.",
        "PR body read-back: stored body is 11516 B vs 11518 B sent — the platform trimmed one of two blank lines before the footer rule; all content lines byte-identical, footer count 1 (session-URL form), no angle brackets, first two lines intact.",
        "Label size/xs on #19317 was set by another actor (the size labeler), not by me; left as is."
      ],
      "open_questions": [
        {
          "question": "Should the seat land the one-word rendering (this PR) or the ruling's :441 sentence verbatim, which needs a SKILL.md ceiling raise 813→814 (a scripts/pm/check-skill-line-ratchet.mjs edit and net +1)?",
          "options": [
            "A: land this PR as is — 同区域 narrowing on :441, concurrency clause delegated to :437, 区域 definition to :449/:278/seat-post-protocol",
            "B: R3 rendering (ruling sentence with 不同区域→异区域, 120 B, plus the deferral half as a second line) and raise the ceiling under the ratchet's maintainer exit quoting ruling 5727164406, as e872ef4 did on 2026-09-19"
          ],
          "recommendation": "A, because it realises every operative clause of 甲 (facet ①: one line narrower), keeps the deferral half and :437 byte-verbatim, adds no script edit and no per-session line cost, and after the change the two lines contradict on no path; B buys only the explicit restatement of what :437 already says, at the price of a ceiling raise the dispatch reserved to the maintainer."
        }
      ],
      "out_of_scope_findings": [
        "noted, not filed: SKILL.md :120 (priority:p0 table row 「⛔ 不豁免同文件串行…」), core-rules :36 (its twin) and references/lanes/services.md :26 (「同文件卡跨轮硬串行」, lane-specific stricter rule) still name the serial discipline by FILE; name references, not a second definition — naming nit outside the three filing classes; 承接者: the domain:skills seat's next SKILL.md card",
        "noted, not filed: check-closing-keyword-parity prints an informational line that packages/spec/api-surface-declarations/system.txt (3,568,357 B) exceeds its 2 MiB cutoff for unregistered files; exit 0, pre-existing on origin/main; 承接者: none identified"
      ]
    }

    Generated by Claude Code

  5. os-steve commented on Sep 20, 2026

    @os-steve
    Collaborator

    ACCEPT — domain:skills#2 (session_017ETYWqMQD4qMtZzAGovWNi, seat post #19287) at 2026-09-20T11:04Z; PR #19317 (draft, head 5676515). The dev's open question is answered here: A — land the one-word narrowing; ⛔ no ceiling raise.

    Checklist, verified on GitHub (⛔ not on the report's self-description):

    • Shape: draft · base main · first line Fixes #18891 · Clause-②: no line-initial · the only closing keyword in the body is that one · no HTML comment · ## 维护者速读(草稿) present · Ruling-ref: 5727164406 in the body · labels skip-changeset + size/xs + documentation.
    • Scope: 2 files, +2 / −2, net 0 in both (SKILL.md 813 / 813, core-rules.md 151 / 151): :441 「同文件」→「同区域」 with the deferral half byte-verbatim; core-rules :105 the same word; :437 byte-unchanged. check-governed-merges --pr 19317: GOVERNED, Tier S (席内达档复核落地), size +2 / −2.
    • Contract: ## Contract review PASS posted on the PR at this head (in-seat; served tier re-read before the act = CONTRACT_REVIEW_TIER); --pair 19317 re-run after the record; ruling 甲 realised clause by clause (the record lists them).
    • Rendering: the ruling's verbatim sentence measures 123 B / 198 B against the 120 B cap on a headroom-0 file — the dev proved that red on the real gate (R1–R3) and found no retirable duplicate; A keeps every operative clause (region-level serial, ordinary concurrency via :437, region defined at :449, 「拿不准就串行」) and adds no script edit; B would only restate :437 at the price of a ratchet raise. Veto window open to the ruling's owner.
    • Gates: the dev's 20 derived families exit 0 with --ran reconciled (+ check:skill-frame-freshness, check:pm-settings-deny-roster); seat-run ratchet / id-lint / governed-prose on the head exit 0; CI on 5676515 at 2026-09-20T11:04Z: 29 check runs, all success or skipped except Type Check · consumer gates and Lint & Repo Gates in progress — landing waits for them.
    • Report: mcp_calls 0 · api_writes 3. Deviations read: assumption 3 refuted in two parts (the 120 B cap is MAX_LINE_BYTES in the ratchet, not governed-prose; the suggested route's texts do not fit) — accepted; no provable duplicate to retire — accepted.
    • Out-of-scope: two noted, not filed; the three file-named references (SKILL.md :120 · core-rules.md :36 · lanes/services.md :26) ride the next SKILL.md card this seat dispatches.

    Landing: Tier S ⇒ ready + auto-merge once every check is green; pm:dispatched comes off at MERGED (the Fixes line closes this card).


    Generated by Claude Code

  6. github-actions commented on Sep 20, 2026

    @github-actions
    Contributor

    os-closed-card-sweep — machine-findable marker for this generated comment.

    Removed the pm-loop state label(s) this closed card no longer claims: pm:dispatched.

    A state label claims work is in flight. This card is closed on a merged delivery, so the claim
    is stale; every other label is left exactly as it was found. Nothing here is a judgement about
    the card, and no verdict-bearing label is ever touched by this sweep.

    posted by half-state-patrol run 35514221788 · trigger schedule

    Generated by Claude Code

  7. added 2 commits that reference this issue on Sep 28, 2026
    547b9ab
    9120837
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