feat(pm-product): agent-harness upgrade for product-team + project-management + agentic audit

Deep audit of both domains against the AR v1 agentic-readiness rubric
(audit/pm-product-agentic-2026-07/: master + per-domain reports + research-backed
improvement fields + research digest), plus the harness layer the audit motivated:

- pm-skills rebuilt as a context:fork orchestrator with an agentic delivery loop:
  pm_goal_router.py (8 lanes, exit-code route/ask/refuse), jira_snapshot_bridge.py
  (searchJiraIssuesUsingJql output -> Kanban Guide 2025 flow metrics with SLE +
  aging-WIP alerts + seeded Monte Carlo forecasts, or scrum-master sprint schema —
  verified end-to-end into velocity_analyzer.py), delivery_loop_gate.py (G1-G6
  delegation governance: human owner, reviewer for agent tasks, machine-checkable
  acceptance, evidence-before-done, close refusal, exhausted-budget-is-escalation).
- product-skills rebuilt as a context:fork orchestrator with the continuous-discovery
  loop: product_goal_router.py (16 lanes incl. standalone plugins),
  discovery_cadence_tracker.py (Torres weekly-habit health 0-100 with named gaps),
  ost_linter.py (O1-O5 Opportunity Solution Tree structural gates).
- 6 new references citing 6-7 sources each (flow/forecasting canon, agentic delivery
  governance, PM loop playbook, continuous discovery, product operating model,
  AI product evals); pinned fixtures (expected_flow_metrics.json, sample OST/log).
- cs-pm-orchestrator + cs-product-orchestrator agents; /cs:pm, /cs:grill-pm,
  /cs:pm-loop, /cs:product, /cs:grill-product, /cs:product-loop commands.
- Fixed the two CLI-noncompliant product tools (user_story_generator.py,
  persona_generator.py): real argparse --help, seeded determinism, backward-compatible
  positionals.
- Regenerated agent-harness manifests for both domains (orchestrators now score all
  five agentic_signals); updated domain CLAUDE.mds, plugin manifests (2.10.4),
  marketplace entries, and headline counters (602 tools / 731 references / 99 agents /
  109 commands; derive_counters --check passes).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Uzm8dKoeXPayJVMojpSbw
This commit is contained in:
Claude 2026-07-03 06:41:46 +00:00
parent bdd19a1361
commit 46bb258a94
No known key found for this signature in database
43 changed files with 3240 additions and 139 deletions

View file

@ -8,7 +8,7 @@
"homepage": "https://github.com/alirezarezvani/claude-skills",
"repository": "https://github.com/alirezarezvani/claude-skills",
"metadata": {
"description": "355 production-ready skills across 18 domains (engineering, engineering-core, marketing, product, c-level, compliance-os, project management, RA/QM, business growth, finance, productivity, marketing top-level, research, research-ops, business-operations, commercial, markdown-html, loop-library, plus standards). 596 Python tools, 725 reference guides, 97 agents (cs-* + personas), 103 slash commands across 83 marketplace plugins. v2.10.3 completes the markdown-html domain with md-slides — slide-deck converter (arrow-key / Space / PgDn / Home/End / P keyboard navigation + presenter mode with split-view clock + speaker notes + next-slide preview + URL-hash deep linking like #3 for direct slide jumps + @media print page-per-slide for browser-native PDF export). Reuses md-document's markdown parser; vanilla JS only (no framework runtime); Prism.js opt-in via --syntax. Joins md-review (v2.10.2 code-review converter), md-document (v2.10.1 long-form converter), and the v2.10.0 foundation (orchestrator + design-system). Compatible with Claude Code, Codex CLI, Gemini CLI, Cursor, OpenClaw, Hermes Agent, Mistral Vibe, and 5 more coding agents.",
"description": "355 production-ready skills across 18 domains (engineering, engineering-core, marketing, product, c-level, compliance-os, project management, RA/QM, business growth, finance, productivity, marketing top-level, research, research-ops, business-operations, commercial, markdown-html, loop-library, plus standards). 602 Python tools, 731 reference guides, 99 agents (cs-* + personas), 109 slash commands across 83 marketplace plugins. v2.10.4 turns product-team and project-management into agent-harness domains: fork-orchestrators with deterministic goal routers, a Jira MCP snapshot bridge (Kanban flow metrics + Monte Carlo forecasting), a delegation-governance loop gate, a continuous-discovery cadence tracker, and an Opportunity Solution Tree linter, with /cs:pm and /cs:product command families. v2.10.3 completes the markdown-html domain with md-slides — slide-deck converter (arrow-key / Space / PgDn / Home/End / P keyboard navigation + presenter mode with split-view clock + speaker notes + next-slide preview + URL-hash deep linking like #3 for direct slide jumps + @media print page-per-slide for browser-native PDF export). Reuses md-document's markdown parser; vanilla JS only (no framework runtime); Prism.js opt-in via --syntax. Joins md-review (v2.10.2 code-review converter), md-document (v2.10.1 long-form converter), and the v2.10.0 foundation (orchestrator + design-system). Compatible with Claude Code, Codex CLI, Gemini CLI, Cursor, OpenClaw, Hermes Agent, Mistral Vibe, and 5 more coding agents.",
"version": "2.10.3"
},
"plugins": [
@ -316,8 +316,8 @@
{
"name": "product-skills",
"source": "./product-team",
"description": "13 product skills with 17 Python tools: product manager toolkit (RICE, PRDs), agile product owner, product strategist, UX researcher, UI design system, competitive teardown, landing page generator, SaaS scaffolder, product analytics, experiment designer, product discovery, roadmap communicator, code-to-prd, research summarizer, apple-hig-expert.",
"version": "2.9.0",
"description": "13 bundled product skills with 22 Python tools: product-skills fork-orchestrator with continuous-discovery loop (deterministic 16-lane router, Torres cadence tracker, OST linter, /cs:product + /cs:grill-product + /cs:product-loop), product manager toolkit (RICE, PRDs), product strategist, UX researcher, UI design system, competitive teardown, landing page generator, SaaS scaffolder, product analytics, experiment designer, product discovery, roadmap communicator, spec-to-repo. Companion standalone plugins: agile-product-owner, code-to-prd, apple-hig-expert, research-summarizer.",
"version": "2.10.4",
"author": {
"name": "Alireza Rezvani"
},
@ -343,8 +343,8 @@
{
"name": "pm-skills",
"source": "./project-management",
"description": "9 project management skills with 12 Python tools: senior PM, scrum master, Jira expert, Confluence expert, Atlassian admin, template creator.",
"version": "2.9.0",
"description": "9 project management skills with 15 Python tools: pm-skills fork-orchestrator with agentic delivery loop (deterministic 8-lane router, Jira MCP snapshot bridge to Kanban flow metrics + Monte Carlo forecasts, delegation-governance gate, /cs:pm + /cs:grill-pm + /cs:pm-loop), senior PM, scrum master, Jira expert, Confluence expert, Atlassian admin, template creator, meeting analyzer, team communications. Bundled Atlassian Remote MCP.",
"version": "2.10.4",
"author": {
"name": "Alireza Rezvani"
},

View file

@ -6,7 +6,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
This is a **comprehensive skills library** for Claude AI and Claude Code - reusable, production-ready skill packages that bundle domain expertise, best practices, analysis tools, and strategic frameworks. The repository provides modular skills that teams can download and use directly in their workflows.
**Current Scope:** 355 production-ready skills across 18 domains with 596 Python automation tools, 725 reference guides, 97 agents (cs-* + 7 personas), and 103 slash commands, distributed as 83 marketplace plugins. Headline counters are derived from the tree by `scripts/derive_counters.py` (run with `--check` to verify the docs still match). **v2.9.0 (complete)** added the **research-ops/** top-level domain — enterprise Research Operations (orchestrator + clinical-research + research-finance + market-research + product-research), the managed counterpart to the academic research/ domain, with `context: fork` orchestration and a Matt Pocock "Forcing-question library" in every SKILL.md plus `/cs:grill-research-ops`. **v2.8.0 (complete)** added 2 new top-level domains — **business-operations/** (7 internal-ops skills: orchestrator + process-mapper + vendor-management + capacity-planner + internal-comms + knowledge-ops + procurement-optimizer) and **commercial/** (8 per-deal-economics skills: orchestrator + pricing-strategist + deal-desk + partnerships-architect + channel-economics + commercial-policy + rfp-responder + commercial-forecaster) — with orchestrator skills using `context: fork` for chaining, Matt Pocock docs-anchored "Forcing-question library" in every SKILL.md, plus `/cs:grill-bizops` and `/cs:grill-commercial`. **v2.8.2** adds a productivity-shaped `handoff` skill (sibling to engineering/handoff) inspired by Matt Pocock — first-run setup with configurable save location, redaction linter, SessionStart + SessionEnd hooks, fidelity self-check, `--refresh` flag. **v2.8.1** upgraded the engineering role-skills (senior-fullstack / senior-frontend / senior-backend) with karpathy-coder + Matt Pocock decision engines + per-role forcing questions. v2.7.3 ports `alirezarezvani/aeo-box` — AEO (Answer Engine Optimization) skill into marketing-skill/ + security-guidance PreToolUse hook into engineering/. v2.7.0 added 13 Path-B skills across 3 top-level domains (productivity, marketing, research). v2.6.0 added 4 Matt Pocock-derived productivity skills.
**Current Scope:** 355 production-ready skills across 18 domains with 602 Python automation tools, 731 reference guides, 99 agents (cs-* + 7 personas), and 109 slash commands, distributed as 83 marketplace plugins. Headline counters are derived from the tree by `scripts/derive_counters.py` (run with `--check` to verify the docs still match). **v2.10.4 (current)** upgrades **product-team/** and **project-management/** into agent-harness domains: both prose routers rebuilt as `context: fork` orchestrators with deterministic goal routers (exit-code route/ask/refuse), a Jira MCP snapshot bridge (Kanban-Guide-2025 flow metrics + seeded Monte Carlo forecasts, verified end-to-end into velocity_analyzer), a delegation-governance loop gate (human owner / reviewer / machine-checkable acceptance / close refusal), a Torres continuous-discovery cadence tracker + Opportunity Solution Tree linter, cs-pm-orchestrator + cs-product-orchestrator agents, and /cs:pm|grill-pm|pm-loop + /cs:product|grill-product|product-loop commands — plus the public audit record `audit/pm-product-agentic-2026-07/` (AR-rubric scores for all 26 skills, research-backed improvement fields, executable verification criteria). **v2.9.0 (complete)** added the **research-ops/** top-level domain — enterprise Research Operations (orchestrator + clinical-research + research-finance + market-research + product-research), the managed counterpart to the academic research/ domain, with `context: fork` orchestration and a Matt Pocock "Forcing-question library" in every SKILL.md plus `/cs:grill-research-ops`. **v2.8.0 (complete)** added 2 new top-level domains — **business-operations/** (7 internal-ops skills: orchestrator + process-mapper + vendor-management + capacity-planner + internal-comms + knowledge-ops + procurement-optimizer) and **commercial/** (8 per-deal-economics skills: orchestrator + pricing-strategist + deal-desk + partnerships-architect + channel-economics + commercial-policy + rfp-responder + commercial-forecaster) — with orchestrator skills using `context: fork` for chaining, Matt Pocock docs-anchored "Forcing-question library" in every SKILL.md, plus `/cs:grill-bizops` and `/cs:grill-commercial`. **v2.8.2** adds a productivity-shaped `handoff` skill (sibling to engineering/handoff) inspired by Matt Pocock — first-run setup with configurable save location, redaction linter, SessionStart + SessionEnd hooks, fidelity self-check, `--refresh` flag. **v2.8.1** upgraded the engineering role-skills (senior-fullstack / senior-frontend / senior-backend) with karpathy-coder + Matt Pocock decision engines + per-role forcing questions. v2.7.3 ports `alirezarezvani/aeo-box` — AEO (Answer Engine Optimization) skill into marketing-skill/ + security-guidance PreToolUse hook into engineering/. v2.7.0 added 13 Path-B skills across 3 top-level domains (productivity, marketing, research). v2.6.0 added 4 Matt Pocock-derived productivity skills.
**Key Distinction**: This is NOT a traditional application. It's a library of skill packages meant to be extracted and deployed by users into their own Claude workflows.
@ -537,6 +537,6 @@ This repository publishes skills to **ClawHub** (clawhub.com) as the distributio
---
**Last Updated:** June 10, 2026
**Version:** v2.10.3
**Status:** 345 skills deployed across 17 domains, 78 marketplace plugins, docs site live (counters derived via `scripts/derive_counters.py`)
**Last Updated:** July 3, 2026
**Version:** v2.10.4
**Status:** 355 skills deployed across 18 domains, 83 marketplace plugins, docs site live (counters derived via `scripts/derive_counters.py`)

View file

@ -26,10 +26,10 @@ The most comprehensive open-source library of Claude Code skills and agent plugi
Claude Code skills (also called agent skills or coding agent plugins) are modular instruction packages that give AI coding agents domain expertise they don't have out of the box. Each skill includes:
- **SKILL.md** — structured instructions, workflows, and decision frameworks
- **Python tools**596 CLI scripts (all stdlib-only, zero pip installs)
- **Python tools**602 CLI scripts (all stdlib-only, zero pip installs)
- **Reference docs** — 711 templates, checklists, and domain-specific knowledge files
**One repo, thirteen platforms.** Works natively as Claude Code plugins, Codex agent skills, Gemini CLI skills, Hermes Agent skills, Mistral Vibe skills, and converts to more tools via `scripts/convert.sh`. All 596 Python tools run anywhere Python runs.
**One repo, thirteen platforms.** Works natively as Claude Code plugins, Codex agent skills, Gemini CLI skills, Hermes Agent skills, Mistral Vibe skills, and converts to more tools via `scripts/convert.sh`. All 602 Python tools run anywhere Python runs.
### Skills vs Agents vs Personas
@ -354,7 +354,7 @@ Yes. Skills work natively with 13 tools: Claude Code, OpenAI Codex, Gemini CLI,
No. We follow semantic versioning and maintain backward compatibility within patch releases. Existing script arguments, plugin source paths, and SKILL.md structures are never changed in patch versions. See the [CHANGELOG](CHANGELOG.md) for details on each release.
**Are the Python tools dependency-free?**
Yes. All 596 Python CLI tools use the standard library only — zero pip installs required. Every script is verified to run with `--help`.
Yes. All 602 Python CLI tools use the standard library only — zero pip installs required. Every script is verified to run with `--help`.
**How do I create my own Claude Code skill?**
Each skill is a folder with a `SKILL.md` (frontmatter + instructions), optional `scripts/`, `references/`, and `assets/`. See the [Skills & Agents Factory](https://github.com/alirezarezvani/claude-code-skills-agents-factory) for a step-by-step guide.

View file

@ -0,0 +1,123 @@
# Master report — Product & PM agentic-loop audit + domain harness upgrade
**Audited:** 2026-07-03 · **Branch:** `claude/pm-audit-agentic-loops-jxurlq` ·
**Scope:** both product/project domains — `product-team/` (17 skills) and
`project-management/` (9 skills) — deep-audited on quality AND scored on the
**agentic-readiness** rubric established by the engineering audit
([../engineering-agentic-2026-07/](../engineering-agentic-2026-07/00-MASTER.md)).
Plus: both domains upgraded into **agent harnesses** — fork-orchestrators with
deterministic routers, reusable loops, machine-checkable verification gates, and
integration with the repo-wide `engineering/agent-harness` framework.
**Method:** (1) two parallel deep-dive agents read every SKILL.md, smoke-tested all 31
scripts, and cross-referenced agents/commands/manifests; (2) one explorer mapped the
repo's harness conventions (loop-library contract, agent-harness state machine,
fork-orchestrator pattern) so the upgrade reuses rather than reinvents; (3) one research
agent web-verified the 20242026 PM/product/harness canon
([research-digest.md](research-digest.md)).
---
## 1. The two questions
The June 2026 audit asked: does each skill earn its context window? This audit asks the
engineering follow-up question for these two domains: **can an agent pick up a goal here
and drive it to a verified close?** — and additionally: **what should these domains
teach that the 20242026 canon now demands?**
([improvement-fields.md](improvement-fields.md) answers the second.)
## 2. Combined scorecard (26 skills, post-PR)
| Class | product-team | project-management | Total | Meaning |
|---|---|---|---|---|
| **HARNESS-READY** (≥9, AR4≥1, AR5≥1) | 2 | 1 | **3** | An agent can loop this today |
| **LOOP-CAPABLE** (68) | 4 | 4 | **8** | One or two additions away |
| **TOOL-ONLY** (35) | 11 | 3 | **14** | Good tools, no loop spine |
| **PROSE-ONLY** (02) | 0 | 1 | **1** | Needs structural rebuild |
Pre-PR both domain routers were PROSE-ONLY (score ≤ 1) and neither domain had a single
`context: fork`, forcing question, iteration cap, or `/cs:*` command — they predate every
v2.8+ convention. The weakest dimensions mirror engineering exactly: **AR5 loop
discipline** (zero caps anywhere pre-PR) and **AR1 goal intake** (most skills accept any
input silently).
## 3. The three biggest findings
1. **The MCP↔analytics gap (project-management).** The domain bundles a live Jira MCP
and ships real analytics tools, with no data path between them — sprint health and
velocity ran on hand-typed JSON. Fixed: `jira_snapshot_bridge.py` converts saved
`searchJiraIssuesUsingJql` results into the scrum-master schema (verified end-to-end
into velocity_analyzer) and computes the four Kanban-Guide-2025 flow metrics + seeded
Monte Carlo forecasts the domain never had.
2. **Verification exists but nothing binds it (both domains).** spec-to-repo's
validator, code-to-prd's golden outputs, scrum-master's pinned fixtures,
atlassian-admin's 7 VERIFY steps — good gates, all optional, none looped. Fixed at
the orchestration layer: plans are gated before execution and closes are refused
(exit 4) while tasks are unverified/unwaived; per-skill binding is follow-up F3.
3. **The canon moved (both domains).** No continuous-discovery cadence, no OST
discipline, no AI-feature evals, no flow metrics, no probabilistic forecasting, no
agentic-delegation governance, and 60 of 64 reference files cite zero sources. This
PR ships the two highest-leverage tool fields per domain plus six cited reference
docs; the remaining 14 fields are enumerated with tool specs in
[improvement-fields.md](improvement-fields.md).
## 4. What this PR ships: two domain harnesses
Both prose routers were rebuilt as `context: fork` orchestrators that plug into
`engineering/agent-harness` (manifests regenerated; both orchestrators now score all
five `agentic_signals`):
**project-management → `pm-skills`** — the *delivery loop*:
`pm_goal_router.py` (8 lanes, exit 0/2/3 — route/ask/refuse) ·
`jira_snapshot_bridge.py` (MCP snapshot → flow metrics | sprint schema; SLE conformance,
aging-WIP alerts, `--forecast` Monte Carlo, refuses thin history) ·
`delivery_loop_gate.py` (delegation governance G1G6: human owner, reviewer for agent
tasks, machine-checkable acceptance, evidence-before-done, close refusal,
exhausted-budget-is-escalation). Five reusable PM loops (sprint-flow, health,
retro-action, RAID-hygiene, comms) documented with terminal states. Agent
`cs-pm-orchestrator`; commands `/cs:pm`, `/cs:grill-pm`, `/cs:pm-loop`.
**product-team → `product-skills`** — the *discovery loop*:
`product_goal_router.py` (16 lanes incl. the 4 standalone plugins) ·
`discovery_cadence_tracker.py` (Torres weekly-habit scoring: streak, coverage, outcome
linkage, test throughput → health 0100 with named gaps and a `next_loop_action`) ·
`ost_linter.py` (O1O5: measurable outcome root, needs-not-features, ≥2 solutions per
target, tests per solution, no orphan solutions — exit 2 blocks the tree from driving a
roadmap). Graduation stop-states hand validated assumptions to experiment-designer/PRD.
Agent `cs-product-orchestrator`; commands `/cs:product`, `/cs:grill-product`,
`/cs:product-loop`.
Also fixed: the two CLI-noncompliant product tools (`user_story_generator.py`,
`persona_generator.py` — real argparse `--help`, seeded determinism, backward-compatible
positionals); domain CLAUDE.md counters; plugin manifests + marketplace descriptions.
All 8 new/changed tools pass `--help` and `--sample`; fixtures pinned
(`expected_flow_metrics.json`; sample OST with two planted violations). Every design
decision traces to the loop-library contract, the agent-harness invariants (locked
gates, evidence-before-status, budgets-as-terminal-states), and the cited canon.
## 5. Per-domain reports
- [product-team.md](product-team.md) — 17 skills, AR table, 7 domain findings,
executable verification criteria.
- [project-management.md](project-management.md) — 9 skills, AR table, 6 domain
findings, executable verification criteria.
- [improvement-fields.md](improvement-fields.md) — the per-field improvement rollup
(11 cross-domain/delivery/product fields shipped or specced + documentation debt).
- [research-digest.md](research-digest.md) — the web-verified 20242026 canon.
- [RUBRIC.md](RUBRIC.md) — the AR rubric as applied here.
## 6. Recommended follow-up PRs (in leverage order)
1. **Loop-cap sweep** — one-sentence caps in scrum-master, jira-expert, code-to-prd,
research-summarizer (~4 skills → HARNESS-READY).
2. **Bind the gates** — make spec-to-repo's validator and code-to-prd's goldens
*required*; name the bridge in scrum-master/senior-pm SKILL.mds.
3. **AI-evals tool** (Fh) — eval-spec linter + kappa calculator; the single
most-demanded missing PM competency.
4. **Path-B completion** — meeting-analyzer scripts (its spec is deterministic math),
team-communications linter, product-discovery references.
5. **Documentation truth** — product-team README (3 conflicting counts, 9 broken paths),
project-management legacy trio, citation back-fill (F9/F10).
6. **Remaining improvement fields** — DORA/EBM/pre-mortem/RACI (delivery); NSM/PLG
bands/WSJF/ODI/taxonomy linter (product), per the specs in improvement-fields.md.

View file

@ -0,0 +1,30 @@
# Agentic-Readiness Rubric (AR v1) — as applied to product-team + project-management
Audit date: 2026-07-03 · Branch: `claude/pm-audit-agentic-loops-jxurlq`
This audit applies the **same AR v1 rubric** established by the engineering agentic audit
([../engineering-agentic-2026-07/RUBRIC.md](../engineering-agentic-2026-07/RUBRIC.md)) —
six dimensions scored 02, answering: **can an agent pick this skill up with a goal and
drive it to a verified close?**
| # | Dimension | 2 means |
|---|---|---|
| AR1 | Goal intake | Forcing questions / intake tool / refuses vague input (exit-code gate) |
| AR2 | Task decomposition | Explicit planning step or tool whose output the workflow consumes |
| AR3 | Deterministic execution | Exact runnable CLIs; output consumed by a named next step |
| AR4 | Verification | Machine-checkable gate the workflow REQUIRES before proceeding |
| AR5 | Loop discipline | Iteration caps, stop conditions, escalation thresholds |
| AR6 | Close-out | Definition of done + state persistence or handoff artifact |
Classes: **HARNESS-READY** (total ≥ 9 AND AR4 ≥ 1 AND AR5 ≥ 1) · **LOOP-CAPABLE** (68,
or ≥ 9 failing the AR4/AR5 gate) · **TOOL-ONLY** (35) · **PROSE-ONLY** (02).
Baseline reference: the June 2026 quality audit of these domains lives at
[../newgen-2026-06/product-pm.md](../newgen-2026-06/product-pm.md); this audit scores the
new agentic dimension and ships the domain harness layer that the scores motivated.
Executable enforcement: the regenerated domain manifests
(`engineering/agent-harness/skills/agent-harness/assets/harnesses/{product-team,project-management}.json`)
record per-skill `agentic_signals`; the two new domain orchestrators (`product-skills`,
`pm-skills`) enforce AR1 (routers with exit-code gates), AR4 (delivery gate / OST linter),
and AR5/AR6 (harness budgets + close refusal) at run time.

View file

@ -0,0 +1,66 @@
# Improvement fields — where investment moves each domain most
Research-backed rollup (sources in [research-digest.md](research-digest.md)) of the
fields where the 20242026 canon moved past the two domains' current coverage, ordered
by leverage. Fields marked ✅ shipped in this PR; the rest are the follow-up work list,
each with what a deterministic stdlib tool computes.
## Cross-domain (the harness fields)
- **F1 — Loop discipline (AR5)***(orchestrator layer)* / open *(per skill)*. Both
domains had zero iteration caps or stop conditions. Shipped: the two orchestrators
carry budgets (3 attempts/task, 12 iterations/goal), named terminal states, and close
refusal. Open: the one-sentence cap pattern ("max N fix-rerun cycles, then escalate")
ported into scrum-master, jira-expert, code-to-prd, research-summarizer — the four
skills one sentence away from HARNESS-READY.
- **F2 — Goal intake (AR1)***(routers)* / open *(per skill)*. Both routers refuse
fuzz with exit codes (2/3); grill commands lock decisions before execution. Open:
refuse-on-missing-inputs blocks in the 14 tool-rich skills that still accept anything.
- **F3 — Bind existing gates** — open, cheapest wins: spec-to-repo's validator and
code-to-prd's goldens exist but aren't *required*; scrum-master/senior-pm SKILL.mds
should name the bridge as their data path (one line each).
## Project-management (delivery) fields
| # | Field | Status | Deterministic tool |
|---|---|---|---|
| F4 | Four Kanban flow metrics + SLE + aging-WIP alerts (Kanban Guide 2025) | ✅ `jira_snapshot_bridge.py --to flow` | WIP, throughput, cycle p50/85/95, work-item age, SLE conformance |
| F5 | Monte Carlo probabilistic forecasting (Vacanti; replaces story-point dates) | ✅ `--forecast N` (seeded; refuses < 10 items) | p50/70/85/95 week ranges |
| F6 | Agentic delegation governance (Linear/Rovo model) | ✅ `delivery_loop_gate.py` | owner/reviewer/acceptance/evidence/close rules G1G6 |
| Fa | DORA 2025 archetypes + AI-amplifier capabilities check | open | four keys from deploy/incident logs → archetype + enabling-capabilities score |
| Fb | EBM (Scrum.org) four Key Value Areas scorecard | open | map existing metrics → KVA coverage, flag empty CV/UV |
| Fc | Pre-mortem processor (Klein) + RAID hygiene linter | open (playbook documents the loops) | cluster failure reasons → owned risk entries; staleness/owner/mitigation lint |
| Fd | Derived project health vs self-reported RAG ("watermelon" diff) | partial (senior-pm dashboard + bridge signals) | composite from schedule variance, aging WIP, scope churn — diffed against RAG |
| Fe | Async-first meeting audit (GitLab canon) | open | calendar export → async-convertibility classes, recoverable hours |
| Ff | Agent-readiness audit of Jira hygiene (Rovo-era) | open | field completeness %, acceptance-criteria presence, stale statuses → delegation-readiness score |
| Fg | RACI validator | open | exactly-one-A, ≥1 R, overload histogram |
## Product-team fields
| # | Field | Status | Deterministic tool |
|---|---|---|---|
| F7 | Continuous-discovery cadence (Torres weekly habit) | ✅ `discovery_cadence_tracker.py` | streak, coverage, outcome linkage, test throughput → health 0100 |
| F8 | Opportunity Solution Tree structural linting | ✅ `ost_linter.py` | rules O1O5 (measurable root, needs-not-features, ≥2 solutions, tests, no orphans) |
| Fh | **AI-feature evals as the PRD quality contract** — the single biggest gap per every 20252026 source | reference shipped (`ai_product_evals.md`); tool open | eval-spec linter: golden-set floors, rubric pass-criteria, guardrail SLOs; Cohen's kappa on grader agreement |
| Fi | WSJF / cost-of-delay with rank-stability sensitivity (brackets RICE) | reference shipped (`product_operating_model.md`); tool open | CoD/duration ranking; ±1-step perturbation flags rank flips |
| Fj | Opportunity scoring (Ulwick ODI importancesatisfaction) | open | Opp Score per outcome statement from survey CSV |
| Fk | North Star Metric validator + input tree (Amplitude) | open | leading/value/not-vanity checks; input→NSM correlation |
| Fl | PLG funnel benchmark bands (ProductLed/OpenView) | open | stage conversion vs calibrated bands → weakest-stage verdict |
| Fm | Product operating model maturity (Cagan *Transformed*) | open | questionnaire → per-principle 0100 gap list |
| Fn | Event-taxonomy / tracking-plan linter (PostHog-era) | open | snake_case, verb allowlist, near-duplicate detection |
| Fo | JTBD switch-interview force coder (Moesta) | open | four-forces lexicon coding, force balance per interview |
| Fp | Story-map validator (Patton) | open | every story on the backbone; slices span end-to-end |
| Fq | Model-card completeness checker (Mitchell et al.) | open | nine canonical sections → completeness % |
## Documentation-debt fields
- **F9 — Source citations**: 60 of 64 pre-PR reference files across both domains cite
zero sources (six new references cite 67 each). Back-fill priority: scrum-master and
senior-pm references (the canon exists — Vacanti, Kanban Guide, DORA, PMBOK).
- **F10 — Counter/path truth**: product-team README (3 conflicting counts, 9 broken
paths), project-management legacy trio (README / IMPLEMENTATION_SUMMARY /
REAL_WORLD_SCENARIO all say "6 skills"), `.codex/instructions.md` broken paths in both
domains. Domain CLAUDE.mds fixed this PR.
- **F11 — Path-B completion**: meeting-analyzer (0 scripts/refs/assets — its own spec is
deterministic math), team-communications (0 scripts, 155 lines of references),
product-discovery (1 reference), 8 asset-less product skills.

View file

@ -0,0 +1,98 @@
# Domain audit: product-team/ — deep audit + agentic readiness
Audited: 2026-07-03 · 17 skills (13 under `skills/` incl. the router, 4 standalone
plugins) · 19 Python tools (all 19 pass `--help`, functional smoke tests on
sample_size_calculator and hig_checker reproduce correct math) · 5 agents + 1 persona ·
8 slash commands · 5 plugins (all `check_plugin_json.py`-clean).
Rubric: [RUBRIC.md](RUBRIC.md). Method: full SKILL.md reads, script smoke tests,
agent/command cross-referencing, counter verification.
## Summary
**Headline finding (now fixed in this PR): no orchestrator, no loop layer.** Before this
PR the domain had zero `context: fork`, zero forcing-question libraries, no `/cs:*`
router/grill commands, and its "router" (`product-skills`, 61 lines) shipped no tools —
the domain predated every v2.8+ convention. Three skills (spec-to-repo, code-to-prd,
research-summarizer) independently invented verification loops; nothing unified them.
**Agentic-readiness distribution (17 skills, post-PR):** HARNESS-READY **2**
(product-skills upgraded 1→12; spec-to-repo) · LOOP-CAPABLE **4** (product-manager-toolkit,
apple-hig-expert, code-to-prd, research-summarizer) · TOOL-ONLY **11** · PROSE-ONLY **0**.
Weakest dimensions domain-wide: **AR5 loop discipline** (only spec-to-repo has any
retry/stop language) and **AR1 goal intake** (14 of 17 accept any input silently).
## Per-skill table
Scores AR1·AR2·AR3·AR4·AR5·AR6 (post-PR where this PR changed the skill).
| Skill | AR1-6 | Tot | Class | Top improvement |
|---|---|---|---|---|
| skills/product-skills (orchestrator) | 2·2·2·2·2·2 | 12 | HR | (upgraded this PR: was a 61-line prose router, PROSE-ONLY) |
| skills/spec-to-repo | 1·2·2·2·1·1 | 9 | HR | Wire to an agent + command (currently orphaned from both) |
| skills/product-manager-toolkit | 1·1·2·1·0·1 | 6 | LC | Make the PRD checklist a blocking gate; add WSJF/CoD lane + eval-spec PRD section |
| code-to-prd (standalone) | 1·2·2·2·0·2 | 9 | LC (AR5 gate) | One sentence: max 2 analyze-fix cycles vs golden `expected_outputs/`, then escalate |
| research-summarizer (standalone) | 1·1·2·2·0·1 | 7 | LC | Cap the Verification Loop (2 re-extraction passes) → instant HR |
| apple-hig-expert (standalone) | 1·0·2·2·0·1 | 6 | LC | Numbered workflow; move `templates/``assets/`; add fix-recheck cap |
| skills/experiment-designer | 1·1·2·1·0·0 | 5 | TO | Make sample-size output a blocking gate on any test recommendation; 423 words is thin |
| skills/ux-researcher-designer | 0·1·2·1·0·1 | 5 | TO | (fake `--help` + unseeded RNG fixed this PR) Validation checklists → exit gates |
| skills/ui-design-system | 0·1·2·1·0·1 | 5 | TO | Add command; disambiguate vs markdown-html/design-system |
| skills/saas-scaffolder | 0·1·2·1·0·1 | 5 | TO | Make the 33-item checklist machine-checkable (reuse spec-to-repo's validator); dedupe references pair |
| agile-product-owner (standalone) | 0·1·2·1·0·1 | 5 | TO | (fake `--help` fixed this PR) INVEST checklist → gate |
| skills/product-analytics | 0·1·2·1·0·0 | 4 | TO | NSM validator + benchmark bands (see improvement-fields F7/F8); anti-patterns table exists, gate doesn't |
| skills/landing-page-generator | 0·1·2·1·0·0 | 4 | TO | Add `distinct_from` vs marketing/landing; render-check gate on emitted TSX |
| skills/product-strategist | 0·1·2·0·0·1 | 4 | TO | Alignment score exists but nothing requires it; outcome-vs-output OKR lint |
| skills/competitive-teardown | 0·1·2·0·0·0 | 3 | TO | Data-verification discipline (it synthesizes scraped claims with no source gate) |
| skills/product-discovery | 0·1·2·0·0·0 | 3 | TO | Wire to the new discovery loop (orchestrator now provides tracker + OST linter); 1 reference, no agent/command |
| skills/roadmap-communicator | 0·0·2·1·0·0 | 3 | TO | Merge-or-disambiguate vs `/changelog` + engineering/changelog-generator; 367 words |
## Domain-level findings
1. **Orchestration gap (fixed this PR).** `product-skills` is now a `context: fork`
orchestrator with a deterministic 16-lane router (`product_goal_router.py`, exit
0/2/3), a recurring discovery loop with two machine gates
(`discovery_cadence_tracker.py`, `ost_linter.py`), a forcing-question library, and
agent-harness integration. Agent `cs-product-orchestrator` + `/cs:product`,
`/cs:grill-product`, `/cs:product-loop` commands added.
2. **References cite no sources: 39 of 43 reference files contain zero URLs/citations.**
Only apple-hig-expert (3/3) and research-summarizer (1/2) meet the ≥5-sources bar. The
3 new orchestrator references cite 7 sources each; the other 39 remain open work.
3. **Two tools faked their `--help` (fixed this PR).** `user_story_generator.py` and
`persona_generator.py` exited 0 while ignoring the flag and running demos;
persona_generator was additionally non-deterministic (unseeded `random.choice`). Both
now use argparse; personas are seeded (default 42).
4. **Stale/contradictory counters + broken paths (open).** product-team/README.md holds 3
mutually inconsistent counts and 9 broken Quick Start paths (missing `skills/`
segment); `.codex/instructions.md` has 3 broken paths; CLAUDE.md says "13 skills" then
lists 16, claims 17 tools (actual 19). The domain plugin.json description claims
skills the bundle doesn't contain. CLAUDE.md counters updated this PR; README overhaul
is follow-up F10.
5. **Unmanaged overlaps (open):** landing-page-generator ↔ `marketing/landing`;
saas-scaffolder ↔ spec-to-repo; roadmap-communicator ↔ `/changelog` +
`engineering/changelog-generator`; ui-design-system ↔ `markdown-html/design-system`.
Only research-summarizer ships a "Distinct From" section. The orchestrator's routing
table now provides partial disambiguation; per-skill `distinct_from` notes remain.
6. **8 of 13 bundled skills ship 0 assets** despite the repo's template-heavy principle;
apple-hig-expert uses a nonstandard `templates/` dir.
7. **Agent/command coverage holes (open):** 6 skills map to no cs-* agent
(product-discovery, roadmap-communicator, spec-to-repo, code-to-prd, apple-hig-expert,
research-summarizer); 10 have no slash command. The orchestrator router reaches all 17
lanes, which mitigates but does not close this.
## Verification criteria (executable)
- **product-skills (orchestrator):** `python3 product-team/skills/product-skills/scripts/product_goal_router.py --sample`
exits 0 and routes to `product-discovery`; `--text "hello"` exits 3;
`discovery_cadence_tracker.py --input assets/sample_discovery_log.json` exits 0 with
`health_score` 62.0 and verdict `AT-RISK`; `ost_linter.py --input assets/sample_ost.json`
exits 2 with exactly one O2 and one O4 violation; `--sample` variants all exit 0.
- **spec-to-repo:** `validate_project.py --strict` on a scaffolded repo exits 0 before
the workflow may report done (existing contract, holds).
- **code-to-prd:** analyzer output diffs clean against `expected_outputs/` goldens
(existing contract, holds).
- **persona_generator (fixed):** `--help` prints argparse usage (not a demo); two `json`
runs produce byte-identical output.
- **user_story_generator (fixed):** `--help` prints argparse usage; `sprint 30` still
plans a 30-point sprint (backward-compatible positional).
- **Manifest truth:** `harness_manifest_builder.py --domain product-team --no-timestamp`
produces a diff-clean `product-team.json` with `product-skills` scoring all five
`agentic_signals` true and 3 wired, sample-supporting tools.

View file

@ -0,0 +1,101 @@
# Domain audit: project-management/ — deep audit + agentic readiness
Audited: 2026-07-03 · 9 skills · 12 Python tools pre-PR (all pass `--help`; end-to-end
runs of velocity_analyzer and project_health_dashboard reproduce documented fixtures),
15 post-PR · 1 agent pre-PR, 2 post · 3 commands pre-PR (+`/sprint-plan` generic), 6
post · plugin.json valid (`["./skills"]` canonical form).
Rubric: [RUBRIC.md](RUBRIC.md). Method: full SKILL.md reads, script smoke tests, MCP
tool-reference grepping, counter verification.
## Summary
**Headline finding #1 (fixed this PR): the MCP↔analytics gap.** The domain bundles a
live Atlassian Remote MCP (`.mcp.json`) and disciplined tool documentation
(`references/atlassian-mcp-tools.md`, verified live 2026-06-10), yet its two analytics
skills (senior-pm, scrum-master) had **zero** MCP references — nothing connected
`searchJiraIssuesUsingJql` output to the scripts' input schemas. Every sprint-health or
velocity run required hand-built JSON. `jira_snapshot_bridge.py` closes this: raw MCP
search results → scrum-master sprint schema (verified: piped output runs
velocity_analyzer clean) → plus the four Kanban flow metrics + seeded Monte Carlo
forecasting the domain never had.
**Headline finding #2 (fixed this PR): pre-modern agentics.** Zero `context: fork`, zero
forcing questions, no `/cs:*` namespace, no loop with named terminal states. What existed
was raw material: atlassian-admin's 7 concrete VERIFY steps, scrum-master's
data-sufficiency gates with pinned expected outputs (avg 20.2 pts, health 78.3,
action-item completion 46.7%), confluence/templates' verify-before-proceed steps.
**Agentic-readiness distribution (9 skills, post-PR):** HARNESS-READY **1** (pm-skills
upgraded 1→12) · LOOP-CAPABLE **4** (scrum-master, jira-expert, atlassian-admin,
atlassian-templates) · TOOL-ONLY **3** (senior-pm, confluence-expert, meeting-analyzer) ·
PROSE-ONLY **1** (team-communications).
## Per-skill table
Scores AR1·AR2·AR3·AR4·AR5·AR6 (post-PR where this PR changed the skill).
| Skill | AR1-6 | Tot | Class | Top improvement |
|---|---|---|---|---|
| pm-skills (orchestrator) | 2·2·2·2·2·2 | 12 | HR | (upgraded this PR: was a 50-line prose router, PROSE-ONLY) |
| scrum-master | 1·1·2·2·0·1 | 7 | LC | One sentence: cap re-analysis at 2 passes then escalate → instant HR; consume the bridge (`--to sprint`) instead of hand-built JSON |
| atlassian-admin | 0·1·2·2·0·2 | 7 | LC | Intake gate (refuse without approver named); its VERIFY steps are the domain's best — port the pattern to siblings |
| jira-expert | 0·1·2·2·0·1 | 6 | LC | Cap fix-revalidate cycles at 3; ship a sample workflow JSON asset (users must guess the validator's schema) |
| atlassian-templates | 0·1·2·1·1·1 | 6 | LC | Ship static template assets; expected-output fixture for the scaffolder |
| senior-pm | 0·1·2·1·0·1 | 5 | TO | Consume the bridge's flow output in the health dashboard; make KPI thresholds (on-time > 80% etc.) exit-code gates; portfolio-kpis.md is 32 lines |
| confluence-expert | 0·1·2·1·0·1 | 5 | TO | Make its Verify steps blocking; sample input for content_audit_analyzer |
| meeting-analyzer | 1·1·0·1·0·1 | 4 | TO | Ship the deterministic tools its own prose describes (speaking-ratio, filler counts = exactly the repo's "algorithm over AI" case); 0 scripts/refs/assets |
| team-communications | 1·1·0·0·0·0 | 2 | PO | References are 1565 lines (the skill's premise is "follow the reference exactly"); add a 3P-format linter script |
## Domain-level findings
1. **Orchestration + loop layer (fixed this PR).** `pm-skills` is now a `context: fork`
orchestrator: deterministic 8-lane router (`pm_goal_router.py`), the Jira bridge, and
a delegation-governance gate (`delivery_loop_gate.py` — G1 human owner, G2 reviewer
for agent tasks, G3 machine-checkable acceptance, G4 evidence-before-done, G5 close
refusal, G6 exhausted-budget-is-escalation), all wired to the repo harness
(`assets/harnesses/project-management.json`). Agent `cs-pm-orchestrator` +
`/cs:pm`, `/cs:grill-pm`, `/cs:pm-loop` added. Five reusable PM loops documented in
`references/pm_loop_playbook.md` (sprint-flow, health, retro-action, RAID-hygiene,
comms), each with machine gates and named terminal states.
2. **References cited zero sources (partially fixed).** 0 URLs across all 21 pre-PR
reference files — Schwaber/Sutherland, Vacanti, DORA, Kanban Guide all absent. The 3
new orchestrator references cite 67 sources each; back-filling the other 21 is
follow-up F9.
3. **Stale counters everywhere except plugin.json (open).** README ("6 world-class
skills"), IMPLEMENTATION_SUMMARY ("All 6", references `/mnt/user-data/outputs/` build
paths), REAL_WORLD_SCENARIO ("6 Expert Skills"), cs-project-manager agent ("six
skills"), CLAUDE.md (lists 6 of 9 — meeting-analyzer, team-communications, pm-skills
absent). CLAUDE.md updated this PR; the legacy trio (README /
IMPLEMENTATION_SUMMARY / REAL_WORLD_SCENARIO) should be rewritten or retired (F10).
4. **MCP integration is bimodal (structural, now bridged).** Concrete in 4 skills
(jira-expert 14 refs, confluence-expert 11, atlassian-templates 11, atlassian-admin 4
read-only-correct); zero in the 2 analytics skills. The bridge closes the data path;
the two SKILL.mds should still name it (one line each, F3).
5. **Two contributed skills violate the Path-B contract (open).** meeting-analyzer: zero
scripts/references/assets — its own spec (speaking-time %, filler-word counts) is
deterministic computation the repo mandates be scripted. team-communications: zero
scripts, 4 references totaling 155 lines.
6. **`/sprint-plan` counts against product-team but lives half in this domain** — the
sprint-planning integration pattern in CLAUDE.md calls product-team's
user_story_generator; fine, but the CLAUDE.md example used the old positional CLI
(still works — verified backward-compatible after this PR's argparse fix).
## Verification criteria (executable)
- **pm-skills (orchestrator):** `pm_goal_router.py --sample` exits 0 routing to
`scrum-master`; `--text "audit our jira permissions"` exits 2 (single signal → ask);
`--text "hello world"` exits 3. `jira_snapshot_bridge.py --input
assets/sample_jira_snapshot.json --to flow --forecast 20` exits 0 and matches
`assets/expected_flow_metrics.json` (p50=9, p85=14, p95=16 days; 90.9% SLE conformance;
aging alert on PHX-112; forecast p85 = 12 weeks); `--to sprint` output runs
`velocity_analyzer.py` to exit 0 (avg 11.8 pts over 4 sprints); a 2-sprint snapshot
exits 5. `delivery_loop_gate.py --sample` exits 0; sample plan passes `--mode plan`
(exit 0) and is refused by `--mode close` (exit 4, T2 in_progress).
- **scrum-master:** existing fixture contract holds — velocity_analyzer on
`assets/sample_sprint_data.json` reports avg 20.2 pts on 6 sprints.
- **atlassian-admin:** each VERIFY step names a concrete check (e.g. `GET
/rest/api/3/user?accountId=... returns "active": false`) — keep as the domain's AR4
exemplar.
- **Manifest truth:** `harness_manifest_builder.py --domain project-management
--no-timestamp` produces a diff-clean `project-management.json` with `pm-skills`
scoring all five `agentic_signals` true and 3 wired, sample-supporting tools.

View file

@ -0,0 +1,76 @@
# Research digest — the 20242026 canon behind this audit
Web-verified 2026-07-03. Full citations inline; this digest is the source layer for
[improvement-fields.md](improvement-fields.md) and the six new reference docs shipped
into the two orchestrators.
## Product management: where the canon moved
1. **Discovery became a weekly operating rhythm.** Torres (*Continuous Discovery
Habits*; producttalk.org/opportunity-solution-trees) reframed discovery as weekly
customer touchpoints anchored to one outcome, with the OST as the structural artifact
and assumption tests (Bland, *Testing Business Ideas*) as the unit of progress.
2. **The org-level frame is the product operating model.** Cagan's *Transformed* (SVPG,
2024): empowered teams, outcomes over output, innovation over predictability — 20
first principles (svpg.com/the-product-operating-model-an-introduction).
3. **Evals are the new PRD for AI features** — the consensus 2025 AI-PM competency:
golden set + rubric + guardrail SLOs before building (Lenny's Newsletter "Beyond vibe
checks"; Braintrust "Evals for PMs"; Aakash Gupta "AI Evals"); model cards for the
buyer-facing half (Mitchell et al., arxiv.org/abs/1810.03993).
4. **Metrics spine: North Star + input tree** (Amplitude, *The North Star Playbook*),
with PLG benchmark bands for verdicts (ProductLed; OpenView: activation median ~17%,
best-in-class 3350%+; free→paid median ~9%, PQL-driven 2530%).
5. **Prioritization is a bracket, not a framework**: RICE (steady state) + WSJF/cost of
delay (Reinertsen; SAFe WSJF + Yip's false-precision critique) + ODI opportunity
scoring (Ulwick). Sensitivity analysis counters the documented WSJF failure mode.
6. **Analytics practice is taxonomy-first** (PostHog product-analytics best practices):
naming discipline and tracking-plan review before any metric above it.
## Project management / delivery: where the canon moved
1. **Flow metrics are mandatory, not optional.** The Kanban Guide (May 2025,
kanbanguides.org) mandates exactly four measures — WIP, throughput, cycle time, work
item age — plus an SLE; age is the leading indicator.
2. **Forecasting went probabilistic.** Vacanti (*Actionable Agile Metrics*; *When Will
It Be Done?*; scrum.org Monte Carlo guidance): sample historical throughput, answer
with p50/70/85/95 ranges, never a date; refuse thin history.
3. **DORA 2025** (dora.dev/dora-report-2025) replaced elite/high/medium/low with seven
team archetypes over eight measures; core finding: AI **amplifies** existing org
strengths/dysfunctions (individual output up ~98% more merged PRs, org delivery flat
without enabling capabilities). SPACE (Forsgren/Storey, ACM Queue) remains the
multi-dimension corrective; EBM (scrum.org) the value-measurement frame.
4. **Risk practice:** Klein's pre-mortem (HBR 2007, ~30% better risk identification);
RAID hygiene as a linting problem; derived health vs self-reported RAG to catch
watermelon projects.
5. **Async-first delivery:** GitLab handbook (handbook.gitlab.com, asynchronous work) —
written 3-question standups 35 min vs 1530 sync; ~37% meeting-hour reduction. Moghe,
*The Async-First Playbook* (2023).
6. **The vendors shipped agentic PM.** Atlassian Rovo GA'd agents in Jira (assignable,
@mentionable, "every action logged and auditable", Teamwork Graph 150B+ connections,
MCP access — atlassian.com/software/rovo; Team '26 coverage, SiliconANGLE 2026-05-06).
Linear shipped the accountability pattern: agent as contributor, **human stays
primary assignee** (linear.app/agents; changelog 2026-03-24).
## Agentic harness design principles (applied in this PR)
1. **Workflows first, agents when needed** — Anthropic, "Building Effective Agents"
(anthropic.com/research/building-effective-agents): prompt chaining, routing,
parallelization, orchestrator-workers, evaluator-optimizer; the last "when there are
clear evaluation criteria and iterative refinement provides measurable value."
→ The routers are workflows; the loops engage only for goals with fresh feedback.
2. **Definition-of-done must be machine-checkable; never trust self-report** — the
plan→act→verify(deterministic)→reflect shape. → G3/G4 in `delivery_loop_gate.py`;
OST linter exit codes; agent-harness's evidence rule.
3. **Budgets and stop conditions are first-class** — max iterations, attempt caps,
escalation on confidence loss; otherwise reflection is infinite retry. → 3/12 caps,
G6, terminal-state taxonomy (loop-library: success, clean no-op, blocked,
approval-required, exhausted, stagnated).
4. **Human accountability stays attached to delegated work** (Linear; Rovo audit
discipline). → G1/G2; no un-reviewed Jira transitions; admin actions are
approval-required states.
5. **Context via structured interfaces, not prompt-stuffing** (Teamwork Graph / MCP;
Anthropic's ACI emphasis). → snapshot-file pattern: every loop iteration is
executable by a fresh session from files.
6. **Evaluator-optimizer pairs with PM-owned evals** — the golden set + rubric IS the
evaluator's criteria; the loop may never edit the gate it is judged by (this repo's
autoresearch locked-evaluator invariant, generalized).

View file

@ -357,16 +357,72 @@
{
"name": "product-skills",
"path": "product-team/skills/product-skills",
"description": "Router/index for the 12 product skills bundled in this plugin (RICE prioritization, OKRs, UX research, design tokens, competitive teardown, analytics, experiments, discovery, roadmaps, spec-to-repo, landing pages, SaaS scaffolding). Use when a product request doesn't obviously match one skill and you need to pick the right one (e.g., 'help me prioritize features', 'plan a product experiment').",
"tools": [],
"description": "Use when coordinating product work across the 12 bundled product sub-skills (RICE, OKRs, UX research, design tokens, competitive teardown, analytics, experiments, discovery, roadmaps, spec-to-repo, landing pages, SaaS scaffolding) or the 4 standalone product-team plugins (user stories, Apple HIG, code-to-PRD, research summarizer). Triggers on 'help me prioritize', 'plan a product experiment', 'we ship features nobody uses', 'run the discovery loop', 'is our OST sound'. Forks context to route to one sub-skill via a deterministic signal router and returns a digest; can also drive a continuous-di",
"tools": [
{
"script": "product-team/skills/product-skills/scripts/discovery_cadence_tracker.py",
"wired": true,
"supports_sample": true,
"verification": [
{
"cmd": "python3 product-team/skills/product-skills/scripts/discovery_cadence_tracker.py --help",
"expect_exit": 0,
"kind": "smoke"
},
{
"cmd": "python3 product-team/skills/product-skills/scripts/discovery_cadence_tracker.py --sample",
"expect_exit": 0,
"kind": "sample"
}
]
},
{
"script": "product-team/skills/product-skills/scripts/ost_linter.py",
"wired": true,
"supports_sample": true,
"verification": [
{
"cmd": "python3 product-team/skills/product-skills/scripts/ost_linter.py --help",
"expect_exit": 0,
"kind": "smoke"
},
{
"cmd": "python3 product-team/skills/product-skills/scripts/ost_linter.py --sample",
"expect_exit": 0,
"kind": "sample"
}
]
},
{
"script": "product-team/skills/product-skills/scripts/product_goal_router.py",
"wired": true,
"supports_sample": true,
"verification": [
{
"cmd": "python3 product-team/skills/product-skills/scripts/product_goal_router.py --help",
"expect_exit": 0,
"kind": "smoke"
},
{
"cmd": "python3 product-team/skills/product-skills/scripts/product_goal_router.py --sample",
"expect_exit": 0,
"kind": "sample"
}
]
}
],
"agentic_signals": {
"goal_intake": true,
"refusal_gate": false,
"verification": false,
"loop_discipline": false,
"close_out": false
"refusal_gate": true,
"verification": true,
"loop_discipline": true,
"close_out": true
},
"references": []
"references": [
"ai_product_evals.md",
"continuous_discovery_canon.md",
"product_operating_model.md"
]
},
{
"name": "product-strategist",

View file

@ -177,16 +177,72 @@
{
"name": "pm-skills",
"path": "project-management/skills/pm-skills",
"description": "Router/index for the 8 project-management skills bundled in this plugin (senior PM quant toolkit, scrum master, Jira/JQL, Confluence, Atlassian admin, Atlassian templates, meeting analyzer, team communications). Use when a PM request doesn't obviously match one skill and you need to pick the right one (e.g., 'our sprints feel off', 'audit our Jira permissions'). Bundles an Atlassian Remote MCP config (.mcp.json) for live Jira/Confluence access.",
"tools": [],
"description": "Use when coordinating project-delivery work across the 8 project-management sub-skills \u2014 sprint/velocity analytics, portfolio health, Jira/JQL, Confluence, Atlassian admin, templates, meeting analysis, team comms. Triggers on 'our sprints feel off', 'project health report', 'audit our Jira permissions', 'when will it be done', 'run the delivery loop'. Forks context to route to one sub-skill via a deterministic signal router and returns a digest; can also drive a full goal\u2192plan\u2192execute\u2192verify\u2192close delivery loop through the repo-wide agent-harness with Jira MCP data bridged into the domain's an",
"tools": [
{
"script": "project-management/skills/pm-skills/scripts/delivery_loop_gate.py",
"wired": true,
"supports_sample": true,
"verification": [
{
"cmd": "python3 project-management/skills/pm-skills/scripts/delivery_loop_gate.py --help",
"expect_exit": 0,
"kind": "smoke"
},
{
"cmd": "python3 project-management/skills/pm-skills/scripts/delivery_loop_gate.py --sample",
"expect_exit": 0,
"kind": "sample"
}
]
},
{
"script": "project-management/skills/pm-skills/scripts/jira_snapshot_bridge.py",
"wired": true,
"supports_sample": true,
"verification": [
{
"cmd": "python3 project-management/skills/pm-skills/scripts/jira_snapshot_bridge.py --help",
"expect_exit": 0,
"kind": "smoke"
},
{
"cmd": "python3 project-management/skills/pm-skills/scripts/jira_snapshot_bridge.py --sample",
"expect_exit": 0,
"kind": "sample"
}
]
},
{
"script": "project-management/skills/pm-skills/scripts/pm_goal_router.py",
"wired": true,
"supports_sample": true,
"verification": [
{
"cmd": "python3 project-management/skills/pm-skills/scripts/pm_goal_router.py --help",
"expect_exit": 0,
"kind": "smoke"
},
{
"cmd": "python3 project-management/skills/pm-skills/scripts/pm_goal_router.py --sample",
"expect_exit": 0,
"kind": "sample"
}
]
}
],
"agentic_signals": {
"goal_intake": true,
"refusal_gate": false,
"verification": false,
"loop_discipline": false,
"close_out": false
"refusal_gate": true,
"verification": true,
"loop_discipline": true,
"close_out": true
},
"references": []
"references": [
"agentic_delivery_governance.md",
"flow_forecasting_canon.md",
"pm_loop_playbook.md"
]
},
{
"name": "scrum-master",

View file

@ -1,7 +1,7 @@
{
"name": "product-skills",
"description": "13 production-ready product skills: product manager toolkit (RICE, PRDs), agile product owner, product strategist, UX researcher, UI design system, competitive teardown, landing page generator, SaaS scaffolder, product analytics, experiment designer, product discovery, roadmap communicator, code-to-prd, research summarizer, apple-hig-expert (Apple Human Interface Guidelines), spec-to-repo. Agent skill and plugin for Claude Code, Codex, Gemini CLI, Cursor, OpenClaw.",
"version": "2.9.0",
"description": "13 production-ready product skills bundled in this plugin: product-skills fork-orchestrator with continuous-discovery loop (deterministic 16-lane router, Torres cadence tracker, OST linter), product manager toolkit (RICE, PRDs), product strategist, UX researcher, UI design system, competitive teardown, landing page generator, SaaS scaffolder, product analytics, experiment designer, product discovery, roadmap communicator, spec-to-repo. Companion standalone plugins: agile-product-owner, code-to-prd, apple-hig-expert, research-summarizer. Agent skill and plugin for Claude Code, Codex, Gemini CLI, Cursor, OpenClaw.",
"version": "2.10.4",
"author": {
"name": "Alireza Rezvani",
"url": "https://alirezarezvani.com"

View file

@ -1,10 +1,33 @@
# Product Team Skills - Claude Code Guidance
This guide covers the 13 production-ready product management skills and their Python automation tools.
This guide covers the 17 production-ready product management skills (13 bundled incl. the orchestrator + 4 standalone plugins) and their Python automation tools.
## Orchestrator & Discovery Loop (product-skills)
`skills/product-skills/` is the domain's `context: fork` orchestrator and agent harness adapter:
```bash
# Route a product goal deterministically across all 16 lanes (exit 0 route / 2 ask / 3 no signal)
python3 skills/product-skills/scripts/product_goal_router.py --text "help me prioritize features"
# Score the continuous-discovery cadence (Torres weekly habit; refuses on < 2 interviews)
python3 skills/product-skills/scripts/discovery_cadence_tracker.py --input discovery_log.json
# Lint the Opportunity Solution Tree (exit 2 blocks the tree from driving a roadmap)
python3 skills/product-skills/scripts/ost_linter.py --input ost.json
```
Commands: `/cs:product` (router) · `/cs:grill-product` (canon-cited grilling) ·
`/cs:product-loop` (the discovery loop). Agent: `cs-product-orchestrator`. Build-scale
goals compile through `engineering/agent-harness` with the `product-team.json` manifest.
Hard rules: no roadmap cites a tree that fails the linter; single-participant claims are
anecdotes; AI features ship with eval specs (see
`skills/product-skills/references/ai_product_evals.md`).
## Product Skills Overview
**Available Skills:**
0. **product-skills/** - Domain orchestrator (`context: fork`) + continuous-discovery loop (3 tools: goal router, cadence tracker, OST linter)
1. **product-manager-toolkit/** - RICE prioritization, customer interview analysis (2 tools)
2. **agile-product-owner/** - User story generation, sprint planning (1 tool)
3. **product-strategist/** - OKR cascade, strategic planning (1 tool)
@ -22,11 +45,11 @@ This guide covers the 13 production-ready product management skills and their Py
15. **apple-hig-expert/** - Apple Human Interface Guidelines compliance and design (1 tool: hig_checker)
16. **spec-to-repo/** - Convert a spec document into a scaffolded repository
**Total Tools:** 17 Python automation tools
**Total Tools:** 22 Python automation tools
**Agents:** 5 (cs-product-manager, cs-agile-product-owner, cs-product-strategist, cs-ux-researcher, cs-product-analyst)
**Agents:** 6 (cs-product-orchestrator, cs-product-manager, cs-agile-product-owner, cs-product-strategist, cs-ux-researcher, cs-product-analyst)
**Slash Commands:** 8 (/rice, /okr, /persona, /user-story, /competitive-matrix, /prd, /sprint-plan, /code-to-prd)
**Slash Commands:** 11 (/cs:product, /cs:grill-product, /cs:product-loop, /rice, /okr, /persona, /user-story, /competitive-matrix, /prd, /sprint-plan, /code-to-prd)
## Python Automation Tools
@ -312,7 +335,7 @@ python roadmap-communicator/scripts/changelog_generator.py --from v1.0.0 --to HE
---
**Last Updated:** May 10, 2026
**Skills Deployed:** 13/13 product skills production-ready
**Total Tools:** 17 Python automation tools
**Agents:** 5 | **Commands:** 8
**Last Updated:** July 3, 2026
**Skills Deployed:** 17/17 product skills production-ready (product-skills is now a fork-orchestrator + discovery loop)
**Total Tools:** 22 Python automation tools
**Agents:** 6 | **Commands:** 11

View file

@ -0,0 +1,81 @@
---
name: cs-product-orchestrator
description: Outcome-first product lead. Routes product inquiries (prioritization, OKRs, UX research, design systems, competitive, analytics, experiments, discovery, roadmaps, scaffolding, stories, HIG, code-to-PRD, summarization) to the right sub-skill via the product-skills orchestrator, and drives the continuous-discovery loop with machine gates (cadence tracker + OST linter). Forks context to keep heavy intake (interview logs, event exports, competitor data) out of the parent thread. Signature forcing question — "What outcome does this serve, and which tested assumption says it will?"
tools: Read, Write, Edit, Glob, Grep, Bash, Skill
model: sonnet
---
# Product Orchestrator
You are an outcome-first product lead. Everything hangs from one measurable outcome;
opportunities are customer needs, not features in disguise; solutions earn roadmap slots
by surviving assumption tests, not by being someone's favorite. You run discovery as a
weekly loop with machine gates, and you bracket prioritization frameworks instead of
worshiping one.
## Voice
**"What outcome does this serve, and which tested assumption says it will?"**
The trap you protect against: the feature factory — shipping output, celebrating
velocity, never checking whether anyone's behavior changed.
## Your 16 lanes
12 bundled: product-manager-toolkit (PRIORITIZE) · product-strategist (STRATEGY) ·
ux-researcher-designer (UX) · ui-design-system (DESIGN_SYSTEM) · competitive-teardown
(COMPETITIVE) · product-analytics (ANALYTICS) · experiment-designer (EXPERIMENT) ·
product-discovery (DISCOVERY) · roadmap-communicator (ROADMAP) · spec-to-repo
(SPEC_TO_REPO) · landing-page-generator (LANDING) · saas-scaffolder (SAAS_SCAFFOLD).
4 standalone plugins: agile-product-owner (STORIES) · apple-hig-expert (HIG) ·
code-to-prd (CODE_TO_PRD) · research-summarizer (SUMMARIZE).
## Routing logic
1. Run `python3 product-team/skills/product-skills/scripts/product_goal_router.py --text "<goal>"`.
2. Exit 0 → load the routed skill's SKILL.md (`skill_path` covers the standalone
plugins), follow its workflow in the forked context.
3. Exit 2 → ask ONE clarifying question naming the candidates, with a recommended answer.
4. Exit 3 → ask the user to restate the goal with the deliverable named. Never guess.
## The discovery loop (your recurring duty)
Weekly: score the log (`discovery_cadence_tracker.py` — refuses on < 2 interviews), act
on `next_loop_action`, lint the tree (`ost_linter.py` — exit 0 required before any
roadmap cites it), keep the streak alive. DORMANT 4+ weeks → escalate to the product
lead by name. HEALTHY + validated assumption → graduate to experiment-designer or a PRD.
## How you communicate (Matt Pocock grill discipline)
One question per turn; always recommend; explore the workspace before asking (an
`ost.json` or `discovery_log.json` resolves the lane silently); depth-first on
multi-lane inquiries; never silently chain. Digest ≤ 200 words: analyzed, top 3 findings
(canon-cited), top 3 next actions (named owner), artifact path, one grill challenge.
Hard outputs:
- Insights carry participant counts — singletons are anecdotes, flagged as such.
- Experiment recommendations carry the computed sample size and MDE.
- Prioritization names its framework (RICE / WSJF / opportunity score) and why.
- AI features get an eval spec (golden set + rubric + guardrails) in the PRD, per
`references/ai_product_evals.md`.
## Anti-patterns
- ❌ Cite an OST that fails the linter, or skip the linter because the tree "looks right"
- ❌ Promote a single-participant quote to an insight
- ❌ Answer "what should we build" without asking what outcome it serves
- ❌ Run all 16 lanes "to be thorough" — route to one, digest, chain on confirmation
- ❌ Report an exhausted loop budget as success
## When to escalate
- Delivery/sprint/Jira execution → `project-management` (cs-pm-orchestrator)
- Campaign/landing marketing → `marketing-skill` / `marketing/landing`
- Pricing and packaging economics → `commercial`
- Generic loop mechanics → `engineering/agent-harness` harness-runner
## Available commands
`/cs:product <inquiry>` (router) · `/cs:grill-product <plan>` (grill first) ·
`/cs:product-loop` (discovery loop) · plus the domain's `/rice`, `/okr`, `/persona`,
`/user-story`, `/competitive-matrix`, `/prd`, `/sprint-plan`, `/code-to-prd`.

View file

@ -326,13 +326,23 @@ def create_sample_epic():
}
def main():
import sys
import argparse
parser = argparse.ArgumentParser(
description="Generate INVEST user stories from the bundled sample epic, or plan "
"a sprint from the generated backlog.")
parser.add_argument("mode", nargs="?", choices=["epic", "sprint"], default="epic",
help="'epic' breaks the sample epic into stories; 'sprint' plans "
"a sprint from that backlog (default: epic).")
parser.add_argument("capacity", nargs="?", type=int, default=30,
help="Sprint capacity in story points (sprint mode, default: 30).")
args = parser.parse_args()
generator = UserStoryGenerator()
if len(sys.argv) > 1 and sys.argv[1] == 'sprint':
if args.mode == 'sprint':
# Generate sprint planning
capacity = int(sys.argv[2]) if len(sys.argv) > 2 else 30
capacity = args.capacity
# Create sample backlog
epic = create_sample_epic()

View file

@ -0,0 +1,59 @@
---
description: Matt Pocock-style interrogation of a product plan against the product canon (Torres, Cagan Transformed, Reinertsen/WSJF, Amplitude North Star, evals-as-PRD). One forcing question per turn with a recommended answer; refuses to invoke any sub-skill or start a loop until the outcome-defining decisions are locked. Use before running /cs:product or /cs:product-loop on a fuzzy plan.
argument-hint: "<product plan, roadmap, feature idea, or strategy to interrogate>"
---
# /cs:grill-product — grill a product plan before running it
Interrogate this plan — do not execute anything yet:
**$ARGUMENTS**
Five rules (preserved from Matt Pocock, MIT): one question per turn · always give a
recommended answer · explore the workspace before asking · walk the decision tree
depth-first · track answered questions and their dependencies.
## Decision tree
- **Branch 1 — Outcome**: "What single measurable outcome does this serve, with a number?
Recommended: write it as the OST root before anything else. Canon: Torres,
*Continuous Discovery Habits*."
- **Branch 2 — Evidence**: "Which tested assumption says this will work — and how many
independent participants back it? Recommended: link the surviving assumption test;
singletons are anecdotes. Canon: Bland, *Testing Business Ideas*; Torres."
- **Branch 3 — Structure**: "Does the tree pass the linter? Recommended: run
`ost_linter.py` — exit 0 before any roadmap cites it; feature-phrased opportunities
(O2) and untested solutions (O4) are the usual failures. Canon: Torres OST discipline."
- **Branch 4 — Prioritization honesty**: "Would delaying any item a quarter erode its
value? Recommended: if yes, run WSJF/cost-of-delay next to RICE and flag rank flips on
one-step estimate changes. Canon: Reinertsen; the WSJF false-precision critique."
- **Branch 5 — Measurement**: "Is your North Star a leading value metric with an input
tree, or revenue/vanity? Recommended: leading value metric; funnel verdicts need
benchmark bands. Canon: Amplitude, *The North Star Playbook*; ProductLed benchmarks."
- **Branch 6 — AI features**: "If any feature is probabilistic: where is the eval —
golden set, rubric, guardrail SLOs? Recommended: write the eval spec into the PRD
before building; vibe-check launches are shipping without tests. Canon: evals-as-PRD
(Lenny's/Braintrust)."
Per-turn output format:
```
Q[i]/[total]: [precise question]
Recommended: [answer + canon-cited rationale]
(Confirm, or override?)
```
## Stop conditions
- All branches resolved → invoke `/cs:product` (question) or `/cs:product-loop`
(recurring discovery) with the locked decisions inlined.
- User says "stop grilling, just run it" → run with unresolved branches flagged in the
digest.
- Abandoned → save the partial grill to `product-grill-{timestamp}.md`.
## Distinct from
- `engineering/grill-me` — generic plan interrogation. This grills against the product
canon.
- `/cs:product` — routes; this refuses to route until decisions are locked.

View file

@ -0,0 +1,49 @@
---
description: Run the continuous-discovery loop — score the weekly cadence (Torres), act on the named gap, lint the Opportunity Solution Tree as the machine gate, and keep the streak alive with explicit stop states. The product-domain recurring loop; graduates validated assumptions to experiments or PRDs.
argument-hint: "[path to discovery_log.json] [path to ost.json]"
---
# /cs:product-loop — the continuous-discovery loop
Inputs (defaults: `discovery_log.json` and `ost.json` in the workspace; shapes in
`product-team/skills/product-skills/assets/`):
**$ARGUMENTS**
## Sequence (one iteration per invocation)
1. **Observe**
```bash
python3 product-team/skills/product-skills/scripts/discovery_cadence_tracker.py --input discovery_log.json
```
Exit 5 (< 2 interviews): there is no cadence to measure help the user book the
first two weekly touchpoints and write the outcome statement; stop there.
2. **Choose** — the report's `next_loop_action` is the choice. Typical actions: book the
missing weekly touchpoint · re-anchor the interview guide on the outcome · test the
top untested assumption (route to `product-discovery`'s assumption_mapper to rank).
3. **Act** — execute with the routed sub-skill's tools (ux-researcher-designer for the
interview, experiment-designer for the test design). One bounded action per
iteration.
4. **Verify**
```bash
python3 product-team/skills/product-skills/scripts/ost_linter.py --input ost.json
```
Exit 2 → fix the listed O1O5 violations before the tree may drive any roadmap or
experiment. Then re-run the cadence tracker and confirm the health score did not
drop.
5. **Record** — update `discovery_log.json` (interview/test entries) and `ost.json`;
note the health score in the digest so the trend is visible across iterations.
6. **Repeat or stop** — terminal states:
- **Graduate**: HEALTHY + a validated assumption → hand off to `experiment-designer`
(A/B gate) or `product-manager-toolkit` (PRD with eval spec if the feature is
AI-powered).
- **Escalate**: DORMANT 4+ weeks → name the product lead and say the habit is dead —
never let discovery die silently.
- **Clean no-op**: cadence HEALTHY, no gaps — book next week's touchpoint and exit.
## Rules
- Never modify the linter or tracker to make a gate pass.
- Insights require recurrence across independent participants — singletons stay
anecdotes.
- The loop edits the log and the tree, never the gates (locked-evaluator invariant).

View file

@ -0,0 +1,47 @@
---
description: Top-level product-team router. Classifies a product inquiry across 16 lanes (prioritization, OKRs, UX, design system, competitive, analytics, experiments, discovery, roadmaps, spec-to-repo, landing, SaaS scaffold, stories, HIG, code-to-PRD, summarizer) with a deterministic script and forks context to the right sub-skill via the product-skills orchestrator, returning a ≤200-word digest with one grill challenge.
argument-hint: "<product inquiry: prioritize features, plan an experiment, discovery health, etc.>"
---
# /cs:product — Product Team router
Route this inquiry through the `product-skills` orchestrator:
**$ARGUMENTS**
## Routing (deterministic — run the script, don't eyeball)
```bash
python3 product-team/skills/product-skills/scripts/product_goal_router.py --text "$ARGUMENTS" --output json
```
- Exit 0 → load `skill_path`/SKILL.md (covers the 4 standalone plugins too) and follow
that skill's own workflow in a fork.
- Exit 2 → ask ONE clarifying question naming the listed candidates, recommended answer
first.
- Exit 3 → ask the user to restate the goal with the deliverable named. Never guess.
- Explore the workspace first — an `ost.json`, `discovery_log.json`, or `features.csv`
resolves the lane silently. Never silently chain a second sub-skill.
## Output (≤200-word digest)
- What was analyzed
- Top 3 findings, each anchored to a canon citation
- Top 3 next actions with a named owner
- Artifact path
- One grill challenge (e.g. "This roadmap cites an OST that fails the linter — which
opportunity backs item 3?")
## Hard rules
- Insights carry participant counts; singletons are anecdotes.
- Experiments carry computed sample size + MDE, never gut feel.
- Prioritization names its framework (RICE / WSJF / opportunity score) and why.
- AI features get an eval spec (golden set + rubric + guardrails) in the PRD.
- Recurring discovery work goes to `/cs:product-loop` instead.
## Distinct from
- `project-management` — how to deliver. This domain is what to build.
- `marketing/landing` — from-scratch marketing pages; `landing-page-generator` here
scaffolds product Next.js/TSX pages.

View file

@ -1,61 +1,180 @@
---
name: "product-skills"
description: "Router/index for the 12 product skills bundled in this plugin (RICE prioritization, OKRs, UX research, design tokens, competitive teardown, analytics, experiments, discovery, roadmaps, spec-to-repo, landing pages, SaaS scaffolding). Use when a product request doesn't obviously match one skill and you need to pick the right one (e.g., 'help me prioritize features', 'plan a product experiment')."
version: 2.9.0
description: "Use when coordinating product work across the 12 bundled product sub-skills (RICE, OKRs, UX research, design tokens, competitive teardown, analytics, experiments, discovery, roadmaps, spec-to-repo, landing pages, SaaS scaffolding) or the 4 standalone product-team plugins (user stories, Apple HIG, code-to-PRD, research summarizer). Triggers on 'help me prioritize', 'plan a product experiment', 'we ship features nobody uses', 'run the discovery loop', 'is our OST sound'. Forks context to route to one sub-skill via a deterministic signal router and returns a digest; can also drive a continuous-discovery loop (Torres cadence tracker + OST linter as machine gates) or a full goal→plan→execute→verify→close run through the repo-wide agent-harness. Distinct from project-management (how to deliver vs what to build), marketing/landing (from-scratch pages), and engineering/agent-harness (the generic loop engine this orchestrator plugs into)."
context: fork
version: 2.10.4
author: Alireza Rezvani
license: MIT
tags:
- product
- product-management
- ux
- ui
- saas
- agile
agents:
- claude-code
- codex-cli
- openclaw
tags: [product, product-management, orchestrator, discovery, ux, analytics, agent-harness]
compatible_tools: [claude-code, codex-cli, cursor, antigravity, opencode, gemini-cli]
---
# Product Skills — Router
# Product Team — Domain Orchestrator & Discovery Loop
This plugin bundles **12 product skills** (this router is the 13th folder under `product-team/skills/`). Each skill is self-contained: read its `SKILL.md`, run its `scripts/`, apply its `references/` and `assets/`.
This orchestrator does two jobs. **Routing:** fork context, classify a product inquiry
with `scripts/product_goal_router.py` across all 16 product-team lanes (12 bundled + 4
standalone plugins), run exactly one, return a digest. **Looping:** run product work as
bounded agentic loops with machine-checkable gates — the continuous-discovery loop
(weekly cadence scored by `discovery_cadence_tracker.py`, tree structure enforced by
`ost_linter.py`) and goal-scale runs through the repo-wide agent-harness.
## Routing table
## When to invoke
Match the request against the signals below, then load `product-team/skills/<skill>/SKILL.md`. If two or more rows match, ask the user one clarifying question before loading anything.
| Symptom | Sub-skill |
|---|---|
| "Prioritize features / RICE / PRD" | `product-manager-toolkit` |
| "OKRs, strategy cascade" | `product-strategist` |
| "Personas, usability, research synthesis" | `ux-researcher-designer` |
| "Design tokens, WCAG contrast" | `ui-design-system` |
| "Competitor matrix, teardown" | `competitive-teardown` |
| "Retention, cohorts, funnels, KPIs" | `product-analytics` |
| "A/B test, sample size, hypothesis" | `experiment-designer` |
| "Discovery, assumptions, opportunity trees" | `product-discovery` |
| "Roadmap comms, release notes, changelog" | `roadmap-communicator` |
| "Spec → runnable repo" | `spec-to-repo` |
| "Landing page (Next.js/Tailwind)" | `landing-page-generator` |
| "SaaS boilerplate" | `saas-scaffolder` |
| "User stories, sprint capacity" | `agile-product-owner` (standalone) |
| "Apple HIG audit" | `apple-hig-expert` (standalone) |
| "PRD from an existing codebase" | `code-to-prd` (standalone) |
| "Summarize papers/articles" | `research-summarizer` (standalone) |
| Request signals | Skill | Path |
|---|---|---|
| Prioritize features, RICE scores, interview synthesis | product-manager-toolkit | `skills/product-manager-toolkit/` |
| OKRs, strategy cascade, objective alignment | product-strategist | `skills/product-strategist/` |
| Personas, usability findings, research synthesis | ux-researcher-designer | `skills/ux-researcher-designer/` |
| Design tokens, component specs, WCAG contrast | ui-design-system | `skills/ui-design-system/` |
| Competitor analysis, feature/pricing matrix | competitive-teardown | `skills/competitive-teardown/` |
| Retention, cohorts, funnel analysis | product-analytics | `skills/product-analytics/` |
| A/B test design, sample size, hypothesis gates | experiment-designer | `skills/experiment-designer/` |
| Opportunity trees, assumption mapping, discovery | product-discovery | `skills/product-discovery/` |
| Roadmap formats per audience, changelogs | roadmap-communicator | `skills/roadmap-communicator/` |
| Turn a written spec into a repo scaffold | spec-to-repo | `skills/spec-to-repo/` |
| Landing page (Next.js TSX + Tailwind) | landing-page-generator | `skills/landing-page-generator/` |
| Bootstrap a SaaS app skeleton | saas-scaffolder | `skills/saas-scaffolder/` |
## Quick start
## Routing logic (deterministic)
```bash
# Example: route a prioritization request
cat product-team/skills/product-manager-toolkit/SKILL.md
python3 product-team/skills/product-manager-toolkit/scripts/rice_prioritizer.py --help
python3 scripts/product_goal_router.py --text "<the goal>" --output json
```
## Related product-team plugins (packaged separately, not in this bundle)
Exit 0 → `route_to` names the skill (with `skill_path`, including the standalone
plugins): load its SKILL.md and follow its workflow. Exit 2 → ask ONE clarifying question
naming the listed candidates, with a recommended answer. Exit 3 → no signal: ask the user
to restate the goal with the deliverable named. Never guess silently; never silently
chain — digest first, confirm, then chain.
- `product-team/agile-product-owner/` — user stories, sprint capacity
- `product-team/code-to-prd/` — reverse-engineer a PRD from a codebase
- `product-team/apple-hig-expert/` — Apple HIG audits (Liquid Glass era)
- `product-team/research-summarizer/` — document summarization with citation extraction
## The discovery loop (the domain's recurring agentic loop)
## Rules
Modern discovery is a weekly habit, not a project phase (Torres). Run it as a bounded
loop with two machine gates:
- Route to exactly one skill, then follow that skill's own workflow.
- This router ships no tools of its own — if no row matches, say so and ask rather than improvising.
1. **Observe** — maintain `discovery_log.json` (interviews, assumption tests; shape in
`assets/sample_discovery_log.json`) and score the cadence:
```bash
python3 scripts/discovery_cadence_tracker.py --input discovery_log.json
```
Refuses on < 2 interviews (exit 5) there is no cadence to measure yet. Output:
health 0100, verdict HEALTHY/AT-RISK/DORMANT, named gaps, and `next_loop_action`.
2. **Choose** — the tracker's `next_loop_action` IS the choice: book the touchpoint,
re-anchor the guide on the outcome, or test the top untested assumption (route to
`product-discovery`'s assumption_mapper for prioritization).
3. **Act** — run the interview / assumption test with the routed sub-skill's tools.
4. **Verify** — keep the tree structurally sound before it may drive a roadmap:
```bash
python3 scripts/ost_linter.py --input ost.json # exit 2 = NEEDS-REWORK, fix before citing the tree
```
Rules: one measurable outcome root (O1), opportunities are needs not features (O2),
targeted opportunities compare ≥ 2 solutions (O3), every solution has an assumption
test (O4), no orphan solutions (O5 — the feature-factory tell).
5. **Record / Repeat-or-stop** — update the log, keep the weekly streak alive. Stop
states: HEALTHY + validated assumption → graduate to `experiment-designer` (build the
A/B gate) or `product-manager-toolkit` (PRD); DORMANT for 4+ weeks → escalate to the
product lead by name — do not quietly let discovery die.
For build-scale goals ("turn this validated spec into a repo and verify it"), compile
through the repo-wide harness instead:
```bash
python3 engineering/agent-harness/skills/agent-harness/scripts/goal_compiler.py \
--goal "<goal>" --manifest engineering/agent-harness/skills/agent-harness/assets/harnesses/product-team.json \
--out .agent-harness/plan.json
```
The domain's three strongest close-out gates plug in as task verifications:
`spec-to-repo/scripts/validate_project.py` (exit 0), `code-to-prd`'s golden
`expected_outputs/`, and `research-summarizer`'s citation-count check.
## Hard rules
1. **Evidence before conviction**: no roadmap item cites the OST unless `ost_linter.py`
exits 0; no insight is asserted from a single participant (anecdote, not insight).
2. **Outcome-first**: every loop hangs from one measurable outcome — the linter's O1 rule
is the intake gate.
3. **Experiments are gated by math**: sample size from
`experiment-designer/scripts/sample_size_calculator.py`, never gut feel; report the
MDE with the verdict.
4. **Prioritization shows its framework**: RICE for steady-state, WSJF/cost-of-delay when
time sensitivity dominates, opportunity scoring for underserved needs — name which and
why (see [references/product_operating_model.md](references/product_operating_model.md)).
5. **AI features ship with evals**: a golden set + rubric is the PRD's quality contract
for probabilistic features
([references/ai_product_evals.md](references/ai_product_evals.md)).
6. **Never modify a gate you are judged by**; exhausted budgets escalate to a named human,
never report as success.
## Forcing-question library (grill-with-docs pattern)
One per turn, recommended answer, canon citation. Never run a sub-skill or start a loop
until the lane-defining decision is locked:
- **DISCOVERY lane**: "What is the single outcome this discovery serves, stated with a
number? Recommended: write it as the OST root first — opportunities without an outcome
are a feature factory. Canon: Torres, *Continuous Discovery Habits*; opportunity
solution trees (producttalk.org)."
- **PRIORITIZE lane**: "Does time sensitivity change this ranking — would delaying any
item a quarter erode its value? Recommended: if yes, run WSJF/cost-of-delay alongside
RICE and compare ranks; flag items whose rank flips on a one-step estimate change.
Canon: Reinertsen, *Principles of Product Development Flow*; SAFe WSJF false-precision
critique."
- **EXPERIMENT lane**: "What baseline rate and MDE justify this test's runtime?
Recommended: compute n first; if you can't reach it in 4 weeks, test a bigger lever.
Canon: statistical power analysis (experiment-designer)."
- **ANALYTICS lane**: "Is your North Star a leading indicator of value exchange, or
revenue/vanity? Recommended: leading value metric with an input tree. Canon: Amplitude,
*The North Star Playbook*."
- **STRATEGY lane**: "Are these OKRs outcomes or shipping lists? Recommended: outcomes —
output OKRs are the #1 operating-model failure. Canon: Cagan, *Transformed* (SVPG,
2024)."
- **BUILD lanes (spec-to-repo / saas-scaffolder)**: "Which validated assumption says this
should be built at all? Recommended: link the OST test that survived; building is the
most expensive way to test an idea. Canon: Torres; Bland, *Testing Business Ideas*."
## Assumptions
1. The user owns (or advises the owner of) the product decision.
2. Discovery data lives in the workspace as JSON logs — the loop is file-backed and
resumable; every tool ships `--sample` so the shape is visible first.
3. The four standalone plugins are installed alongside the bundle (the router still
routes to them by path if not).
## Non-goals
- Not the delivery loop — sprint/flow/Jira work routes to `project-management`.
- Not the generic loop engine — that is `engineering/agent-harness`; this orchestrator is
the product-domain adapter (router + discovery gates).
- Not campaign marketing — `marketing/landing` builds from-scratch marketing pages;
`landing-page-generator` here scaffolds product Next.js/TSX pages.
## Output artifacts
| Mode | Artifact |
|---|---|
| Route | Sub-skill's own artifact + ≤ 200-word digest with one canon-cited challenge |
| Discovery loop | `discovery_log.json` + cadence report + linted `ost.json` |
| Harness run | `.agent-harness/plan.json` + `state.json` + close handoff |
## Anti-patterns (do not)
- ❌ Run all 16 lanes "to be thorough" — route to one, digest, chain on confirmation
- ❌ Cite an OST that fails the linter, or promote a single-participant anecdote to insight
- ❌ Ship an AI feature whose PRD has no eval (golden set + rubric)
- ❌ Let the discovery streak die silently — DORMANT escalates by name
- ❌ Treat RICE as the only prioritization lens when deadlines dominate
## References
- [references/continuous_discovery_canon.md](references/continuous_discovery_canon.md) —
Torres, OST, assumption testing, JTBD switch interviews, story mapping
- [references/product_operating_model.md](references/product_operating_model.md) — Cagan
*Transformed*, North Star framework, PLG benchmarks, WSJF/ODI vs RICE
- [references/ai_product_evals.md](references/ai_product_evals.md) — evals-as-PRD, model
cards, evaluator-optimizer loops
- Loop engine: `engineering/agent-harness` · Loop vocabulary: `loop-library`

View file

@ -0,0 +1,20 @@
{
"_comment": "Continuous-discovery log shape — feed to scripts/discovery_cadence_tracker.py.",
"outcome": "increase paid conversion from 9% to 12% by Q4",
"interviews": [
{"date": "2026-05-05", "participant": "P1", "outcome_linked": true,
"assumptions_tested": ["users understand the trial limits"]},
{"date": "2026-05-12", "participant": "P2", "outcome_linked": true,
"assumptions_tested": []},
{"date": "2026-05-26", "participant": "P3", "outcome_linked": false,
"assumptions_tested": ["pricing page is the drop-off point"]},
{"date": "2026-06-02", "participant": "P4", "outcome_linked": true,
"assumptions_tested": ["annual plan framing increases upgrades"]}
],
"assumption_tests": [
{"date": "2026-05-15", "assumption": "users understand the trial limits",
"result": "invalidated"},
{"date": "2026-06-05", "assumption": "annual plan framing increases upgrades",
"result": "inconclusive"}
]
}

View file

@ -0,0 +1,26 @@
{
"_comment": "Opportunity Solution Tree shape — feed to scripts/ost_linter.py. This sample deliberately contains one O2 violation (feature-phrased opportunity) and one O4 violation (untested solution).",
"outcome": {
"statement": "Increase week-4 retention from 22% to 30%",
"metric": "week-4 retention"
},
"opportunities": [
{
"statement": "New users can't tell whether setup worked",
"target": true,
"solutions": [
{"statement": "Post-setup verification checklist",
"tests": [{"assumption": "users abandon because they doubt setup succeeded", "type": "interview"}]},
{"statement": "Live sample-data preview after connect",
"tests": [{"assumption": "a working preview reduces first-week drop-off", "type": "prototype"}]}
]
},
{
"statement": "Add an onboarding wizard",
"solutions": [
{"statement": "Onboarding wizard v2", "tests": []}
]
}
],
"solutions": []
}

View file

@ -0,0 +1,67 @@
# AI Product Evals — the new PRD quality contract
The single most-demanded new PM competency of 20252026, and the biggest coverage gap
this domain had. For deterministic features the PRD's acceptance criteria are the quality
contract; for **probabilistic (AI) features, the eval is the contract** — encode what
"good" means as data + rubric *before* building, or you ship on vibes.
## Evals are the new PRD
The PM owns three artifacts per AI feature:
1. **Golden set** — a labeled collection of real inputs with expected-quality outputs,
covering every intent the feature claims to handle plus the known failure modes
(hallucination, refusal, off-topic, unsafe). Floor: enough examples per intent that a
regression is statistically visible, and the set grows from production incidents.
2. **Rubric** — the dimensions of "good" (accuracy, groundedness, tone, format,
safety), each with a pass criterion a grader (human or LLM-judge) can apply
consistently. Check grader consistency with inter-rater agreement (Cohen's kappa)
before trusting LLM-judge scores.
3. **Guardrail metrics** — the SLOs that page someone: hallucination rate ceiling,
refusal-rate band, latency/cost budgets.
Anti-pattern: "vibe check" launches — demo-driven quality assessment with no golden set,
no rubric, no regression gate. It is the AI equivalent of shipping without tests.
## Model/system cards
Enterprise and regulated buyers expect a model card documenting intended use,
out-of-scope use, eval data and results (disaggregated where bias matters), and
limitations (Mitchell et al.'s nine canonical sections; Anthropic/OpenAI system cards in
current practice). The PM owns the product-facing half: intended use, eval results,
limitations users will hit.
## The loop connection (evaluator-optimizer)
The same generator/critic loop that powers agent harnesses is what PM-owned evals feed:
the golden set + rubric become the evaluator's criteria, and Anthropic's guidance is
explicit that the evaluator-optimizer pattern pays off exactly "when there are clear
evaluation criteria and iterative refinement provides measurable value." Practically:
- The eval spec is the `done_when` of any agent-harness task that touches an AI feature.
- Eval runs are the locked evaluator — the feature loop may edit prompts/retrieval/
models, never the golden set it is judged by (autoresearch invariant).
- Experiment-designer's sample-size math applies to eval deltas too: a 2-point rubric
improvement on 30 examples is noise.
## Where this lands in the domain today
- `experiment-designer` — extend hypothesis gates to eval-delta hypotheses.
- `product-manager-toolkit` — PRD template gains an "Eval spec" section for AI features
(golden set size, rubric dimensions, guardrail SLOs, owner).
- `product-analytics` — guardrail metrics join the KPI tree as SLO-style entries.
## Sources
1. Lenny's Newsletter, "Beyond vibe checks: A PM's complete guide to evals" —
https://www.lennysnewsletter.com/p/beyond-vibe-checks-a-pms-complete
2. Braintrust, "Evals for PMs" — https://www.braintrust.dev/blog/evals-for-pms
3. Aakash Gupta, "AI Evals" — https://www.news.aakashg.com/p/ai-evals
4. Mitchell et al., "Model Cards for Model Reporting" (FAT* 2019) —
https://arxiv.org/abs/1810.03993
5. Anthropic, "Building Effective Agents" (evaluator-optimizer applicability) —
https://www.anthropic.com/research/building-effective-agents
6. Jacob Cohen, "A Coefficient of Agreement for Nominal Scales" (1960) — kappa as the
inter-rater agreement statistic
7. This repo: `engineering/autoresearch-agent` (locked evaluator), `engineering/self-eval`
(anti-inflation scoring)

View file

@ -0,0 +1,71 @@
# Continuous Discovery Canon
The method layer behind `discovery_cadence_tracker.py` and `ost_linter.py`. The
20242026 discovery canon reframed discovery from a project phase into a **weekly
operating rhythm** with a structural artifact (the Opportunity Solution Tree) and a unit
of progress (the assumption test).
## The weekly habit (Torres)
Teresa Torres' definition of continuous discovery: the product trio (PM, designer,
engineer) has **at least weekly touchpoints with customers**, in pursuit of a desired
**outcome**, conducting **small research activities** (interviews, assumption tests).
Corollaries the tracker scores:
- **Cadence, not volume**: 4 interviews in one week then silence for a month is a broken
habit — hence the streak (30 pts) and week-coverage (30 pts) components.
- **Outcome-anchored**: interviews that don't tie back to the outcome drift into feature
tourism — hence the linkage component (20 pts).
- **Assumption tests are the throughput**: Torres' target rhythm resolves assumptions
continuously; piling up untested assumptions is discovery theater — hence the
throughput component (20 pts) and the untested-backlog gap.
## The Opportunity Solution Tree (why each lint rule exists)
- **O1 — one measurable outcome root**: the tree hangs from exactly one outcome, stated
with a metric and target. Multiple outcomes = multiple trees.
- **O2 — opportunities are needs, not features**: an opportunity is a customer need,
pain, or desire surfaced by research. "Add an onboarding wizard" is a solution wearing
an opportunity's clothes; the build-verb heuristic catches it.
- **O3 — compare ≥ 2 solutions per targeted opportunity**: Torres' compare-and-contrast
discipline; a single pet solution skips the decision.
- **O4 — every solution carries an assumption test**: untested solutions are opinions;
the test types (interview, prototype, smoke test, concierge) come from Bland's
desirability/viability/feasibility/usability mapping.
- **O5 — no orphan solutions**: a solution attached to no opportunity is the
feature-factory anti-pattern in its purest form.
## Assumption mapping & test sequencing (Bland)
Rank assumptions by **importance × evidence-weakness** and test the riskiest first
(leap-of-faith assumptions). Match test type to assumption class — desirability →
interview/smoke test; feasibility → spike/prototype; viability → pricing test/concierge.
This is `product-discovery/scripts/assumption_mapper.py`'s scoring model; the tracker's
untested-backlog gap feeds it.
## JTBD switch interviews (Moesta)
When interviews need depth, run the switch interview: reconstruct a real past purchase
timeline (first thought → passive looking → active looking → decision) and code the four
forces — push of the current situation, pull of the new solution, anxiety of the new,
habit of the present. Progress happens when push + pull outweigh anxiety + habit.
## Story mapping (Patton)
The bridge from a validated opportunity to a sliced backlog: backbone of activities
left-to-right, stories vertically, release slices horizontally — each slice an
end-to-end walking skeleton, never a vertical feature column.
## Sources
1. Teresa Torres, *Continuous Discovery Habits* (Product Talk LLC, 2021) and
https://www.producttalk.org/opportunity-solution-trees/
2. David J. Bland & Alexander Osterwalder, *Testing Business Ideas* (Wiley, 2019)
3. Bob Moesta, *Demand-Side Sales 101* (2020); Jobs-to-be-Done switch-interview practice
— https://jobstobedone.org/
4. Jeff Patton, *User Story Mapping* (O'Reilly, 2014)
5. Christian Rohrer, "When to Use Which User-Experience Research Methods", NN/g —
https://www.nngroup.com/articles/which-ux-research-methods/
6. Marty Cagan, *Inspired* (2nd ed., Wiley, 2018) — discovery/delivery separation
7. Product Talk, "The Product Operating Model and Continuous Discovery" —
https://www.producttalk.org/the-product-operating-model/

View file

@ -0,0 +1,69 @@
# Product Operating Model, Metrics & Prioritization Brackets
The strategy layer behind the orchestrator's STRATEGY/ANALYTICS/PRIORITIZE forcing
questions. Three moves define the 20242026 canon: the product operating model as the
org-level frame, the North Star framework as the metrics spine, and prioritization as a
**bracket of frameworks** rather than RICE-for-everything.
## The product operating model (Cagan, *Transformed*, 2024)
The transformation agenda in three principles: **empowered teams** (problems to solve,
not features to build), **outcomes over output**, **innovation over predictability**
elaborated as 20 first principles across how you build / solve problems / decide what to
work on. The tell-tale failures the orchestrator grills for: OKRs that are shipping
lists, roadmaps as commitments of output, teams measured on velocity instead of outcome.
## North Star framework (Amplitude)
A valid North Star Metric is (a) a **leading indicator** of sustainable business results,
(b) a measure of **value exchange** with the customer, (c) not revenue and not a vanity
count. It decomposes into an **input-metric tree** (breadth × depth × frequency ×
efficiency) that teams can actually move. AARRR remains the funnel taxonomy, but the
NSM + input tree is the strategy-to-analytics bridge product-analytics work should hang
from.
## PLG benchmark bands
Verdicts need bands, not vibes (medians from ProductLed/OpenView benchmark corpora,
20242025): signup→activation median ≈ 17% (best-in-class 3350%+); free→paid median
≈ 9% (PQL-driven motions 2530%). A funnel scorer without calibrated bands cannot say
"weak stage" honestly.
## Prioritization: bracket RICE, don't replace it
| Situation | Framework | Why |
|---|---|---|
| Steady-state backlog | **RICE** | Reach/impact/confidence/effort — cheap, comparable |
| Time sensitivity dominates (deadlines, market windows) | **WSJF / Cost of Delay** (Reinertsen) | RICE is time-blind; CoD/duration surfaces value erosion |
| Underserved-needs hunting | **Opportunity scoring** (Ulwick ODI) | importance + max(importance satisfaction, 0) ranks unmet outcomes |
Two disciplines regardless of framework: (1) **name which framework and why** before
scoring; (2) **sensitivity-check the ranking** — perturb each estimate one step and flag
items whose rank flips (the documented WSJF false-precision failure; SAFe's own critics'
point). `rice_prioritizer.py` covers lane 1; lanes 23 are scored by hand against the
formulas here until dedicated tools land.
## Event taxonomy governance (PostHog/Amplitude-era)
Analytics rot starts at instrumentation: enforce snake_case, present-tense verb
allowlists, object_verb ordering, compact event sets, and tracking-plan review before
new events ship. A taxonomy with near-duplicate events ("signup", "sign_up",
"user_signed_up") cannot support any metric above it.
## Sources
1. Marty Cagan (SVPG), *Transformed: Moving to the Product Operating Model* (Wiley,
2024); https://www.svpg.com/the-product-operating-model-an-introduction/
2. Amplitude, *The North Star Playbook*
https://amplitude.com/books/north-star/about-north-star-framework
3. ProductLed, "Product-Led Growth Benchmarks" —
https://productled.com/blog/product-led-growth-benchmarks; OpenView PLG benchmarks —
https://openviewpartners.com/blog/your-guide-to-product-led-growth-benchmarks/
4. Don Reinertsen, *The Principles of Product Development Flow* (Celeritas, 2009) — cost
of delay; SAFe WSJF — https://framework.scaledagile.com/wsjf
5. Anthony Ulwick, *What Customers Want* (McGraw-Hill, 2005) — Outcome-Driven Innovation
opportunity algorithm (strategyn.com)
6. Jason Yip, "Problems I have with SAFe-style WSJF" —
https://jchyip.medium.com/problems-i-have-with-safe-style-wsjf-772df2beaf02
7. PostHog, product analytics best practices —
https://posthog.com/docs/product-analytics/best-practices

View file

@ -0,0 +1,185 @@
#!/usr/bin/env python3
"""discovery_cadence_tracker.py — score a team's continuous-discovery habit.
Operationalizes Teresa Torres' continuous-discovery canon (weekly customer
touchpoints, outcome-first framing, assumption tests as the unit of progress) as a
deterministic recurring loop: feed it the discovery log each week (Observe), read the
named gaps (Choose), run the next interview or assumption test (Act), re-run the
tracker (Verify), and keep the streak alive (Repeat). The health score is the loop's
acceptance gate a subagent can branch on it mechanically.
Input JSON (see --sample):
{"outcome": "increase paid conversion from 9% to 12% by Q4",
"interviews": [{"date": "YYYY-MM-DD", "participant": str,
"outcome_linked": bool, "assumptions_tested": [str]}],
"assumption_tests": [{"date": "YYYY-MM-DD", "assumption": str,
"result": "validated|invalidated|inconclusive"}]}
Scoring (0100): weekly streak 30 · week coverage 30 · outcome linkage 20 ·
assumption-test throughput 20. Verdicts: HEALTHY >= 70 · AT-RISK 4069 · DORMANT < 40.
Exit codes: 0 scored · 2 unreadable input · 5 insufficient history (< 2 interviews
start the habit before measuring it). Deterministic: the analysis date defaults to
the newest date in the log, never the wall clock (override with --as-of).
Stdlib only.
"""
import argparse
import json
import sys
from datetime import date, timedelta
SAMPLE_LOG = {
"outcome": "increase paid conversion from 9% to 12% by Q4",
"interviews": [
{"date": "2026-05-05", "participant": "P1", "outcome_linked": True,
"assumptions_tested": ["users understand the trial limits"]},
{"date": "2026-05-12", "participant": "P2", "outcome_linked": True,
"assumptions_tested": []},
{"date": "2026-05-26", "participant": "P3", "outcome_linked": False,
"assumptions_tested": ["pricing page is the drop-off point"]},
{"date": "2026-06-02", "participant": "P4", "outcome_linked": True,
"assumptions_tested": ["annual plan framing increases upgrades"]},
],
"assumption_tests": [
{"date": "2026-05-15", "assumption": "users understand the trial limits",
"result": "invalidated"},
{"date": "2026-06-05", "assumption": "annual plan framing increases upgrades",
"result": "inconclusive"},
],
}
def parse_date(value):
try:
return date.fromisoformat(str(value)[:10])
except (TypeError, ValueError):
return None
def week_of(d: date):
return d.isocalendar()[:2]
def analyze(log: dict, as_of: date) -> dict:
interviews = [
{**i, "date": parse_date(i.get("date"))}
for i in log.get("interviews", [])
]
interviews = [i for i in interviews if i["date"] and i["date"] <= as_of]
tests = [
{**t, "date": parse_date(t.get("date"))}
for t in log.get("assumption_tests", [])
]
tests = [t for t in tests if t["date"] and t["date"] <= as_of]
interview_weeks = {week_of(i["date"]) for i in interviews}
first = min(i["date"] for i in interviews)
total_weeks = max(((as_of - first).days // 7) + 1, 1)
# Streak: consecutive weeks with >= 1 interview, counting back from as_of's week.
streak, cursor = 0, as_of
while week_of(cursor) in interview_weeks:
streak += 1
cursor -= timedelta(days=7)
coverage = len(interview_weeks) / total_weeks
linked = sum(1 for i in interviews if i.get("outcome_linked"))
linkage = linked / len(interviews)
resolved = sum(1 for t in tests if t.get("result") in ("validated", "invalidated"))
# Torres cadence target: >= 1 resolved assumption test per 2 weeks.
test_target = max(total_weeks / 2, 1)
throughput = min(resolved / test_target, 1.0)
score = round(
min(streak / 4, 1.0) * 30 + coverage * 30 + linkage * 20 + throughput * 20, 1)
verdict = "HEALTHY" if score >= 70 else ("AT-RISK" if score >= 40 else "DORMANT")
gaps = []
if streak == 0:
gaps.append("no interview in the current week — the weekly habit is broken "
"(Torres: touchpoints are a cadence, not a project phase)")
if coverage < 0.75:
missed = total_weeks - len(interview_weeks)
gaps.append(f"{missed} of {total_weeks} weeks had zero customer touchpoints")
if linkage < 0.8:
gaps.append(f"only {linked}/{len(interviews)} interviews tie back to the outcome — "
"re-anchor the interview guide on the outcome")
if throughput < 1.0:
gaps.append(f"{resolved} resolved assumption tests vs a target of "
f"{int(test_target)} — assumptions are piling up untested")
untested = {a for i in interviews for a in i.get("assumptions_tested", [])}
tested = {t.get("assumption") for t in tests}
backlog = sorted(untested - tested)
if backlog:
gaps.append(f"assumptions surfaced but never tested: {'; '.join(backlog[:3])}")
return {
"outcome": log.get("outcome", ""),
"as_of": as_of.isoformat(),
"weeks_observed": total_weeks,
"interviews": len(interviews),
"distinct_participants": len({i.get("participant") for i in interviews}),
"weekly_streak": streak,
"week_coverage_pct": round(coverage * 100, 1),
"outcome_linkage_pct": round(linkage * 100, 1),
"assumption_tests_resolved": resolved,
"health_score": score,
"verdict": verdict,
"gaps": gaps,
"next_loop_action": (gaps[0] if gaps else
"cadence healthy — book next week's touchpoint before this one ends"),
}
def main() -> int:
ap = argparse.ArgumentParser(
description="Score a continuous-discovery log for cadence health (Torres canon).")
ap.add_argument("--input", help="Path to the discovery log JSON ('-' for stdin).")
ap.add_argument("--as-of", help="Analysis date YYYY-MM-DD (default: newest date in log).")
ap.add_argument("--output", choices=["json", "human"], default="json")
ap.add_argument("--sample", action="store_true",
help="Analyze a built-in sample log and exit 0.")
args = ap.parse_args()
if args.sample:
log = SAMPLE_LOG
elif args.input:
try:
log = json.load(sys.stdin if args.input == "-"
else open(args.input, encoding="utf-8"))
except (OSError, ValueError) as exc:
print(f"ERROR: cannot read log: {exc}", file=sys.stderr)
return 2
else:
ap.error("--input is required (or use --sample)")
interviews = [i for i in log.get("interviews", []) if parse_date(i.get("date"))]
if len(interviews) < 2:
print("REFUSED: fewer than 2 dated interviews in the log — there is no cadence to "
"measure yet. Book the first two weekly touchpoints, then re-run.",
file=sys.stderr)
return 5
as_of = parse_date(args.as_of) if args.as_of else max(
d for d in
[parse_date(i.get("date")) for i in log.get("interviews", [])] +
[parse_date(t.get("date")) for t in log.get("assumption_tests", [])]
if d)
report = analyze(log, as_of)
if args.output == "json":
print(json.dumps(report, indent=2))
else:
print(f"Discovery health: {report['health_score']}/100 ({report['verdict']})")
print(f"Streak: {report['weekly_streak']} wk · coverage "
f"{report['week_coverage_pct']}% · linkage {report['outcome_linkage_pct']}% "
f"· tests resolved {report['assumption_tests_resolved']}")
for g in report["gaps"]:
print(f" gap: {g}")
print(f"Next: {report['next_loop_action']}")
return 0
if __name__ == "__main__":
sys.exit(main())

View file

@ -0,0 +1,160 @@
#!/usr/bin/env python3
"""ost_linter.py — structural linter for Opportunity Solution Trees.
The OST (Torres) is the structural artifact of modern product discovery:
outcome opportunities solutions assumption tests. Teams don't need prose
advice about trees they need their actual tree checked. This linter enforces the
structural rules deterministically, so an agent loop can use "ost_linter exits 0"
as the acceptance gate before a roadmap or experiment plan is allowed to cite the
tree.
Rules:
O1 exactly one outcome root, phrased measurably (contains a number, or a
`metric` field is present)
O2 opportunities are needs/pains/desires, not features flag statements that
start with build-verbs (add/build/implement/create/integrate/launch/ship)
O3 every opportunity marked "target": true has >= 2 solutions under
consideration (compare-and-contrast, never a single pet solution)
O4 every solution carries >= 1 assumption test
O5 no orphan solutions attached directly to the outcome a solution without an
opportunity is the feature-factory anti-pattern
Input JSON (see --sample):
{"outcome": {"statement": str, "metric": str?},
"opportunities": [{"statement": str, "target": bool?,
"children": [<nested opportunities>]?,
"solutions": [{"statement": str,
"tests": [{"assumption": str, "type": str}]}]}],
"solutions": [ ... ] # anything here is an O5 violation by definition
}
Exit codes: 0 clean (warnings allowed) · 2 violations found · 3 unreadable input.
Stdlib only, deterministic.
"""
import argparse
import json
import re
import sys
BUILD_VERBS = re.compile(
r"^\s*(add|build|implement|create|integrate|launch|ship|develop|make)\b", re.I)
SAMPLE_TREE = {
"outcome": {"statement": "Increase week-4 retention from 22% to 30%",
"metric": "week-4 retention"},
"opportunities": [
{"statement": "New users can't tell whether setup worked",
"target": True,
"solutions": [
{"statement": "Post-setup verification checklist",
"tests": [{"assumption": "users abandon because they doubt setup succeeded",
"type": "interview"}]},
{"statement": "Live sample-data preview after connect",
"tests": [{"assumption": "a working preview reduces first-week drop-off",
"type": "prototype"}]},
]},
{"statement": "Add an onboarding wizard",
"solutions": [
{"statement": "Onboarding wizard v2", "tests": []},
]},
],
"solutions": [],
}
def walk_opportunities(nodes, path="opportunities"):
for idx, node in enumerate(nodes or []):
here = f"{path}[{idx}]"
yield here, node
yield from walk_opportunities(node.get("children"), here + ".children")
def lint(tree: dict):
violations, warnings = [], []
outcome = tree.get("outcome")
if not isinstance(outcome, dict) or not str(outcome.get("statement", "")).strip():
violations.append({"rule": "O1", "where": "outcome",
"problem": "missing outcome root — an OST hangs from exactly one outcome"})
else:
stmt = outcome.get("statement", "")
if not (re.search(r"\d", stmt) or str(outcome.get("metric", "")).strip()):
violations.append({"rule": "O1", "where": "outcome",
"problem": f"outcome is not measurable: '{stmt[:80]}'"
"state a metric and a target number"})
opp_count = 0
for where, opp in walk_opportunities(tree.get("opportunities")):
opp_count += 1
stmt = str(opp.get("statement", ""))
if BUILD_VERBS.match(stmt):
violations.append({"rule": "O2", "where": where,
"problem": f"opportunity phrased as a feature: '{stmt[:80]}'"
"rewrite as the customer need/pain/desire behind it"})
solutions = opp.get("solutions") or []
if opp.get("target") and len(solutions) < 2:
violations.append({"rule": "O3", "where": where,
"problem": f"targeted opportunity has {len(solutions)} solution(s) — "
"Torres: compare >= 2 candidate solutions, never one pet idea"})
for sidx, sol in enumerate(solutions):
if not (sol.get("tests") or []):
violations.append({"rule": "O4", "where": f"{where}.solutions[{sidx}]",
"problem": f"solution '{str(sol.get('statement', ''))[:60]}' has no "
"assumption test — untested solutions are opinions"})
orphans = tree.get("solutions") or []
for sidx, sol in enumerate(orphans):
violations.append({"rule": "O5", "where": f"solutions[{sidx}]",
"problem": f"orphan solution '{str(sol.get('statement', ''))[:60]}' attached to "
"no opportunity — the feature-factory anti-pattern"})
if opp_count == 0 and not violations:
warnings.append("tree has an outcome but zero opportunities — map the opportunity "
"space before jumping to solutions")
return violations, warnings, opp_count
def main() -> int:
ap = argparse.ArgumentParser(
description="Lint an Opportunity Solution Tree for structural discipline (Torres canon).")
ap.add_argument("--input", help="Path to the OST JSON ('-' for stdin).")
ap.add_argument("--output", choices=["json", "human"], default="json")
ap.add_argument("--sample", action="store_true",
help="Lint a built-in sample tree (contains one O2 and one O4 violation) and exit 0.")
args = ap.parse_args()
if args.sample:
tree = SAMPLE_TREE
elif args.input:
try:
tree = json.load(sys.stdin if args.input == "-"
else open(args.input, encoding="utf-8"))
except (OSError, ValueError) as exc:
print(f"ERROR: cannot read tree: {exc}", file=sys.stderr)
return 3
else:
ap.error("--input is required (or use --sample)")
violations, warnings, opp_count = lint(tree)
result = {
"opportunities": opp_count,
"violations": violations,
"warnings": warnings,
"verdict": "STRUCTURALLY-SOUND" if not violations else "NEEDS-REWORK",
}
if args.output == "json":
print(json.dumps(result, indent=2))
else:
print(f"Verdict: {result['verdict']} ({opp_count} opportunities, "
f"{len(violations)} violation(s))")
for v in violations:
print(f" [{v['rule']}] {v['where']}: {v['problem']}")
for w in warnings:
print(f" (warn) {w}")
if args.sample:
return 0
return 0 if not violations else 2
if __name__ == "__main__":
sys.exit(main())

View file

@ -0,0 +1,207 @@
#!/usr/bin/env python3
"""product_goal_router.py — deterministic lane classifier for the product-team domain.
Scores a product goal/inquiry against the 12 bundled sub-skill lanes plus the 4
standalone product-team plugins (same two-signal threshold discipline as the
research-ops / commercial / markdown-html orchestrators). Emits a routing decision
an agent can branch on mechanically.
Exit codes:
0 confident route emitted (route_to set)
2 ambiguous ask ONE clarifying question naming the top two lanes
3 no signal do not guess; ask the user to restate the goal
Stdlib only. Deterministic: same text in, same route out.
"""
import argparse
import json
import sys
SIGNALS = {
"PRIORITIZE": {
"skill": "product-manager-toolkit",
"path": "product-team/skills/product-manager-toolkit",
"keywords": ["prioritize", "rice", "backlog ranking", "feature ranking",
"prd", "product requirements", "interview synthesis", "wsjf",
"cost of delay"],
},
"STRATEGY": {
"skill": "product-strategist",
"path": "product-team/skills/product-strategist",
"keywords": ["okr", "objective", "strategy", "quarterly planning",
"north star", "vision", "alignment"],
},
"UX": {
"skill": "ux-researcher-designer",
"path": "product-team/skills/ux-researcher-designer",
"keywords": ["persona", "journey map", "usability", "user research",
"research synthesis", "interview guide"],
},
"DESIGN_SYSTEM": {
"skill": "ui-design-system",
"path": "product-team/skills/ui-design-system",
"keywords": ["design token", "component spec", "design system",
"wcag", "contrast", "typography scale"],
},
"COMPETITIVE": {
"skill": "competitive-teardown",
"path": "product-team/skills/competitive-teardown",
"keywords": ["competitor", "competitive", "teardown", "pricing matrix",
"market position", "feature comparison"],
},
"ANALYTICS": {
"skill": "product-analytics",
"path": "product-team/skills/product-analytics",
"keywords": ["retention", "cohort", "funnel", "kpi", "activation",
"churn", "aarrr", "north star metric", "tracking plan",
"event taxonomy"],
},
"EXPERIMENT": {
"skill": "experiment-designer",
"path": "product-team/skills/experiment-designer",
"keywords": ["a/b test", "ab test", "experiment", "sample size",
"hypothesis", "mde", "statistical power", "eval"],
},
"DISCOVERY": {
"skill": "product-discovery",
"path": "product-team/skills/product-discovery",
"keywords": ["discovery", "opportunity", "assumption", "opportunity solution tree",
"ost", "continuous discovery", "customer interview cadence",
"jtbd", "jobs to be done"],
},
"ROADMAP": {
"skill": "roadmap-communicator",
"path": "product-team/skills/roadmap-communicator",
"keywords": ["roadmap", "release notes", "changelog", "launch comms",
"now next later"],
},
"SPEC_TO_REPO": {
"skill": "spec-to-repo",
"path": "product-team/skills/spec-to-repo",
"keywords": ["spec to repo", "scaffold from spec", "build from spec",
"generate the repo", "turn this spec into"],
},
"LANDING": {
"skill": "landing-page-generator",
"path": "product-team/skills/landing-page-generator",
"keywords": ["landing page", "hero section", "waitlist page", "marketing page"],
},
"SAAS_SCAFFOLD": {
"skill": "saas-scaffolder",
"path": "product-team/skills/saas-scaffolder",
"keywords": ["saas boilerplate", "saas skeleton", "bootstrap a saas",
"auth and billing", "stripe integration scaffold"],
},
# Standalone product-team plugins (packaged separately, routable all the same)
"STORIES": {
"skill": "agile-product-owner",
"path": "product-team/agile-product-owner/skills/agile-product-owner",
"keywords": ["user story", "user stories", "acceptance criteria", "invest",
"epic breakdown", "sprint capacity", "story splitting"],
},
"HIG": {
"skill": "apple-hig-expert",
"path": "product-team/apple-hig-expert/skills/apple-hig-expert",
"keywords": ["hig", "human interface guidelines", "ios design", "liquid glass",
"tap target", "apple design"],
},
"CODE_TO_PRD": {
"skill": "code-to-prd",
"path": "product-team/code-to-prd/skills/code-to-prd",
"keywords": ["reverse engineer", "code to prd", "prd from code",
"document this codebase as a prd", "existing app into a prd"],
},
"SUMMARIZE": {
"skill": "research-summarizer",
"path": "product-team/research-summarizer/skills/research-summarizer",
"keywords": ["summarize this paper", "summarize research", "citation extraction",
"compare these papers", "article summary"],
},
}
SAMPLE_GOAL = ("we keep shipping features nobody uses — I want a weekly discovery "
"habit and an opportunity solution tree before the next roadmap review")
def score(text: str) -> dict:
low = text.lower()
scores, hits = {}, {}
for lane, spec in SIGNALS.items():
matched = [kw for kw in spec["keywords"] if kw in low]
scores[lane] = len(matched)
hits[lane] = matched
return {"scores": scores, "hits": hits}
def decide(scores: dict) -> dict:
ranked = sorted(scores.items(), key=lambda kv: (-kv[1], kv[0]))
(top_lane, top), (second_lane, second) = ranked[0], ranked[1]
if top == 0:
return {"decision": "NO_SIGNAL", "exit": 3}
if top >= 2 and (second == 0 or top >= 2 * second):
return {"decision": "ROUTE", "lane": top_lane, "exit": 0}
candidates = [top_lane] + ([second_lane] if second > 0 else [])
return {"decision": "ASK", "candidates": candidates, "exit": 2}
def main() -> int:
ap = argparse.ArgumentParser(
description="Deterministic lane router for product-team goals.")
src = ap.add_mutually_exclusive_group()
src.add_argument("--text", help="Goal / inquiry text to classify.")
src.add_argument("--input", help="Read goal text from a file ('-' for stdin).")
ap.add_argument("--output", choices=["json", "human"], default="json")
ap.add_argument("--sample", action="store_true",
help="Classify a built-in sample goal and exit.")
args = ap.parse_args()
if args.sample:
text = SAMPLE_GOAL
elif args.text:
text = args.text
elif args.input:
text = (sys.stdin.read() if args.input == "-"
else open(args.input, encoding="utf-8").read())
else:
ap.error("one of --text, --input, or --sample is required")
result = score(text)
verdict = decide(result["scores"])
out = {
"goal": text.strip()[:300],
"scores": {k: v for k, v in result["scores"].items() if v},
"decision": verdict["decision"],
}
if verdict["decision"] == "ROUTE":
lane = verdict["lane"]
out["route_to"] = SIGNALS[lane]["skill"]
out["skill_path"] = SIGNALS[lane]["path"]
out["matched_signals"] = result["hits"][lane]
elif verdict["decision"] == "ASK":
out["candidates"] = [
{"lane": lane, "skill": SIGNALS[lane]["skill"], "score": result["scores"][lane]}
for lane in verdict["candidates"]
]
out["instruction"] = ("Ask ONE clarifying question naming both candidate lanes, "
"with a recommended answer. Never guess silently.")
else:
out["instruction"] = ("No lane signal. Ask the user to restate the goal with the "
"deliverable named. Do not route on fuzz.")
if args.output == "json":
print(json.dumps(out, indent=2))
else:
print(f"Decision: {out['decision']}")
if "route_to" in out:
print(f"Route to: {out['route_to']} ({out['skill_path']})")
print(f"Signals: {', '.join(out['matched_signals'])}")
elif "candidates" in out:
names = " vs ".join(c["skill"] for c in out["candidates"])
print(f"Ambiguous: {names} — ask one clarifying question.")
else:
print("No signal — ask the user to restate the goal.")
return verdict["exit"]
if __name__ == "__main__":
sys.exit(main())

View file

@ -541,10 +541,22 @@ def create_sample_user_data():
]
def main():
import sys
import argparse
parser = argparse.ArgumentParser(
description="Generate a research-backed persona from bundled sample data.")
parser.add_argument("format", nargs="?", choices=["json", "human"], default="human",
help="Output format (default: human).")
parser.add_argument("--output", dest="output_flag", choices=["json", "human"],
help="Output format (flag form, overrides the positional).")
parser.add_argument("--seed", type=int, default=42,
help="RNG seed for deterministic persona names (default: 42).")
args = parser.parse_args()
output = args.output_flag or args.format
random.seed(args.seed)
generator = PersonaGenerator()
# Create sample data
user_data = create_sample_user_data()
@ -561,7 +573,7 @@ def main():
persona = generator.generate_persona_from_data(user_data, interview_insights)
# Output
if len(sys.argv) > 1 and sys.argv[1] == 'json':
if output == 'json':
print(json.dumps(persona, indent=2))
else:
print(generator.format_persona_output(persona))

View file

@ -1,7 +1,7 @@
{
"name": "pm-skills",
"description": "9 project management skills: senior PM, scrum master, Jira expert, Confluence expert, Atlassian admin, template scaffolder, and Atlassian MCP-bundled (Remote SSE) integration. Agent skill and plugin for Claude Code, Codex, Gemini CLI, Cursor, OpenClaw.",
"version": "2.9.0",
"description": "9 project management skills: pm-skills fork-orchestrator with agentic delivery loop (deterministic 8-lane router, Jira MCP snapshot bridge to flow metrics/Monte Carlo forecasts, delegation-governance gate), senior PM, scrum master, Jira expert, Confluence expert, Atlassian admin, template scaffolder, meeting analyzer, team communications — plus bundled Atlassian Remote MCP (SSE) integration. Agent skill and plugin for Claude Code, Codex, Gemini CLI, Cursor, OpenClaw.",
"version": "2.10.4",
"author": {
"name": "Alireza Rezvani",
"url": "https://alirezarezvani.com"

View file

@ -1,22 +1,50 @@
# Project Management Skills - Claude Code Guidance
This guide covers the 9 production-ready project management skills, 12 Python automation tools, and bundled Atlassian Remote MCP integration (`.mcp.json` ships with the plugin — OAuth handled by Claude Code, no env vars required).
This guide covers the 9 production-ready project management skills, 15 Python automation tools, and bundled Atlassian Remote MCP integration (`.mcp.json` ships with the plugin — OAuth handled by Claude Code, no env vars required).
## PM Skills Overview
**Available Skills:**
1. **senior-pm/** - Portfolio health, risk analysis, resource planning (3 scripts)
2. **scrum-master/** - Sprint health, velocity forecasting, retrospectives (3 scripts)
3. **jira-expert/** - JQL building, workflow validation (2 scripts)
4. **confluence-expert/** - Space structure, content auditing (2 scripts)
5. **atlassian-admin/** - Permission auditing (1 script)
6. **atlassian-templates/** - Template scaffolding (1 script)
1. **pm-skills/** - Domain orchestrator (`context: fork`) + agentic delivery loop (3 scripts: goal router, Jira snapshot bridge, delivery loop gate)
2. **senior-pm/** - Portfolio health, risk analysis, resource planning (3 scripts)
3. **scrum-master/** - Sprint health, velocity forecasting, retrospectives (3 scripts)
4. **jira-expert/** - JQL building, workflow validation (2 scripts)
5. **confluence-expert/** - Space structure, content auditing (2 scripts)
6. **atlassian-admin/** - Permission auditing (1 script)
7. **atlassian-templates/** - Template scaffolding (1 script)
8. **meeting-analyzer/** - Meeting transcript behavioral analysis (prompt-driven; scripts are follow-up work)
9. **team-communications/** - 3P updates, newsletters, FAQs (reference-driven)
**Total Tools:** 12 Python automation tools
**Agent:** cs-project-manager (orchestrates all 6 skills)
**Slash Commands:** 3 (/sprint-health, /project-health, /retro)
**Total Tools:** 15 Python automation tools
**Agents:** 2 — cs-pm-orchestrator (routing + delivery loop) and cs-project-manager (legacy per-skill orchestration)
**Slash Commands:** 6 (/cs:pm, /cs:grill-pm, /cs:pm-loop, /sprint-health, /project-health, /retro)
**Key Feature:** Atlassian MCP Server integration for direct Jira/Confluence operations
## Orchestrator & Delivery Loop (pm-skills)
`skills/pm-skills/` is the domain's `context: fork` orchestrator and agent harness adapter:
```bash
# Route a PM goal deterministically (exit 0 route / 2 ask / 3 no signal)
python3 skills/pm-skills/scripts/pm_goal_router.py --text "our sprints feel off"
# Bridge a saved searchJiraIssuesUsingJql result into analyzable inputs
python3 skills/pm-skills/scripts/jira_snapshot_bridge.py --input snapshot.json --to flow --forecast 20
python3 skills/pm-skills/scripts/jira_snapshot_bridge.py --input snapshot.json --to sprint > sprint_data.json
python3 skills/scrum-master/scripts/velocity_analyzer.py sprint_data.json
# Gate agent-executed delivery loops (G1 human owner … G6 exhausted budget = escalation)
python3 skills/pm-skills/scripts/delivery_loop_gate.py --plan plan.json --mode plan # exit 2 = blocked
python3 skills/pm-skills/scripts/delivery_loop_gate.py --plan plan.json --mode close # exit 4 = refused
```
Multi-task goals compile through the repo-wide harness
(`engineering/agent-harness` with the `project-management.json` manifest). Hard rules:
agents contribute, humans own; forecasts are Monte Carlo ranges, never dates; exhausted
budgets escalate — never reported as success. The five reusable PM loops (sprint-flow,
health, retro-action, RAID-hygiene, comms) are documented in
`skills/pm-skills/references/pm_loop_playbook.md`.
## Atlassian MCP Integration
**Purpose:** Direct integration with Jira and Confluence via Model Context Protocol (MCP)
@ -179,8 +207,8 @@ python atlassian-templates/scripts/template_scaffolder.py meeting-notes
---
**Last Updated:** June 10, 2026
**Skills Deployed:** 9/9 PM skills production-ready
**Total Tools:** 12 Python automation tools
**Agent:** cs-project-manager | **Commands:** 3
**Last Updated:** July 3, 2026
**Skills Deployed:** 9/9 PM skills production-ready (pm-skills is now a fork-orchestrator + delivery loop)
**Total Tools:** 15 Python automation tools
**Agents:** cs-pm-orchestrator, cs-project-manager | **Commands:** 6
**Integration:** Atlassian Remote MCP Server (bundled via `.mcp.json`) for Jira/Confluence automation

View file

@ -0,0 +1,77 @@
---
name: cs-pm-orchestrator
description: Flow-first delivery lead. Routes project-management inquiries (sprint/velocity, portfolio health, Jira/JQL, Confluence, Atlassian admin, templates, meetings, comms) to the right sub-skill via the pm-skills orchestrator, and drives delivery goals through bounded agentic loops with machine-checkable gates. Forks context to keep heavy intake (Jira snapshots, retro logs, transcripts) out of the parent thread. Signature forcing question — "What single observable outcome means DONE, and which command proves it?"
tools: Read, Write, Edit, Glob, Grep, Bash, Skill
model: sonnet
---
# PM Orchestrator
You are a flow-first delivery lead. You measure before you forecast, derive health
instead of accepting self-reported green, and you never let a loop close on optimism.
Agents contribute; humans own — every task you plan names a human owner, and every
acceptance criterion is a command or a threshold.
## Voice
**"What single observable outcome means DONE, and which command proves it?"**
The trap you protect against: verification theater — status set to Done with no
evidence, forecasts stated as dates, watermelon projects reported green while aging WIP
rots.
## Your 8 lanes
| Lane | Skill | Signals |
|---|---|---|
| HEALTH | senior-pm | portfolio, risk EMV, capacity, exec report |
| SPRINT | scrum-master | velocity, retro, ceremonies, flow, forecast |
| JIRA | jira-expert | JQL, workflows, boards, automation |
| CONFLUENCE | confluence-expert | spaces, page trees, content audits |
| ADMIN | atlassian-admin | users, permissions, SSO |
| TEMPLATES | atlassian-templates | blueprints, storage-format scaffolds |
| MEETINGS | meeting-analyzer | transcripts, talk time, action items |
| COMMS | team-communications | 3P updates, newsletters, FAQs |
## Routing logic
1. Run `python3 project-management/skills/pm-skills/scripts/pm_goal_router.py --text "<goal>"`.
2. Exit 0 → load the routed skill's SKILL.md, follow its workflow in the forked context.
3. Exit 2 → ask ONE clarifying question naming the candidates, with a recommended answer.
4. Exit 3 → ask the user to restate the goal with the deliverable named. Never guess.
## How you communicate (Matt Pocock grill discipline)
One question per turn; always recommend; explore the workspace before asking (a saved
Jira snapshot or retro log resolves the lane silently); depth-first on multi-lane
inquiries; never silently chain. Digest ≤ 200 words: what was analyzed, top 3 findings
(canon-cited), top 3 next actions (named human owner), artifact path, one grill
challenge.
Hard outputs:
- Flow numbers come from `jira_snapshot_bridge.py` on real snapshot data — never from
memory or hand-typed estimates.
- Forecasts are Monte Carlo percentile ranges (p50/p70/p85/p95), never single dates.
- Loop plans pass `delivery_loop_gate.py --mode plan` (exit 0) before execution and
`--mode close` (exit 0) before you report done.
## Anti-patterns
- ❌ Route to two skills at once, or run all 8 "to be thorough"
- ❌ Accept "make our delivery better" — grill until the outcome and its proof command are
named
- ❌ Transition Jira issues to Done, change permissions, or delete anything inside a loop
without the named human approver
- ❌ Report an exhausted attempt/iteration budget as success
## When to escalate
- What-to-build questions → `product-team` (cs-product-orchestrator)
- Internal-ops process mapping → `business-operations`
- Generic loop mechanics / other domains → `engineering/agent-harness` harness-runner
- Regulatory/compliance delivery → `ra-qm-team`
## Available commands
`/cs:pm <inquiry>` (router) · `/cs:grill-pm <plan>` (grill first) · `/cs:pm-loop <goal>`
(delivery loop) · plus the domain's `/sprint-health`, `/project-health`, `/retro`.

View file

@ -0,0 +1,57 @@
---
description: Matt Pocock-style interrogation of a delivery plan against the PM canon (Kanban Guide 2025, Vacanti, DORA 2025, EBM, Klein, GitLab async-first). One forcing question per turn with a recommended answer; refuses to invoke any sub-skill or start a loop until the lane-defining decisions are locked. Use before running /cs:pm or /cs:pm-loop on a fuzzy plan.
argument-hint: "<delivery plan, goal, or status quo to interrogate>"
---
# /cs:grill-pm — grill a delivery plan before running it
Interrogate this plan — do not execute anything yet:
**$ARGUMENTS**
Five rules (preserved from Matt Pocock, MIT): one question per turn · always give a
recommended answer · explore the workspace before asking · walk the decision tree
depth-first · track answered questions and their dependencies.
## Decision tree
- **Branch 1 — Outcome**: "What single observable outcome means DONE, and which command
proves it? Recommended: a named artifact + a command that exits 0 against it. Canon:
agent-harness verifier's law."
- **Branch 2 — Measurement**: "Are you measuring flow before forecasting? Recommended:
run `jira_snapshot_bridge.py --to flow` first — WIP, throughput, cycle time, age.
Canon: Kanban Guide (May 2025) four mandatory measures."
- **Branch 3 — Forecast honesty**: "Is any date in this plan a single-point promise?
Recommended: replace with Monte Carlo p50/p85 ranges; refuse forecasts on < 10
completed items. Canon: Vacanti, *When Will It Be Done?*"
- **Branch 4 — Ownership**: "For every task an agent will execute: who is the human owner
and who reviews? Recommended: name both now; `delivery_loop_gate.py` will refuse the
plan otherwise. Canon: Linear agents model; Atlassian Rovo audit discipline."
- **Branch 5 — Risk**: "Have you run a pre-mortem on this plan? Recommended: 30 minutes,
'it's six months later and this failed — why?'; convert top clusters to owned risks.
Canon: Klein, HBR 2007."
- **Branch 6 — Budgets**: "What are the retry and iteration caps, and who reviews
escalations? Recommended: 3 attempts/task, 12 iterations/goal, a named human. Canon:
loop-library terminal states."
Per-turn output format:
```
Q[i]/[total]: [precise question]
Recommended: [answer + canon-cited rationale]
(Confirm, or override?)
```
## Stop conditions
- All branches resolved → invoke `/cs:pm` (question) or `/cs:pm-loop` (goal) with the
locked decisions inlined.
- User says "stop grilling, just run it" → run with unresolved branches flagged in the
digest.
- Abandoned → save the partial grill to `pm-grill-{timestamp}.md`.
## Distinct from
- `engineering/grill-me` — generic plan interrogation. This grills against the PM canon.
- `/cs:pm` — routes; this refuses to route until decisions are locked.

View file

@ -0,0 +1,50 @@
---
description: Drive a project-delivery goal through a bounded agentic loop — Jira MCP snapshot → flow/sprint analytics bridge → routed sub-skill execution → machine-verified gates → close refused until everything is verified or human-waived. The PM-domain adapter over engineering/agent-harness.
argument-hint: "<delivery goal, e.g. 'get sprint 14 to a verified close with health >= 70'>"
---
# /cs:pm-loop — run a delivery goal to a verified close
Goal:
**$ARGUMENTS**
## Sequence (gates are blocking — never skip forward)
1. **Intake gate** — the goal must name an observable outcome and its proof. If vague,
run the `/cs:grill-pm` branches first (one question per turn). Do not loop on fuzz.
2. **Observe** — pull fresh data: `mcp__atlassian__getAccessibleAtlassianResources` (get
cloudId) → `mcp__atlassian__searchJiraIssuesUsingJql` → save `snapshot.json`, then:
```bash
python3 project-management/skills/pm-skills/scripts/jira_snapshot_bridge.py --input snapshot.json --to flow
python3 project-management/skills/pm-skills/scripts/jira_snapshot_bridge.py --input snapshot.json --to sprint > sprint_data.json
```
3. **Plan** — write the task plan (owners, executors, reviewers, machine-checkable
acceptance per task; shape via `delivery_loop_gate.py --sample`), then gate it:
```bash
python3 project-management/skills/pm-skills/scripts/delivery_loop_gate.py --plan plan.json --mode plan
```
Exit 2 → fix the listed G1G4 violations before executing. For multi-task goals,
compile through the repo harness instead (`goal_compiler.py` with the
`project-management.json` manifest) and drive it with `loop_controller.py`.
4. **Execute** — one task at a time: route with `pm_goal_router.py`, run the routed
sub-skill's own tools, record real exit codes and evidence. Retry means a changed
approach; max 3 attempts per task.
5. **Verify** — the task's acceptance command must exit 0; sub-skill gates apply
(scrum-master's ≥3-sprints rule, atlassian-admin's VERIFY steps). Never adjudicate
your own verification; never edit a gate to make it pass.
6. **Close**
```bash
python3 project-management/skills/pm-skills/scripts/delivery_loop_gate.py --plan plan.json --mode close
```
Exit 4 → close refused: finish, escalate, or get a human waiver (with reason). Exit 0
→ report the handoff: tasks, statuses, evidence, waivers, and the flow-metrics
before/after.
## Rules
- Terminal states: success · clean no-op · blocked · approval-required · exhausted ·
stagnated. Exhausted budgets escalate to the named human — never reported as success.
- Jira writes are auditable: no `transitionJiraIssue` to Done without verify evidence;
admin/destructive actions are approval-required, full stop.
- Max 12 loop iterations per goal; 3 attempts per task.

View file

@ -0,0 +1,45 @@
---
description: Top-level project-management router. Classifies a PM inquiry across 8 lanes (sprint/flow, portfolio health, Jira, Confluence, admin, templates, meetings, comms) with a deterministic script and forks context to the right sub-skill via the pm-skills orchestrator, returning a ≤200-word digest with a named owner and one grill challenge.
argument-hint: "<PM inquiry: sprint health, project status, JQL, permissions, retro, comms, etc.>"
---
# /cs:pm — Project Management router
Route this inquiry through the `pm-skills` orchestrator:
**$ARGUMENTS**
## Routing (deterministic — run the script, don't eyeball)
```bash
python3 project-management/skills/pm-skills/scripts/pm_goal_router.py --text "$ARGUMENTS" --output json
```
- Exit 0 → load `skill_path`/SKILL.md and follow that skill's own workflow in a fork.
- Exit 2 → ask ONE clarifying question naming the listed candidates, recommended answer
first.
- Exit 3 → ask the user to restate the goal with the deliverable named. Never guess.
- Explore the workspace first — a saved Jira snapshot, retro log, or transcript resolves
the lane silently. Never silently chain a second sub-skill.
## Output (≤200-word digest)
- What was analyzed (with the data source — snapshot file, not memory)
- Top 3 findings, each anchored to a canon citation
- Top 3 next actions with a named human owner
- Artifact path
- One grill challenge (e.g. "Your health report is self-reported RAG — where's the
derived diff that catches watermelons?")
## Hard rules
- Flow numbers come from `jira_snapshot_bridge.py` on real snapshot data.
- Forecasts are Monte Carlo percentile ranges, never single dates.
- Live Jira/Confluence ops use only the tools in
`project-management/references/atlassian-mcp-tools.md` — never invent tool names.
- Goals (not questions) go to `/cs:pm-loop` instead.
## Distinct from
- `product-team` — what to build. This domain is how to deliver it.
- `/cs:harness` — the generic loop engine; `/cs:pm-loop` is its PM-domain adapter.

View file

@ -1,50 +1,173 @@
---
name: "pm-skills"
description: "Router/index for the 8 project-management skills bundled in this plugin (senior PM quant toolkit, scrum master, Jira/JQL, Confluence, Atlassian admin, Atlassian templates, meeting analyzer, team communications). Use when a PM request doesn't obviously match one skill and you need to pick the right one (e.g., 'our sprints feel off', 'audit our Jira permissions'). Bundles an Atlassian Remote MCP config (.mcp.json) for live Jira/Confluence access."
version: 2.9.0
description: "Use when coordinating project-delivery work across the 8 project-management sub-skills — sprint/velocity analytics, portfolio health, Jira/JQL, Confluence, Atlassian admin, templates, meeting analysis, team comms. Triggers on 'our sprints feel off', 'project health report', 'audit our Jira permissions', 'when will it be done', 'run the delivery loop'. Forks context to route to one sub-skill via a deterministic signal router and returns a digest; can also drive a full goal→plan→execute→verify→close delivery loop through the repo-wide agent-harness with Jira MCP data bridged into the domain's analytics tools. Distinct from product-team (what to build vs how to deliver it), business-operations (internal ops), and engineering/agent-harness (the generic loop engine this orchestrator plugs into)."
context: fork
version: 2.10.4
author: Alireza Rezvani
license: MIT
tags:
- project-management
- jira
- confluence
- atlassian
- scrum
- agile
agents:
- claude-code
- codex-cli
- openclaw
tags: [project-management, orchestrator, jira, confluence, atlassian, scrum, agile, flow-metrics, agent-harness]
compatible_tools: [claude-code, codex-cli, cursor, antigravity, opencode, gemini-cli]
---
# Project Management Skills — Router
# Project Management — Domain Orchestrator & Delivery Loop
This plugin bundles **8 PM skills** (this router is the 9th folder under `project-management/skills/`). Each skill is self-contained. The bundled `.mcp.json` wires the Atlassian Remote MCP (`https://mcp.atlassian.com/v1/sse`, OAuth handled by Claude Code).
This orchestrator does two jobs. **Routing:** fork context, classify a PM inquiry with
`scripts/pm_goal_router.py`, run exactly one of the 8 sub-skills, return a digest.
**Looping:** turn a delivery goal into a bounded agentic loop — pull live Jira data via the
bundled Atlassian MCP, bridge it into the domain's deterministic analytics tools, verify
every step with machine-run gates, and refuse to close until everything is verified or a
human waives it. The bundled `.mcp.json` wires the Atlassian Remote MCP
(`https://mcp.atlassian.com/v1/sse`, OAuth handled by Claude Code).
## Routing table
## When to invoke
Match the request, then load `project-management/skills/<skill>/SKILL.md`. If multiple rows match, ask one clarifying question first.
| Symptom | Sub-skill |
|---|---|
| "Project/portfolio health, risk EMV, capacity" | `senior-pm` |
| "Sprint velocity, retro follow-through, ceremony health, when-will-it-be-done" | `scrum-master` |
| "JQL, Jira workflows, boards, automation" | `jira-expert` |
| "Confluence spaces, page trees, content audits" | `confluence-expert` |
| "Users, groups, permissions, SSO" | `atlassian-admin` |
| "Reusable Jira/Confluence templates" | `atlassian-templates` |
| "Meeting transcripts, talk time, action items" | `meeting-analyzer` |
| "Status updates, 3P updates, stakeholder comms" | `team-communications` |
| Request signals | Skill | Path |
|---|---|---|
| Project health, risk EMV, three-point estimates | senior-pm | `skills/senior-pm/` |
| Sprint velocity, retro analysis, ceremony health | scrum-master | `skills/scrum-master/` |
| JQL queries, Jira workflows, boards | jira-expert | `skills/jira-expert/` |
| Confluence spaces, page structure, content audits | confluence-expert | `skills/confluence-expert/` |
| User/permission/scheme administration | atlassian-admin | `skills/atlassian-admin/` |
| Reusable Confluence/Jira templates | atlassian-templates | `skills/atlassian-templates/` |
| Meeting transcripts, talk-time, action items | meeting-analyzer | `skills/meeting-analyzer/` |
| Status updates, 3P updates, stakeholder comms | team-communications | `skills/team-communications/` |
## Routing logic (deterministic)
## Quick start
Run the router — do not eyeball the table when a script can decide:
```bash
# Example: route a sprint-health request
cat project-management/skills/scrum-master/SKILL.md
ls project-management/skills/scrum-master/scripts/
python3 scripts/pm_goal_router.py --text "<the goal>" --output json
```
## Rules
Exit 0 → `route_to` names the sub-skill: load its SKILL.md and follow its workflow.
Exit 2 → ask ONE clarifying question naming the listed candidates, with a recommended
answer. Exit 3 → no signal: ask the user to restate the goal with the deliverable named.
Never guess silently; never silently chain a second sub-skill — digest first, confirm, then
chain.
- Live Jira/Confluence operations go through the Atlassian Remote MCP (camelCase tool names such as `createJiraIssue`, `searchJiraIssuesUsingJql`, `createConfluencePage` — canonical list in `project-management/references/atlassian-mcp-tools.md`). Admin operations are NOT covered by the MCP — use admin.atlassian.com or the REST API per atlassian-admin.
- Route to exactly one skill, then follow that skill's workflow. This router ships no tools of its own.
## The delivery loop (agentic)
For goals (not questions) — "get sprint 14 to a verified close", "produce a portfolio
health report from live Jira", "make our flow metrics visible weekly" — run the
loop-library contract (Observe → Choose → Act → Verify → Record → Repeat-or-stop):
1. **Observe** — pull fresh state: `mcp__atlassian__searchJiraIssuesUsingJql` (get
`cloudId` via `getAccessibleAtlassianResources` first), save the result JSON, then
bridge it:
```bash
python3 scripts/jira_snapshot_bridge.py --input snapshot.json --to flow # WIP, throughput, cycle time p50/85/95, work-item age, SLE, aging alerts
python3 scripts/jira_snapshot_bridge.py --input snapshot.json --to sprint > s.json # scrum-master schema
python3 ../scrum-master/scripts/velocity_analyzer.py s.json # velocity + volatility + forecast
```
Add `--forecast N` for a seeded Monte Carlo "when will N items be done" answer
(refuses on < 10 completed items thin history forecasts are lies).
2. **Choose** — route the next task with `pm_goal_router.py`; one task at a time.
3. **Act** — execute with the routed sub-skill's own tools per its SKILL.md.
4. **Verify** — gate the plan and every close with:
```bash
python3 scripts/delivery_loop_gate.py --plan plan.json --mode plan # exit 2 = blocked
python3 scripts/delivery_loop_gate.py --plan plan.json --mode close # exit 4 = close refused
```
Plus each sub-skill's own gates (scrum-master's ≥ 3-sprints rule, atlassian-admin's
VERIFY steps). Never adjudicate your own verification.
5. **Record / Repeat-or-stop** — for multi-task goals, run the state through the repo-wide
harness (it enforces attempt caps, iteration budgets, and evidence logging):
```bash
python3 engineering/agent-harness/skills/agent-harness/scripts/goal_compiler.py \
--goal "<goal>" --manifest engineering/agent-harness/skills/agent-harness/assets/harnesses/project-management.json \
--out .agent-harness/plan.json
python3 engineering/agent-harness/skills/agent-harness/scripts/loop_controller.py init|next|record|verify|close ...
```
Terminal states: success, clean no-op, blocked, approval-required, exhausted,
stagnated. An exhausted budget is an escalation — never a success report.
## Hard rules (agentic delegation governance)
1. **Agents are contributors, never owners** (Linear model): every loop task carries a
named human owner; agent-executed tasks also carry a named human reviewer.
`delivery_loop_gate.py` enforces this (G1/G2).
2. **Acceptance must be machine-checkable** — a command, or a criterion with a threshold.
"Looks good" is not a gate (G3).
3. **Every Jira/Confluence write is auditable and reversible-first** (Rovo discipline):
never `transitionJiraIssue` to Done without verify evidence; destructive/irreversible
actions (deletes, permission changes, org-wide admin) are approval-required terminal
states, not loop steps.
4. **Never modify a gate you are judged by** — same locked-evaluator invariant as
autoresearch-agent.
5. **Forecasts are ranges with confidence, never dates** — Monte Carlo percentiles
(p50/p70/p85/p95), per Vacanti. Single-date promises are the anti-pattern.
6. **Max 3 attempts per task, 12 loop iterations per goal** — then escalate to the named
human with the evidence log.
## Forcing-question library (grill-with-docs pattern)
One per turn, recommended answer, canon citation. Never run a sub-skill or start a loop
until the lane-defining decision is locked:
- **SPRINT lane**: "Do you want to *measure* flow (cycle time, WIP, throughput, age) or
*forecast* delivery? Recommended: measure first — a forecast off unmeasured flow is
noise. Canon: Kanban Guide (May 2025) four mandatory flow measures; Vacanti,
*Actionable Agile Metrics*."
- **HEALTH lane**: "Is your project status self-reported RAG or derived from signals?
Recommended: derive it (schedule variance, aging WIP, scope churn) and diff against the
self-report — that diff finds watermelon projects. Canon: Kanban Guide 2025;
DORA 2025 (AI amplifies, doesn't fix, weak signals)."
- **JIRA lane**: "Is this configuration change deployable to a test project first?
Recommended: always stage in a test project; jira-expert's workflow validator must exit
0 before production. Canon: jira-expert validation workflow."
- **ADMIN lane**: "Is this action reversible, and who approves it? Recommended: name the
approver before touching permissions — admin actions are approval-required terminal
states in any loop. Canon: atlassian-admin VERIFY discipline; loop-library stop states."
- **LOOP intake**: "What single observable outcome means DONE, and which command proves
it? Recommended: a named artifact + a command that exits 0 against it. Canon:
agent-harness verifier's law; Anthropic, *Building Effective Agents* (evaluator needs
clear criteria)."
- **MEETINGS/COMMS lanes**: "Could this meeting be an async written update? Recommended:
status-broadcast meetings convert to async 3P updates; decision meetings keep sync.
Canon: GitLab async-first handbook."
## Assumptions
1. The user has (or is preparing analysis for someone with) delivery authority.
2. Jira/Confluence access goes through the bundled MCP; capabilities NOT in
`project-management/references/atlassian-mcp-tools.md` (project/sprint/board/space
creation, admin config) are done in the web UI — never invent tool names.
3. Inputs may be partial — every tool ships `--sample` so the shape is visible first.
## Non-goals
- Not a replacement for the sub-skills — the orchestrator routes and loops; the
sub-skills do the work.
- Not the generic loop engine — that is `engineering/agent-harness`; this orchestrator is
the PM-domain adapter (data bridge + governance gate + lane router).
- Does not decide *what* to build — that's `product-team`.
## Output artifacts
| Mode | Artifact |
|---|---|
| Route | Sub-skill's own artifact + ≤ 200-word digest with one canon-cited challenge |
| Flow report | `flow_metrics.json` (bridge output) with SLE conformance + aging alerts |
| Delivery loop | `.agent-harness/plan.json` + `state.json` + gate verdicts + close handoff |
## Anti-patterns (do not)
- ❌ Run all 8 sub-skills "to be thorough" — route to one, digest, chain on confirmation
- ❌ Report sprint health or forecasts from hand-typed numbers when a Jira snapshot is one
MCP call away — bridge real data
- ❌ Close a loop with unverified tasks, or report an exhausted budget as success
- ❌ Let an agent be the assignee of record — humans own, agents contribute
- ❌ Auto-transition Jira issues or touch permissions inside a loop without the named
approver
## References
- [references/flow_forecasting_canon.md](references/flow_forecasting_canon.md) — Kanban
Guide 2025, Vacanti Monte Carlo, DORA 2025, EBM, SPACE
- [references/agentic_delivery_governance.md](references/agentic_delivery_governance.md) —
Linear/Rovo delegation models, Anthropic agent patterns, audit discipline
- [references/pm_loop_playbook.md](references/pm_loop_playbook.md) — the five reusable PM
loops (sprint, health, retro-action, RAID-hygiene, comms) mapped to the loop contract
- Canonical MCP tool list: `project-management/references/atlassian-mcp-tools.md`
- Loop engine: `engineering/agent-harness` · Loop vocabulary: `loop-library`

View file

@ -0,0 +1,53 @@
{
"mode": "flow",
"as_of": "2026-06-10",
"counts": {
"total": 14,
"done": 11,
"wip": 2
},
"cycle_time_days": {
"p50": 9,
"p85": 14,
"p95": 16,
"basis": "created\u2192resolved (approximation; Jira exports rarely carry an in-progress timestamp)"
},
"throughput": {
"done_per_week": 2.08,
"weeks_observed": 5.3
},
"sle": {
"days": 14,
"conformance_pct": 90.9
},
"work_item_age": [
{
"key": "PHX-112",
"summary": "Realtime presence indicators",
"age_days": 15
},
{
"key": "PHX-113",
"summary": "Usage analytics dashboard",
"age_days": 2
}
],
"aging_wip_alerts": [
{
"key": "PHX-112",
"summary": "Realtime presence indicators",
"age_days": 15
}
],
"warnings": [],
"forecast": {
"items": 20,
"method": "Monte Carlo over historical weekly throughput (10k trials, seeded)",
"weeks": {
"p50": 11,
"p70": 12,
"p85": 12,
"p95": 13
}
}
}

View file

@ -0,0 +1,19 @@
{
"_comment": "Saved output shape of mcp__atlassian__searchJiraIssuesUsingJql — feed to scripts/jira_snapshot_bridge.py. Expected flow output pinned in expected_flow_metrics.json.",
"issues": [
{"key": "PHX-101", "fields": {"summary": "User authentication service", "status": {"name": "Done"}, "created": "2026-05-04T09:00:00.000+0000", "resolutiondate": "2026-05-08T16:00:00.000+0000", "customfield_10016": 5, "sprint": {"name": "Sprint 11"}, "assignee": {"displayName": "A. Rivera"}, "priority": {"name": "High"}}},
{"key": "PHX-102", "fields": {"summary": "Dashboard layout", "status": {"name": "Done"}, "created": "2026-05-04T09:00:00.000+0000", "resolutiondate": "2026-05-12T11:00:00.000+0000", "customfield_10016": 3, "sprint": {"name": "Sprint 11"}, "assignee": {"displayName": "B. Okafor"}, "priority": {"name": "Medium"}}},
{"key": "PHX-103", "fields": {"summary": "Password reset flow", "status": {"name": "Done"}, "created": "2026-05-05T09:00:00.000+0000", "resolutiondate": "2026-05-13T15:00:00.000+0000", "customfield_10016": 2, "sprint": {"name": "Sprint 11"}, "assignee": {"displayName": "A. Rivera"}, "priority": {"name": "Medium"}}},
{"key": "PHX-104", "fields": {"summary": "Billing webhooks", "status": {"name": "Done"}, "created": "2026-05-11T09:00:00.000+0000", "resolutiondate": "2026-05-20T10:00:00.000+0000", "customfield_10016": 8, "sprint": {"name": "Sprint 12"}, "assignee": {"displayName": "C. Duarte"}, "priority": {"name": "High"}}},
{"key": "PHX-105", "fields": {"summary": "Email notifications", "status": {"name": "Done"}, "created": "2026-05-12T09:00:00.000+0000", "resolutiondate": "2026-05-19T17:00:00.000+0000", "customfield_10016": 3, "sprint": {"name": "Sprint 12"}, "assignee": {"displayName": "B. Okafor"}, "priority": {"name": "Medium"}}},
{"key": "PHX-106", "fields": {"summary": "Audit log export", "status": {"name": "Done"}, "created": "2026-05-13T09:00:00.000+0000", "resolutiondate": "2026-05-22T12:00:00.000+0000", "customfield_10016": 5, "sprint": {"name": "Sprint 12"}, "assignee": {"displayName": "D. Weiss"}, "priority": {"name": "Low"}}},
{"key": "PHX-107", "fields": {"summary": "Mobile responsive nav", "status": {"name": "Done"}, "created": "2026-05-18T09:00:00.000+0000", "resolutiondate": "2026-05-27T09:30:00.000+0000", "customfield_10016": 5, "sprint": {"name": "Sprint 13"}, "assignee": {"displayName": "A. Rivera"}, "priority": {"name": "High"}}},
{"key": "PHX-108", "fields": {"summary": "Rate limiting middleware", "status": {"name": "Done"}, "created": "2026-05-19T09:00:00.000+0000", "resolutiondate": "2026-05-29T14:00:00.000+0000", "customfield_10016": 3, "sprint": {"name": "Sprint 13"}, "assignee": {"displayName": "C. Duarte"}, "priority": {"name": "Medium"}}},
{"key": "PHX-109", "fields": {"summary": "Data export CSV", "status": {"name": "Done"}, "created": "2026-05-20T09:00:00.000+0000", "resolutiondate": "2026-06-03T16:00:00.000+0000", "customfield_10016": 2, "sprint": {"name": "Sprint 13"}, "assignee": {"displayName": "D. Weiss"}, "priority": {"name": "Low"}}},
{"key": "PHX-110", "fields": {"summary": "SSO SAML integration", "status": {"name": "Done"}, "created": "2026-05-25T09:00:00.000+0000", "resolutiondate": "2026-06-10T10:00:00.000+0000", "customfield_10016": 8, "sprint": {"name": "Sprint 14"}, "assignee": {"displayName": "C. Duarte"}, "priority": {"name": "High"}}},
{"key": "PHX-111", "fields": {"summary": "Search relevance tuning", "status": {"name": "Done"}, "created": "2026-06-01T09:00:00.000+0000", "resolutiondate": "2026-06-09T11:00:00.000+0000", "customfield_10016": 3, "sprint": {"name": "Sprint 14"}, "assignee": {"displayName": "B. Okafor"}, "priority": {"name": "Medium"}}},
{"key": "PHX-112", "fields": {"summary": "Realtime presence indicators", "status": {"name": "In Progress"}, "created": "2026-05-26T09:00:00.000+0000", "customfield_10016": 8, "sprint": {"name": "Sprint 14"}, "assignee": {"displayName": "A. Rivera"}, "priority": {"name": "High"}}},
{"key": "PHX-113", "fields": {"summary": "Usage analytics dashboard", "status": {"name": "In Progress"}, "created": "2026-06-08T09:00:00.000+0000", "customfield_10016": 5, "sprint": {"name": "Sprint 14"}, "assignee": {"displayName": "D. Weiss"}, "priority": {"name": "Medium"}}},
{"key": "PHX-114", "fields": {"summary": "Legacy importer deprecation", "status": {"name": "To Do"}, "created": "2026-06-09T09:00:00.000+0000", "customfield_10016": 3, "sprint": {"name": "Sprint 14"}, "assignee": {"displayName": "B. Okafor"}, "priority": {"name": "Low"}}}
]
}

View file

@ -0,0 +1,71 @@
# Agentic Delivery Governance
The accountability layer behind `delivery_loop_gate.py`. When agents execute delivery
work, the failure mode is not bad output — it is **unowned output**: work no human is
accountable for, verified by nobody, closed by the optimism of the thing that did it.
The 20252026 vendors converged on the same governance shape; this file encodes it.
## The delegation model (why G1/G2 exist)
- **Linear's shipped design**: issues can be delegated to agents, but the **human stays
primary assignee; the agent is a contributor**. Delegation transfers execution, never
accountability. → Gate G1: every task names a human owner.
- **Atlassian Rovo (GA 2026)**: agents are assignable and @mentionable inside Jira, but
"every action remains logged and auditable", and multi-step plans pause for human
oversight at decision points. → Gate G2: agent-executed tasks name a human reviewer;
hard rule: no un-reviewed `transitionJiraIssue` to Done, no permission changes inside a
loop.
## Verification discipline (why G3/G4 exist)
- **Machine-checkable definition of done**: the reliable loop shape is plan → act →
verify with a deterministic verifier → reflect. A criterion without a command or a
threshold ("looks good", "improved") cannot gate anything. → G3: acceptance = a `cmd`,
or a criterion containing a measurable number.
- **Never trust self-report**: the agent that did the work does not adjudicate the work.
Evidence precedes status: `done` without recorded evidence is rejected (G4) — the same
invariant as agent-harness's "a verify pass without --evidence is exit 6" and
autoresearch-agent's locked evaluator ("never modify the gate you are judged by").
## Terminal-state honesty (why G5/G6 exist)
From the loop-library contract: loops end in a **named terminal state** — success, clean
no-op, blocked, approval-required, exhausted, stagnated. Two corollaries the gate
enforces:
- Close is refused while any task is neither done nor waived (G5); waivers are human
decisions with recorded rationale.
- An exhausted budget (attempts or iterations) is an **escalation**, never a success
report (G6). Budgets are first-class: max attempts per task, max loop iterations, and
the stop fires mechanically, not when the agent feels finished.
## Design principles for PM loops
1. **Workflows before agents** (Anthropic): most PM automation is a routed workflow
(classify → run tool → report). Reach for the autonomous loop only when the task needs
fresh feedback each cycle — flow snapshots, retro follow-through, RAID hygiene.
2. **Evaluator-optimizer needs clear criteria**: the generator/critic loop pays off
exactly when acceptance is machine-checkable — which is why the gate forces G3 before
any loop starts.
3. **Context from structured interfaces, not prompt-stuffing**: the agent's Jira context
comes through the MCP (Teamwork-Graph-style structured access), snapshotted to a file
the loop can re-read — every iteration is executable by a fresh session.
4. **Agent-readiness is a data-hygiene property**: agents amplify the Jira they are given
(DORA 2025's amplifier finding). Field completeness, acceptance criteria in
descriptions, and honest statuses are prerequisites, not nice-to-haves.
## Sources
1. Linear, "Agents in Linear" / Linear for Agents — https://linear.app/agents and
https://linear.app/docs/agents-in-linear
2. Atlassian Rovo — https://www.atlassian.com/software/rovo and Rovo agents docs
https://support.atlassian.com/rovo/docs/agents/
3. Anthropic, "Building Effective Agents" (orchestrator-workers, evaluator-optimizer,
simplicity-first) — https://www.anthropic.com/research/building-effective-agents
4. Forward Future, Loop Library (terminal-state taxonomy; "never report an error or
exhausted budget as success") — vendored at `loop-library/SKILL.md`
5. DORA, *State of DevOps 2025* (AI as amplifier) — https://dora.dev/dora-report-2025/
6. This repo: `engineering/agent-harness` references/verification_discipline.md
(reward-hacking failure mode; locked evaluators)
7. SiliconANGLE, "Atlassian opens Teamwork Graph, pushes Rovo agentic execution"
(Team '26 coverage) — https://siliconangle.com/2026/05/06/

View file

@ -0,0 +1,76 @@
# Flow Metrics & Probabilistic Forecasting Canon
The measurement layer behind `jira_snapshot_bridge.py --to flow`. The 20242026 delivery
canon moved from velocity/story-point folklore to **flow measurement + probabilistic
forecasting + outcome measures**. This file anchors every number the bridge emits.
## The four mandatory flow measures (Kanban Guide, May 2025)
The Kanban Guide mandates exactly four measures — teams that track anything must track
these:
| Measure | Definition | Bridge field |
|---|---|---|
| **WIP** | Work items started but not finished | `counts.wip` |
| **Throughput** | Items finished per unit of time | `throughput.done_per_week` |
| **Cycle time** | Elapsed time started → finished | `cycle_time_days.p50/p85/p95` |
| **Work item age** | Elapsed time for *unfinished* started items | `work_item_age` |
Plus a **Service Level Expectation (SLE)**: "we finish items of this type within N days,
X% of the time." The bridge defaults the SLE to the p85 cycle time and reports
conformance. **Work item age is the leading indicator** — an in-progress item older than
the p85 SLE is the earliest visible slip signal (`aging_wip_alerts`); cycle time only
tells you after the fact.
Caveat the bridge prints itself: Jira exports rarely carry an in-progress timestamp, so
cycle time is approximated created→resolved. When your workflow logs a real start
transition, prefer it.
## Percentiles, not averages
Cycle-time distributions are right-skewed; the mean lies. Report p50/p85/p95
(Vacanti). Commit externally at p85, plan internally at p50, treat p95 as the tail-risk
budget.
## Monte Carlo forecasting (replaces story-point velocity)
"When will it be done?" is answered by sampling historical throughput, not by dividing
backlog points by velocity: sample the weekly-throughput history 10k times, read the
p50/p70/p85/p95 week counts (`--forecast N`). Rules the bridge enforces:
- **Refuses on < 10 completed items across < 4 distinct weeks** — thin history produces
confident nonsense.
- **Seeded RNG** — same data in, same forecast out (audit-reproducible).
- **Ranges with confidence, never a date** — a single-date promise is the anti-pattern.
## Outcome measures above flow
Flow says whether delivery is smooth, not whether it is *valuable*:
- **DORA 2025**: replaced low/high/elite clusters with seven team archetypes over eight
measures; core 2025 finding — AI *amplifies* an org's existing strengths and
dysfunctions (individual output up, org delivery flat without enabling capabilities).
- **EBM (Scrum.org)**: four Key Value Areas — Current Value, Unrealized Value,
Time-to-Market, Ability to Innovate. Most orgs measure only T2M; empty CV/UV areas mean
you are measuring motion, not value.
- **SPACE**: any metrics portfolio must span ≥ 3 of Satisfaction/Performance/Activity/
Communication/Efficiency — activity-only portfolios (PR counts) are the documented
anti-pattern.
- **Derived health beats self-reported RAG**: diff derived signals (aging WIP, scope
churn, schedule variance) against the self-reported status to find "watermelon"
projects (green outside, red inside) — the pattern behind senior-pm's dashboard.
## Sources
1. The Kanban Guide (May 2025) — https://kanbanguides.org/the-kanban-guide/
2. Daniel Vacanti, *Actionable Agile Metrics for Predictability* and *When Will It Be
Done?* (ActionableAgile Press)
3. Scrum.org, "4 Key Flow Metrics and How to Use Them" —
https://www.scrum.org/resources/blog/4-key-flow-metrics-and-how-use-them-scrums-events
4. Scrum.org, "Monte Carlo Forecasting in Scrum" —
https://www.scrum.org/resources/blog/monte-carlo-forecasting-scrum
5. DORA, *Accelerate State of DevOps Report 2025* — https://dora.dev/dora-report-2025/
6. Scrum.org, *The Evidence-Based Management Guide*
https://www.scrum.org/resources/evidence-based-management
7. Forsgren, Storey et al., "The SPACE of Developer Productivity", ACM Queue —
https://queue.acm.org/detail.cfm?id=3454124

View file

@ -0,0 +1,92 @@
# The PM Loop Playbook — five reusable delivery loops
Concrete instantiations of the loop contract (Observe → Choose → Act → Verify → Record →
Repeat-or-stop) for day-to-day PM work. Each loop names its trigger, its machine gate,
and its terminal states — a loop without a named stop is just an unbounded retry.
## Loop 1 — Sprint flow loop (weekly)
- **Observe**: `searchJiraIssuesUsingJql` → save snapshot →
`jira_snapshot_bridge.py --to flow`.
- **Choose**: highest-leverage signal first — aging-WIP alerts beat cycle-time trends
(age is the leading indicator; cycle time is a lagging one).
- **Act**: unblock/swarm/split the flagged item with the team; scrum-master skill for
ceremony-level fixes.
- **Verify**: next week's bridge run — the flagged item left `aging_wip_alerts`, SLE
conformance did not drop.
- **Stop states**: success (no alerts 2 weeks running) · stagnated (same item flagged 3
weeks → escalate to the delivery lead by name) · approval-required (fix needs scope
change).
## Loop 2 — Health-report loop (per reporting period)
- **Observe**: bridge `--to sprint``velocity_analyzer.py` +
`sprint_health_scorer.py`; senior-pm's `project_health_dashboard.py` for the portfolio.
- **Choose**: diff derived health against the self-reported RAG — investigate the largest
divergence first (watermelon detection).
- **Act**: senior-pm workflows (risk register, capacity rebalance).
- **Verify**: divergence shrinks next period; every red flag has a named owner + dated
action.
- **Stop states**: success · blocked (data quality too poor to derive — fix Jira hygiene
first, see agent-readiness note in agentic_delivery_governance.md).
## Loop 3 — Retro action loop (per sprint)
The retro is not the loop — the **action-item completion rate** is. Scrum-master's
retrospective_analyzer computes it (fixture: 46.7%).
- **Observe**: `retrospective_analyzer.py` on the retro log.
- **Choose**: oldest open action item with a named owner.
- **Act**: drive it to done or explicitly kill it (a cancelled action with a reason beats
a zombie).
- **Verify**: completion rate trend up across 3 sprints.
- **Stop states**: success (≥ 70% completion) · stagnated (rate flat 3 sprints → the retro
format is the problem; change the ritual, per Klein's pre-mortem alternative).
## Loop 4 — RAID hygiene loop (biweekly)
- **Observe**: risk register / RAID log staleness — entries missing owner, next-review
date, or mitigation; issues open > 30 days.
- **Choose**: stalest critical-severity entry.
- **Act**: senior-pm's `risk_matrix_analyzer.py` re-score; pre-mortem session for new
workstreams (prospective hindsight measurably improves risk identification — Klein).
- **Verify**: zero critical entries without owner+mitigation; staleness p85 < review
cadence.
- **Stop states**: success · clean no-op (nothing stale — record and exit; do not invent
work).
## Loop 5 — Comms cadence loop (weekly)
- **Observe**: which status-broadcast meetings ran this week; which stakeholder updates
shipped.
- **Choose**: convert the largest status-broadcast meeting to an async 3P update
(GitLab's handbook-first model: written 3-question standups take 35 min vs 1530 sync;
GitLab reports ~37% meeting-hour reduction).
- **Act**: team-communications skill (3P format); meeting-analyzer on the transcripts of
the meetings that remain.
- **Verify**: sync:async ratio trending down; no stakeholder escalation citing "I didn't
know".
- **Stop states**: success · approval-required (a stakeholder insists on sync — their
call, record it).
## Rules that hold across all five
1. One bounded, reversible change per iteration (autoresearch's "ONE change" rule).
2. Fresh state before every consequential action — re-pull the snapshot, don't act on
last week's.
3. Separate the optimizing signal from the acceptance gate — if you optimize SLE
conformance, verify with throughput + age too (anti-overfit, loop-library).
4. Every escalation names a human and attaches the evidence log.
## Sources
1. Forward Future, Loop Library — the Observe→…→Repeat-or-stop contract and terminal-state
taxonomy (vendored at `loop-library/SKILL.md`)
2. The Kanban Guide (May 2025) — https://kanbanguides.org/the-kanban-guide/
3. Gary Klein, "Performing a Project Premortem", HBR 2007 —
https://hbr.org/2007/09/performing-a-project-premortem
4. GitLab Handbook, asynchronous work —
https://handbook.gitlab.com/handbook/company/culture/all-remote/asynchronous/
5. Sumeet Moghe, *The Async-First Playbook* (2023)
6. This repo: `engineering/autoresearch-agent` (one-change-per-iteration, locked
evaluator), `engineering/agent-harness` (state machine, budgets)

View file

@ -0,0 +1,152 @@
#!/usr/bin/env python3
"""delivery_loop_gate.py — governance gate for agent-executed delivery loops.
Encodes the 20252026 agentic-delegation canon as a machine-checkable gate
(Linear's agents model: the human stays accountable for delegated work; Atlassian
Rovo: every agent action stays auditable; loop-library: exhausted budgets are never
reported as success). Run it on a delivery-loop plan before executing (--mode plan)
and again before closing (--mode close). Pairs with the repo-wide
engineering/agent-harness loop_controller.py, which enforces the run-time state
machine; this gate enforces the PM-specific accountability rules the controller
does not know about.
Plan JSON shape (see --sample):
{"goal": str,
"budgets": {"max_attempts_per_task": int, "max_loop_iterations": int},
"iteration": int,
"tasks": [{"id","title","owner","executor":"human|agent","reviewer",
"acceptance": {"cmd": str} | {"criterion": str},
"status":"todo|in_progress|done|blocked|waived",
"evidence": str, "attempts": int, "waive_reason": str}]}
Rules enforced:
G1 every task has a named human owner (agents are contributors, never owners)
G2 agent-executed tasks name a human reviewer distinct from nobody
G3 acceptance is machine-checkable: a cmd, or a criterion containing a measurable
threshold (a digit) "looks good" is not a gate
G4 done requires non-empty evidence; waived requires a waive_reason
G5 close is refused while any task is neither done nor waived
G6 close is refused when budgets are exhausted with work remaining that is an
escalation, not a success
Exit codes: 0 pass · 2 plan violations · 3 unreadable input · 4 close refused.
Stdlib only, deterministic.
"""
import argparse
import json
import re
import sys
SAMPLE_PLAN = {
"goal": "Get sprint 14 to a verified close with a health score >= 70",
"budgets": {"max_attempts_per_task": 3, "max_loop_iterations": 12},
"iteration": 4,
"tasks": [
{"id": "T1", "title": "Pull sprint snapshot via searchJiraIssuesUsingJql",
"owner": "Sarah Chen", "executor": "agent", "reviewer": "Sarah Chen",
"acceptance": {"cmd": "python3 scripts/jira_snapshot_bridge.py --input snapshot.json --to sprint"},
"status": "done", "evidence": "sprint_data.json written, 4 sprints", "attempts": 1},
{"id": "T2", "title": "Score sprint health",
"owner": "Sarah Chen", "executor": "agent", "reviewer": "Mike Rodriguez",
"acceptance": {"criterion": "sprint_health_scorer.py composite >= 70"},
"status": "in_progress", "evidence": "", "attempts": 1},
],
}
def check_plan(plan):
violations, warnings = [], []
tasks = plan.get("tasks", [])
if not tasks:
violations.append({"rule": "G1", "task": "-", "problem": "plan has no tasks"})
for t in tasks:
tid = t.get("id", "?")
if not str(t.get("owner", "")).strip():
violations.append({"rule": "G1", "task": tid,
"problem": "no named human owner (Linear rule: agents are contributors, never owners)"})
if t.get("executor") == "agent" and not str(t.get("reviewer", "")).strip():
violations.append({"rule": "G2", "task": tid,
"problem": "agent-executed task has no named human reviewer"})
acc = t.get("acceptance") or {}
cmd = str(acc.get("cmd", "")).strip()
criterion = str(acc.get("criterion", "")).strip()
if not cmd and not (criterion and re.search(r"\d", criterion)):
violations.append({"rule": "G3", "task": tid,
"problem": "acceptance is not machine-checkable "
"(need a cmd, or a criterion with a measurable threshold)"})
status = t.get("status", "todo")
if status == "done" and not str(t.get("evidence", "")).strip():
violations.append({"rule": "G4", "task": tid,
"problem": "done without evidence — never record a verify pass you did not observe"})
if status == "waived" and not str(t.get("waive_reason", "")).strip():
violations.append({"rule": "G4", "task": tid,
"problem": "waived without a waive_reason (waivers are human decisions with rationale)"})
max_attempts = plan.get("budgets", {}).get("max_attempts_per_task")
if max_attempts and t.get("attempts", 0) >= max_attempts and status not in ("done", "waived", "blocked"):
warnings.append({"rule": "G6", "task": tid,
"note": f"attempts exhausted ({t.get('attempts')}/{max_attempts}) — escalate, do not retry"})
return violations, warnings
def check_close(plan):
refusals = []
for t in plan.get("tasks", []):
if t.get("status") not in ("done", "waived"):
refusals.append({"rule": "G5", "task": t.get("id", "?"),
"problem": f"status is '{t.get('status', 'todo')}' — close refused while tasks are unverified and unwaived"})
budgets = plan.get("budgets", {})
max_iter = budgets.get("max_loop_iterations")
if max_iter and plan.get("iteration", 0) > max_iter and refusals:
refusals.append({"rule": "G6", "task": "-",
"problem": f"iteration {plan['iteration']} > cap {max_iter} with open tasks — "
"this is an ESCALATION, never a success report"})
return refusals
def main() -> int:
ap = argparse.ArgumentParser(
description="Accountability gate for agent-executed PM delivery loops.")
ap.add_argument("--plan", help="Path to the loop plan JSON ('-' for stdin).")
ap.add_argument("--mode", choices=["plan", "close"], default="plan")
ap.add_argument("--output", choices=["json", "human"], default="json")
ap.add_argument("--sample", action="store_true",
help="Print a valid sample plan and exit 0.")
args = ap.parse_args()
if args.sample:
print(json.dumps(SAMPLE_PLAN, indent=2))
return 0
if not args.plan:
ap.error("--plan is required (or use --sample to see the expected shape)")
try:
plan = json.load(sys.stdin if args.plan == "-" else open(args.plan, encoding="utf-8"))
except (OSError, ValueError) as exc:
print(f"ERROR: cannot read plan: {exc}", file=sys.stderr)
return 3
violations, warnings = check_plan(plan)
result = {"mode": args.mode, "goal": plan.get("goal", ""),
"violations": violations, "warnings": warnings}
exit_code = 0
if args.mode == "close":
refusals = check_close(plan)
result["close_refusals"] = refusals
result["verdict"] = "CLOSE-REFUSED" if (refusals or violations) else "CLOSE-OK"
exit_code = 4 if (refusals or violations) else 0
else:
result["verdict"] = "PLAN-BLOCKED" if violations else "PLAN-OK"
exit_code = 2 if violations else 0
if args.output == "json":
print(json.dumps(result, indent=2))
else:
print(f"Verdict: {result['verdict']}")
for v in violations + result.get("close_refusals", []):
print(f" [{v['rule']}] {v['task']}: {v['problem']}")
for w in warnings:
print(f" (warn {w['rule']}) {w['task']}: {w['note']}")
return exit_code
if __name__ == "__main__":
sys.exit(main())

View file

@ -0,0 +1,268 @@
#!/usr/bin/env python3
"""jira_snapshot_bridge.py — turn a Jira MCP issue export into analyzable inputs.
Closes the domain's biggest wiring gap: `mcp__atlassian__searchJiraIssuesUsingJql`
returns issue JSON, but the domain's deterministic analytics tools
(scrum-master/velocity_analyzer.py, sprint_health_scorer.py) expect their own
sprint-record schema, and nothing computed flow metrics at all. This bridge accepts
a saved Jira search result (raw MCP shape with `issues[].fields`, or a flat list of
simplified issue dicts) and emits:
--to flow the four mandatory Kanban flow measures (Kanban Guide, May 2025):
WIP, throughput, cycle time (p50/p85/p95), work-item age plus SLE
conformance and aging-WIP alerts, and an optional Monte Carlo
"when will N items be done" forecast (Vacanti-style, seeded, refuses
on < 10 completed items).
--to sprint scrum-master sprint-record JSON (pipe into velocity_analyzer.py /
sprint_health_scorer.py). Refuses with exit 5 on < 3 sprints,
mirroring velocity_analyzer's own minimum.
Cycle time here is createdresolved (Jira's export rarely carries an in-progress
timestamp); the output labels this approximation explicitly.
Exit codes: 0 ok · 2 unreadable/invalid input · 5 insufficient data for the
requested mode. Stdlib only; deterministic (as-of defaults to the newest timestamp
in the data, never the wall clock; the forecast RNG is seeded).
"""
import argparse
import json
import math
import random
import sys
from datetime import date, timedelta
DONE_STATUSES = {"done", "closed", "resolved", "released"}
NOT_STARTED_STATUSES = {"to do", "todo", "open", "backlog", "new", "created"}
POINT_FIELD_CANDIDATES = ["story_points", "storyPoints", "customfield_10016", "points"]
SAMPLE_SNAPSHOT = {
"issues": [
{"key": "PROJ-1", "fields": {"summary": "Login flow", "status": {"name": "Done"},
"created": "2026-05-04T09:00:00.000+0000",
"resolutiondate": "2026-05-08T16:00:00.000+0000",
"customfield_10016": 5, "sprint": {"name": "Sprint 12"},
"assignee": {"displayName": "A. Rivera"}}},
{"key": "PROJ-2", "fields": {"summary": "Rate limiting", "status": {"name": "In Progress"},
"created": "2026-05-18T09:00:00.000+0000", "customfield_10016": 3,
"sprint": {"name": "Sprint 13"}, "assignee": {"displayName": "B. Okafor"}}},
]
}
def parse_date(value):
if not value:
return None
text = str(value)[:10]
try:
return date.fromisoformat(text)
except ValueError:
return None
def name_of(value):
if isinstance(value, dict):
return value.get("name") or value.get("displayName") or ""
return str(value) if value else ""
def sprint_of(value):
if isinstance(value, list) and value:
value = value[-1]
return name_of(value)
def normalize(raw, points_field):
if isinstance(raw, dict) and "issues" in raw:
records = raw["issues"]
elif isinstance(raw, list):
records = raw
else:
raise ValueError("expected {'issues': [...]} or a JSON list of issues")
issues = []
for rec in records:
f = rec.get("fields", rec) if isinstance(rec, dict) else {}
points = None
for cand in ([points_field] if points_field else []) + POINT_FIELD_CANDIDATES:
if cand and f.get(cand) is not None:
points = f.get(cand)
break
status = name_of(f.get("status")).lower()
issues.append({
"key": rec.get("key") or f.get("key") or "?",
"summary": f.get("summary", ""),
"status": status,
"done": status in DONE_STATUSES,
"started": status not in NOT_STARTED_STATUSES,
"created": parse_date(f.get("created")),
"resolved": parse_date(f.get("resolutiondate") or f.get("resolved")),
"points": float(points) if points is not None else None,
"sprint": sprint_of(f.get("sprint") or f.get("customfield_10020")),
"assignee": name_of(f.get("assignee")),
"priority": name_of(f.get("priority")).lower(),
})
return [i for i in issues if i["created"]]
def percentile(sorted_values, pct):
if not sorted_values:
return None
rank = max(1, math.ceil(pct / 100 * len(sorted_values)))
return sorted_values[rank - 1]
def flow_report(issues, as_of, sle_days, forecast_items, seed):
done = [i for i in issues if i["done"] and i["resolved"]]
wip = [i for i in issues if not i["done"] and i["started"]]
cycles = sorted(max((i["resolved"] - i["created"]).days, 0) for i in done)
p50, p85, p95 = (percentile(cycles, p) for p in (50, 85, 95))
span_days = max((as_of - min(i["created"] for i in issues)).days, 7) if issues else 7
weeks = max(span_days / 7.0, 1.0)
weekly = {}
for i in done:
wk = i["resolved"].isocalendar()[:2]
weekly[wk] = weekly.get(wk, 0) + 1
sle = sle_days if sle_days else p85
conformance = (
round(100 * sum(1 for c in cycles if c <= sle) / len(cycles), 1)
if cycles and sle is not None else None
)
aging = sorted(
({"key": i["key"], "summary": i["summary"][:60],
"age_days": (as_of - i["created"]).days} for i in wip),
key=lambda a: -a["age_days"],
)
aging_alerts = [a for a in aging if p85 is not None and a["age_days"] > p85]
report = {
"mode": "flow",
"as_of": as_of.isoformat(),
"counts": {"total": len(issues), "done": len(done), "wip": len(wip)},
"cycle_time_days": {"p50": p50, "p85": p85, "p95": p95,
"basis": "created→resolved (approximation; Jira exports rarely carry an in-progress timestamp)"},
"throughput": {"done_per_week": round(len(done) / weeks, 2),
"weeks_observed": round(weeks, 1)},
"sle": {"days": sle, "conformance_pct": conformance},
"work_item_age": aging[:10],
"aging_wip_alerts": aging_alerts,
"warnings": [],
}
if len(done) < 10:
report["warnings"].append(
f"only {len(done)} completed items — flow percentiles are low-confidence below 10")
if forecast_items:
if len(weekly) < 4 or len(done) < 10:
report["warnings"].append(
"forecast refused: need >= 10 completed items across >= 4 distinct weeks "
"(Vacanti: throughput sampling needs real history)")
else:
rng = random.Random(seed)
samples = list(weekly.values())
trials = []
for _ in range(10000):
remaining, wk = forecast_items, 0
while remaining > 0 and wk < 520:
remaining -= rng.choice(samples)
wk += 1
trials.append(wk)
trials.sort()
report["forecast"] = {
"items": forecast_items,
"method": "Monte Carlo over historical weekly throughput (10k trials, seeded)",
"weeks": {f"p{p}": percentile(trials, p) for p in (50, 70, 85, 95)},
}
return report
def sprint_export(issues):
by_sprint = {}
for i in issues:
if i["sprint"]:
by_sprint.setdefault(i["sprint"], []).append(i)
if len(by_sprint) < 3:
print(f"REFUSED: {len(by_sprint)} sprint(s) in snapshot — velocity analysis needs >= 3 "
"(same gate as velocity_analyzer.py). Widen the JQL date range.", file=sys.stderr)
return None
ordered = sorted(by_sprint.items(),
key=lambda kv: min(i["created"] for i in kv[1]))
sprints = []
for n, (name, items) in enumerate(ordered, 1):
planned = sum(i["points"] or 0 for i in items)
completed = sum(i["points"] or 0 for i in items if i["done"])
starts = min(i["created"] for i in items)
ends = max((i["resolved"] or i["created"]) for i in items)
sprints.append({
"sprint_number": n, "sprint_name": name,
"start_date": starts.isoformat(), "end_date": ends.isoformat(),
"planned_points": round(planned, 1), "completed_points": round(completed, 1),
"added_points": 0, "removed_points": 0,
"carry_over_points": round(planned - completed, 1) if planned > completed else 0,
"team_capacity": 0, "working_days": 10,
"team_size": len({i["assignee"] for i in items if i["assignee"]}),
"stories": [{
"id": i["key"], "title": i["summary"][:80], "points": i["points"] or 0,
"status": "completed" if i["done"] else ("in_progress" if i["started"] else "not_started"),
"assigned_to": i["assignee"], "created_date": i["created"].isoformat(),
**({"completed_date": i["resolved"].isoformat()} if i["resolved"] else {}),
"blocked_days": 0, "priority": i["priority"] or "medium",
} for i in items],
"blockers": [],
})
return {
"team_info": {"name": "bridged-from-jira", "size": 0,
"scrum_master": "", "product_owner": ""},
"sprints": sprints,
"_note": ("Bridged from a Jira snapshot: added/removed/carry-over/capacity and "
"ceremonies are not derivable from issue exports — fill them in or accept "
"the conservative defaults before scoring sprint health."),
}
def main() -> int:
ap = argparse.ArgumentParser(
description="Bridge a saved Jira MCP search result into flow metrics or "
"scrum-master sprint-record JSON.")
ap.add_argument("--input", help="Path to the saved Jira search JSON ('-' for stdin).")
ap.add_argument("--to", choices=["flow", "sprint"], default="flow")
ap.add_argument("--points-field", help="Custom field id carrying story points "
"(e.g. customfield_10016).")
ap.add_argument("--as-of", help="Analysis date YYYY-MM-DD (default: newest date in data).")
ap.add_argument("--sle-days", type=int, help="Service Level Expectation in days "
"(default: the p85 cycle time).")
ap.add_argument("--forecast", type=int, metavar="N",
help="Monte Carlo forecast: weeks to finish N more items.")
ap.add_argument("--seed", type=int, default=42)
ap.add_argument("--sample", action="store_true",
help="Print a sample input snapshot and exit 0.")
args = ap.parse_args()
if args.sample:
print(json.dumps(SAMPLE_SNAPSHOT, indent=2))
return 0
if not args.input:
ap.error("--input is required (or use --sample to see the expected shape)")
try:
raw = json.load(sys.stdin if args.input == "-" else open(args.input, encoding="utf-8"))
issues = normalize(raw, args.points_field)
except (OSError, ValueError) as exc:
print(f"ERROR: cannot read snapshot: {exc}", file=sys.stderr)
return 2
if not issues:
print("ERROR: no issues with a created date found in the snapshot.", file=sys.stderr)
return 2
if args.to == "sprint":
result = sprint_export(issues)
if result is None:
return 5
print(json.dumps(result, indent=2))
return 0
as_of = parse_date(args.as_of) if args.as_of else max(
(i["resolved"] or i["created"]) for i in issues)
report = flow_report(issues, as_of, args.sle_days, args.forecast, args.seed)
print(json.dumps(report, indent=2))
return 0
if __name__ == "__main__":
sys.exit(main())

View file

@ -0,0 +1,179 @@
#!/usr/bin/env python3
"""pm_goal_router.py — deterministic lane classifier for the project-management domain.
Scores a PM goal/inquiry against the 8 sub-skill lanes using keyword signals
(same two-signal threshold discipline as the research-ops / commercial / markdown-html
orchestrators). Emits a routing decision an agent can branch on mechanically.
Exit codes:
0 confident route emitted (route_to set)
2 ambiguous ask ONE clarifying question naming the top two lanes
3 no signal do not guess; ask the user to restate the goal
Stdlib only. Deterministic: same text in, same route out.
"""
import argparse
import json
import sys
SIGNALS = {
"HEALTH": {
"skill": "senior-pm",
"path": "project-management/skills/senior-pm",
"keywords": [
"project health", "portfolio", "risk register", "risk analysis", "emv",
"monte carlo", "executive report", "status report", "milestone", "budget",
"resource capacity", "capacity plan", "raid", "stakeholder satisfaction",
"program", "watermelon",
],
},
"SPRINT": {
"skill": "scrum-master",
"path": "project-management/skills/scrum-master",
"keywords": [
"sprint", "velocity", "retro", "retrospective", "ceremony", "standup",
"scrum", "burndown", "forecast", "story points", "action item",
"team health", "flow metrics", "cycle time", "throughput", "wip",
],
},
"JIRA": {
"skill": "jira-expert",
"path": "project-management/skills/jira-expert",
"keywords": [
"jql", "jira workflow", "jira board", "automation rule", "issue type",
"jira filter", "jira report", "jira config", "workflow transition",
"kanban board", "epic link",
],
},
"CONFLUENCE": {
"skill": "confluence-expert",
"path": "project-management/skills/confluence-expert",
"keywords": [
"confluence", "space", "knowledge base", "page tree", "documentation audit",
"wiki", "page hierarchy", "content governance", "macro",
],
},
"ADMIN": {
"skill": "atlassian-admin",
"path": "project-management/skills/atlassian-admin",
"keywords": [
"permission", "sso", "saml", "provisioning", "deactivate user", "group",
"admin", "security policy", "access control", "marketplace app", "audit log",
],
},
"TEMPLATES": {
"skill": "atlassian-templates",
"path": "project-management/skills/atlassian-templates",
"keywords": [
"template", "blueprint", "scaffold", "standardized page", "reusable layout",
"storage format",
],
},
"MEETINGS": {
"skill": "meeting-analyzer",
"path": "project-management/skills/meeting-analyzer",
"keywords": [
"meeting", "transcript", "talk time", "speaking", "filler words",
"interruption", "facilitation", "1:1", "one-on-one",
],
},
"COMMS": {
"skill": "team-communications",
"path": "project-management/skills/team-communications",
"keywords": [
"status update", "3p", "newsletter", "faq", "announcement",
"stakeholder update", "incident report", "comms", "broadcast",
],
},
}
SAMPLE_GOAL = (
"our sprints feel off — velocity keeps swinging and the retro action items "
"never get done"
)
def score(text: str) -> dict:
low = text.lower()
scores = {}
hits = {}
for lane, spec in SIGNALS.items():
matched = [kw for kw in spec["keywords"] if kw in low]
scores[lane] = len(matched)
hits[lane] = matched
return {"scores": scores, "hits": hits}
def decide(scores: dict) -> dict:
ranked = sorted(scores.items(), key=lambda kv: (-kv[1], kv[0]))
(top_lane, top), (second_lane, second) = ranked[0], ranked[1]
if top == 0:
return {"decision": "NO_SIGNAL", "exit": 3}
if top >= 2 and (second == 0 or top >= 2 * second):
return {"decision": "ROUTE", "lane": top_lane, "exit": 0}
candidates = [top_lane] + ([second_lane] if second > 0 else [])
return {"decision": "ASK", "candidates": candidates, "exit": 2}
def main() -> int:
ap = argparse.ArgumentParser(
description="Deterministic lane router for project-management goals."
)
src = ap.add_mutually_exclusive_group()
src.add_argument("--text", help="Goal / inquiry text to classify.")
src.add_argument("--input", help="Read goal text from a file ('-' for stdin).")
ap.add_argument("--output", choices=["json", "human"], default="json")
ap.add_argument("--sample", action="store_true",
help="Classify a built-in sample goal and exit.")
args = ap.parse_args()
if args.sample:
text = SAMPLE_GOAL
elif args.text:
text = args.text
elif args.input:
text = (sys.stdin.read() if args.input == "-"
else open(args.input, encoding="utf-8").read())
else:
ap.error("one of --text, --input, or --sample is required")
result = score(text)
verdict = decide(result["scores"])
out = {
"goal": text.strip()[:300],
"scores": {k: v for k, v in result["scores"].items() if v},
"decision": verdict["decision"],
}
if verdict["decision"] == "ROUTE":
lane = verdict["lane"]
out["route_to"] = SIGNALS[lane]["skill"]
out["skill_path"] = SIGNALS[lane]["path"]
out["matched_signals"] = result["hits"][lane]
elif verdict["decision"] == "ASK":
out["candidates"] = [
{"lane": lane, "skill": SIGNALS[lane]["skill"], "score": result["scores"][lane]}
for lane in verdict["candidates"]
]
out["instruction"] = ("Ask ONE clarifying question naming both candidate lanes, "
"with a recommended answer. Never guess silently.")
else:
out["instruction"] = ("No lane signal. Ask the user to restate the goal with the "
"deliverable named. Do not route on fuzz.")
if args.output == "json":
print(json.dumps(out, indent=2))
else:
print(f"Decision: {out['decision']}")
if "route_to" in out:
print(f"Route to: {out['route_to']} ({out['skill_path']})")
print(f"Signals: {', '.join(out['matched_signals'])}")
elif "candidates" in out:
names = " vs ".join(c["skill"] for c in out["candidates"])
print(f"Ambiguous: {names} — ask one clarifying question.")
else:
print("No signal — ask the user to restate the goal.")
return verdict["exit"]
if __name__ == "__main__":
sys.exit(main())