Skill: groundwork
Lays the groundwork every other skill stands on: the per-project configuration (${CLAUDE_PLUGIN_ROOT}/shared/workflow-context.md). Runs once per project; rerunning updates the existing config instead of duplicating it. groundwork writes config as its job — the "offer to persist" write-back protocol governs the other skills when they resolve roles ad hoc. Respond in the conversation language (docs/agents/language.md; not yet configured → mirror the user's language).
Load before acting: ${CLAUDE_PLUGIN_ROOT}/shared/workflow-context.md (the config this skill writes) and ${CLAUDE_PLUGIN_ROOT}/shared/guardrails.md — this skill writes project files; the loading contract applies.
Process
1 — Detect (silent, no questions yet)
Run the capability detection from ${CLAUDE_PLUGIN_ROOT}/shared/workflow-context.md for all four roles plus validation:
- Tracker: tracker MCPs by capability signature (never by server prefix);
git remote -v;gh auth status/glab auth status; existingtasks/directory. - Repo:
git rev-parse --show-toplevel; remote host; base branch —gh repo view --json defaultBranchRef -q .defaultBranchRef.name, falling back togit symbolic-ref refs/remotes/origin/HEAD, thengit ls-remote --symref origin HEAD, then assumemain. If the assumed base doesn't exist locally either (freshgit init), record the current local branch instead and flag the mismatch intracker.mdand the handoff. - Reviewer:
.coderabbit.yamlpresent, orgh pr list --search "reviewed-by:coderabbitai" --state all --limit 5returning results (swap the login to probe other known bots). Treat a failed command and an empty result the same — both mean "no bot detected" (ghsubcommands are inconsistent here: some exit 1, some exit 0 with empty output). Detected bot →watch: onby default; otherwise self-review, no watch. - Notifier: notifier MCPs by capability signature; otherwise chat.
- Validation:
package.jsonscripts — root and per workspace (monorepo signals:workspacesfield,pnpm-workspace.yaml,turbo.json; workspaces declared but empty → record root commands and note it).Makefile; commands declared inCLAUDE.md/AGENTS.md. PR size budget: grep guideline files (CLAUDE.md,GUIDELINES.md,CONTRIBUTING.md) for a declared max-PR-size rule; not found → this is always asked in step 2 (recommended option: "500 changed production lines") — never silently omitted. - Labels:
gh label list(or tracker equivalent); scan.github/workflows/*.ymlfor jobs that fail on missing labels — those labels become therequiredset inlabels.md. - Observability: dependencies and config files (
newrelic,datadog,@sentry/*,prom-client, OpenTelemetry SDKs,winston/pino); dashboards-as-code ininfra/; guideline files. Not detected → leave for lazy resolution (create-tasks asks the first time a card needs it). - Guardrails (Layer 2): guideline files (
CLAUDE.md,AGENTS.md,GUIDELINES.md,CONTRIBUTING.md) for stated conventions; generated-code markers ("do not edit" headers, codegen output dirs) → proposeprotectedentries. - Language: the language the user has been writing in this session — becomes the recommended answer for the conversation-language question in step 2; never silently assumed into config.
If docs/agents/ already exists, load it and treat this run as a review — a three-way reconcile: keep user-edited values unless they name a resource that no longer exists; show removals and additions as one diff; confirm before deleting any key. The ## Agent skills section update in step 4 follows the same never-overwrite-silently rule.
2 — Propose and ask (one batched round; zero only when existing config already answers everything)
Present one summary of detected values. If every open choice resolved by detection or pre-existing config, skip the ask entirely. Otherwise, a single AskUserQuestion (up to 4 questions) covering only the genuinely open choices, detected option first marked "(Recommended)". Typical open choices:
- Tracker when several are viable (e.g. Linear MCP connected and GitHub remote): which platform owns the cards?
- GitHub/GitLab with no tracker MCP: GitHub Issues (recommended) or local Markdown?
- Notifier target when a notifier exists (which channel / DM?).
- PR size budget when no guideline declares one — free numeric choice: offer "500 changed production lines (Recommended)" as the anchor and accept whatever number the team wants (no allowed range — the value is the team's call). Always asked when not detected.
- Conversation language — always asked when not already configured: which language should the pipeline use to talk to you? Recommended option = the language the user is writing in. Skill files are English; the conversation doesn't have to be — the answer goes to
docs/agents/language.mdso every skill in every future session opens in the right language.
3 — Write config
Write docs/agents/ in the project (create the directory if missing). Short prose header + a fenced block of values per file — human-readable, PR-reviewable. Templates:
tracker.md
platform: github-issues # linear | jira | notion | github-issues | gitlab | markdown | ... scope: acme/acme-api # workspace/project/team — or the cards directory for markdown product_docs: docs/product/ base_branch: main language: user # artifact language: user (default) | en | pt-BR | ... — for teams whose cards must be readable by everyone # Mode A (tracker MCP) only — map lifecycle states to the platform's real state names: # states: { todo: "Backlog", in-progress: "In Progress", in-review: "In Review", done: "Done" }
labels.md — write the complete role map from ${CLAUDE_PLUGIN_ROOT}/shared/pr-flow.md § Labels (all state, category and chaos:* roles — omitting rows breaks the "never ask again" promise later), mapping each role to this repo's actual labels; default role = label name. Include the required: set detected in step 1. Pure Markdown tracker with no remote → labels have no platform to live on; write the file as an explicit n/a (markdown mode — frontmatter labels are free-form) instead of a map nobody consumes.
reviewer.md
reviewer: self-review # <bot login> | self-review | human-only watch: off # on = do-task chains into /watch-pr after opening the PR escalation: none # team/handle to request review from when a PR ships over budget (e.g. org/tech-leads)
notifier.md
channel: chat # chat | slack | discord | teams | email target: none # channel/DM id when not chat — personal ids go to user memory, never here
language.md
conversation: pt-BR # language every skill uses to talk to the invoking user — asked by groundwork, never silently assumed. Artifact language (cards/PR comments) lives in tracker.md
validation.md
lint: npm run lint typecheck: npm run typecheck test: npm run test pr_size_budget: 500 # max changed production lines per PR (tests/fixtures/generated excluded) guidelines: AGENTS.md # files every implementation must read first (groundwork step 4 guarantees it exists)
observability.md (write when detected; otherwise create-tasks resolves it lazily — full chain in workflow-context § Observability)
platform: none # newrelic | datadog | grafana | sentry | cloudwatch | otel | none logger: console # detected logger — or pino (Node default suggestion) — or console if the user declined conventions: none # event naming, dashboards-as-code location, alert policy dir
guardrails.md (optional — write only when the project has rules beyond the universal invariants in ${CLAUDE_PLUGIN_ROOT}/shared/guardrails.md)
protected: [] # extra paths skills must never edit (generated code, vendored dirs) forbidden: [] # extra operations beyond the universal invariants notes: none
Personal facts the user gave you (their Slack member ID, DM preferences) go to user memory, never into the repo.
4 — Wire it into every session (every agent)
Write the ## Agent skills section into the project's AGENTS.md (the cross-agent standard — opencode, Codex, Gemini CLI, Cursor and others auto-read it) and into CLAUDE.md (what Claude Code auto-loads). Same stanza in both, created when missing, kept in sync on reruns — and never rewrite anything else in either file:
markdown## Agent skills This project is configured for the ship-it pipeline. Role config lives in docs/agents/ (tracker, labels, reviewer, notifier, validation). Skills must read it instead of asking. Learned project rules are written back there. Conversation language: pt-BR (source of truth: docs/agents/language.md).
This is what makes the config load in every future session — the write-back loop's entry point. The conversation-language line is a deliberate exception to "index only, no values inline": CLAUDE.md/AGENTS.md are auto-loaded at session start, so mirroring the language there means the very first reply is already in the right language — before any skill loads config. docs/agents/language.md stays the source of truth; on reruns the stanza line is regenerated from it.
5 — Handoff
Report: each role → resolved value → source (config — pre-existing / detected / asked / default), files written, and the pipeline order (/create-product → /create-tasks → /do-task → /chaos-engineering). If the notifier resolved to chat, add the fleet warning: unattended/automode runs that park will notify nobody — configure a real notifier before running fleets (autonomy.md). If the user wanted a platform whose MCP isn't connected, give the registration instructions for their environment and remind them a session restart is required — config already written survives the restart.
Guardrails (this skill, on top of shared/guardrails.md)
- Never create labels, projects or channels on any platform — groundwork only maps what exists.
- Never store tokens/secrets in
docs/agents/— connection auth belongs to MCP/CLI config. CLAUDE.md/AGENTS.mdedits are append/update of the## Agent skillssection only; never rewrite the rest.


