Unified Tooling Implementation Proposal
Unified Tooling Implementation Proposal
Purpose: Define a comprehensive tooling strategy that enables the Git-Based PDP/Spec Process through specific tool assignments, workflows, and automation pipelines.
Relationship: This proposal implements the process defined in PDP-SPEC-PROCESS-PROPOSAL.md by specifying HOW tools support each stage of the pipeline.
1. Executive Summary
1.1 The Vision
A unified tooling ecosystem where:
- Git repositories are the single source of truth for all product artifacts
- Cursor serves as the universal collaborative editor for both PMs and developers
- Claude Code powers intelligent generation (TxDD/SDD) and research tasks
- Automation workflows handle publishing, synchronization, and notifications
1.2 Core Principles
| Principle | Implementation |
|---|---|
| Git-Native | All artifacts live in version-controlled repos |
| Tool Specialization | Each tool has a clear, distinct purpose |
| Human-in-the-Loop | AI generates, humans validate and approve |
| Automation First | Repetitive tasks automated via GitHub Actions |
| Observable | All state changes trigger notifications |
1.3 Key Outcomes
- PMs adopt developer workflows (PRs, reviews, branches) for product artifacts
- Claude Code accelerates artifact generation without replacing human judgment
- Single source of truth eliminates document sprawl across tools
- Publishing is automated from Git to Notion/JIRA/Slack
2. Tool Taxonomy
2.1 Tool Categories
The tooling ecosystem is organized into four functional categories based on their primary purpose:
GENERATION Tools (Create new content)
| Tool | Users | Primary Use |
|---|---|---|
| Claude Code | Engineers | TxDD, SDD, code generation |
| Claude.AI | PMs & Knowledge Workers | PRDs, specs, analysis |
STORAGE Tools (Version control, source of truth)
| Tool | Users | Primary Use |
|---|---|---|
| Git Repositories | All | All artifacts with versioning and workflow |
EDITING Tools (Modify existing content)
| Tool | Users | Primary Use |
|---|---|---|
| Cursor | PMs & Engineers | PRDs/specs (PMs) AND Code (Devs) |
| Obsidian | PMs & Knowledge Workers | Knowledge work, notes, research |
TRANSACTIONAL Tools (Communication, light commenting)
| Tool | Users | Primary Use |
|---|---|---|
| Slack | All | Team communication |
| Notion | All | Publishing, dashboards |
| Google Drive | All | Document sharing |
| Gmail | All | Email communication |
| Google Sheets | All | Data (future: connect to data lake TBD) |
2.2 Architecture Overview
flowchart TB
subgraph Generation ["GENERATION"]
CC[Claude Code<br/>Engineers]
CA[Claude.AI<br/>PMs/Knowledge Workers]
end
subgraph Storage ["STORAGE (Source of Truth)"]
GIT[(Git Repositories<br/>Versioned Artifacts)]
end
subgraph Editing ["EDITING"]
CUR[Cursor<br/>PRDs/Specs & Code<br/>PMs & Devs]
OBS[Obsidian<br/>Knowledge Work]
end
subgraph Transactional ["TRANSACTIONAL"]
SL[Slack]
NO[Notion]
GD[Google Drive]
GM[Gmail]
GS[Google Sheets<br/>Data Lake TBD]
end
CC --> GIT
CA --> GIT
GIT <--> CUR
GIT <--> OBS
GIT --> |GitHub Actions| NO
GIT --> |Webhooks| SL
GIT --> |Sync| GD
2.3 Role-Tool Mapping
| Role | Cursor | Claude Code | GitHub | Notion (Read) | JIRA |
|---|---|---|---|---|---|
| PM | PRD authoring, Initiative writing, Specs | TxDD: Generate stories from PRDs | PR reviews, Approvals | Reference only | Epic/Story viewing |
| Engineering Manager | Team charter authoring, PRD review | Research, Analysis | PR reviews, Approvals | Reference only | Sprint management |
| Developer | Code implementation, Spec review | SDD: Generate code from specs | PR reviews, Code PRs | Reference only | Story updates |
| Tech Lead | Architecture docs, PRD review, Code | SDD, Code review assist | PR reviews, Approvals | Reference only | Epic planning |
| CPO/CTO | High-level review | Strategic analysis | Final approvals | Dashboards | Portfolio view |
2.4 Tool Responsibilities
┌─────────────────────────────────────────────────────────────────────────────┐
│ SOURCE OF TRUTH: Git Repos │
│ │
│ ┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐ │
│ │ PRD Repository │ │ Code Repositories │ │ Docs Repository │ │
│ │ - Initiatives │ │ - Feature code │ │ - Team Charters │ │
│ │ - Experiments │ │ - Tests │ │ - Architecture │ │
│ │ - PRDs │ │ - Infrastructure │ │ - Runbooks │ │
│ └────────┬─────────┘ └────────┬─────────┘ └────────┬─────────┘ │
│ │ │ │ │
└────────────┼───────────────────────┼───────────────────────┼───────────────┘
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ EDITING LAYER: Cursor │
│ │
│ PMs: PRD editing, Initiative authoring, Experiment documentation │
│ Devs: Code implementation, Test writing, Documentation │
│ Shared: Collaborative editing, AI-assisted completion, Review comments │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ GENERATION LAYER: Claude Code │
│ │
│ TxDD (Ticket-Driven Development): │
│ - PRD → JIRA Epic structure │
│ - User stories → Acceptance criteria │
│ - Initiative → Experiment templates │
│ │
│ SDD (Spec-Driven Development): │
│ - PRD requirements → Implementation skeleton │
│ - Acceptance criteria → Test cases │
│ - Architecture spec → Code scaffolding │
│ │
│ Research & Analysis: │
│ - Market research → Initiative input │
│ - Technical feasibility → Experiment design │
│ - Post-ship data → Learning synthesis │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ AUTOMATION LAYER: GitHub Actions │
│ │
│ Publishing: │
│ - Approved PRD → Notion product space │
│ - Shipped feature → Slack #product-updates │
│ - Experiment complete → Notion dashboard update │
│ │
│ Synchronization: │
│ - PRD approved → Create JIRA Epic │
│ - Stories added → Create JIRA Stories │
│ - Status change → Update JIRA status │
│ │
│ Notifications: │
│ - Initiative created → Slack #product-initiatives │
│ - PRD ready for review → Slack DM to approvers │
│ - Feature shipped → Slack #eng-releases │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
2.5 Local-First Workflow
Users sync work locally and can work offline:
- Git clone provides full local copy of all artifacts
- Obsidian works entirely offline with local vault
- Cursor operates on local files with periodic sync
- Changes sync to remote on
git push
Offline capabilities: - Draft PRDs and specs without connectivity - Review and annotate documents locally - Queue commits for later push - Full search across local artifacts
Sync expectations: - Daily sync minimum for active projects - Pre-meeting sync for collaborative sessions - Resolve conflicts promptly on reconnection
3. Git Workflow for Knowledge Work
3.1 Ship/Show/Ask Model
Based on Martin Fowler's Ship/Show/Ask framework, we adopt a pragmatic branching model that balances speed with collaboration:
| Change Type | Method | Review | When to Use |
|---|---|---|---|
| Ship | Direct to main | None | Solo work, initial builds, obvious fixes |
| Show | Merge then notify | Post-merge | Team visibility, minor coordinated changes |
| Ask | Pull Request | Pre-merge | Major changes, proposals, cross-team impact |
3.2 Branching Rules
- Work on
mainto build something initially (solo development) - Create branch when expanding to team collaboration
- Minor/coordinated changes: direct push with semantic version bump
- Major additions or change proposals: PR workflow required
3.3 Commit Conventions
All commits follow conventional commit format:
| Prefix | Use Case |
|---|---|
docs: |
Document changes |
feat: |
New features/content |
fix: |
Corrections |
refactor: |
Restructuring without behavior change |
chore: |
Maintenance, dependencies |
Examples:
docs: add user authentication PRD
feat: implement OAuth2 login flow
fix: correct acceptance criteria for edge case
refactor: reorganize initiative templates
3.4 When to Use Each Method
flowchart TD
A[Making a Change] --> B{Who is affected?}
B -->|Just me| C[SHIP: Direct to main]
B -->|Team should know| D{Is it risky?}
B -->|Need approval| E[ASK: Pull Request]
D -->|No, minor change| F[SHOW: Merge then notify]
D -->|Yes, breaking change| E
C --> G[Commit directly to main]
F --> H[Merge to main, post to Slack]
E --> I[Create PR, request review]
4. Repository and Project Governance
4.1 Repos vs Projects Relationship
Repositories are containers for versioned artifacts. Projects are units of work with defined scope, resources, and outcomes.
- Repos are a superset/intersection of projects
- Projects live in the main repo their work overlaps with
- A single repo may contain multiple projects
- A project may span repos only when technically necessary (rare)
repo-a/
├── projects/
│ ├── project-alpha/ # Lives here - primary work is in repo-a
│ └── project-beta/
└── src/
repo-b/
├── projects/
│ └── project-gamma/
└── src/
4.2 Initiation Requirements
| Artifact Type | Approval Required | Authority Level |
|---|---|---|
| New Repository | Kartik Yellepeddi (CPO) + Bob (CTO) | Executive |
| New Project | Director-level signoff | Director |
| New Initiative/Experiment | Project lead | IC/Manager |
Repository Creation Criteria: - Clear separation of concerns from existing repos - Defined ownership and maintenance plan - Documented purpose in repo README
Project Creation Criteria: - Defined scope and success metrics - Resource estimate (see below) - Sponsoring director identified
4.3 Resource Allocation Model
All work by anyone must be in a project. No orphan work.
Time Units
| Role Level | Project Allocation Unit | Notes |
|---|---|---|
| Individual Contributor | 1/4 time (25%) | Minimum meaningful contribution |
| Manager | 1/2 time (50%) | Balance between IC work and management |
| Sr. Manager+ | Not attached | Coordination, not execution |
Project Metadata Requirements
Each project's metadata (YAML frontmatter) must include resource estimates and OKR alignment:
---
id: PRJ-2026-042
title: Group Forecast Extraction
status: active
okr_alignment:
objective: "O2: Accelerate Time to Value"
key_results:
- kr_id: KR2.1
description: "Reduce implementation time by 30%"
contribution: "Enables faster data onboarding"
kpis:
- name: "Extraction accuracy"
target: ">95%"
measurement: "Automated validation"
- name: "Processing time"
target: "<2 hours"
measurement: "Pipeline metrics"
resources:
people:
- role: engineer
allocation: 0.50 # 2 quarter-units = half-time
- role: engineer
allocation: 0.25
- role: manager
allocation: 0.50
fixed_costs:
infrastructure: 500 # $/month
tooling: 200 # $/month
total_monthly: 700
estimated_duration: 3 # months
---
OKR Alignment Requirements: - Every project must link to at least one Key Result - KPIs must be measurable and have defined targets - Alignment reviewed during quarterly OKR check-ins - Projects not supporting any KR require explicit justification (experimentation/slack allocation)
Reconciliation
Resource estimates are reconciled against actuals via: 1. Meeting time analysis - Calendar data 2. Commit analysis - Git contribution patterns 3. Quarterly review - Planned vs actual
Slack Allocation
- ~20% slack reserved for experimentation, learning, and unplanned work
- Slack is not "free time" - still tracked, just not pre-allocated
- Innovation projects can draw from slack pool
4.4 Project Lifecycle
PROPOSED → APPROVED → ACTIVE → COMPLETED/ARCHIVED
↓ ↓ ↓
(Director) (Resources) (Reconciliation)
signoff allocated reviewed
Completion criteria: - Success metrics evaluated - Actuals reconciled with estimates - Learnings documented - Artifacts archived or promoted
5. Off-the-Shelf Tooling
5.1 Buy vs. Build Philosophy
We prioritize off-the-shelf solutions over custom development. Build custom only when: - No existing solution fits our workflow - Integration requirements are Duetto-specific - The effort provides significant competitive advantage
5.2 MCP Servers (No Custom Build Needed)
| Server | Purpose | Source | Status |
|---|---|---|---|
@notionhq/notion-mcp-server |
Official Notion integration | npm | Available |
@ldraney/github-mcp |
GitHub API operations | npm | Available |
slack-mcp-server |
Slack messaging | npm | Available |
@rokealvo/jira-mcp |
JIRA integration | npm | Available |
Installation:
npm install -g @notionhq/notion-mcp-server
npm install -g @ldraney/github-mcp
npm install -g slack-mcp-server
npm install -g @rokealvo/jira-mcp
5.3 Obsidian Plugins
| Plugin | Stars | Purpose |
|---|---|---|
obsidian-git |
9.7k | Auto git sync, commit on save |
Templater |
4.6k | Advanced templates with scripting |
Dataview |
5.2k | Query and display document metadata |
Configuration for obsidian-git:
# .obsidian/plugins/obsidian-git/data.json
{
"autoSaveInterval": 5,
"autoPullInterval": 10,
"commitMessage": "docs: vault backup {{date}}",
"syncMethod": "rebase"
}
5.4 CLI Tools
| Tool | Purpose | Installation |
|---|---|---|
markdownlint-cli2 |
Markdown linting | npm install -g markdownlint-cli2 |
ajv-cli |
YAML/JSON schema validation | npm install -g ajv-cli |
prettier |
Code/doc formatting | npm install -g prettier |
gh |
GitHub CLI | brew install gh |
Pre-commit hook example:
#!/bin/bash
# .git/hooks/pre-commit
# Lint markdown files
markdownlint-cli2 "**/*.md" --ignore node_modules
# Validate frontmatter
for file in $(git diff --cached --name-only | grep '\.md$'); do
ajv validate -s schemas/frontmatter.schema.json -d "$file"
done
5.5 GitHub Actions (Off-the-Shelf)
| Action | Purpose | Source |
|---|---|---|
slackapi/slack-github-action |
Slack notifications | GitHub Marketplace |
actions/github-script |
Custom GitHub operations | GitHub Marketplace |
stefanzweifel/git-auto-commit-action |
Auto-commit changes | GitHub Marketplace |
Custom actions we need to build:
- Notion publish action (uses our scripts/notion/ scripts)
- JIRA sync action (uses our scripts/jira/ scripts)
6. Duetto Installer
6.1 Concept
A unified setup tool that creates a complete PDP/SDLC workspace:
npx create-pdp-sdlc-workspace duetto-product
6.2 What It Does
- Create project structure from template
- Install MCP server dependencies (
notion-mcp-server,github-mcp, etc.) - Initialize git with pre-commit hooks
- Copy templates and schemas (initiatives, experiments, PRDs)
- Configure VS Code/Cursor settings (extensions, snippets)
- Set up Obsidian vault (if Obsidian user)
6.3 Package Structure
create-pdp-sdlc-workspace/
├── bin/
│ └── create-workspace.js
├── templates/
│ ├── project/ # Project structure template
│ ├── vscode/ # VS Code/Cursor settings
│ ├── obsidian/ # Obsidian vault config
│ ├── github/ # GitHub Actions workflows
│ └── schemas/ # Frontmatter schemas
├── scripts/
│ ├── install-mcp.js # MCP server installation
│ ├── setup-git.js # Git initialization
│ └── configure-editor.js # Editor configuration
└── package.json
6.4 Interactive Prompts
$ npx create-pdp-sdlc-workspace my-product
? Project name: my-product
? Primary editor: (Use arrow keys)
> Cursor
VS Code
Obsidian
? Install MCP servers? Yes
? Configure GitHub Actions? Yes
? Team size: 5-10
Creating workspace...
✓ Created project structure
✓ Installed MCP servers
✓ Initialized git repository
✓ Configured editor settings
✓ Created GitHub Actions workflows
Done! cd my-product to get started.
7. Artifact Workflow
7.1 Pipeline Overview
The PDP pipeline with tool assignments:
INITIATIVE → EXPERIMENTS → PRD → EPIC/STORIES → CODE → MEASURE → LEARN
│ │ │ │ │ │ │
Cursor Cursor + Cursor Claude Code Cursor Analytics Claude Code
Claude Claude Claude (TxDD) Claude Tools (synthesis)
(assist) (design) (review) (SDD)
7.2 Stage-by-Stage Workflow
Stage 1: Initiative Creation
Primary Tool: Cursor (with Claude Code assist)
flowchart LR
A[Problem/Opportunity] --> B[PM opens Cursor]
B --> C[Create from template]
C --> D[Claude Code: Generate hypothesis alternatives]
D --> E[PM selects/refines hypothesis]
E --> F[Create PR]
F --> G[Team review]
G --> H[Merge to main]
Cursor Workflow: 1. Open PRD repository in Cursor 2. Create new file from initiative template 3. Use AI assist to brainstorm hypothesis alternatives 4. Fill in metric targets from team charter 5. Commit and push to feature branch 6. Create PR for team review
Claude Code Assist:
Prompt: "Given this problem statement and team metric, generate 3
alternative hypotheses we could test. For each, suggest an initial
experiment design."
Input: Problem statement, Team charter metrics
Output: 3 structured hypotheses with experiment suggestions
Stage 2: Experiment Design & Execution
Primary Tool: Cursor (with Claude Code for design)
flowchart LR
A[Validated Initiative] --> B[PM designs experiment]
B --> C[Claude Code: Generate experiment structure]
C --> D[PM executes experiment]
D --> E[Document findings in Cursor]
E --> F[Update learning section]
F --> G[Update initiative status]
Claude Code Assist:
Prompt: "Design an experiment to test this hypothesis. Include:
- Validation method (interview/analytics/prototype/A-B test/spike)
- Sample size requirements
- Success/failure criteria with specific thresholds
- Timeline estimate"
Input: Hypothesis from initiative
Output: Structured experiment design document
Stage 3: PRD Development
Primary Tool: Cursor (with Claude Code for generation)
flowchart LR
A[Validated Experiments] --> B[PM drafts PRD in Cursor]
B --> C[Claude Code: Generate user stories]
C --> D[Claude Code: Generate acceptance criteria]
D --> E[PM review and refine]
E --> F[Create PR for approval]
F --> G[Approvers review in GitHub]
G --> H[Merge approved PRD]
Claude Code - User Story Generation:
Prompt: "Based on this PRD overview and validated experiment findings,
generate user stories in the format:
'As a [persona], I want [capability] so that [benefit]'
Include acceptance criteria in Gherkin format for each story."
Input: PRD overview, Experiment learnings, Personas
Output: User stories with acceptance criteria
Stage 4: TxDD - Ticket-Driven Development
Primary Tool: Claude Code (automated via GitHub Actions)
flowchart LR
A[Approved PRD] --> B[GitHub Action triggers]
B --> C[Claude Code: Generate Epic structure]
C --> D[Claude Code: Generate Story breakdown]
D --> E[JIRA API: Create Epic]
E --> F[JIRA API: Create Stories]
F --> G[Link back to PRD]
Claude Code - TxDD Generation:
Prompt: "Convert this PRD into a JIRA Epic and Stories structure.
Epic should include:
- Summary (from PRD title)
- Description (from PRD overview)
- Acceptance criteria (from PRD success metrics)
- Labels (from PRD tags)
Stories should include:
- Summary (from user story)
- Description (from acceptance criteria)
- Story points estimate (based on complexity signals)
- Component tags"
Input: Approved PRD document
Output: JSON structure for JIRA Epic + Stories
Stage 5: SDD - Spec-Driven Development
Primary Tool: Claude Code (developer-initiated)
flowchart LR
A[JIRA Story assigned] --> B[Dev opens Cursor]
B --> C[Claude Code: Generate implementation skeleton]
C --> D[Claude Code: Generate test cases]
D --> E[Dev implements and refines]
E --> F[Create PR with story link]
F --> G[Code review]
G --> H[Merge and deploy]
Claude Code - SDD Generation:
Prompt: "Based on this user story and acceptance criteria, generate:
1. Implementation skeleton with:
- File structure
- Function signatures
- Key data structures
- Integration points
2. Test cases covering:
- Each Gherkin scenario
- Edge cases
- Error conditions
Follow the existing code patterns in [repository]."
Input: User story, Acceptance criteria, Codebase context
Output: Implementation skeleton + test cases
Stage 6: Measurement & Learning
Primary Tool: Claude Code (synthesis from multiple sources)
flowchart LR
A[Feature shipped] --> B[Analytics data collected]
B --> C[Claude Code: Synthesize metrics]
C --> D[Claude Code: Generate learning report]
D --> E[PM reviews and validates]
E --> F[Update Initiative outcome]
F --> G[Archive or iterate]
Claude Code - Learning Synthesis:
Prompt: "Synthesize the post-ship results for this feature:
Sources:
- Analytics metrics: [data]
- User feedback: [data]
- Support tickets: [data]
Generate:
1. Metric performance vs. targets
2. Key learnings (what worked, what didn't)
3. Recommendations (iterate, pivot, or complete)"
Input: Analytics export, Feedback compilation, PRD success metrics
Output: Learning report for initiative closure
8. Integration Architecture
8.1 System Diagram
┌─────────────────┐
│ GitHub │
│ (API + UI) │
└────────┬────────┘
│
┌──────────────────────────────────┼──────────────────────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Cursor Client │ │ Claude Code │ │ GitHub Actions │
│ │ │ │ │ │
│ - Edit files │◄────────────►│ - TxDD/SDD │◄────────────►│ - CI/CD │
│ - Git ops │ Context │ - Research │ Triggers │ - Validation │
│ - AI assist │ sharing │ - Synthesis │ + outputs │ - Publishing │
└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
│ │ │
│ │ │
▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│ External Integrations │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ Notion │ │ JIRA │ │ Slack │ │Analytics│ │
│ │ │ │ │ │ │ │ │ │
│ │Published│ │ Epics │ │ Notifs │ │ Metrics │ │
│ │PRDs │ │ Stories │ │ Updates │ │ Data │ │
│ └─────────┘ └─────────┘ └─────────┘ └─────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
8.2 Data Flow
| Trigger | Source | Action | Destination |
|---|---|---|---|
| PR merged to main | GitHub | Validate frontmatter | GitHub Actions |
| PRD status = approved | GitHub Actions | Publish PRD | Notion API |
| PRD status = approved | GitHub Actions | Create Epic | JIRA API |
| Initiative created | GitHub Actions | Post update | Slack #product-initiatives |
| Experiment completed | GitHub Actions | Update dashboard | Notion API |
| Feature shipped | GitHub Actions | Post announcement | Slack #eng-releases |
| JIRA Epic completed | JIRA Webhook | Update PRD status | GitHub API |
8.3 Authentication & Secrets
| Service | Auth Method | Secret Storage |
|---|---|---|
| GitHub | GitHub App | Native |
| Notion | Integration Token | GitHub Secrets |
| JIRA | API Token | GitHub Secrets |
| Slack | Bot Token | GitHub Secrets |
| Claude API | API Key | GitHub Secrets |
9. Publishing Workflows
9.1 PRD to Notion Publishing
Trigger: PRD status changes to approved
# .github/workflows/publish-to-notion.yml
name: Publish PRD to Notion
on:
push:
paths:
- 'prds/**/*.md'
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Detect approved PRDs
id: detect
run: |
# Find PRDs that changed to approved status
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD -- 'prds/**/*.md')
APPROVED_PRDS=""
for file in $CHANGED_FILES; do
STATUS=$(grep "^status:" "$file" | awk '{print $2}')
if [[ "$STATUS" == "approved" ]]; then
APPROVED_PRDS+="$file "
fi
done
echo "prds=$APPROVED_PRDS" >> $GITHUB_OUTPUT
- name: Publish to Notion
if: steps.detect.outputs.prds != ''
env:
NOTION_TOKEN: ${{ secrets.NOTION_API_KEY }}
NOTION_DATABASE_ID: ${{ secrets.NOTION_PRD_DATABASE }}
run: |
for prd in ${{ steps.detect.outputs.prds }}; do
python scripts/publish-to-notion.py "$prd"
done
Notion Database Schema:
| Property | Type | Source |
|---|---|---|
| Title | Title | frontmatter.title |
| ID | Text | frontmatter.id |
| Status | Select | frontmatter.status |
| Author | Person | frontmatter.author |
| Initiative | Relation | frontmatter.parent_initiative |
| Tags | Multi-select | frontmatter.tags |
| GitHub URL | URL | Repository link |
| Last Updated | Date | frontmatter.updated |
9.2 Slack Notifications
Trigger: Various artifact state changes
# .github/workflows/slack-notifications.yml
name: Slack Notifications
on:
push:
paths:
- 'initiatives/**/*.md'
- 'experiments/**/*.md'
- 'prds/**/*.md'
jobs:
notify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Detect changes and notify
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
run: |
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD)
for file in $CHANGED_FILES; do
TYPE=$(grep "^type:" "$file" 2>/dev/null | awk '{print $2}' || echo "")
STATUS=$(grep "^status:" "$file" 2>/dev/null | awk '{print $2}' || echo "")
TITLE=$(grep "^title:" "$file" 2>/dev/null | cut -d'"' -f2 || echo "")
case "$TYPE-$STATUS" in
initiative-discovery)
CHANNEL="#product-initiatives"
MESSAGE="New Initiative: $TITLE - Ready for discovery"
;;
initiative-validated)
CHANNEL="#product-initiatives"
MESSAGE="Initiative Validated: $TITLE - Moving to PRD"
;;
initiative-killed)
CHANNEL="#product-initiatives"
MESSAGE="Initiative Killed: $TITLE - Learning captured"
;;
experiment-completed)
CHANNEL="#product-initiatives"
MESSAGE="Experiment Complete: $TITLE"
;;
prd-review)
CHANNEL="#product-reviews"
MESSAGE="PRD Ready for Review: $TITLE"
;;
prd-approved)
CHANNEL="#product-updates"
MESSAGE="PRD Approved: $TITLE - Moving to delivery"
;;
prd-shipped)
CHANNEL="#eng-releases"
MESSAGE="Feature Shipped: $TITLE"
;;
esac
if [[ -n "$CHANNEL" && -n "$MESSAGE" ]]; then
curl -X POST https://slack.com/api/chat.postMessage \
-H "Authorization: Bearer $SLACK_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"channel\": \"$CHANNEL\", \"text\": \"$MESSAGE\"}"
fi
done
9.3 JIRA Synchronization
Trigger: PRD status changes to approved
# .github/workflows/jira-sync.yml
name: JIRA Epic Creation
on:
push:
paths:
- 'prds/**/*.md'
jobs:
create-epic:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 2
- name: Detect approved PRDs
id: detect
run: |
CHANGED_FILES=$(git diff --name-only HEAD~1 HEAD -- 'prds/**/*.md')
for file in $CHANGED_FILES; do
PREV_STATUS=$(git show HEAD~1:"$file" 2>/dev/null | grep "^status:" | awk '{print $2}' || echo "")
CURR_STATUS=$(grep "^status:" "$file" | awk '{print $2}')
# Only trigger if status changed TO approved
if [[ "$PREV_STATUS" != "approved" && "$CURR_STATUS" == "approved" ]]; then
echo "prd=$file" >> $GITHUB_OUTPUT
fi
done
- name: Create JIRA Epic
if: steps.detect.outputs.prd != ''
env:
JIRA_BASE_URL: ${{ secrets.JIRA_BASE_URL }}
JIRA_EMAIL: ${{ secrets.JIRA_EMAIL }}
JIRA_API_TOKEN: ${{ secrets.JIRA_API_TOKEN }}
run: |
python scripts/create-jira-epic.py "${{ steps.detect.outputs.prd }}"
- name: Update PRD with Epic ID
if: steps.detect.outputs.prd != ''
run: |
# Update epic_id in frontmatter
# Commit and push update
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add "${{ steps.detect.outputs.prd }}"
git commit -m "chore: Link JIRA Epic to PRD"
git push
10. PM-Specific Cursor Setup
10.1 Recommended Extensions
| Extension | Purpose |
|---|---|
| YAML | Frontmatter validation and highlighting |
| Markdown All in One | MD preview, TOC generation |
| GitLens | Git history, blame, compare |
| GitHub Pull Requests | PR management in editor |
| Mermaid Preview | Diagram rendering |
10.2 Workspace Settings
// .vscode/settings.json (in PRD repo)
{
"editor.wordWrap": "on",
"editor.quickSuggestions": {
"other": true,
"comments": false,
"strings": true
},
"files.associations": {
"*.md": "markdown"
},
"[markdown]": {
"editor.defaultFormatter": "yzhang.markdown-all-in-one",
"editor.formatOnSave": true
},
"yaml.schemas": {
"schemas/frontmatter.schema.json": ["initiatives/**/*.md", "experiments/**/*.md", "prds/**/*.md"]
}
}
10.3 Code Snippets for PMs
// .vscode/markdown.code-snippets
{
"Initiative Frontmatter": {
"prefix": "init",
"body": [
"---",
"title: \"${1:Initiative title}\"",
"id: I-2026-${2:NNN}",
"type: initiative",
"status: discovery",
"metric_target: \"${3:Team metric}\"",
"hypothesis: \"We believe ${4:action} will move ${5:metric} by ${6:amount}\"",
"confidence: low",
"max_experiments: 3",
"time_box: \"6 weeks\"",
"created: ${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE}",
"updated: ${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE}",
"author: ${7:PM Name}",
"team: TC-${8:NNN}",
"related_experiments: []",
"related_prd: null",
"tags:",
" - ${9:product-area}",
" - q${10:1}-2026",
"---",
"",
"# Initiative: ${1:Initiative title}",
"",
"## The Bet",
"",
"$0"
]
},
"Experiment Frontmatter": {
"prefix": "exp",
"body": [
"---",
"title: \"${1:Experiment title}\"",
"id: E-2026-${2:NNN}",
"type: experiment",
"parent_initiative: I-2026-${3:NNN}",
"status: planned",
"",
"hypothesis:",
" statement: \"We believe ${4:X} will ${5:Y} because ${6:Z}\"",
" confidence: low",
" validation_method: ${7|interview,analytics,prototype,a_b_test,spike|}",
"",
"time_box: \"2 weeks\"",
"success_criteria: \"${8:Threshold}\"",
"",
"learning:",
" outcome: null",
" key_insight: null",
" recommendation: null",
" evidence: []",
"",
"created: ${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE}",
"updated: ${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE}",
"author: ${9:PM Name}",
"tags:",
" - ${10:product-area}",
"---",
"",
"# Experiment: ${1:Experiment title}",
"",
"$0"
]
},
"PRD Frontmatter": {
"prefix": "prd",
"body": [
"---",
"title: \"${1:Feature name}\"",
"id: PRD-2026-${2:NNN}",
"type: prd",
"status: draft",
"version: 1.0.0",
"created: ${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE}",
"updated: ${CURRENT_YEAR}-${CURRENT_MONTH}-${CURRENT_DATE}",
"author: ${3:PM Name}",
"parent_initiative: I-2026-${4:NNN}",
"validated_experiments: [E-2026-${5:NNN}]",
"epic_id: null",
"approvers:",
" - CPO",
" - CTO",
" - Engineering Lead",
"stakeholders:",
" - CS Lead",
" - Sales Lead",
"tags:",
" - ${6:product-area}",
" - ${7|p0-critical,p1-high,p2-medium,p3-low|}",
" - q${8:1}-2026",
"---",
"",
"# PRD: ${1:Feature name}",
"",
"## 1. Overview",
"",
"$0"
]
},
"User Story": {
"prefix": "story",
"body": [
"### US-${1:NNN}: ${2:Story title}",
"",
"**As a** ${3:persona},",
"**I want** ${4:capability},",
"**So that** ${5:benefit}.",
"",
"#### Acceptance Criteria",
"",
"```gherkin",
"Scenario: ${6:Happy path}",
" Given ${7:precondition}",
" When ${8:action}",
" Then ${9:outcome}",
"```",
"",
"$0"
]
},
"Gherkin Scenario": {
"prefix": "gherkin",
"body": [
"```gherkin",
"Scenario: ${1:Scenario name}",
" Given ${2:precondition}",
" When ${3:action}",
" Then ${4:outcome}",
"```",
"$0"
]
}
}
10.4 AI-Assisted PRD Review Prompts
Save these as reusable prompts in Cursor:
Completeness Check:
Review this PRD for completeness. Check for:
1. All required frontmatter fields populated
2. Link to parent initiative and validated experiments
3. Clear problem statement with evidence
4. User stories with Gherkin acceptance criteria
5. Success metrics with baseline, target, and measurement method
6. Dependencies identified
7. Out of scope clearly defined
8. Post-ship learning plan
Identify any missing or incomplete sections.
Consistency Check:
Check this PRD for internal consistency:
1. Do success metrics align with the parent initiative's metric target?
2. Do user stories cover all requirements mentioned in the overview?
3. Are acceptance criteria testable and unambiguous?
4. Do dependencies align with timeline?
5. Is scope appropriate given the validated experiment findings?
Flag any inconsistencies.
Testability Check:
Review the acceptance criteria in this PRD:
1. Is each criterion in proper Gherkin format?
2. Are all preconditions clearly defined?
3. Are outcomes specific and measurable?
4. Are there scenarios for edge cases and error conditions?
5. Can QA write automated tests from these criteria?
Suggest improvements for any criteria that aren't testable.
10.5 Git Workflow for PMs
# Daily workflow aliases (add to .bashrc or .zshrc)
# Start new initiative
alias new-init='cp templates/initiative-template.md initiatives/2026/I-2026-$(date +%Y%m%d).md && cursor initiatives/2026/I-2026-$(date +%Y%m%d).md'
# Start new experiment
alias new-exp='cp templates/experiment-template.md experiments/2026/E-2026-$(date +%Y%m%d).md && cursor experiments/2026/E-2026-$(date +%Y%m%d).md'
# Start new PRD
new-prd() {
mkdir -p "prds/active/PRD-2026-$1"
cp templates/prd-template.md "prds/active/PRD-2026-$1/PRD-2026-$1.md"
cursor "prds/active/PRD-2026-$1/PRD-2026-$1.md"
}
# Create PR for spec
spec-pr() {
BRANCH=$(git branch --show-current)
gh pr create --title "$1" --body-file "$2" --reviewer "pm-lead,tech-lead" --label "spec"
}
# Check my open PRs
alias my-prs='gh pr list --author "@me" --state open'
# Check PRs awaiting my review
alias review-prs='gh pr list --search "review-requested:@me"'
11. Developer-Specific Cursor Setup
11.1 SDD Integration
Cursor AI Rules for Code Generation:
// .cursor/rules
{
"rules": [
{
"name": "Link to specs",
"description": "Always include JIRA story ID in commit messages and PR descriptions",
"pattern": "When generating code, include reference to JIRA story: STORY-XXX"
},
{
"name": "Test-first",
"description": "Generate tests before implementation",
"pattern": "For each acceptance criterion, generate test cases first"
},
{
"name": "Follow patterns",
"description": "Match existing codebase patterns",
"pattern": "Analyze existing code patterns before generating new code"
}
]
}
11.2 Test Generation from Gherkin
Claude Code Prompt:
Convert these Gherkin acceptance criteria to test cases.
Framework: [pytest/jest/junit]
Pattern: Follow existing test patterns in [directory]
For each scenario:
1. Create a test function with descriptive name
2. Implement Given/When/Then as Arrange/Act/Assert
3. Include edge case variations
4. Add necessary fixtures/mocks
Acceptance Criteria:
[paste Gherkin scenarios]
11.3 Code Review Workflow
# Developer aliases for SDD workflow
# Start work on story
start-story() {
STORY_ID=$1
git checkout main
git pull
git checkout -b "feature/$STORY_ID"
# Fetch story details from JIRA
gh api "/repos/{owner}/{repo}/issues" --jq ".[] | select(.title | contains(\"$STORY_ID\"))"
}
# Generate tests from PRD acceptance criteria
gen-tests() {
PRD_FILE=$1
# Extract Gherkin from PRD and generate tests
grep -A 10 "```gherkin" "$PRD_FILE" | claude-code "Generate pytest tests from these scenarios"
}
# Create PR linked to story
story-pr() {
STORY_ID=$1
gh pr create \
--title "feat($STORY_ID): ${*:2}" \
--body "Implements $STORY_ID
## Changes
-
## Testing
-
## PRD Reference
[Link to PRD section]
" \
--label "feature"
}
12. Implementation Phases
12.1 Phase 1: Install Off-the-Shelf MCP Servers (Weeks 1-2)
Objective: Install and configure existing MCP servers for tool integrations
| Task | Owner | Deliverable |
|---|---|---|
Install @notionhq/notion-mcp-server |
DevOps | Notion integration working |
Install @ldraney/github-mcp |
DevOps | GitHub API access |
Install slack-mcp-server |
DevOps | Slack messaging working |
Install @rokealvo/jira-mcp |
DevOps | JIRA integration working |
| Configure secrets and tokens | DevOps | All auth working |
Exit Criteria: - [ ] All MCP servers installed and responding - [ ] Tokens configured in secrets management - [ ] Basic operations tested (create, read, update)
12.2 Phase 2: Configure Obsidian + Git Plugins (Weeks 3-4)
Objective: Set up knowledge worker editing environment with Git integration
| Task | Owner | Deliverable |
|---|---|---|
| Install Obsidian for PM team | IT | Licensed installations |
Configure obsidian-git plugin |
PM Lead | Auto-sync working |
Configure Templater plugin |
PM Lead | Initiative/PRD templates |
| Create vault structure | PM Lead | Standard folder layout |
| PM training: Obsidian + Git | PM Lead | Training session |
Exit Criteria: - [ ] All PMs have Obsidian configured - [ ] Auto-commit on save working - [ ] Templates for all artifact types - [ ] At least 1 PM completed full workflow
12.3 Phase 3: Deploy GitHub Actions Workflows (Weeks 5-8)
Objective: Automate publishing and notification pipelines
| Task | Owner | Deliverable |
|---|---|---|
| Set up Notion publishing workflow | DevOps | PRD -> Notion automated |
| Set up Slack notifications | DevOps | State changes notify |
| Set up JIRA sync workflow | DevOps | PRD -> Epic automated |
| Set up pre-commit validation | DevOps | Frontmatter validation |
| Test all automation pipelines | All | Integration tests passing |
Exit Criteria: - [ ] Approved PRDs auto-publish to Notion - [ ] State changes trigger Slack notifications - [ ] JIRA Epics created from approved PRDs - [ ] Pre-commit hooks validate frontmatter
12.4 Phase 4: Create Duetto Installer Package (Weeks 9-12)
Objective: Package workspace setup for easy replication
| Task | Owner | Deliverable |
|---|---|---|
Create create-pdp-sdlc-workspace package |
DevOps | npm package |
| Bundle all templates and schemas | PM Lead | Template directory |
| Add editor configuration automation | DevOps | VS Code/Cursor/Obsidian configs |
| Write documentation | All | User guide |
| Pilot with 2 new projects | Pilot team | Validated workflow |
Exit Criteria:
- [ ] npx create-pdp-sdlc-workspace works end-to-end
- [ ] New team can set up in <30 minutes
- [ ] Documentation covers all scenarios
- [ ] 2 projects successfully using installer
12.5 Legacy: Original Phase Structure (Reference)
The following phases from the original proposal are superseded by the buy-vs-build approach above, but retained for reference:
Phase 1: Foundation (Weeks 1-2) [Superseded]
Objective: Establish repository structure and basic tooling
This phase is covered by Phases 1-2 above using off-the-shelf tooling.
Phase 2: Cursor Rollout (Weeks 3-4) [Superseded]
Objective: PMs actively using Cursor for all product artifacts
This phase is covered by Phase 2 above, with Obsidian as an alternative editing option.
Phase 3: Claude Code TxDD/SDD (Weeks 5-8) [Retained]
This capability is orthogonal to the buy-vs-build approach and can be implemented in parallel.
| Task | Owner | Deliverable |
|---|---|---|
| Define TxDD prompt templates | PM Lead + Tech Lead | Documented prompts |
| Define SDD prompt templates | Tech Lead | Documented prompts |
| Pilot TxDD: PRD -> JIRA Epic | Pilot PM | Generated Epic |
| Pilot SDD: Story -> Tests | Pilot Dev | Generated tests |
| Document best practices | All | Runbook |
Phase 4: Automation Pipelines (Weeks 9-12) [Superseded]
Objective: Implement publishing and synchronization workflows
This phase is covered by Phase 3 above using GitHub Actions.
12.6 Phase 5: Metrics and Optimization (Ongoing)
Objective: Measure success and iterate
| Task | Owner | Deliverable |
|---|---|---|
| Define success metrics | PM Lead | Metrics document |
| Implement metrics collection | DevOps | Automated tracking |
| Monthly review cadence | All | Review meeting |
| Process iteration | All | Updated workflows |
13. Success Metrics
13.1 Adoption Metrics
| Metric | Baseline | Target (3 months) | Target (6 months) |
|---|---|---|---|
| % of PRDs created in Git | 0% | 80% | 100% |
| % of initiatives with experiments | 0% | 50% | 80% |
| PMs using Cursor daily | 0 | 50% | 100% |
| Claude Code TxDD usage | 0 | 30% of PRDs | 70% of PRDs |
| Claude Code SDD usage | 0 | 20% of stories | 50% of stories |
13.2 Efficiency Metrics
| Metric | Baseline | Target (3 months) | Measurement |
|---|---|---|---|
| Time: Initiative to approved PRD | Unknown | Establish baseline | Git timestamps |
| Time: PRD to JIRA Epic | Manual (~2 hrs) | <15 min (automated) | Workflow logs |
| PRD revision cycles before approval | Unknown | Reduce by 30% | PR comments |
| Manual Notion updates | 100% manual | 0% manual | Workflow logs |
| Manual JIRA creation | 100% manual | <20% manual | Workflow logs |
13.3 Quality Metrics
| Metric | Baseline | Target | Measurement |
|---|---|---|---|
| PRD completeness score | Unknown | >90% | Automated validation |
| Acceptance criteria testability | Unknown | >95% testable | QA review |
| Traceability: Feature to initiative | 0% | 100% | Frontmatter links |
| Post-ship learning capture rate | Unknown | 100% | Status transitions |
13.4 Learning Metrics (from parent proposal)
| Metric | Baseline | Target | Measurement |
|---|---|---|---|
| Initiative kill rate | Unknown | 30-50% (healthy) | Status counts |
| Discovery phase duration | Unknown | <6 weeks | Git timestamps |
| Feature success rate (met targets) | Unknown | Improve over baseline | Retros |
14. Risks and Mitigations
14.1 Risk: PM Adoption Resistance
Symptom: PMs continue using Confluence/Google Docs instead of Git
Mitigations: - Training investment: Dedicated onboarding sessions, not self-service - PM champions: Identify 1-2 PMs as early adopters and advocates - Quick wins: Show immediate value (snippets, AI assist, automation) - Support channel: Dedicated Slack channel for PM Git questions - Gradual rollout: Start with new initiatives, migrate existing over time
14.2 Risk: Over-reliance on AI Generation
Symptom: Teams accept AI output without critical review
Mitigations: - Human-in-the-loop mandate: All AI-generated content requires human review - Quality gates: Automated checks for common AI errors - Training: Teach teams to critically evaluate AI output - Feedback loop: Track AI generation accuracy, iterate prompts
14.3 Risk: Tool Sprawl
Symptom: Tools added without retiring old ones
Mitigations: - Explicit retirement: Confluence for PRDs deprecated on Phase 2 completion - Single source of truth: Git is authoritative, Notion is read-only publication - Tool audit: Quarterly review of tool usage
14.4 Risk: Automation Fragility
Symptom: GitHub Actions fail, blocking workflows
Mitigations: - Monitoring: Alert on workflow failures - Manual fallback: Document manual steps for each automation - Incremental rollout: One automation at a time, validate before next - Testing: Workflow tests in staging environment
14.5 Risk: Context Loss in Claude Code
Symptom: AI generations miss important context, produce poor output
Mitigations: - Structured prompts: Well-defined prompt templates with required context - Context injection: Automatically include relevant artifacts in prompts - Iterative refinement: Multiple generation passes with human feedback - Fallback to manual: Clear criteria for when not to use AI generation
15. Appendix: Script Examples
15.1 Notion Publishing Script
#!/usr/bin/env python3
# scripts/publish-to-notion.py
import os
import sys
import yaml
import requests
from pathlib import Path
NOTION_API_URL = "https://api.notion.com/v1"
NOTION_TOKEN = os.environ["NOTION_TOKEN"]
DATABASE_ID = os.environ["NOTION_DATABASE_ID"]
def extract_frontmatter(filepath):
"""Extract YAML frontmatter from markdown file."""
content = Path(filepath).read_text()
if content.startswith("---"):
_, fm, body = content.split("---", 2)
return yaml.safe_load(fm), body.strip()
return {}, content
def create_notion_page(frontmatter, body, github_url):
"""Create or update Notion page from PRD."""
headers = {
"Authorization": f"Bearer {NOTION_TOKEN}",
"Notion-Version": "2022-06-28",
"Content-Type": "application/json"
}
# Check if page exists
existing = find_existing_page(frontmatter["id"])
properties = {
"Title": {"title": [{"text": {"content": frontmatter["title"]}}]},
"ID": {"rich_text": [{"text": {"content": frontmatter["id"]}}]},
"Status": {"select": {"name": frontmatter["status"]}},
"Author": {"rich_text": [{"text": {"content": frontmatter["author"]}}]},
"GitHub URL": {"url": github_url},
"Updated": {"date": {"start": frontmatter["updated"]}}
}
if frontmatter.get("tags"):
properties["Tags"] = {"multi_select": [{"name": t} for t in frontmatter["tags"]]}
if existing:
# Update existing page
response = requests.patch(
f"{NOTION_API_URL}/pages/{existing}",
headers=headers,
json={"properties": properties}
)
else:
# Create new page
response = requests.post(
f"{NOTION_API_URL}/pages",
headers=headers,
json={
"parent": {"database_id": DATABASE_ID},
"properties": properties
}
)
return response.json()
def find_existing_page(prd_id):
"""Find existing page by PRD ID."""
headers = {
"Authorization": f"Bearer {NOTION_TOKEN}",
"Notion-Version": "2022-06-28",
"Content-Type": "application/json"
}
response = requests.post(
f"{NOTION_API_URL}/databases/{DATABASE_ID}/query",
headers=headers,
json={
"filter": {
"property": "ID",
"rich_text": {"equals": prd_id}
}
}
)
results = response.json().get("results", [])
return results[0]["id"] if results else None
if __name__ == "__main__":
filepath = sys.argv[1]
frontmatter, body = extract_frontmatter(filepath)
# Construct GitHub URL
repo = os.environ.get("GITHUB_REPOSITORY", "org/repo")
github_url = f"https://github.com/{repo}/blob/main/{filepath}"
result = create_notion_page(frontmatter, body, github_url)
print(f"Published: {result.get('url', 'unknown')}")
15.2 JIRA Epic Creation Script
#!/usr/bin/env python3
# scripts/create-jira-epic.py
import os
import sys
import yaml
import requests
from pathlib import Path
JIRA_BASE_URL = os.environ["JIRA_BASE_URL"]
JIRA_EMAIL = os.environ["JIRA_EMAIL"]
JIRA_API_TOKEN = os.environ["JIRA_API_TOKEN"]
PROJECT_KEY = os.environ.get("JIRA_PROJECT_KEY", "PROD")
def extract_frontmatter(filepath):
"""Extract YAML frontmatter from markdown file."""
content = Path(filepath).read_text()
if content.startswith("---"):
_, fm, body = content.split("---", 2)
return yaml.safe_load(fm), body.strip()
return {}, content
def create_jira_epic(frontmatter, github_url):
"""Create JIRA Epic from PRD frontmatter."""
auth = (JIRA_EMAIL, JIRA_API_TOKEN)
headers = {"Content-Type": "application/json"}
# Map PRD priority to JIRA priority
priority_map = {
"p0-critical": "Highest",
"p1-high": "High",
"p2-medium": "Medium",
"p3-low": "Low"
}
priority = "Medium"
for tag in frontmatter.get("tags", []):
if tag in priority_map:
priority = priority_map[tag]
break
epic_data = {
"fields": {
"project": {"key": PROJECT_KEY},
"summary": frontmatter["title"],
"description": {
"type": "doc",
"version": 1,
"content": [
{
"type": "paragraph",
"content": [
{"type": "text", "text": f"PRD: {github_url}"}
]
},
{
"type": "paragraph",
"content": [
{"type": "text", "text": f"Initiative: {frontmatter.get('parent_initiative', 'N/A')}"}
]
}
]
},
"issuetype": {"name": "Epic"},
"priority": {"name": priority},
"labels": frontmatter.get("tags", []),
"customfield_10001": frontmatter["id"], # PRD ID custom field
}
}
response = requests.post(
f"{JIRA_BASE_URL}/rest/api/3/issue",
auth=auth,
headers=headers,
json=epic_data
)
return response.json()
def update_prd_with_epic(filepath, epic_key):
"""Update PRD frontmatter with JIRA Epic ID."""
content = Path(filepath).read_text()
# Simple replacement - assumes epic_id: null exists
updated = content.replace("epic_id: null", f"epic_id: {epic_key}")
Path(filepath).write_text(updated)
if __name__ == "__main__":
filepath = sys.argv[1]
frontmatter, body = extract_frontmatter(filepath)
# Construct GitHub URL
repo = os.environ.get("GITHUB_REPOSITORY", "org/repo")
github_url = f"https://github.com/{repo}/blob/main/{filepath}"
result = create_jira_epic(frontmatter, github_url)
epic_key = result.get("key")
if epic_key:
print(f"Created Epic: {epic_key}")
update_prd_with_epic(filepath, epic_key)
print(f"Updated PRD with epic_id: {epic_key}")
else:
print(f"Error creating Epic: {result}")
sys.exit(1)
16. Next Steps
Immediate Actions (This Week)
- Review and approve this proposal with stakeholders
- Schedule PM training for Git basics and Cursor
- Set up PRD repository with template structure
- Identify pilot PM for Phase 2
Dependencies
| Dependency | Owner | Status |
|---|---|---|
| Parent proposal (PDP-SPEC-PROCESS-PROPOSAL) approved | Bob | Draft |
| Cursor licenses procured | IT | Pending |
| GitHub org permissions for PMs | DevOps | Pending |
| Notion API token available | DevOps | Available |
| JIRA API access configured | DevOps | Pending |
| Slack bot created | DevOps | Pending |
Status: DRAFT Created: 2026-02-08 Updated: 2026-02-08 Author: Robert Matsuoka