Skip to content

pm-dispatch: flip the REST curl channel from degraded fallback to DEFAULT read path for list/dedup/card reads — the GraphQL pool is the scarce bucket #11364

Description

@claude

Authorized: maintainer 2026-08-23, live PM chat — options ①②③ of the GraphQL-pool optimization discussion approved verbatim as 「1+2+3」. Filed by the skills seat (session 5213b871-5164-5bc3-8874-28b336bbcd40), self-triaged under the skills-lane exception. This card is option ①.

Measured facts (2026-08-23, platform-readings conventions)

  • Every seat account's GraphQL bucket is 5,000 points/hour; the MCP list/search family rides GraphQL entirely and unconditionally fetches Projects field values per issue (the failure string names it). Point cost scales with requested nodes, not call count.
  • The container curl channel authenticates with the App installation token: REST core 15,000/hour, an INDEPENDENT bucket that sits nearly idle (measured 14,938 remaining while the seat's GraphQL bucket was exhausted twice in one day).
  • Bonus correctness: REST list labels=a,b is true AND; MCP list_issues labels array is OR (both sides independently measured, rows already in platform-readings).

Change

Promote the documented degraded read path to the DEFAULT: list-heavy reads (lane inventories, dedup scans, card/PR reads, label read-backs) go through the curl REST channel first; MCP/GraphQL is reserved for operations with no REST twin (and for writes that need it). Surfaces:

  • references/platform-readings.md API-quota section: reword the git-first/degraded rows so the REST channel is stated as the default read order, not the fallback (ceiling 134, headroom 0 — payment by in-place compression; the sanitizer-row consolidation planned in the restructuring round's PR-2 may free lines in the same file).
  • references/dispatch-runbook.md quota rows (rate_limit pre-read etc.): same reorder.

Tier: references-only ⇒ opus build + contract-review-tier acceptance (clause ① construction split per SKILL.md model tiering).

Serial constraint

The whole pm-dispatch face is occupied by the #11086 restructuring round (PR-1 open, PR-2 pending). This card queues BEHIND #11086's PRs — do not dispatch while that round holds the hot-file chain.

Related: option ② card (dev subagent usage shaping) and option ③ card (right-sized reads + mutation pacing), filed in the same stroke.


Generated by Claude Code

Activity

  1. claude commented on Aug 23, 2026

    @claude
    ContributorAuthor

    Trio index (one ruling, three cards): #11364 = option ① REST-default reads · #11365 = option ② dev usage shaping · #11366 = option ③ right-sized reads + mutation pacing. All three queue behind the #11086 restructuring PRs on the pm-dispatch hot-file chain; ①+③ share the platform-readings quota section — fold-or-serial must be answered at claim time (five-gate test likely passes for folding ①+③).


    Generated by Claude Code

  2. claude commented on Aug 23, 2026

    @claude
    ContributorAuthor

    Trio extension: #11375 lands the CONTENT half of this card (the session-verified REST operation mapping table, suggested new file references/rest-channel.md) — this card keeps the POLICY half. Strong fold candidate: the claiming seat answers fold-or-serial for #11364+#11375(+#11366) at claim time.


    Generated by Claude Code

  3. os-zhuang commented on Aug 24, 2026

    @os-zhuang
    Contributor

    Claim: skills seat direct dispatch (maintainer 2026-08-24, live PM chat, verbatim 「一堆skills 的任务是不是应该派发处理了。」)
    Session: 5213b871-5164-5bc3-8874-28b336bbcd40
    Branch: claude/issue-11364-rest-default-read-path
    Domain: domain:skills
    FOLD — this card is primary; #11375 and #11366 fold in. Five-gate: same authorization stroke (maintainer 2026-08-23 quota rulings 「1+2+3」 + 「可走 REST 的操作清单,同意立卡」), same file family (references/platform-readings.md quota section + new references/rest-channel.md + check-skill-line-ratchet.mjs CEILINGS row), each member carries its own named acceptance criterion (policy flip visible in the read-order text / the mapping table landed verbatim with provenance dates / the perPage+pacing rows present), no cross-lane surface, no gate weakened.
    File surface: .claude/skills/pm-dispatch/references/platform-readings.md · new .claude/skills/pm-dispatch/references/rest-channel.md · scripts/pm/check-skill-line-ratchet.mjs (CEILINGS data row for the new file ONLY — ⛔ no mechanism change; #11106 owns the bytes-vs-lines question and is deliberately NOT folded: different deliverable class) · pointer edits in SKILL.md only if an existing line must repoint (stop on breach; explain in report)
    Clause-②: governed surface (.claude/**) — draft PR, human merge; references-only tier per #11375's own body: opus build + contract-review-tier acceptance by this seat.
    Serial constraints cleared: pm-dispatch hot-file chain free (#11086 round closed); no open PR touches these references (checked this hour via the open-PR sweep); #11106 (ratchet mechanism) and #11365 (os-dev.md surface) deliberately serialized BEHIND this fold.
    Also riding per the recorded #11621 fold rider (maintainer 「动手吧」, scope addendum at #11375 comment 5394097785): the merged_by=enqueuing-actor row, the queue-routing distinguishing reading, and the required-checks rename-coupling row (#11621 comment 5394267839).


    Generated by Claude Code

  4. claude commented on Aug 24, 2026

    @claude
    ContributorAuthor
    {
      "issue": 11364,
      "status": "done",
      "branch": "claude/issue-11364-rest-default-read-path",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/11749",
      "premise_still_valid": true,
      "summary": "All three folded cards landed in one draft PR on the pm-dispatch reference surface. #11364: platform-readings.md's API-quota section now states the read order as git then REST then MCP/GraphQL, with the container curl channel (App installation token, REST core 15,000/hr, independent bucket) as the DEFAULT path for list/dedup/card/PR/label reads and GraphQL reserved for the operations with no REST twin; every measured fact and provenance date already in the file is preserved, and the downstream wording that still called REST a fallback was brought in line in three places. #11375: the mapping table landed as a new 46-line references/rest-channel.md with per-row 2026-08-23 provenance, plus the 2026-08-24 addendum rows. #11366: the two quota rows (right-size perPage; pace mutations ~1s apart) were paid for in place. TWO PREMISE CORRECTIONS, both declared in the PR body rather than papered over. (1) The dispatched row 'repo-wide event=merge_group count, zero on an enforced queue = empty required set' did NOT land as written: that inference was falsified on #11621 itself 29 minutes after the addendum was authored (0 to 8 at 2026-08-24T11:04:47Z), and I re-measured 224 this session before writing the row, per that correction's own instruction to re-measure rather than inherit. What landed is the surviving durable form - the count answers 'has it happened yet', not 'does the mechanism exist'; zero is a weak prior; the decisive reading is the attempted action - with the measured history kept as the row's tombstone. Readings (a) direct-merge 405 and (b) added_to_merge_queue survive untouched, and a third attempted-action reading (update-branch refusal on a queued PR) was added. (2) The card's 'the only four' non-migratable operations are FIVE: platform-readings.md already carries a 2026-08-24 measured row that issue transfer has no REST route, so landing 'only four' verbatim would have shipped a contradiction with its sibling file; transfer is listed as item 5, additive, no row dropped. Ceiling assumption held and improved: platform-readings.md was indeed at 133/133; the consolidation paid for both new rows in place with three lines to spare, so its ceiling was LOWERED 133 to 130 (shrinking needs no ruling) rather than held. New CEILINGS row for rest-channel.md at its landed 46, headroom 0, data rows only - no mechanism change. One-home-each verified per fact. Also checked and NOT changed: dispatch-runbook.md, which #11364's body asked to reorder but which carries no read-order policy at all (its single quota row is a pre-dispatch batch-sizing rule) - editing it would have been a no-op.",
      "tests": "Gate families derived from the real changeset, not from the dispatch list: `node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack` with no path args, exit 0, provenance line 'gate list derived from the tree of objectstack-ai/objectstack at commit 41b3060d' and '--repo checked against this checkout's origin remote - it holds'; 3 paths, 12 matched families. All 12 green at final HEAD 41b3060d (tree clean, 0 modified paths), exit codes captured by redirect-then-capture, never through a pipe. Quoting each gate's own verdict line: check:pm-skill-ratchet -> 'platform-readings.md is 130 lines (ceiling 130; headroom 0)' + 'rest-channel.md is 46 lines (ceiling 46; headroom 0)' + 'self-test: 20 cases pass'; check:pm-skill-id-lint -> '22 file(s) clean (pattern /#[0-9]{3,}/g)'; check:doc-authoring -> 'doc authoring guard: 389 files clean - no bare metadata literals'; check:pm-governed-merges -> 'self-test: 129 assertions'; check:skill-frame-sync -> '4 copies of the decision frame are structurally isomorphic across 3 files'; check:doc-formula-expressions -> '22 record-scoped formula example(s) across 421 files / 1449 TS blocks judged clean' (needed pnpm install + the lint dependency closure + the lint package's own dist, all three routed through scripts/pm/os-verify-lock.sh - VERDICT lines: 'command-exit 0 held the lock 6s waited 141s', 'command-exit 0 held the lock 132s waited 0s', 'command-exit 0 held the lock 10s waited 284s'); check:nul-bytes -> 'OK (scanned 6554 text file(s); no raw ASCII control bytes)'; check:agent-test-spelling, check:cross-package-test-inputs, check:entry-guard, check:parse-guard, check:pnpm-filter-targets and scripts/check-cross-package-test-inputs.mjs all exit 0. BEYOND the derived list: the derivation warns that 3 artifact-roster gates sit in a directory one of my paths is in, where a 'silent' verdict 'reads as a clearance and is not' - so check:pm-dispatch-gates ('dispatch-gates self-test: 579 cases pass') and check:pm-governed-prose ('2 instruction surface(s) name all 5 registered governed surfaces') were RUN rather than inferred; both exit 0. Own control-byte scan of the three touched files: zero hits. No ablation in this card (documentation surface, no code path to mutate). No changeset by design; skip-changeset applied additively via POST .../issues/11749/labels and READ BACK after the bots settled: ['documentation','size/s','skip-changeset'] - the size-labeler's group PUT had already landed and did not wipe the additive write.",
      "open_questions": [
        {
          "question": "The merge_group zero-count row landed in corrected form rather than verbatim, because the inference it asserts was falsified on the source card before I picked it up (0 to 8 at 2026-08-24T11:04:47Z; re-measured 224 this session). PM should confirm this substitution is what was wanted, since the acceptance criterion said the addendum rows land as written.",
          "options": [
            "A - keep the corrected form now landed: the count is a weak prior, the decisive reading is the attempted action, with the 0/8/224 history as the row's own tombstone",
            "B - land the original wording verbatim ('zero = empty required set') as the addendum specified",
            "C - drop reading (c) entirely and keep only the two attempted-action readings"
          ],
          "recommendation": "A. B writes a known-false inference into doctrine that the source card itself retracted, and the retraction's stated lesson is precisely that a count is not a mechanism reading - so B would enshrine the error the card exists to record. C loses the useful negative: the count reading is worth keeping as a documented dead end, because the next seat will otherwise re-derive it. A is also the only option consistent with the same correction's instruction to re-measure rather than inherit a count."
        },
        {
          "question": "GitHub appended a SECOND signature footer to the PR body on creation (a '---' separator plus a duplicate of the session-URL footer I wrote; body read back byte-for-byte otherwise intact, nothing truncated). Not filed as a card: there is no repo surface to fix, and it is a write-side platform reading belonging to the very fact sheet family this seat owns. PM decides whether it earns a platform-readings row.",
          "options": [
            "A - PM adds a write-side row: the create path appends its own signature footer, so a body that already carries one lands with two",
            "B - leave it unrecorded as cosmetic",
            "C - file it as a finding-labelled card for a later measured pass (one observation is a thin basis for a doctrine row)"
          ],
          "recommendation": "C if it is to be recorded at all. One observation on one create call does not meet this file's own evidence bar - the boundary would have to state whether it fires on every create, only when a footer is already present, and whether edits duplicate it again. I left the duplicate in place rather than editing it out, since editing a 7KB body to fix a cosmetic blemish spends a measured sanitizer risk for nothing."
        }
      ],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  5. os-zhuang commented on Aug 24, 2026

    @os-zhuang
    Contributor

    ACCEPT (fold: #11364 + #11375 + #11366) — reviewer of record: skills seat (dispatching seat, references-only tier acceptance per #11375's own body), session 5213b871-5164-5bc3-8874-28b336bbcd40. PR: #11749 (draft, head 41b3060d).

    Verified against the landed files, not the report's prose: the read-order policy flip is in place with every measured fact and provenance date preserved and the three downstream "fallback" wordings brought in line; rest-channel.md landed at 46/46 with per-row provenance, the five-item non-migratable list, the queue-routing section carrying the full 2026-08-24 doctrine (merged_by, attempted-action readings ×3, the rename-coupling row with the maintainer's as-configured 9 and his verbatim 「我觉得够了」, the push-only exclusion rule); the #11366 rows paid for in place; platform-readings.md ceiling lowered 133 → 130 — the consolidation bought both new rows and three lines of shrink. One-home-each verified; dispatch-runbook.md correctly measured as a no-op rather than edited to satisfy the card's wording. 12 derived + 2 explicitly-run gate families green at the head, ratchet lines quoted.

    Rulings on the two open questions (dispatching seat's discretion, recorded):

    1. A — the corrected form stands. The acceptance criterion's "as written" was this seat's own phrasing, and its intent was the FACTS; the zero-count inference was falsified on the source card 29 minutes after the addendum was authored (0→8 at 11:04Z, re-measured 224 before landing), so landing B would enshrine an inference its own source retracted, and C would delete the documented dead end the next seat will otherwise re-derive. The tombstone form — count answers "has it happened yet", the decisive reading is the attempted action, history quoted — is exactly this file's evidence discipline, and the added third attempted-action reading (update-branch refusal on a queued PR) is a genuine improvement.
    2. Routed to the existing card, not a new one: the duplicate-footer-on-create observation joins [finding] A PR-body PATCH APPENDS a fresh bare attribution footer on every edit instead of rewriting it — AGENTS.md's rule records that the session form survives, but not that footers accrete #11273 as a measurement comment (that card already accretes the PATCH-append and comment-inject measurements from this afternoon; the create path is its fourth write-path data point). One observation stays below this file's doctrine bar until it recurs — correctly left out of the fact sheet.

    Clause-②: no accept/reject movement (references prose + a ratchet data row). Landing: .claude/** governed — PR stays draft, human merge. On merge, #11364/#11375/#11366 close via the Fixes lines and #11621 closes by hand per its recorded condition.


    Generated by Claude Code

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