Skip to content

pm-dispatch: a SessionStart hook prints the lane's seat-post stub and the SKILL.md pointer, because a multi-repo project's working directory does not surface the repo's .claude/skills (maintainer's word 2026-10-23) #25380

Closed

Description

@objectstack-fleet

Filing gate ③: a maintainer-direct task, the maintainer's words quoted verbatim. Filed from the Claude Code project "Objectstack" (account os-elon-musk) by the research thread 车队机制迁往 Projects on the maintainer's word there. ⛔ Not a claim. Lane self-applied under exception 二 (.claude/** hooks and settings are governed Tier S, the lane table's domain:skills row); grade suggested p3; triage may regrade.

Reader (who acts): the domain:skills seat 2 (seat post #19287), in one PR on .claude/settings.json + a new .claude/hooks/session-start-fleet.sh (+ its .selftest.sh, as every sibling hook has) + one pointer line in .claude/skills/pm-dispatch/references/seat-lifecycle.md. Size S–M.

The maintainer's words (2026-10-23, the project's thread 车队机制迁往 Projects, verbatim)

包括Claude code projects 我打开之后怎么让他自动加载相关的技能要求。
同意,你现在就立卡派发处理。

What was measured

  • In a Claude Code project that attaches three repositories (objectstack, objectui, hotcrm) the session's working directory is the parent of the three checkouts. Each repository's CLAUDE.md IS loaded at session start, and the PreToolUse guards in objectstack/.claude/settings.json DO fire in project threads (measured on card threads 2026-10-22/23). But objectstack/.claude/skills/pm-dispatch did not appear in any thread's available-skill list (checked 2026-10-23 04:30Z from such a thread), so no thread could invoke /pm-dispatch; every seat thread of the last two days read SKILL.md by hand only because the maintainer's project instructions told it to.
  • There is no SessionStart hook in the repository today (.claude/settings.json has PreToolUse only).

Wanted

A SessionStart hook, registered in .claude/settings.json beside the existing guards, that prints to the session (stdout → context) at most ~15 lines:

  1. The pointer: Fleet protocol: read .claude/skills/pm-dispatch/SKILL.md (and the stage references its index names) before any dispatch, claim, review or landing act. plus the latest touch sha of SKILL.md on the checkout's HEAD (git log -1 --format=%h -- .claude/skills/pm-dispatch/SKILL.md), so a seat can compare it with its opening mark (seat-lifecycle.md 〈开轮互斥〉).
  2. If the environment names a lane (OS_FLEET_LANE, set by the project's instructions or environment; absent ⇒ the line says lane: not set), the lane's seat-post number from references/lanes/<lane>.md and the one-line reminder 「the seat post is a stub; posture and ledger live in the project」.
  3. Nothing else: no network, no GitHub read (the proxy and the write gate are not this hook's business), exit 0 always — a hook that fails must never block a session.

The hook is a dependency-free bash script shaped like its siblings (guard-*.sh + *.selftest.sh), and seat-lifecycle.md gains one line saying the hook exists and what it prints, ⛔ not a second copy of the pointer text.

Not wanted: uploading pm-dispatch as a claude.ai account skill (two sources of one rule, against 「规则住本仓」 and the ratchet); editing AGENTS.md (Tier H).

Acceptance

  • Opening a project thread whose checkout includes objectstack shows the pointer lines in the session's first context; verified once from a project thread and recorded in the PR body with the exact lines.
  • bash .claude/hooks/session-start-fleet.selftest.sh green; the hook exits 0 with and without OS_FLEET_LANE, and on a checkout where the skill file is missing.
  • pnpm check:pm-skill-ratchet green (one line added to seat-lifecycle.md, paid by one deletion or within ceiling).
  • Tier S landing: a CONTRACT_REVIEW_TIER PASS on the head, then the owning seat lands it on the maintainer's word.

Dedupe

MCP search_issues, objectstack, "SessionStart hook settings.json print lane seat pointer pm-dispatch SKILL.md read before acting multi-repo project skills not discovered" → 32 hits; the top ten are #24974, #19287, #7623, #23445, #22979, #22316, #22372, #22257, #20385, #7518. None adds a SessionStart hook or addresses skill discovery in a multi-repo project. New.

Dedupe words: SessionStart hook pm-dispatch pointer · multi-repo project skills not discovered · OS_FLEET_LANE seat stub.

Activity

  1. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 (card thread) · 2026-10-23T04:56Z · p3, tooling, domain:skills. Adds a SessionStart hook that prints the pm-dispatch pointer (and the lane's seat-post stub when OS_FLEET_LANE is set) so a multi-repo project session finds the skill, on the maintainer's 2026-10-23 word on the card.
    Session: session_01SSWEKCxzY8HYr8EsFpR8VG (card thread of domain:skills seat 2, seat session session_01REMuzhz6MWRjg8uohedMnM)
    Account: os-elon-musk (the seat's linked user; always the card's assignee)
    Branch: claude/project-thread-06hewe (the card thread's designated push branch, platform-assigned at thread creation; the claude/issue-<n>-<slug> convention cannot be used by a project thread, a measured platform exception)
    Worktree: the card thread's own checkout
    Domain: domain:skills
    Seat: domain:skills#2 (seat post #19287)
    File surface: .claude/settings.json (one SessionStart registration beside the existing guards); new .claude/hooks/session-start-fleet.sh and .claude/hooks/session-start-fleet.selftest.sh; one line in .claude/skills/pm-dispatch/references/seat-lifecycle.md (away from L69 and 〈座位贴协议〉); scripts/pm/check-skill-line-ratchet.mjs only if that line needs a ceiling row at its landed count. (stop on breach; explain in the report)
    ⛔ Not in scope: any Tier H file; SKILL.md and every other reference; uploading the skill as an account skill; any network or GitHub read in the hook.
    Container & model: M, mode:thread (the maintainer's word: one project thread per M-or-larger or p1 card), model: CONTRACT_REVIEW_TIER (reason: no path mandate from dispatch-gates.mjs --tier at d12e650d for these paths; the maintainer ruled in this project 「改技能的卡用 fable」 and this hook exists only to load the skill), effort: high (M). Governed surface .claude/** is Tier S: a CONTRACT_REVIEW_TIER PASS record on the PR's head plus all-green checks; landing waits for the maintainer.
    Clause-②: no
    Metadata-protocol: none
    Responsibility: n/a — not a defect card (a maintainer word not yet written into the repo)
    Thread-read: none
    Serial constraints cleared: seat-lifecycle.md is also edited by PR #25348 (L69) and will be by #25379 (thread claude/project-thread-hxtlri, 〈座位贴协议〉); one line, placed apart, merge main when told. .claude/settings.json and .claude/hooks/**: no open PR found at claim time.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 23, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 25380,
      "status": "done",
      "branch": "claude/project-thread-06hewe",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/25386",
      "session": "session_01SSWEKCxzY8HYr8EsFpR8VG",
      "premise_still_valid": true,
      "summary": "New SessionStart hook .claude/hooks/session-start-fleet.sh prints the pm-dispatch pointer, the SKILL.md path and its latest touch on HEAD (a shallow clone's graft boundary is labelled as one, never presented as a measured touch), an optional note when CLAUDE_PROJECT_DIR is not this checkout, and the lane line (OS_FLEET_LANE => seat-post number read from a `Seat post: #N` line in references/lanes/LANE.md plus the stub reminder; absent => `lane: not set`). No network, no GitHub read, no write, exit 0 always, located from its own path. Registered in .claude/settings.json beside the PreToolUse guards; hermetic selftest with 58 cases; seat-lifecycle.md +1 line in 〈开轮互斥〉 paid by the opening reader-routing sentence the SKILL.md index already carries (96 -> 95, ceiling untouched). Two premises measured against the card: (A1) in this project thread CLAUDE_PROJECT_DIR is unset in the Bash environment and the registered PreToolUse guard did NOT block a known-blocked command, so the nested checkout's settings.json is probably not loaded in this thread shape — whether a project thread ever runs the hook is a platform question the PR cannot settle; (A5) no references/lanes/*.md carries a seat-post number, so the hook prints `not recorded` until one line per lane file is added (outside this card's surface).",
      "tests": "bash .claude/hooks/session-start-fleet.selftest.sh -> `session-start-fleet selftest: 58 passed, 0 failed`, exit 0 (hermetic fixture: git repo + SKILL.md + two lane files; cases cover pointer verbatim, touch sha = git log -1 -- SKILL.md, shallow-boundary labelling both directions, lane set/unset/empty/no file/no number/path chars/shell metachars, cwd and CLAUDE_PROJECT_DIR not inputs, <=15 lines, bash -n, executable bit, settings.json wiring, NON-VACUITY: mutated pointer caught, exit-1 copy seen, set -u abort still exits 0). Hook run on this checkout prints 4 lines, exit 0, with and without OS_FLEET_LANE. No ablation: no tested runtime behaviour changed (hook + selftest + settings + one reference line).",
      "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack (no paths; change set off the merge base: 4 files, 390 changed lines) -> 19 commands, each run on head e75a6b53 with the exit captured before any pipe; --ran: `19 derived famil(ies) accounted for — 19 run, 0 NOT-MEASURED`, all exit 0. First sweep had two reds, both resolved before the final sweep: check:bash32-floor exit 1 (the selftest spelled the forbidden tokens into a grep pattern; removed in e75a6b53) and lint check:doc-formula-expressions exit 3 PREREQUISITE NOT MET (@objectstack/formula and @objectstack/lint unbuilt; built, exit 0). check:pm-skill-ratchet: seat-lifecycle.md 95 lines, ceiling 96, headroom 1; new line 115 bytes. CI families (pnpm lint, hook self-test discovery step, type-check lanes): read from the PR's check-runs, not re-run locally.",
      "dogfood_battery": "n/a — no `!` in the PR title and no (narrowing) arm",
      "mcp_calls": "7 — all reads: issue_read get + get_comments x2 (#25380), pull_request_read get_files (#25348), pull_request_read get (#25348); no MCP write tool",
      "api_writes": "3 — git push x2 (branch claude/project-thread-06hewe); fleet-write relay pr_create (POST /repos/objectstack-ai/objectstack/pulls + issues/25386/assignees + issues/25386/labels, run 39905209657); plus this report comment and one verification comment via post-stamped",
      "open_questions": [
        { "question": "A1: the nested checkout's .claude/settings.json does not appear to be loaded in a project thread rooted at the parent directory (PreToolUse guard did not fire; CLAUDE_PROJECT_DIR unset). Should the pointer also be carried by a channel the project thread demonstrably loads (each repo's CLAUDE.md is loaded; project instructions), or is the platform question measured first?", "options": ["A keep the hook as the mechanism and measure one post-merge project thread for the pointer lines before deciding anything else", "B also add one pointer line to objectstack/CLAUDE.md (Tier H, separate card)"], "recommendation": "A, because the card's wanted mechanism is the hook, the measurement is one thread away, and B is a Tier H edit the maintainer must rule on" }
      ],
      "out_of_scope_findings": [
        "carrier: skills seat · references/lanes/*.md carry no `Seat post: #N` line, so the hook prints `not recorded` for every lane until one line per lane file is written (one reference edit, outside this card's surface) · noted, not filed",
        "carrier: skills seat · platform reading for platform-readings.md: in a project thread rooted at the parent of the checkouts, CLAUDE_PROJECT_DIR is unset in the tool environment and the objectstack PreToolUse guards do not fire (measured 2026-10-23 on this card thread with guard-tree-enum's first block case) · noted, not filed"
      ]
    }

    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

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions