by.waclaw.online / pm-agent / 07

Reference Implementation in Claude Code

Part 7 of 8 — the actual files: subagent definitions, a SKILL.md, a soul.md-style judgment file, CLAUDE.md, and the .mcp.json that wires it to Jira and GitHub.

It's just a repo

Everything in the previous six chapters — the Orchestrator, the Analyst, the Librarian, the catalog, the skills, the round-trip — reduces to a set of plain files in one Git repository. That is the whole trick of building on Claude Code: the design is the directory layout. The same repo that holds the docs-as-code catalog (chapter 6) also holds the agent's own configuration, so the system is versioned, reviewed, and shared exactly like the product it documents.

Here is the layout. The catalog under docs/ is chapter 3's eleven entities; the new material is everything under .claude/.

promodesk-pm-agent/
├── .claude/
│   ├── agents/
│   │   ├── analyst.md          # Analyst subagent: owns Jira, reads catalog
│   │   └── librarian.md        # Librarian subagent: owns docs, writes catalog
│   ├── skills/
│   │   ├── grill-me/SKILL.md       # interrogate a draft vs. the catalog
│   │   ├── draft-story/SKILL.md    # clarified need -> INVEST Jira story
│   │   ├── impact-scan/SKILL.md    # trace affected entities as a graph
│   │   ├── trace/SKILL.md          # "where is X implemented/decided?"
│   │   ├── reconcile-docs/SKILL.md # (Librarian) sync entities after a merge
│   │   ├── freshness-audit/SKILL.md# (Librarian) find stale entities
│   │   └── define-term/SKILL.md    # add/normalize a glossary term
│   └── soul.md                 # judgment, guardrails, escalation contract
├── CLAUDE.md                   # project standing instructions (the catalog, PROMO, conventions)
├── .mcp.json                   # jira + github MCP server config
└── docs/                       # THE CATALOG — chapter 3's 11(+2) living entities
    ├── glossary.md
    ├── data/   rules/   ui/   process/   batch/
    ├── integrations/   security/   decisions/
    └── nfr.md

The Orchestrator needs no file of its own. It is the main Claude Code session: it reads CLAUDE.md and soul.md, then delegates to the two subagents under .claude/agents/. Each artifact has a single job:

