Skip to content

Skills optimization flight — skills/objectstack-pm-dispatch: RESTRUCTURE (≈ −4,255 tok, −29%) — monorepo-only lore inert in a customer project, the report JSON printed twice, and four drifts from the internal dev contract (report double-channel, premise_still_valid, the stash ban, the Session: line) #14300

Closed

Description

@os-litant

Member card of the skills catalog optimization program #14292 (maintainer mandate 2026-09-02, verbatim: 「审核所有的 skills,进行全面的优化。」). Filed by the skills lane seat (session session_01LraLgQVGq8egUwfYZpbYt1). Read-only audit at objectstack origin/main a59f78d. The full findings table is the audit record: the dev posts it verbatim as the first comment on this card at claim time (seat scratchpad audit/objectstack-pm-dispatch/findings.md).

⚠️ Fence: this is the PUBLISHED process skill. .claude/skills/pm-dispatch/** and .claude/agents/os-dev.md are a separate corpus under audit #13597 — read them only as the comparison oracle, ⛔ never edit them in this flight, ⛔ never in the same PR.

Audit summary

One file, SKILL.md, 1,086 lines, 14,549 tokens, headroom 0 — 7.7% of the bundle, the 2nd-largest published SKILL.md, 1.75× the other process skill. Teaches no ObjectStack surface (0 TypeScript fences). Customer decision points covered: 5 (label state machine; safe claim; dispatch with a binding template; review-against-GitHub and land; escalate vs decide) ≈ 2,900 tokens per decision. Customer-inert or duplicated text measured at 4,445 tokens (30.6%) before any restructure. Verdict RESTRUCTURE: zero progressive disclosure, zero evals, two blocks duplicated inside the file (the report JSON at 869-882 / 894-908; the sanitizer trap at 346-365 / 884-888), a 2,376-token verbatim paste-block paid in every session, and a second job (upstream reporting) restating objectstack-platform :59-70.

Top findings

id span proposal delta
PMD-B-01 SKILL.md:729-891, 916-986 MOVE-TO rules/dev-template.md (DEFERRED, #14296 items 1+4) −3,258 from entry
PMD-C-01 SKILL.md:916-986 vs objectstack-platform :59-70 DELETE the upstream-reporting job; keep ≤250-token residue pointing at objectstack-platform −882
PMD-E-05 SKILL.md:987-1033 REWRITE-AS-CONSTRUCT — shard registry conclusion is one line for a single-repo project −580
PMD-E-02 SKILL.md:416-452 RETIRE-SURFACE — "N independent implementations" is the platform's compiler problem, not an app's −565
PMD-E-03 SKILL.md:591-618 DELETE two non-escalation bullets (ADR-0049 "arm"/governance shapes) −508
PMD-D-01 SKILL.md:192-217 REWRITE-AS-CONSTRUCT — sweep rationale, cross-seat producers, anecdote −380
PMD-D-02 SKILL.md:507-528 REWRITE-AS-CONSTRUCT — the 8-card baseline printed and disclaimed −290
PMD-D-04 SKILL.md:654-706 vs 826-857 REWRITE-AS-CONSTRUCT — four-axis frame stated twice −450 (MED)
PMD-E-04 SKILL.md:769-786 REWRITE-AS-CONSTRUCT — design spec of a lock script the customer does not have −250
PMD-B-03 SKILL.md:346-357 DELETE sanitizer specimens; rules at 359-365 carry the decision −200
PMD-B-02 SKILL.md:894-908 DELETE — the same report JSON printed twice −115
PMD-D-03 SKILL.md:483-495 DELETE check-in anecdote; keep the two rules at 496-506 −170 (MED)
PMD-A-01 SKILL.md:10-14 DELETE the "report a platform bug" trigger from the description −30
PMD-G-01 SKILL.md:557-559 vs 1051 DELETE — "the PM's own tooling PRs" contradicts "The PM writes no files" −25

Drift vs the internal contract (sync in this flight, paid by the deletions above)

  • PMD-F-01 :455-457 "a lossless channel" — the internal contract requires the report TWICE, GitHub first, in both modes, first line the literal plaintext os-dev-report (⛔ not an HTML comment), because a container restart killed three devs mid-final-message. Also a falsehood: :456-457 is contradicted 17 lines later at :474-475.
  • PMD-F-02 the template never asks the dev to re-check the issue's premises and the report has no premise_still_valid; internally a no-PR report with premise_still_valid: false is a first-class deliverable.
  • PMD-F-03 grep -c stash = 0, yet the template ships the exact topology the trap lives in (worktree-first + "parallel agents share ONE container"); both repos carry the ban at Prime-Directive level.
  • PMD-F-04/F-05 the claim shape omits the Session: line (branch-only identity under-determines in cloud mode); :367-369 asserts devs push early while the template pushes fourth — the reclaim predicate can fire against a live agent. Make the template push the empty branch first.
  • Falsehood :1036-1039 "the template enforces … a container-wide verification lock" — the template delegates the mechanism to the host project; should read requires.

Flight scope

IMPLEMENT (same-file, shrink-only): all rows above except PMD-B-01 and PMD-H-01; the four drift syncs (paid by PMD-E-02 / PMD-E-04 / PMD-B-02 as the auditor sized them); PMD-C-01 as delete + ≤250-token residue pointing at objectstack-platform SKILL.md:59-70; the description trigger edit (regenerate skills/README.md).

DEFER (pending #14296 items 1 and 4): PMD-B-01 (split the template into rules/dev-template.md), PMD-H-01 (evals).

Flight constraints (binding)

  • ONE draft PR, first line Fixes #<this card>; governed ⇒ stays draft; review requests are the seat's step.
  • Token ratchet: SKILL.md may not grow; additions paid by deletions in the same file; ⛔ re-wrap is not payment; ⛔ no ceiling raise; ⛔ no new files; ⛔ do not touch the ratchet script.
  • ⛔ Never edit another package's files; frontmatter edits ⇒ regenerate skills/README.md (pnpm --filter @objectstack/spec gen:skill-docs).
  • Gates: node scripts/check-skills-token-ratchet.mjs, pnpm check:skill-compatibility, pnpm check:skill-identifier-liveness, plus node scripts/pm/dispatch-gates.mjs --commands <changed paths>; record the head sha.
  • PR body: per-item 落点 | before | after list keyed by finding id; token delta; Clause-②: no (no contract surface).

Refs: #14292 · #14296 · #13597 (the internal corpus, separate audit).

Activity

  1. self-assigned this
    on Sep 2, 2026
  2. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    Claim: PM loop round 2
    Session: session_01LraLgQVGq8egUwfYZpbYt1
    Branch: claude/issue-14300-skills-pm-dispatch-optimization
    Worktree: objectstack-issue-14300
    Domain: domain:skills
    File surface: skills/objectstack-pm-dispatch/SKILL.md ONLY (shrink-only; no file deleted ⇒ ⛔ no edit to scripts/check-skills-token-ratchet.mjs); skills/README.md + content/docs/ai/skills-reference.mdx regenerated only because the drift gate demands it after the PMD-A-01 description edit; ⛔ .claude/skills/pm-dispatch/** and .claude/agents/os-dev.md are the comparison ORACLE, read-only, never in this PR; ⛔ no other package (stop on breach; explain in the report)
    Container & model: M (one 14,549-token file, structural diet + five drift syncs against the internal contract), mode:subagent, model: fable — node scripts/pm/dispatch-gates.mjs --tier skills/objectstack-pm-dispatch/SKILL.md reads MANDATORY claude-fable-5 (clause ①, 2026-08-20 narrowing: the published PM skill carries two enforced copies of the decision frame and ships verbatim to third-party projects); no exit applies — this is not a one-line mechanical edit and quota is available
    Clause-②: no — no contract surface (0 TypeScript fences, no accept/reject semantics); no needs:contract-review; the skill-face review is the seat's in-seat review at tier
    Serial constraints cleared: the two frame-sync copies in this file (:643 "every option on the four fixed axes below." and :832 "Analyze every option on four fixed axes:") are gate-pinned against .claude/skills/pm-dispatch/SKILL.md and .claude/agents/os-dev.md — both copies STAY and neither block is edited, so PMD-D-04 is EXCLUDED from this flight (its only remedy removes a copy the gate requires); .claude/skills/pm-dispatch/SKILL.md (PR #14230) and .claude/agents/os-dev.md (PR #14229) are held by unmerged PRs — this flight syncs the five drifts to the contract text on origin/main and lists #14229's pending deltas as a follow-up sync, never edits them; PMD-C-01's residue points at objectstack-platform's "The App / Platform Boundary" section BY HEADING (the platform flight #14351 moved it and keeps it); no open PR touches skills/objectstack-pm-dispatch/**; in flight alongside #14299 (platform, patch round) and #14302 (query) on disjoint directories

    Decision re-read: no maintainer ruling on this card; binding inputs = the mandate, the value gate, the ratchet discipline, and #14296 (items 1 + 4 defer PMD-B-01; item 2 defers PMD-H-01). Landing form: first line Part of #14300 (the deferred split and evals keep the card open).


    Generated by Claude Code

  3. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    Claim: dev seat, dispatched by PM loop round 2 (mode:subagent)
    Session: session_01LraLgQVGq8egUwfYZpbYt1
    Branch: claude/issue-14300-skills-pm-dispatch-optimization (empty branch pushed first as the write-route probe: exit 0)
    Worktree: objectstack-issue-14300 (base 96b627d1)
    File surface: skills/objectstack-pm-dispatch/SKILL.md only, plus skills/README.md and content/docs/ai/skills-reference.mdx as generator output after the PMD-A-01 description edit. Assignee untouched. .claude/skills/pm-dispatch/** and .claude/agents/os-dev.md read as the comparison oracle only.

    Next comment on this card is the audit record (audit/objectstack-pm-dispatch/findings.md, first line audit-record), posted with a transliteration key for the angle-bracket-shaped fragments.


    Generated by Claude Code

  4. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    audit-record — skills/objectstack-pm-dispatch (read-only audit at a59f78d)

    Posted by the dev seat at claim time; this is the finding-by-finding spec for the flight on #14300.

    Transliteration key (deviation from a byte-verbatim post, disclosed). The GitHub comment sanitizer is measured to eat angle-bracket / HTML-comment-shaped fragments, and this seat has no raw-REST read path to verify byte survival (repo-scoped REST returns 403 for this session). The 18 angle-bracket fragments on 13 lines of the file are therefore spelled without angle brackets, as the platform flight did on #14299. Nothing else is changed — every finding id, span, evidence, proposal, delta, gate verdict, confidence and human-floor flag is byte-identical to audit/objectstack-pm-dispatch/findings.md:

    on disk in this comment
    HTML comment wrapping os:check os:check HTML-comment markers
    HTML comment wrapping BEGIN GENERATED: skills … the BEGIN GENERATED: skills HTML-comment marker
    HTML comment wrapping dev-report the dev-report HTML-comment marker
    angle-n N
    angle-url or null URL or null
    angle-path PATH
    angle-domain DOMAIN
    angle-repo dash issue dash angle-n REPO-issue-N
    claude/issue dash angle-n dash angle-slug claude/issue-N-SLUG
    session underscore angle-id session_ID
    angle-branch BRANCH
    angle-upstream hash angle-n UPSTREAM#N

    Audit — skills/objectstack-pm-dispatch (published, read-only)

    Pinned ref: objectstack origin/main = a59f78d. Verified the working file is byte-identical
    to the pinned blob (git show a59f78d:skills/objectstack-pm-dispatch/SKILL.md | md5sum ==
    md5sum of the checkout copy = 3948bdb8c73dba124ebc2e61a832d1db). All spans below are at
    that ref. Local HEAD is a39b02a, but git diff a59f78d HEAD -- skills/ is empty.

    Package facts (measured)

    Fact Value Source
    Files 1 (SKILL.md) — no rules/, no references/, no contracts/, no evals/ ls skills/objectstack-pm-dispatch/
    Tokens 14,549 (ceiling 14,549; headroom 0) node scripts/check-skills-token-ratchet.mjs
    Bundle share 14,549 / 187,854 = 7.7 % same run, "bundle total" row
    Rank 2nd largest SKILL.md (after objectstack-ui 25,441); larger than objectstack-data 13,892 and objectstack-platform 12,984 same run
    vs sibling process skill 1.75× objectstack-upgrade (8,333) same run
    Fenced blocks 16 total: 3 bash, 2 json, 1 text, rest bare grep -nE '^{3,4}'`
    TypeScript fences 0; os:check HTML-comment markers 0 same grep; gate rule read from packages/spec/scripts/check-skill-examples.ts:18-23
    evals/ absent; 8 of 11 published packages have one ls -d skills/*/evals

    Because the package contains zero ts/tsx fences, dimension E's type-check sweep has no
    surface: nothing in it can be reached by check-skill-examples.ts, and nothing needs a
    marker. Recorded as a measured negative, not a finding.

    Section budget (measured, ceil(bytes/4))

    Section Span Tokens
    frontmatter 1-29 366
    intro 30-49 224
    Quickstart 50-78 216
    Configuration 79-117 521
    Arguments 118-133 158
    State model 134-170 454
    §0 Backlog sweep 171-237 980
    §1 Fetch candidates 238-261 249
    §2 Triage 262-306 688
    §3 Select the batch 307-319 164
    §4 Claim 320-376 761
    §5 Dispatch 377-415 381
    — One semantics, N implementations 416-452 565
    — Dispatch backends 453-470 244
    §6 Collect 471-528 902
    §7 Review each report 529-564 491
    §8 Escalate 565-647 1324
    — Four-axis frame 648-706 925
    §9 Round report 707-715 79
    Stop conditions 716-728 99
    Developer-agent template 729-891 2376
    Report contract 892-915 194
    Upstream reporting 916-986 882
    Multiple PMs / shards 987-1033 656
    Resource discipline (PM) 1034-1048 158
    Guardrails 1049-1065 196
    Adapting this loop 1066-1086 307

    The customer's five real decision points

    Derived from what a single-repo ObjectStack app project with no internal tooling can act
    on, not from the doc's own headings:

    1. Provision the three labels and read them as a state machine (134-170, 151-159).
    2. Claim an issue so two agents cannot collide (320-343, 371-375).
    3. Compose a dispatch prompt with a binding operating template (377-415, 729-891).
    4. Review the returned PR against GitHub and land it (529-564).
    5. Decide what to escalate versus decide under a veto window (565-595, 648-706).

    Everything measured below as monorepo lore changes none of these five.


    Findings

    PMD-A-01 · TRIGGER PRECISION · skills/objectstack-pm-dispatch/SKILL.md:10-14

    Evidence. The frontmatter advertises a second, unrelated job: "Ships the developer-agent
    operating template … and the upstream-reporting procedure for platform defects an app
    project finds
    . Use when asked to … or to report a platform bug found while building an
    app.
    " A customer agent that trips over a platform defect while authoring metadata loads
    14,549 tokens to reach the 882-token §"Upstream reporting" (916-986), of which ~600 restates
    skills/objectstack-platform/SKILL.md:59-70 (see PMD-C-01). skills/README.md's index row is
    generated from this same description (the BEGIN GENERATED: skills HTML-comment marker, README:29-45), so
    the mis-routing is mirrored into the catalog automatically.
    Proposal. MOVE-TO skills/objectstack-platform (the ~250 tokens of unique procedure) and
    delete both the "Ships … upstream-reporting procedure" clause and the "or to report a platform
    bug" trigger; regenerate README via pnpm --filter @objectstack/spec gen:skill-docs.
    Delta. −30 (frontmatter only; the section itself is counted in PMD-C-01).
    Gate. ① Yes — it decides which package a customer loads for a bug report. ② Yes, deletion.
    ③ N/A (frontmatter). Confidence HIGH. Human floor YES (changes a published trigger).

    PMD-A-02 · TRIGGER PRECISION · skills/README.md:94-110

    Evidence. "Cross-skill routing" carries 4 bullets, all pairs of domain skills
    (data/automation, automation/ui, formula, platform/data). Nothing routes between the two
    process skills, and nothing tells an app author when a process skill applies at all. Both
    process packages sit in the generated index (README:44-45) with no disambiguation, and their
    descriptions overlap on the word "process" and on escalation-to-owner language
    (objectstack-upgrade frontmatter: "work the semantic residue … to a decision with the
    project's owner").
    Proposal. ADD one routing bullet ("Delivery loop vs protocol upgrade …"). Payment must
    come from README itself; the generated index block (29-45) is generator-owned and cannot pay.
    Delta. +25 unpaid — flagged, not recommended without a maintainer ruling.
    Gate. ① Yes. ② No. ③ Bullet in an existing list. Confidence MED. Human floor no.

    PMD-B-01 · STRUCTURE · whole file (1-1086)

    Evidence. One 14,549-token file with no progressive disclosure at all. Two blocks are
    needed only at a specific moment yet are paid in every session: the developer-agent template
    (729-891, 2,376 tok) is a verbatim paste-block consumed only when a dispatch is actually
    composed, and §"Upstream reporting" (916-986, 882 tok) is a different job entirely.
    skills/README.md:57-64 lists rules/ as an available optional directory for any skill; the
    "process skill carries SKILL.md alone" sentence (README:66-69) is scoped to references/
    ("gen:skill-refs only visits skills listed in its SKILL_MAP"), so it does not block a
    rules/ split.
    Proposal. MOVE-TO rules/dev-template.md (the paste-block, linked from §5) and — with
    PMD-C-01 — out of the package for upstream reporting.
    Delta. −3,258 from the always-loaded entry file (a new rules/ file takes its own ceiling).
    Gate. ① Yes — it decides what a PM pays before it has dispatched anything. ② Partly
    (relocation, not deletion). ③ Yes, the template stays a construct. Confidence HIGH.
    Human floor YES (restructures files; new ratchet ceiling).

    PMD-B-02 · STRUCTURE · SKILL.md:869-882 and 894-908

    Evidence. The same 8-key report schema is printed twice, 12 lines apart, differing only in
    placeholder-vs-literal values ("issue": N vs "issue": 123; "pr": "URL or null" vs
    "pr": "https://github.com/acme/hotcrm/pull/456 | null"). Only 909-914 adds new rules
    ("open_questions must be non-empty when status is needs_decision"; "out_of_scope_findings
    should already be filed …").
    Proposal. DELETE the fence at 894-908; keep 909-914 as a note under the template.
    Delta. −115. Gate. ① No decision is changed by the second copy. ② Yes. ③ Construct
    preserved. Confidence HIGH. Human floor no.

    PMD-B-03 · DENSITY · SKILL.md:346-357 (232 tok), duplicated in substance at 884-888 (73 tok)

    Evidence. The sanitizer trap is taught twice. 346-357 spends 12 lines on measured
    specimens — "the dev-report HTML-comment marker came back as nothing at all, expected N to be 19 came
    back as expected to be 19, git log -- PATH came back as git log -- " — plus three
    lines on why this differs from step 0's truncation shape. The actionable rules are 359-365
    ("Write literal angle brackets as HTML entities … read it back"), and 884-888 restates the
    whole trap inside the pasted template for the dev.
    Proposal. DELETE 346-357, replacing with one clause on 359 ("measured: code spans are not
    protection — an HTML comment came back empty").
    Delta. −200. Gate. ① No — the rule at 359-365 already changes the decision; the
    specimens change nothing. ② Yes. ③ Rules survive as a construct. Confidence HIGH.
    Human floor no.

    PMD-C-01 · CROSS-PACKAGE REDUNDANCY · SKILL.md:916-986 (882 tok) vs skills/objectstack-platform/SKILL.md:59-70

    Evidence — both locations quoted.
    pm-dispatch:918-924 — "The temptation is to make the app tolerate it and move on. Do not. A
    workaround in the app hides the defect from the people who can fix it, ships a second source of
    truth to every future author, and outlives the upstream fix by years."
    platform:59-61 — "Business features belong in the app; capability belongs in the platform.
    A missing default, a wrong diagnostic, a shape the spec refuses — the fix is upstream. Raise it
    there; do not compensate for it here."
    pm-dispatch:974-985 — park via Blocked-by: or "pin the current upstream version with the
    unblock condition written down … A pin with no recorded unblock condition is a workaround with
    better manners"; "'We worked around it' is never a resolution".
    platform:62-69 — "A platform defect means waiting for the platform fix. No defensive
    coding, no shape tolerance … Record the block against the platform issue so it is
    machine-visible; before resuming, confirm the version you pin carries the fix (merged
    upstream ≠ present on your pin) and re-run the defect's own reproduction."
    Which anchor survives. objectstack-platform — it is the app-bootstrap package every app
    project loads to stand the project up, it already carries the doctrine, and it is where an
    agent already is when it hits the defect. The genuinely unique residue in pm-dispatch is ~250
    tokens: derive the upstream repo from the dependency's package.json repository (925-930);
    minimal repro + pinned versions + cite the contract (944-958); file as a guest — never apply
    the upstream's queue labels, never assign, never add to their board
    (959-971).
    Proposal. MOVE-TO skills/objectstack-platform (~250 tok of residue), DELETE the rest.
    Delta. −882 here (+~250 there).
    Gate. ① Yes — it decides which package owns the doctrine. ② Yes, mostly deletion. ③ The
    survivor is a 3-bullet checklist. Confidence HIGH on the overlap, MED on the exact split.
    Human floor YES (moves published capability text across packages).

    PMD-D-01 · DENSITY / MONOREPO · SKILL.md:192-217 (433 tok)

    Evidence. "Why the sweep is a disjunction and not one 'unlabeled' filter." followed by
    two "standing producers" that exist only here: "Cross-seat transfer tickets (the handing-off
    side applies the queue label as part of the transfer) and tickets filed mechanically by a
    steward automation both carry pm:queue on arrival, while a single-producer discipline for
    classification labels
    forbids those same producers from applying one", plus the anecdote "a
    project that had published exactly that rule hours earlier still produced such a card the same
    day". "Seat", "steward automation", "lane" (180) and "protocol posts" (215) are used as defined
    terms and are defined nowhere in the package; an app project has none of them.
    Proposal. REWRITE-AS-CONSTRUCT — keep the 3-item disjunct list (179-191), fold the ⚠️
    scoping caution (209-217) to one line and the ⏳ updated_at floor (219-225) to one line, drop
    the producers and the anecdote.
    Delta. −380. Gate. ① No — the customer either runs the predicate or (per the ⚠️ at
    209-214) must not; the rationale changes neither. ② Yes. ③ Yes, list survives.
    Confidence HIGH. Human floor no.

    PMD-D-02 · DENSITY · SKILL.md:507-528 (357 tok)

    Evidence. The section states the number is not transferable and then prints it anyway:
    "Two same-day samples from this repo's loop show why no single number can be inherited: four
    text-only documentation cards landed at 93 / 96 / ~95 / ~110 min, while four mixed cards from
    the same day spanned ~64 min to ~2 h 50 min (the two long ones waiting on CI). Eight cards, one
    day, one toolchain …". The decision-changing content is the rule at 507-512 + 516-518.
    Proposal. REWRITE-AS-CONSTRUCT — "A silence threshold is a collection boundary, not a
    verdict of death. Before concluding a dispatched agent is dead, require one of: a direct status
    query showing it dead, the host reporting the session stopped, or silence past a completion
    baseline you measured in your own project."
    Delta. −290. Gate. ① No — the data is explicitly disclaimed as non-inheritable.
    ② Yes. ③ Yes. Confidence HIGH. Human floor no.

    PMD-D-03 · DENSITY · SKILL.md:483-495 (of the 404-tok block 483-506)

    Evidence. "Measured three times in one day on this loop: a scheduled message still
    delivered after its timer had been cancelled
    , carrying text two rounds out of date. One of
    them read 'no branch and no report ⇒ judge the agent unreliable and dispatch a fresh one'; by
    delivery time that agent had opened a PR which was already reviewed and accepted …". The two
    rules that follow (496-506: open every check-in with "idempotent — re-read the state before
    acting"; state criteria never conclusions; "cancellation is not a guarantee of non-delivery")
    are general and genuinely decision-changing, and already carry the surprising fact.
    Proposal. DELETE 483-495; keep 496-506 intact.
    Delta. −170. Gate. ① No — 496-506 already changes the decision. ② Yes. ③ The two rules
    are the construct. Confidence MED (the anecdote is the only place the cancelled-timer fact
    is shown; it is however stated at 505-506). Human floor no.

    PMD-D-04 · DENSITY · SKILL.md:654-706 (861 tok) vs 826-857 (574 tok)

    Evidence. The four-axis frame is stated twice in one file, in near-identical wording. PM-side
    axis ④: "Startup scope discipline. Do not grow the declared surface while the core is still
    forming. 'We already shipped it' earns nothing: a shipped-but-unconsumed capability gets no
    sunk-cost exemption
    ." Template copy: "Startup scope discipline — do not grow the declared
    surface: a shipped-but-unconsumed capability gets no sunk-cost exemption." The weight and
    ranking rules are likewise duplicated ("Axis ② carries the highest weight — at least 50%",
    697-706, vs "Long-term soundness carries the highest weight, at least 50%", 853-857). The
    template copy must stay verbatim (it is pasted into a zero-context prompt).
    Proposal. REWRITE-AS-CONSTRUCT the PM-side copy as a 4-row table (axis · question ·
    evidence standard) plus the ranking/weight rule, pointing at the template block for full wording.
    Delta. −450. Gate. ① No new decision from the second full prose copy. ② Partly. ③ Yes —
    a table replaces prose. Confidence MED. Human floor no (no semantics removed).

    PMD-E-01 · MONOREPO ASSUMPTION · SKILL.md:179-217

    Evidence. Disjuncts 2 and 3 are keyed on a "classification label" — "none of the labels
    your project reads as 'already routed' (area, component, owning team, lane)". This is the
    monorepo's domain:* lane vocabulary (.claude/skills/pm-dispatch/SKILL.md:36 runs seats by
    DOMAIN lane). The package's own ⚠️ at 209-214 makes the disjuncts self-disabling where
    the label does not exist: "Where it does not exist, its absence is universal, so the disjunct
    matches every open queue card in that repository and the sweep becomes its own noise source."
    A customer app project has no classification labels, so 2 of the 3 disjuncts and their entire
    rationale are inert by construction — the customer pays 433 tokens (PMD-D-01) to learn a
    predicate it must not run.
    Proposal. Folded into PMD-D-01; additionally define or drop "seat"/"lane"/"steward
    automation"/"protocol posts".
    Delta. counted in PMD-D-01. Confidence HIGH. Human floor no.

    PMD-E-02 · MONOREPO ASSUMPTION · SKILL.md:416-452 (565 tok)

    Evidence. "#### One semantics, N independent implementations". Its own applicability clause
    names the platform's problem, not an app's: "that rule is implemented more than once, by
    compilers or evaluators that share no code. Query filters, expression languages,
    permission predicates and serialization formats
    all tend to grow this shape as a project adds
    backends." An ObjectStack app project consumes one compiled query/expression surface from
    @objectstack/spec; it authors no compiler and has no second evaluator to enumerate. The two
    maintenance disciplines that follow (440-452, 201 tok — "The inventory is maintained by PR",
    "Re-verify before pasting", frozen surfaces stay listed) are entirely about owning such an
    inventory.
    Proposal. RETIRE-SURFACE from the published package (it belongs to the internal corpus,
    outside the published boundary).
    Delta. −565. Gate. ① Changes no decision an app project can make. ② Yes, deletion.
    ③ N/A. Confidence HIGH. Human floor YES (removes published capability text).

    PMD-E-03 · MONOREPO ASSUMPTION · SKILL.md:591-611 (398 tok) + 612-618 (110 tok)

    Evidence. Two of the six "named non-escalation classes" are platform-governance shapes.
    591-592: "A declaration silently dropped on a new arm, when a sibling arm already has a
    ruling.
    When a declared key is silently ignored on one arm of a component and an
    earlier ruling already made that same key a loud authoring error on a sibling arm, the new
    arm joins the existing rejection set by default" — this is the enforce-or-remove /
    declared = enforced machinery of this repo's spec work (the same vocabulary drives the
    spec-property-retirement internal playbook), and an app project authoring metadata against a
    fixed published spec has no "arm of a component" carrying declarations. 612-618: "Two
    implementations of one operation
    … the side that already carries the governance —
    authorization gates, user consent, de-duplication, audit trail — is the default survivor"
    — a platform-runtime concern.
    Proposal. DELETE both bullets; keep "Restore-invariant fixes", "Sequencing and dependency
    ordering", "Verification strategy", and the needs_decision-relay bullet.
    Delta. −508. Gate. ① No decision an app PM makes. ② Yes. ③ N/A. Confidence HIGH.
    Human floor YES.

    PMD-E-04 · MONOREPO ASSUMPTION · SKILL.md:769-786 (290 tok)

    Evidence. Four correctness properties of a container-wide verification lock — "ONE shared
    heavy-verify lock per container, so every agent contends on the same file"; "The acquisition
    budget fits inside a SINGLE foreground tool call"; "A queue timeout is distinguishable from the
    wrapped command's own failure"; "Hold duration is observable". This is the design spec of this
    repo's scripts/pm/os-verify-lock.sh (the internal os-dev agent calls it by path). The
    published text concedes the customer has none: "The MECHANISM is the host project's (its
    wrapper, its lock path, its budget — put it in the conventions file)". A customer standing up
    the loop on day one therefore reads 290 tokens instructing it to build lock infrastructure
    before it may dispatch.
    Proposal. REWRITE-AS-CONSTRUCT — one line: "Serialize build/test through a single
    container-wide lock; queueing is normal, queueing with no end in sight is a finding — report it
    naming the holder."
    Delta. −250. Gate. ① The 4 properties change no decision for a project with no wrapper.
    ② Yes. ③ Yes. Confidence HIGH. Human floor YES (removes published guidance).

    PMD-E-05 · MONOREPO ASSUMPTION · SKILL.md:987-1033 (656 tok)

    Evidence. The whole section presupposes ≥2 repositories — which Configuration (79-117)
    declares the non-default case ("With no config the loop runs against the current repository:
    it is the only shard and the backlog", 60-61) — plus a shard registry issue: "Shard
    ownership is registered, never assumed.
    A registry issue in the backlog repository records
    which session owns which shard. A PM taking over a shard comments there as its FIRST action,
    and again when handing off." That is this monorepo's pm:seat seat-post protocol
    (.claude/skills/pm-dispatch/SKILL.md state model row: "pm:seat 座位登记贴 —— 协议载体") under
    another name. Its own conclusion is one line: "Multiple PMs on the same queue: prohibited."
    Proposal. REWRITE-AS-CONSTRUCT — one Guardrails bullet: "One PM per queue. Scale with
    batch / mode:cloud, never a second scheduler; a second PM takes a whole other repository as
    its shard and never claims outside it."
    Delta. −580. Gate. ① For the documented default (single repo) it changes nothing.
    ② Yes. ③ Yes. Confidence HIGH. Human floor YES.

    PMD-E-06 · MONOREPO ASSUMPTION (minor) · SKILL.md:553-556

    Evidence. The landing path leads with the merge-queue case — "where a merge queue
    exists, mark the PR ready and add it to the queue once every check is green (the queue rebuilds
    against the current default branch, which is the sanctioned path)" — before the case every app
    project is actually in. Properly conditional, so not a defect, but it front-loads the path the
    customer does not have.
    Proposal. Reorder so the serial-merge case leads. Delta. −30.
    Gate. ① Marginal. ② No. ③ No. Confidence LOW. Human floor no.

    PMD-F-01 · DRIFT vs INTERNAL CORPUS · SKILL.md:455-457 and 465-469

    Evidence — published (retired form). "mode:subagent (default). … Reports come back
    directly as each agent's final message — a lossless channel. Prefer this mode; it is simpler
    and nothing can be lost between agent and reviewer." The issue-comment report is required in
    cloud mode only (465-469).
    Evidence — internal oracle (current form). .claude/agents/os-dev.md:20-22 and 351-359:
    the report is delivered twice, GitHub first, in both modes — as an issue comment whose first
    line is the literal plaintext os-dev-report (explicitly "⛔ 不用 HTML 注释"), then as the final
    message; the reason is measured — a container restart killed three devs mid-final-message and
    the comment was the only surviving copy, so zero work was lost. The published package's own
    line 474-475 already concedes the channel loses work ("An agent that dies or returns malformed
    output counts as status: \"blocked\"").
    Proposal. ADD the both-modes comment rule + read-back to the template's final-message
    section (~50 tok), paid by DELETE of the duplicate JSON at 894-908 (PMD-B-02, −115).
    Delta. −65 net. Gate. ① Yes — it decides where the report is written. ② The addition is
    paid by a same-file deletion. ③ Yes, it is one rule line on an existing construct.
    Confidence HIGH. Human floor YES (changes published report semantics).

    PMD-F-02 · DRIFT vs INTERNAL CORPUS · SKILL.md:729-891 (template) and 892-915 (contract)

    Evidence. The PM-side stale-premise check exists (249-260: "An issue describes the
    repository as of its filing date, and an active default branch moves fast"). The binding
    template the dev actually receives never repeats it
    , and the report contract has no field for
    the result. The internal oracle made this a numbered basic rule:
    .claude/agents/os-dev.md:78-81 rule 6 — "issue 正文是线索,不是规格。动手前对 origin/main
    核验其前提 … 一份带 premise_still_valid: false、附证据、无 PR 的报告是一等交付物;证伪
    issue 是好运行" — and the internal report schema carries "premise_still_valid": true
    (os-dev.md:430). Without it a dev on a dead premise has no sanctioned return shape: blocked
    means infrastructure (published 858-860) and needs_decision means underspecified (826-830),
    so the template's own incentives push a PR onto a falsified premise.
    Proposal. ADD one template line ("Verify the issue's premises against origin/{default}
    before your first edit; a no-PR report with premise_still_valid: false and evidence is a
    first-class delivery") + the JSON key (~60 tok), paid by DELETE of PMD-E-02 (−565).
    Delta. −505 net. Gate. ① Yes — it changes what a dev does when the issue is wrong.
    ② Paid by a larger same-file deletion. ③ Yes, one key on an existing JSON construct.
    Confidence HIGH. Human floor YES (adds a published report field).

    PMD-F-03 · DRIFT vs INTERNAL CORPUS · SKILL.md:745-750 + 763

    Evidence. grep -c stash SKILL.md = 0. The template teaches the exact topology in which
    the trap lives: worktree-first ("git worktree add --no-track ../REPO-issue-N … Never edit a
    shared checkout — other agents switch its HEAD under you", 745-750) plus "parallel agents
    share ONE container
    " (763). refs/stash lives in the common .git directory, so all
    worktrees of one clone share one LIFO stack — which is why both repos carry the ban at
    Prime-Directive level with a measured incident: /home/user/objectui/CLAUDE.md — "two agents
    stashing in their own worktrees push and pop the same stack … pop reports success; the
    only symptom is someone else's files appearing in your git status … it happened between two
    parallel agents (objectui#3430) and cost both of them their in-flight changes."
    The published package ships the topology without the guard.
    Proposal. ADD two lines to template rule 1 ("Never git stash — the stack is shared
    across every worktree of one clone. Use git diff > /tmp/wip.patch or a throwaway wip
    commit", ~40 tok), paid by DELETE of PMD-E-04's lock properties (−250).
    Delta. −210 net. Gate. ① Yes — it changes the command a dev reaches for. ② Paid by a
    larger same-file deletion. ③ Yes, two bullets. Confidence HIGH. Human floor YES.

    PMD-F-04 · DRIFT vs INTERNAL CORPUS · SKILL.md:336-338, 342-343

    Evidence — published claim shape. "> Claim: PM loop round N / > Branch:
    claude/issue-N-SLUG / > Worktree: REPO-issue-N", with the identity key being the
    branch: "if an earlier claim comment with a different branch name exists, you lost".
    Evidence — internal (current). .claude/skills/pm-dispatch/SKILL.md:535-541 makes
    > Session: \session_ID`a non-optional line ("session ID 不可省"), keeps the literalClaim:first line as a maintainer-ruled machine predicate (2026-08-11), and names the comment **timestamp** the sole arbiter./home/user/objectstack/CLAUDE.mdstates the same at Prime-Directive level: "a claim is assign **plus a claim comment with your session ID and branch**". The published branch-only discriminator under-determines inmode:cloud— a mode the published skill itself supports — because the branch slug is derived from the issue, so two cloud sessions racing the same issue can generate the *same* branch name and both read "no earlier claim with a different branch". **Proposal.**ADDtheSession:` line to the claim shape (~15 tok), paid from PMD-D-01.
    Delta. +15 (paid). Gate. ① Yes — it decides who yields in a race. ② Paid.
    ③ Yes, one row of an existing template. Confidence MED-HIGH. Human floor no.

    PMD-F-05 · DRIFT / INTERNAL CONTRADICTION · SKILL.md:367-369 vs 800-810

    Evidence. PM-side prose asserts a behaviour the template never asks for: "Developer agents
    push their branch early
    — a remote branch is the hardest evidence of work in flight, and it
    closes the gap between 'claimed' and 'a PR exists'", and the stale-claim reclaim at 371-375 then
    reads that remote branch ("A claim older than ~24 h whose promised branch does not exist on
    the remote and has no PR is presumed dead"). But the binding template's "Definition of done, in
    order" (800-810) lists "Pushed: git push -u origin …" fourth, after implementation, tests
    and the release-note artifact. A dev following the template has no remote branch for most of
    its run, so the reclaim predicate can fire against a live agent. The internal oracle closes
    this: .claude/agents/os-dev.md rule 1 — "建好分支后的第一个动作:先把空分支推上去(任何
    编辑之前 git push -u origin BRANCH)" — doubling as a write-credentials probe (403 ⇒ stop and
    report blocked).
    Proposal. ADD "push the empty branch immediately after creating it (also a write-access
    probe: a 403 here is blocked, not a retry loop)" to template rule 1 (~25 tok), paid from
    PMD-D-02.
    Delta. +25 (paid). Gate. ① Yes — it removes a contradiction that can trigger a wrongful
    reclaim. ② Paid. ③ Yes. Confidence HIGH. Human floor no.

    PMD-G-01 · CONSISTENCY · SKILL.md:557-559 vs 1051

    Evidence. Guardrails: "The PM writes no files." (1051). Step 7 ACCEPT: "This applies to
    developer-agent PRs dispatched by this loop only — the PM's own tooling PRs stay with the
    maintainer." (557-559). The second sentence presupposes PM-authored PRs the first forbids. It is
    residue of the internal exception the published copy dropped:
    .claude/skills/pm-dispatch/SKILL.md — "PM 不写文件、不写代码。 唯一例外:维护者逐 PR
    明示授权
    的 .claude/ 内部工具 PR".
    Proposal. DELETE the "the PM's own tooling PRs" clause.
    Delta. −25. Gate. ① Yes — it removes an apparent licence to author PRs. ② Yes. ③ N/A.
    Confidence HIGH. Human floor no.

    PMD-G-02 · CONSISTENCY (measured negative) · whole file

    Evidence. Retired-spelling sweep run per the rubric (silently|ignored|dropped|legacy| deprecat|\bM9\b|v5\.0|\bOLD\b|\bNEW\b|17\.[0-9]|project): no residue. All 14 "silently"/
    "ignored"/"dropped" hits are ordinary prose about behaviour (105, 450, 479, 592, 974, 1008 …);
    line 754's "NEW, UNASSIGNED issues" is English emphasis, not the retired CEL NEW token; the
    only version reference is current-major and internally consistent — 979: "pinned at 17.2.0;
    unpin when UPSTREAM#N ships in >= 17.3". No project-as-workspace usage.
    Proposal. none. Delta. 0. Confidence HIGH. Human floor no.

    PMD-H-01 · EVALS · package has no evals/

    Evidence. ls -d skills/*/evals returns 8 directories (ai, api, automation, data, i18n,
    platform, query, ui). Both process skills — this one and objectstack-upgrade — have none.
    This is the second-largest published package (14,549 tok, 7.7 % of the bundle) with zero
    graded rubric, while objectstack-data (13,892) ships one and objectstack-query (5,443) ships
    a 558-token one. Its decisions are unusually gradeable: escalate vs decide under the veto window
    (565-595); batch independence (307-319); ACCEPT vs REWORK against GitHub rather than against the
    report (529-548); and — the one this audit shows matters most — whether a given rule applies to
    a project with no seats, lanes or lock wrapper.
    Proposal. ADD evals/README.md (~300 tok). It is a new file, so it takes a new ceiling
    rather than being paid by deletion inside SKILL.md; that needs a maintainer ruling quoted in
    the PR.
    Delta. +300 (new file). Gate. ① Yes — evals are how the package's own drift gets caught.
    ② No. ③ Yes, a rubric is a construct. Confidence HIGH. Human floor YES (new ceiling).

    PMD-I-01 · SIZE PROPORTIONALITY · whole package

    Evidence. 14,549 tokens for a package that teaches no ObjectStack surface at all: 0
    TypeScript fences, 0 os:check markers, no references/_index.md, no Zod pointer. It costs
    more than objectstack-data (13,892) and objectstack-platform (12,984), which teach the
    product, and 1.75× the other process skill (8,333). Against the five customer decision
    points enumerated above that is ~2,900 tokens per decision. Measured customer-inert or
    duplicated text totals ≈ 4,445 tokens (30.6 %) before the structural move; with the template
    and upstream sections relocated (PMD-B-01, PMD-C-01) ≈ 7,350 tokens (50 %) leaves the
    always-loaded entry file. The package sits at headroom 0 on its ceiling, so it currently
    cannot absorb any of the three additions in PMD-F-01/02/03 without the deletions that pay them.
    Proposal. Apply the deletions above; then re-ratchet.
    Delta. −4,255 net across all findings (14,549 → ~10,294).
    Gate. ① Yes. ② Yes. ③ Yes. Confidence HIGH. Human floor YES.


    Incidental falsehoods (by-product, not the job)

    IF-1 · SKILL.md:456-457 — "Reports come back directly as each agent's final message — a
    lossless channel
    … nothing can be lost between agent and reviewer." Contradicted inside
    the same package
    17 lines later at 474-475: "An agent that dies or returns malformed output
    counts as status: \"blocked\" with its raw output attached" — i.e. the channel is known to lose
    whole reports. Independently disproved by the internal oracle
    (.claude/agents/os-dev.md:355-357), which records a container restart killing three devs
    mid-final-message with the GitHub comment as the only surviving copy.

    IF-2 · SKILL.md:1036-1039 — "serialized heavy phases — which the developer-agent
    template enforces
    with a container-wide verification lock, a heap cap, scoped builds and
    worktree cleanup." The template does not enforce it; it explicitly delegates: "The MECHANISM
    is the host project's
    (its wrapper, its lock path, its budget — put it in the conventions
    file)" (771-772). For any project without a wrapper — every customer on day one — nothing is
    enforced. enforces should read requires.


    Verdict

    RESTRUCTURE. Pure-deletion reducible text measures 4,445 tokens = 30.6 %, at the
    DIET/RESTRUCTURE boundary on its own; the structural half decides it. The package is one
    monolithic 14,549-token file with zero progressive disclosure, zero evals, two blocks duplicated
    inside itself (the report JSON, the sanitizer trap), a 2,376-token verbatim paste-block paid in
    every session whether or not a dispatch happens, and an entire second job (upstream reporting)
    that duplicates objectstack-platform and mis-routes customers into a 14.5k-token load.

    The three highest-value additions, each with its payment

    1. Dev-side premise verification + premise_still_valid (PMD-F-02, +60) ← paid by deleting
      "One semantics, N independent implementations" (PMD-E-02, −565). Net −505.
    2. The git stash ban in the template (PMD-F-03, +40) ← paid by deleting the container-lock
      design properties (PMD-E-04, −250). Net −210.
    3. Report as a GitHub comment in BOTH modes, plain-text marker, read it back (PMD-F-01, +50)
      ← paid by deleting the duplicated report JSON (PMD-B-02, −115). Net −65.

    Generated by Claude Code

  5. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    os-dev-report

    {
      "issue": 14300,
      "status": "done",
      "branch": "claude/issue-14300-skills-pm-dispatch-optimization",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/14444",
      "premise_still_valid": true,
      "summary": "skills/objectstack-pm-dispatch/SKILL.md shrunk from 14,549 to 11,567 tokens (net -2,982, lines 1,086 -> 879) in five commits keyed by finding id: PMD-C-01 (upstream reporting cut to a 245-token residue pointing at objectstack-platform's 'The App / Platform Boundary' by heading), E-05, E-02, E-03, D-01(+E-01), D-02, D-03, E-04, B-03, B-02, G-01, A-01 (description trigger dropped; skills/README.md and content/docs/ai/skills-reference.mdx regenerated by gen:skill-docs), the five drift syncs F-01..F-05 quoted from .claude/agents/os-dev.md and CLAUDE.md on origin/main 96b627d1, and the IF-2 'enforces' -> 'requires' correction. PMD-D-04 excluded by check:skill-frame-sync (both frame copies pinned; anchors now at :540 and :729), premise_false none, PMD-B-01 / H-01 deferred to #14296, the ~620-token gap against the card's ~-3,600 target itemised in the PR body, #14229's two pending deltas listed as a follow-up sync. Draft PR #14444 opened with first line 'Part of #14300', skip-changeset applied and read back twice (+4s and +2min: documentation, size/m, skip-changeset). REST channel was gated (403 on a repo-scoped read); card, comments and read-backs went through the zero-quota page payload, writes through MCP.",
      "tests": "head ea50dfb5 (== remote ref). Baseline on the untouched worktree, then after every commit: pnpm check:skill-frame-sync -> '4 copies of the decision frame are structurally isomorphic across 3 files; 4 axes: business-need -> long-term-soundness -> ai-authoring-safety -> startup-scope-discipline' (exit 0); pnpm check:skill-frame-freshness -> 'the decision frame in this tree is current with origin/main' (exit 0); node scripts/check-skills-token-ratchet.mjs -> 'skills/objectstack-pm-dispatch/SKILL.md is 11567 tokens (ceiling 14549; headroom 2982)' (exit 0); pnpm check:skill-identifier-liveness -> 'OK - Leg 1: 500 citation(s) ... (5 ledgered exemption(s)); Leg 2: 9 registered exhaustive section(s)' (exit 0, no Leg 2 heading bound to this file); pnpm check:skill-compatibility -> '11 SKILL.md file(s) reconciled against 78 workspace packages' (exit 0); pnpm --filter @objectstack/spec check:skill-docs -> 'Skill docs in sync' (exit 0); pnpm check:nul-bytes -> 'OK (scanned 7875 text file(s) ... no raw ASCII control bytes)' (exit 0). Re-derived union: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --commands from the tree at ea50dfb5 = 36 commands, every exit captured by redirect before any pipe: 33 green first pass; check:doc-formula-expressions and check:doc-security-posture green after building @objectstack/formula and @objectstack/lint (first pass exit 3 = PREREQUISITE NOT MET); check:skill-examples green after building types/client/client-react under the lock -> '259 prose examples type-check across 3 surface(s)' (first pass exit 1 = client-react dist unbuilt); node scripts/check-test-completeness.mjs NOT MEASURED locally by design (exit 3, needs a saved turbo test log; CI supplies it). node scripts/check-empty-changeset.mjs --base origin/main -> 'No empty-frontmatter changeset introduced by this diff'. Heavy steps under scripts/pm/os-verify-lock.sh (OS_VERIFY_LOCK_SLOT=issue-14300): spec build VERDICT command-exit 0 (waited 308s, held 206s); one earlier client-react closure build hit the 10-minute foreground cap (exit 143, lock held by issue-14304) and was re-run as a minimal types/client/client-react build (held 16s). Every edit asserted count-of-one on the exact source span and re-grepped after write (deleted anchors 0, inserted anchors 1). PR body read back from the rendered page: 44/44 sentinel fragments present, draft. Audit-record comment read back byte-identical to the local transliterated copy except one collapsed blank line before the footer. CI on #14444: in_progress at report time (not polled).",
      "mcp_calls": "5 - claim comment, audit-record comment, create_pull_request, issue_write (skip-changeset), this report comment; all reads went through git and the zero-quota issue/PR page payload",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  6. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    ACCEPT — skills-lane seat (session session_01LraLgQVGq8egUwfYZpbYt1), reviewer of record, verified against GitHub not the report.


    Generated by Claude Code

  7. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    Round 1 MERGED — PR #14444 landed on main at 08:57Z (approved by os-zhuang). The card stays open for its second round.
    Session: session_01LraLgQVGq8egUwfYZpbYt1

    Ruling landed. #14296 was ruled 1A 2A 3A 4A at 09:27Z (comment 5507419465): item 1 authorizes the entry + rules/ split under three conditions (the same PR nets ≥ 10% off the whole package; every new file's ceiling pinned at its landed count; a split is never a channel for added prose; the PR body quotes the ruling), and item 4 sets this package's target — stay in the catalog, ≈ 30% off to ≤ 10k tokens, the developer template externalized to rules/dev-template.md, the four internal-contract drifts corrected (round 1 already synced the drifts it could reach inside one file).

    State: pm:dispatched → pm:queue (not pm:blocked — the blocker is gone). Round 2 scope, for the next dispatch: the split PR per items 1 + 4 on a fresh branch from main, skills/objectstack-pm-dispatch/** only, Part of #14300, governed ⇒ draft, needs:contract-review on both carriers (the rules/ extraction moves contract text), the two decision-frame copies gate-pinned to the internal file and never edited. Dispatched when a heavy slot frees (≤ 3 heavy in flight; #14315 / #14316 are in flight now).


    Generated by Claude Code

  8. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    Round 2 gated — pm:queue → pm:blocked, Blocked-by: #14568.
    Session: session_01LraLgQVGq8egUwfYZpbYt1

    The ui split (#14298 round 2) measured that a byte-conserving split cannot net ≥ 10% off its package in the same PR once round 1 has taken the priced deletions; this package's split (template → rules/dev-template.md after PR #14444 landed the diet) is the same shape. Decision batch 2 (#14568, one item) asks the maintainer whether #14296 item 1's condition (a) binds the PR arithmetically or is the anti-growth guard; the reading given there governs this round too. Re-queued the moment #14568 is ruled.


    Generated by Claude Code

  9. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    Unblocked — #14568 ruled A (director seat, comment 5511939006, 15:22Z): condition (a) of the #14296 item-1 ruling is the programme-level anti-growth guard, and the ruling states it applies identically to this package's split. A split PR lands token-neutral or negative; the package arithmetic is the programme's (round 1, PR #14444, plus the split).

    State pm:blocked → pm:dispatched in the same stroke (claim for round 2; assignee unchanged). Round 2 = the #14296 item-4 split of skills/objectstack-pm-dispatch/SKILL.md into entry + rules/ with the template in rules/, entry ≤ 10k tokens, plus this card's deferred items as recorded in the seat's ACCEPT on #14444. Dispatch brief follows on the dev's claim comment; branch claude/issue-14300-pm-dispatch-split. Governed skills/** ⇒ draft-only; at CONTRACT_REVIEW_TIER (the published PM skill is a fable-mandated surface); ⛔ never in one PR with .claude/skills/pm-dispatch/**.

    Session: session_01LraLgQVGq8egUwfYZpbYt1


    Generated by Claude Code

  10. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    Claim: dev seat, round 2 (mode:subagent), dispatched on this card by the skills-lane seat
    Session: session_01LraLgQVGq8egUwfYZpbYt1
    Branch: claude/issue-14300-pm-dispatch-split (from origin/main ca48cf37; the empty branch was pushed first as the write-route probe: exit 0, new branch)
    Worktree: objectstack-issue-14300-r2 (base ca48cf37)
    File surface: skills/objectstack-pm-dispatch/SKILL.md (entry, shrinks), skills/objectstack-pm-dispatch/rules/dev-template.md (new — the developer-agent template moved out of the entry), scripts/check-skills-token-ratchet.mjs (exactly two rows: the new file's row pinned at its landed count, the entry's row re-locked at its landed count). Assignee and card labels untouched. Read-only oracles: .claude/agents/os-dev.md, CLAUDE.md, .claude/skills/pm-dispatch/**; scripts/pm/check-skill-line-ratchet.mjs untouched; no other package.
    Scope: the #14296 item 1 + item 4 split under the #14568 = A reading (PR lands token-neutral or negative on the package; programme arithmetic = round 1 −2,982 + this PR), both gate-pinned copies of the decision frame stay in the entry (check:skill-frame-sync reads its copies by file path), the PMD-H-01 disposition with evidence, and the follow-up sync of #14229's two deltas quoted from the oracle on origin/main. Governed skills/** ⇒ draft PR only, never flipped ready; review requests are the seat's step.


    Generated by Claude Code

  11. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    os-dev-report

    {
      "issue": 14300,
      "status": "done",
      "branch": "claude/issue-14300-pm-dispatch-split",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/14660",
      "premise_still_valid": true,
      "summary": "Draft PR #14660 (first line 'Fixes #14300', head fef3b449, base ca48cf37, 2 commits, 3 files) lands the #14296 item-1/item-4 split under the #14568 = A reading: skills/objectstack-pm-dispatch/SKILL.md 11,567 -> 9,708 tokens (entry <= 10k met), the developer-agent template moved verbatim to skills/objectstack-pm-dispatch/rules/dev-template.md (1,838 tokens; one H1 and one {decision_frame} placeholder line added), both gate-pinned copies of the decision frame kept in the entry (anchors at :534 and :633; a moved published-dev copy would make check:skill-frame-sync FAIL on a 0-match start anchor, not pass vacuously), package 11,567 -> 11,546 (-21; split commit -11, sync commit -10), programme account round 1 -2,982 + this PR -21 = -3,003 / 14,549 = -20.6%. Ratchet rows: rules/dev-template.md added at 1,838, SKILL.md re-locked 14,549 -> 9,708, no other row touched, self-test 64/64. PMD-H-01 disposition: premise false, the package has never had an evals/ directory (git ls-tree on origin/main lists SKILL.md only; git grep for objectstack-pm-dispatch/evals empty; no evals ceiling row), so nothing to delete and no row to drop; the audit's +300 evals README proposal is foreclosed by #14296 item 2 = A. #14229's two deltas synced into the template from .claude/agents/os-dev.md on origin/main (rule 1 non-guarantee clause :85-88; ratchet funding discipline :323-327), +108 tokens funded by five verbatim in-package restatements plus one published-only rationale sentence, all itemised in the PR body. Labels on the PR read back as ['documentation','skip-changeset'] (whole-set write after a read showing none; nothing stripped). Assignee and card labels untouched; the 11:50Z comment's 'needs:contract-review on both carriers' was superseded by the dispatch brief (Clause-2: no, clause 1 in-seat), so none applied. Worktree removed without --force after the push (git status clean, HEAD == remote). CI on #14660: in_progress at report time, not polled. Deviation disclosed: the two commits carry the platform-mandated attribution trailer (Co-Authored-By + Claude-Session), which names a model; the dispatch's no-model-identifier clause was applied to the PR body and to this report.",
      "tests": "Baseline at ca48cf37 before any edit: check-skills-token-ratchet 'skills/objectstack-pm-dispatch/SKILL.md 11567 / 14549 (-2982)'; check:skill-frame-sync '35 markdown files scanned'; check:skill-identifier-liveness '41 published file(s)'. After each commit and at head fef3b449 (union re-derived from the tree at fef3b449 with no paths, 25 commands, every exit captured by redirect before any pipe): 23 exit 0 on the first pass — node scripts/check-skills-token-ratchet.mjs '✓ check-skills-token-ratchet: 32 authored bundle file(s) within their ceilings; 11 generator-owned file(s) measured, not ratcheted.' with rows 'SKILL.md 9708 / 9708 (+0)' and 'rules/dev-template.md 1838 / 1838 (+0)', --self-test '64 cases pass'; pnpm check:skill-frame-sync '✓ check-skill-frame-sync: 4 copies of the decision frame are structurally isomorphic across 3 files … 36 markdown files scanned for undeclared copies'; pnpm check:skill-frame-freshness '✓ … the decision frame in this tree is current with origin/main (fetched just now)'; pnpm check:skill-identifier-liveness 'OK — Leg 1: 465 citation(s) over 42 published file(s) … (3 ledgered exemption(s)); Leg 2: 8 registered exhaustive section(s), 0 ledgered gap(s)' (no Leg 2 binding on this file); pnpm check:skill-compatibility '✓ … 11 SKILL.md file(s) reconciled against 79 workspace packages'; pnpm --filter @objectstack/spec run check:skill-docs '✅ Skill docs in sync' (frontmatter untouched, no regeneration); pnpm check:role-word 'OK, no new occurrences' (0 in both files); pnpm check:corpus-claim-drift 'OK, no new claim sites'; pnpm check:doc-authoring, check:pm-governed-merges, check:pm-dispatch-gates ('1240 cases pass'), check:ratchet-remedy-authority, check:watch-hint-literal, check:entry-guard, check:parse-guard, check:pnpm-filter-targets, check:cli-command-ids, check:bash32-floor, check:agent-test-spelling, check:cross-package-test-inputs (both spellings), check-ci-filter-parity, check-shard-attestation, bare-root-worklist --self-test: exit 0 each; pnpm check:nul-bytes 'OK (scanned 7996 text file(s) … no raw ASCII control bytes)'; node scripts/check-empty-changeset.mjs --base origin/main '✓ No empty-frontmatter changeset introduced by this diff'. pnpm --filter @objectstack/lint run check:doc-formula-expressions: first pass exit 3 'PREREQUISITE NOT MET — @objectstack/formula is not built', green after building the lint and formula closures under scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=issue-14300-r2 ('VERDICT command-exit 0 · held the lock 130s · waited 406s'; the first lock attempt timed out 'VERDICT queue-timeout (exit 99) · never acquired · waited 540s', slot kept, resumed after lock-free gate work) — '✓ check:doc-formula-expressions: 22 record-scoped formula example(s) across 422 files / 1364 TS blocks judged clean'. NOT MEASURED: node scripts/check-test-completeness.mjs exit 3 'PREREQUISITE NOT MET — this gate grades a saved turbo run test log, and no log was named' (CI supplies it). Every edit asserted count-of-one on its exact source span before writing and re-grepped after (moved anchors 1 in the destination, 0 in the source; the one aborted sync run threw on its own assertion before any write, git status clean). The cross-file link ./rules/dev-template.md was verified by hand: no doc-link gate walks skills/**.",
      "mcp_calls": "11 — issue_read get_comments on #14300 (the page payload carried only the first 15 timeline items) and on #14296 (the ruling comment), pull_request_read on #14444 (the two-delta list) and twice on #14660 (body and labels read-back), issue_read get_labels on #14660 (failed: PR numbers do not resolve as issues), add_issue_comment ×2 (claim, this report), create_pull_request, issue_write (skip-changeset); card, audit record, round-1 report, #14568 and the oracle went through git and the zero-quota page payload",
      "open_questions": [
        { "question": "The dispatch brief says no model identifiers in commits, while the platform's attribution requirement mandates the 'Co-Authored-By: Claude Fable 5.1' + Claude-Session trailer on every commit (round 1's commits carry the same trailer). Which governs the commit trailer?", "options": ["A keep the platform trailer on commits and keep model identifiers out of PR bodies and reports (what this PR does)", "B rewrite the two commits without the trailer — needs a force-push, which is forbidden, so it can only happen as new commits on a fresh branch"], "recommendation": "A, because the trailer is the platform's attribution contract and the PR body and report already carry no model identifier; B costs a branch rebuild for a trailer the repo's own history uses on every AI commit." }
      ],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  12. os-litant commented on Sep 2, 2026

    @os-litant
    ContributorAuthor

    ACCEPT — round 2, PR #14660 @ fef3b449 (Fixes #14300), with the in-seat skill-face review (clause ①) — PASS

    Session: session_01LraLgQVGq8egUwfYZpbYt1 (skills lane seat)

    Verified against GitHub and on the branch itself (fetched claude/issue-14300-pm-dispatch-split at fef3b449, diff against merge-base ca48cf37):

    All three deferrals the seat's ACCEPT on #14444 recorded (the split, PMD-H-01, the #14229 sync) are closed by this PR ⇒ Fixes #14300 is the right landing form; this card closes on merge and the seat strips pm:dispatched then. The Co-Authored-By trailer question is answered on #13680 (harness attribution, accepted). Follow-up already on the ledger: the role-word baseline class (#14659) — this package carries zero occurrences, so it was not hit here.

    Governed surface (skills/**, fable-mandated): the PR stays draft; review requested from os-zhuang and hotlong; landing is the maintainer's. #12911 (pm-dispatch construct-removal) dispatches on the split tree after this merges.


    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

Labels

documentationImprovements or additions to documentationdomain:skillspriority:p1High: required for production / M2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions