plugins/coordinator/skills/session-start/SKILL.md
Orient session — preflight, load context, choose work
npx skillsauth add oduffy-delphi/coordinator-claude session-startInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Orient this agent by verifying the environment, loading project context, and choosing work.
Design note: Multiple agents may be running concurrently on the same repo. This command orients ONE agent — it does not assume exclusive access to the codebase or the user's attention.
Safety and environment checks. Order matters — each depends on the one before it.
Secure any uncommitted work before touching branches:
git status — if there are ANY uncommitted changes (staged, unstaged, or untracked), commit immediately:
CLAUDE_INVOKING_COMMAND=session-start ~/.claude/plugins/coordinator/bin/coordinator-safe-commit --blanket "chore: session-start sweep — pre-orientation capture"
Do not ask permission. Non-negotiable safety measure.
Before load-bearing work, confirm the EM is on the right model and effort:
medium effort), so say nothing:
bash ~/.claude/plugins/coordinator/bin/check-em-environment.sh
⚠ MODEL DRIFT — not Opus; toggle via /model) and recommend switching before proceeding. (The script also reads the transcript model as a backstop.)On source_is_live machines, coordinator-claude's install IS the source — the operator is the author and never runs /coordinator:setup, so the receipt at ~/.claude/coordinator-setup-state.yaml (the cross-repo chaining gate read by sibling-repo setups) never gets written by the normal path. Self-heal by recording setup_concluded implicitly when the registry confirms source_is_live. Idempotent (first-write-wins), silent on every call, emits no orientation prompt.
~/.claude/plugins/coordinator/bin/coordinator-setup-state.sh auto-record-if-source-is-live
No output to surface. On non-source_is_live machines this is a no-op; on source_is_live machines it writes the receipt once and is a no-op thereafter.
Detect-and-warn only — no auto-reap. Salvage belongs in /workday-start Step 0.6 (runs once per day); session-start fires many times per day and shouldn't move commits between branches as a side-effect of orientation.
~/.claude/plugins/coordinator/bin/agent-worktree-sweep.sh --format text
If any line is emitted (i.e. at least one <repo>/.claude/worktrees/agent-* exists), surface a one-liner:
"{N} agent-isolation worktree(s) on disk — Claude Code auto-creates these for
Agentdispatches and they persist locked until session deletion. Run/workday-startto sweep + salvage, oragent-worktree-sweep.sh --reapto act now."
If no output, skip silently — the common case.
main is read-only. All work — including safety commits — must happen on a work branch. Never commit to main directly.
Get on the right branch:
Push health check: Run git log origin/$(git branch --show-current)..HEAD 2>/dev/null.
If unpushed commits exist, warn: "Found N unpushed commits — auto-push may have failed. Check .git/push-failures.log."
If already on a non-main branch: Report the branch name and continue. Don't switch. "Resuming work on {branch} ({N} commits ahead of main)."
If on main — create a work branch immediately before doing anything else:
git branch --list 'work/{machine}/*'git branch -r --list 'origin/work/{machine}/*'Branch: field.If a branch exists for today (not yet merged):
"Found existing branch work/{machine}/{date}. Resuming."
git checkout {branch}
If no branch for today (or today's was already merged): Run sync-main invariant first:
~/.claude/plugins/coordinator/bin/sync-main.sh --quiet
If it exits non-zero, report the divergence to the PM before creating the branch.
Create: git checkout -b work/{machine}/{date}
If name collision: append suffix: work/{machine}/{date}-2
Note: /workday-start handles branch setup and open-branch consolidation at the start of each workday. If you're starting a new day and workday-start hasn't run yet, the session-start branch creation here is a safety fallback — recommend running /workday-start to also consolidate any open branches from previous days.
Check how long the branch has diverged from main:
git merge-base HEAD origin/maingit log -1 --format=%ci <merge-base-hash>If diverged more than 2 days:
"This branch has been diverged from main for {N} days (since {date}). Long-lived branches accumulate merge risk. I'd recommend merging before new work — want me to run /merge-to-main?"
Wait for the user's response. Do not proceed until the user approves or declines.
If 2 days or fewer: Continue silently.
Load project state into context. These checks are independent of each other.
Read tasks/lessons.md (if it exists) — learned patterns from past corrections. Review every entry.
Read CONTEXT.md (if it exists at the project root) — domain glossary with canonical terms and _Avoid_: synonym lists. If absent, proceed silently — do not flag, suggest, or scaffold.
Note: Project CLAUDE.md and global ~/.claude/CLAUDE.md are already in system context — don't re-read them.
After reading: Note the count. No need to recite principles — they're in CLAUDE.md.
Plugins that ship a doctor skill may write a sentinel at ~/.claude/plugins/<plugin>/data/doctor-last-run.json. Session-start surfaces RED verdicts only — stale-but-green is workday-start's beat, not every-session noise.
~/.claude/plugins/coordinator/bin/scan-addon-health.sh --red-only
~/.claude/plugins/coordinator/bin/scan-addon-health.sh --check-sentinel-presence
If any lines are emitted by either call, surface them verbatim under an Addon Health heading early in the orient output. The --red-only call flags active RED verdicts; the --check-sentinel-presence call emits a one-time bootstrap notice when plugins are installed but no doctor has been run yet (fresh install). The notice is silent on every subsequent session once any sentinel exists. If both calls produce empty output, skip the heading silently.
/project-rag-ue-addon:doctor); the EM may dispatch it directly when surfaced./coordinator:setup and plugin doctors to establish a health baseline.Schema and convention: docs/wiki/addon-health-sentinel.md.
~/.claude/plugins/coordinator/bin/probe-cwd-project-rag-relevance.sh
If it emits any lines, surface them verbatim under a Project-RAG Relevance heading (inline with the Context Load output, separate from Addon Health). If it emits nothing, skip silently — the probe is silent when no project-RAG binding exists for the current cwd.
Run an import probe, then branch on the result. Emit exactly one line into the Context Load output — choose the branch that matches the machine state.
Step 1 — probe import:
python3 -c "import coordinator_whoami"
whoami: not installed (run /coordinator:setup to install the introspection package)
Skip Step 2.Step 2 — read the live session envelope (import succeeded):
python3 -m coordinator_whoami.session 2>/dev/null
Parse the JSON output and inspect binding.kind and status.state.
binding.kind == "unbound": Emit:
whoami: unbound (not in a coordinator-onboarded repo)
binding.kind == "bound": Emit:
whoami: bound → <binding.target> (<status.state>)
where status.state is healthy, degraded, or error — the freshness/reconcile gradient lives on status.state, not on binding.kind.
CLI exits non-zero, or the output is not parseable JSON: Emit:
whoami: degraded (CLI failed; see coordinator-doctor.md probe P-6s)
Canonical full check: docs/wiki/coordinator-doctor.md probe P-6s (the session probe; P-6 remains the project-rag plugin-binding probe — distinct).
Note: the session adopter is the orientation spine — daemon-independent, computed from git+fs. Plugin-specific binding (e.g. project-rag source registration) is surfaced separately and optionally; plugin whoamis are optional ribs, never the orientation spine.
Note: session-start does NOT surface bound-but-cwd-mismatch — that is /project-onboarding's job. Session-start runs every session and would emit false positives for operators working in folders that are not the bound project root.
Run two bin/query-records calls — sub-second by construction, no file walks.
Primary: actionable-now handoffs.
"${HOME}/.claude/plugins/coordinator/bin/query-records.sh" --type handoff \
--where "deployment_state=ready_to_fire AND status=active" \
--sort "-created" --format markdown-list
Report: "Found {N} actionable handoffs (deployment_state=ready_to_fire). Run /pickup <file> to resume one." If empty, say so.
Gated handoffs (always surface count; list when stale).
Two queries — first counts everything awaiting_gate, second lists the stale subset:
"${HOME}/.claude/plugins/coordinator/bin/query-records.sh" --type handoff \
--where "deployment_state=awaiting_gate AND status=active" \
--sort "-created" --format markdown-list
"${HOME}/.claude/plugins/coordinator/bin/query-records.sh" --type handoff \
--where "deployment_state=awaiting_gate AND status=active" \
--older-than 6d --format markdown-list
Reporting rules:
awaiting_gate exist: surface the full list (titles + gate_dependency, not bodies). The PM may want to clear a gate, retarget, or pick one up even before staleness — silently filtering them is what buries actionable work.Rationale: the prior >14-day threshold + "only emit if stale" pattern hid gated handoffs that the PM needed visibility on for cross-workstream planning. Six days is roughly one working week — long enough that a gate that hasn't cleared is worth a glance, short enough to catch drift before it ossifies.
Tracker shortcut. A pre-rendered snapshot of the handoff queue is available at tasks/handoff-tracker.md (written by /session-end and /handoff). Useful for a fast orientation glance; ad-hoc refresh: node plugins/coordinator/bin/render-handoff-tracker.js. Always verify actionable items via the live queries above before acting — the tracker reflects state at the last session exit, not right now.
Stale advisory / call-note markdowns are not pendency. Files in tasks/handoffs/, tasks/, or archive/ that look like live work-items (advisories, call-notes, "next-up.md", deferred-action markdowns) may already be addressed by commits that landed after the file was authored. Before treating any markdown's body as a live action item — even if query-records surfaces it — run git log --oneline --since="<file-mtime>" -- <cited-paths> for the paths it cites. If commits exist on the cited paths since the file's authoring date, the advisory is likely stale; read those commits before re-surfacing the advisory's prescription as live work. Surfacing un-verified stale advisories to the PM as actionable wastes a question.
Acceptance-oracle notice (one-liner, when applicable): When surfacing actionable handoffs or active workstreams, check whether the relevant plan is oracle-bearing (carries a bindable ## Acceptance Criteria table). If so, append a single line to the handoff entry: "Plan carries an acceptance oracle — run bash check-acceptance-oracle.sh <path> for current status." This is informational; do not make it a gate or a hard stop.
Do NOT load, summarize, or act on any handoff. This applies even if there's only one. One handoff is not implicit selection — the PM may not want to pick it up this session, or may have other priorities first. Do NOT set HANDOFF_LOADED. That flag is set ONLY when the PM explicitly directs you to a handoff.
When the PM indicates they want a handoff picked up — by dropping a link, naming it, or saying "pick up that handoff" — read the full file into context. This — and only this — sets HANDOFF_LOADED=true for the Engage section. Alternatively, the PM may use /pickup which is purpose-built for handoff resumption and skips the general orientation ceremony.
Archive lifecycle: /pickup archives the handoff atomically (frontmatter mutation + git mv to archive/handoffs/ + commit, in one operation). Supersession archival happens at /update-docs (chain-aware pass for explicit predecessors named via Continuing from).
Path convention: Active handoffs in tasks/handoffs/, archived in archive/handoffs/. Both git-tracked.
Why query, not grep: deployment_state filters out handoffs that aren't ready for execution — the prior per-file walk surfaced everything regardless of state, which is grep-shaped behavior. Sub-second queryability requires a clear filter; the stale-gate flag preserves the deferred-work signal for awaiting_gate items without forcing them through the primary list.
If tasks/ or archive/ is gitignored: Warn the user — these directories must be tracked. tasks/ contains handoffs and plan docs; archive/ contains the completion history. .claude/ contains only platform-managed files (settings, hooks) and need not be tracked.
Run bash ~/.claude/plugins/coordinator/bin/workday-start-cross-repo-memo-surface.sh. Non-empty output → surface verbatim under heading #### Outstanding cross-repo memos (DoE attention):. Empty → skip silently.
Same surface, same semantics, same helper as /workday-start Step 1.45 — cross-repo memos awaiting this repo's action (status: open) are pendency just like handoffs and deserve the same boot-time visibility. Receiver flips status: open → actioned in place after action. Details: pipelines/workday-start-internals.md § Step 1.45.
Conditional on workday-start: If tasks/.workday-start-marker contains today's date, skip this section — workday-start already reviewed these. If no marker or stale marker, read them as a graceful fallback.
These are operational documents — they tell the EM what's immediately actionable and where the project is headed.
Read each if it exists (first match wins per row), skip silently if not:
| Document | Convention Paths |
|----------|-----------------|
| Action Items | ACTION-ITEMS.md, docs/active/ACTION-ITEMS.md, docs/ACTION-ITEMS.md |
| Roadmap | ROADMAP.md, docs/roadmap.md, docs/ROADMAP.md |
No summary needed — just load them into context. Their content speaks for itself.
Conditional on workday-start: If tasks/.workday-start-marker contains today's date, skip this section — workday-start already reviewed the tracker. If no marker or stale marker, read as a graceful fallback.
Read docs/project-tracker.md (if it exists). This is the strategic tracker that /update-docs maintains — active workstreams, their statuses, dependencies, and blockers.
If it exists: Surface a brief summary:
## Project State
- Active workstreams: [N] — [list names with statuses]
- Blocked items: [N] — [brief description of blockers]
- Ready for execution: [list any items with status Ready/Executing]
This gives the EM visibility into what the project is working on before choosing work in the Engage section. The tracker also informs the work menu — surface tracker items as concrete options alongside the generic categories.
If it doesn't exist: Skip silently.
The SessionStart hook already injected orientation context at boot (cache if fresh, pointers if stale). Do NOT re-read those files here — they're already in context.
If the hook reported no fresh cache, note: "No orientation cache — run /workday-start or /update-docs to generate one." Otherwise, move on silently.
Stale advisory markdowns ≠ pendency. Before treating any tasks/advisory/*.md, tasks/call-notes/*.md, or similarly-named orientation note as a live work item: git log --oneline -- <path> to check authoring and last-touch dates. A markdown that hasn't been touched in >14 days is hypothesis until re-verified against current HEAD — it may describe a state already resolved by subsequent commits.
list-review-trail-records.sh | tail -1) so the EM picks up the chain knowing what was reviewed and where the un-reviewed gap begins.Check if docs/README.md exists. If it does, note briefly: "Documentation index at docs/README.md — [N] wiki guides, [N] research files, [N] plans." (Count by globbing each directory.) This tells the agent and PM that accumulated project knowledge is available.
If docs/README.md does not exist but docs/guides/ or docs/research/ does, note: "Wiki content exists but no docs/README.md index — /update-docs will create one."
If neither exists, skip silently — the project hasn't adopted the wiki system yet.
Fan-out tooling available: fan-out-dispatch.sh (overlap pass + scoped prompt compiler); follow the fan-out methodology to dispatch the compiled wave and hold the EM-serial commit (not a skill — there is no /fan-out command). Use instead of hand-authoring parallel executor prompts. → docs/wiki/dispatching-parallel-agents.md § Executing a Fan-Out Wave.
Conditional on project type: Only for projects where coordinator.local.md declares project_type: game-dev AND project_subtypes contains unreal. Skip silently if either condition is absent.
The capability-catalog (injected at boot) carries the general delegation argument. This section loads the operational routing knowledge needed to delegate effectively in game-dev projects:
Two-tier dispatch model:
| Tier | When | How | |------|------|-----| | 1. Direct | Verification, quick fact-finding, simple one-off mutations | Use your 8 visible tools directly | | 2. Dispatch | Any real work in a single domain | Agent(subagent_type='holodeck-control:ue-{domain}') |
For multi-domain or underspecified tasks, decompose and dispatch domain agents sequentially with verification between steps.
Key constraints:
execute_python_code) is the escape hatch for quick one-liners, not the primary work toolAfter loading, note briefly: "Loaded holodeck delegation context — Tier 2 (domain agents) is the default for real work."
Conditional on MCP availability: Only if project-rag MCP tools are available (check via ToolSearch for mcp__project-rag__project_subsystem_profile). Skip silently if unavailable.
When available, call project_subsystem_profile() with no arguments (list mode) to discover the project's subsystem map. This returns subsystem names with file counts — enough for the EM to know what's available without loading full profiles.
Report briefly: "Project subsystems: {N} available via project_subsystem_profile."
Key behavior change: When you need to understand a subsystem before delegating work, call project_subsystem_profile("<name>") instead of dispatching an Explore agent. The profile returns C++ surface, BP surface, dependencies, and complexity signals — all deterministic SQL at <200ms, replacing 150-300K token Explore dispatches.
Freshness nudge: Also invoke the staleness-survey script. Resolve the plugin CLI path and project root from ~/.claude.json (same resolution as commands/workday-start.md Step 3.6 — do not duplicate threshold logic):
# Resolve plugin CLI path and project root from ~/.claude.json MCP server args
_rag_cli=$(python3 -c "import json,os; d=json.load(open(os.path.expanduser('~/.claude.json'))); args=d['mcpServers']['project-rag']['args']; print(next(a for a in args if a.endswith('.py') or a.endswith('cli')))" 2>/dev/null)
_rag_root=$(python3 -c "import json,os; d=json.load(open(os.path.expanduser('~/.claude.json'))); args=d['mcpServers']['project-rag']['args']; print(args[-1])" 2>/dev/null)
python3 "$_rag_cli" staleness-survey --project-root "$_rag_root" --json
If verdict ≠ current, append one line to the orientation brief:
"Project-RAG last scanned {age}. Verdict: {verdict}. Recommend: {recommendation_command}."
Skip silently if verdict is current, or if either path could not be resolved from ~/.claude.json.
Choose work and load task-specific context.
CRITICAL — Handoff loaded? Check whether the PM has directed you to pick up a handoff (by dropping a link, naming it, or saying to pick it up). Track this as a mental flag: HANDOFF_LOADED=true. If YES:
The handoff IS the work order. Do NOT present a menu. Do NOT ask "what should this agent work on?" Do NOT list the handoff's action items and wait for the user to pick one. Do NOT ask "want me to proceed?"
Instead: read any files the handoff references that aren't yet in context, then immediately begin executing the first action item. You're the next relay runner — the baton has been passed. Pick it up and run.
If the handoff lists multiple next steps, execute them in order unless the PM redirects.
If NO handoff was loaded (PM hasn't directed you to one yet, or no handoffs exist), check for the fresh-install sentinel before presenting the generic menu:
Predicate — fire this branch ONLY when ALL three conditions hold:
~/.claude/.coordinator-fresh-install exists on disk.test -f "$HOME/.claude/.coordinator-fresh-install" && echo "fresh-install" || echo "normal"
If the sentinel exists — fresh-install orientation:
Before doing anything else, consume (delete) the sentinel so this branch does NOT re-fire on subsequent no-handoff sessions:
rm -f "$HOME/.claude/.coordinator-fresh-install"
Then orient the operator toward their ~/.claude meta-repo as the primary surface to evolve:
Welcome — coordinator is installed. Your
~/.claudedirectory is a git-tracked repo that is your live coordinator install. It's the surface you evolve — adding project context, capturing lessons, writing your CLAUDE.md — not the upstreamcoordinator-claudesource.The primary path from here is to
/pickupthe continue-onboarding handoff that the installer left intasks/handoffs/— it walks you through co-writing your CLAUDE.md and running your first/session-starton a real project. If no handoff is visible above, you can start fresh:Suggested first steps:
- Co-write your
~/.claude/CLAUDE.md— personalize your EM persona, coding conventions, and any project-level extensions with the EM's help (just ask)./project-onboardingin your first project repo — sets up tracking, CLAUDE.md, and the post-commit hook./workday-start— run once per day to orient, sweep, and load the day's context.This orientation fires once. The sentinel
~/.claude/.coordinator-fresh-installhas been cleared — subsequent no-handoff sessions will show the standard work menu instead.
Sentinel lifecycle summary (for documentation clarity):
~/.claude/.coordinator-fresh-install.~/.claude/.coordinator-fresh-install is absent, this branch does not fire regardless of handoff state.If the sentinel does NOT exist, fall through to the standard work menu:
What should this agent work on?
~/.claude/tasks/coordinator-improvement-queue.md; local queue: tasks/improvement-queue.md. Surface current depth when framing this option (e.g., "Central: 17 entries, 3 with recurring ≥ 3. Local: 2 entries. Want to tackle some of these?"). Also check tasks/bug-backlog.md — if it exists and has ≥10 open items (P1 + P2 rows, excluding resolved), advocate /bug-blitz as a backlog-grinding option.If $ARGUMENTS is provided, use it to identify the task directly and skip the menu.
Adapt this menu to the project: If the project tracker was loaded, surface its ready/executing items as concrete options. If project-specific plan docs or priority lists exist (check docs/, tasks/, tasks/plans/), surface those too. The menu should reflect what's actually available, not just generic categories.
If continuing from a handoff: Read any files the handoff references that aren't yet in context, then begin the first action item.
If from the menu: Based on the user's choice:
Briefly report:
git status summary — note that uncommitted changes may belong to other concurrent agentsKeep this to 2 lines. This is orientation, not ownership.
tools
Orient session — preflight, load context, choose work
documentation
Wrap up finished work — capture lessons, update docs
development
Triangulate plan-claim / code-reality / review oracles to classify each plan into DELIVERED+REVIEWED / DELIVERED-UNREVIEWED / PARTIAL / IN-FLIGHT / ABANDONED. Run after any crash or 'did we actually finish what we think we finished?' moment.
testing
Check for a published coordinator update and advise a preserve-by-default migration path — never a blind overwrite.