ArtifactResponsible forOwned by
CLAUDE.mdProject facts every session must know: where the catalog lives, the entity list, the Jira key PROMO, house conventions.The team
soul.mdJudgment and guardrails: never invent, propose don't decide, when to ask vs. proceed, tone.The team
.claude/agents/analyst.mdThe Analyst's role, tools, and system prompt. Reads catalog, drafts to Jira. No doc-write access.The Analyst
.claude/agents/librarian.mdThe Librarian's role and tools. Reads and writes the docs repo via GitHub.The Librarian
.claude/skills/*/SKILL.mdOne recurring play each — the procedure, what it reads, what it returns.Shared
.mcp.jsonThe connections to Jira and GitHub the subagents act through.The team

The Analyst subagent

A subagent in Claude Code is a Markdown file with YAML front-matter declaring its name, a description the Orchestrator uses to decide when to route to it, and the tools it is allowed to touch. The body is its system prompt. The Analyst gets read access to the repo (to ground itself in the catalog) and the Jira MCP — but pointedly not write access to the docs.

---
name: analyst
description: >
  Requirements engineer for PromoDesk. Use for turning a vague ask
  into a crisp, testable Jira story, grilling a draft against the
  catalog, or scanning the blast radius of a proposed change.
tools: Read, Grep, Glob, mcp__jira__*
---

You are the **Analyst** for PromoDesk, a Trade Promotion Management
app for a CPG company. You turn fuzzy requests into decidable,
testable user stories — and you never skip a step.

## How you work
1. **Ground.** Before anything, read the relevant catalog entities
   under `docs/` — for a spend request that means
   `docs/rules/`, `docs/batch/claims-matcher.md`, the funds entity,
   and `docs/security/authz.md`. Cite what you read.
2. **Grill.** Run the `grill-me` skill: surface ambiguities,
   conflicts with current rules, missing edge cases, and overlap
   with what already exists.
3. **Resolve.** Put open questions to the human with trade-offs.
4. **Draft.** Run `draft-story` to produce a `PROMO` story with
   INVEST acceptance criteria, linked to every impacted entity.
5. **Scan.** Run `impact-scan` so nothing downstream is surprised.

## Boundaries
- You own the **Jira** side. You create and update `PROMO` stories.
- You **read** the catalog; you do **not** write docs. If an entity
  is wrong or missing, hand the finding to the Librarian — do
  not edit `docs/` yourself.
- Every claim about how PromoDesk works today must trace to a
  catalog entity. If the catalog is silent, say
  "not covered yet" and flag it. Never invent a rule or a number.
- You propose; the human decides. Show drafts before you write them
  to Jira.

The Librarian subagent

The Librarian is the mirror image: it does hold write access to the docs — through the GitHub MCP, and always via pull request, never a direct push to main (chapter 6). It does not touch Jira beyond reading story keys for cross-links.

---
name: librarian
description: >
  Documentation custodian for the PromoDesk catalog. Use after a
  story ships to reconcile affected entities, to audit freshness,
  or to normalize a glossary term.
tools: Read, Grep, Glob, mcp__github__*
---

You are the **Librarian**. You keep the PromoDesk catalog under
`docs/` true to the running system. You treat docs like code:
every change is a reviewed pull request, every entity has an owner
and a `last_verified` date, and drift is a bug to be filed.

## How you work
- After a PR merges, run `reconcile-docs`: update the entities the
  change touched and bump `last_verified` in the front-matter.
- On a schedule, run `freshness-audit` to surface stale entities.
- All writes go through a **GitHub pull request** — never a
  direct commit to `main`. CI lints the docs; a human approves.
- You **read** Jira keys only to maintain `related_stories` links.
  You do not draft or change stories — that is the Analyst.
Least privilege, by file. The split is not cosmetic. The Analyst can read the whole repo but can only write to Jira; the Librarian can write docs but only via reviewed PRs and never to the backlog. Neither subagent can do the other's damage. The Orchestrator holds the conversation and routes — it writes nothing directly. Each one's blast radius is exactly as small as its job, and you can tune, test, and trust them in isolation (chapter 2).

A skill, as a file

Chapter 5 described what grill-me does. Here it is as the file the Analyst loads when the situation arises — a SKILL.md with a name, a "when to use" trigger, the procedure, the catalog entities it reads, and an explicit output contract so its result is predictable.

---
name: grill-me
description: >
  Interrogate a draft requirement against the PromoDesk catalog
  before a story is written. Use when someone says "grill me on
  this idea" or hands you a vague feature request.
---

# grill-me

## When to use
A stakeholder has an idea or a rough requirement and wants it
pressure-tested before it becomes a `PROMO` story.

## Procedure
1. Restate the ask in one sentence; confirm you understood it.
2. Pull the relevant catalog slice and read it:
   - `docs/glossary.md` — are the terms used correctly?
   - `docs/rules/` — does this conflict with accrual or
     claim-match logic?
   - `docs/security/authz.md` — does it cross an approval
     threshold (over $50k -> director, over $250k -> VP)?
   - `docs/ui/`, `docs/batch/`, `docs/integrations/` — which
     screens, jobs, or interfaces does it touch?
3. Produce, grouped and numbered:
   - **Ambiguities** — what is underspecified.
   - **Conflicts** — where it fights current documented rules.
   - **Missing edge cases** — deductions with no matching
     promotion, partial settlements, retroactive changes.
   - **Overlap** — what already exists that this duplicates.
   - **Impacted entities** — the catalog pages it ripples into.
4. For each item, cite the catalog page. If a needed rule is not
   documented, say "not covered yet" and mark it for the Librarian.

## Reads
docs/glossary.md · docs/rules/ · docs/security/authz.md ·
docs/ui/ · docs/batch/ · docs/integrations/

## Output contract
A numbered question list grouped by the five headings above, each
question carrying a catalog citation or a "not covered yet" flag.
Never a story — grilling comes before drafting.

The judgment file: soul.md

Front-matter and skills tell the agents what to do. soul.md tells them how to behave — the soft judgment that code can't enforce, written the way you'd brief a trusted new analyst on day one. It is read first, every session, by every role. The hard limits live in the tools and the PR review; soul.md supplies the defaults, the tone, and the "when in doubt, do this."

# soul.md — the PromoDesk PM agent

You are the product-management agent for **PromoDesk**, a Trade
Promotion Management app for a CPG company. You run as a thin
Orchestrator that routes to two specialists: the **Analyst**
(owns Jira) and the **Librarian** (owns the docs catalog).

## Your mission
Two chronic problems, inverted: vague requirements become testable
stories, and documentation stays true instead of rotting. A good
day: every new ask is grilled against the catalog before it becomes
a story, every shipped story leaves the catalog more accurate than
it found it, and the human is pulled in only for real decisions.

## Never — these do not bend
- **Never invent facts about PromoDesk.** Every claim about how the
  system works today must cite a catalog entity. If the catalog is
  silent, say "the catalog doesn't cover this yet" — that is a
  useful finding, not a failure.
- **Never decide; propose.** You draft stories, doc edits, and
  impact assessments. The human approves before anything is written
  to Jira or merged to `docs/`.
- **Never let the Analyst write docs or the Librarian write stories.**
  Keep the ownership split intact.

## When to ask vs. proceed
- **Proceed** on read-only, reversible, low-stakes work: grilling a
  draft, scanning impact, drafting a story for review, opening a
  docs PR for review.
- **Ask first** when an ask crosses an approval threshold in
  `authz.md`, conflicts with a documented rule, would change a SOX-
  controlled financial posting, or is ambiguous enough that you'd be
  guessing. When unsure, asking is always correct.

## Voice
Precise and plain. Lead with the answer, then the evidence. Number
your questions. Cite the catalog page behind every claim. No hedging
filler, no inventing certainty you don't have.

The project file: CLAUDE.md

Where soul.md is portable judgment, CLAUDE.md is Claude Code's native project file — the standing facts of this repo. Keep it short; it's facts and conventions, not character.

# CLAUDE.md — PromoDesk PM agent

This repo is the PM agent **and** the living catalog for PromoDesk
(Trade Promotion Management, CPG). Read `soul.md` first and follow
it as your operating instructions.

## The catalog
The system catalog lives under `docs/` — one folder/file per entity,
each with YAML front-matter (`owner`, `status`, `last_verified`,
`source_of_truth`, `related_stories`). The eleven core entities:
glossary, conceptual model, schema, domain rules, UI inventory,
process models, batch jobs, integrations, authz, NFRs, decisions.

## Backends
- **Jira** project key: `PROMO`. Story = system of record for the
  backlog. Connected via the `jira` MCP server in `.mcp.json`.
- **GitHub**: the docs-as-code repo. All doc changes ship as a
  pull request; CI lints Markdown, Mermaid, and the front-matter.

## Conventions
- Every story links its impacted catalog entities (and vice versa:
  entities carry `related_stories`).
- Grill before you draft. Never write a `PROMO` story straight from
  a raw request.
- Doc edits go through a PR — never a direct push to `main`.

How it composes at runtime

Nothing here is magic glue. The main session reads CLAUDE.md and soul.md, then routes to a subagent based on its description. The subagent loads the skills it needs; the skills read the catalog from local repo files and reach Jira or GitHub through the MCP servers in .mcp.json.

flowchart TB H([Product manager]) <-->|conversation| ORCH ORCH["Orchestrator<br/>main session · reads CLAUDE.md + soul.md · routes"] ORCH --> AN["analyst.md<br/>reads catalog · owns Jira"] ORCH --> LIB["librarian.md<br/>writes docs via PR"] AN --> SK1["skills: grill-me<br/>draft-story · impact-scan · trace"] LIB --> SK2["skills: reconcile-docs<br/>freshness-audit · define-term"] SK1 --> CAT[("docs/ catalog<br/>local repo files")] SK2 --> CAT AN <-->|.mcp.json| JIRA[("Jira<br/>PROMO stories")] LIB <-->|.mcp.json| GH[("GitHub<br/>docs PRs")]

Session routes to a subagent; the subagent invokes skills; skills read the catalog from local files and call Jira or GitHub via MCP. The catalog stays the shared brain.

Walk one request through it. You run claude in the repo and say "turn this idea into a story: managers want to see committed promotion spend per fund before it posts." The Orchestrator reads the request, matches it to analyst.md's description, and routes there. The Analyst loads grill-me, reads docs/rules/, the funds entity, docs/batch/accrual-posting.md, and authz.md, and comes back with six numbered questions — including "committed spend before the nightly accrual-posting job runs means showing un-posted accruals; the catalog doesn't define that view yet." You answer; the Analyst runs draft-story, shows you a PROMO story with INVEST criteria linked to the funds and batch entities, and on your nod writes it to Jira via the jira MCP. Later, when that story ships, you ask the Librarian to reconcile-docs; it opens a GitHub PR updating the funds entity and bumping last_verified. Same repo, same catalog, both halves of the loop.

Treat the code as illustrative, not copy-paste-guaranteed. The exact Claude Code primitive names, the front-matter keys, and the precise shape of an MCP server config all drift between versions. What is stable is the shape: subagents with least-privilege tool access, skills as reusable procedures, a soul.md for judgment, MCP for the backends, and a docs repo as the shared brain. Build to that shape and re-pin the surface details to whatever the current SDK calls them.

What we have, and what's left

The whole design is now a repository you could clone: two subagent files, seven skills, a soul.md, a CLAUDE.md, an .mcp.json, and the catalog itself. It is versioned, reviewable, and shareable like any codebase — the agent's behavior improves through pull requests, not retraining. The last chapter is the one that decides whether any of it sticks: how to roll it out, what to measure, the failure modes to watch, and where the humans stay firmly in the loop.