proposal implemented

Unified Tooling Implementation Proposal

Bob Matsuoka Updated 2026-03-11
apex tooling implementation

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

  1. Work on main to build something initially (solo development)
  2. Create branch when expanding to team collaboration
  3. Minor/coordinated changes: direct push with semantic version bump
  4. 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

  1. Create project structure from template
  2. Install MCP server dependencies (notion-mcp-server, github-mcp, etc.)
  3. Initialize git with pre-commit hooks
  4. Copy templates and schemas (initiatives, experiments, PRDs)
  5. Configure VS Code/Cursor settings (extensions, snippets)
  6. 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

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)

  1. Review and approve this proposal with stakeholders
  2. Schedule PM training for Git basics and Cursor
  3. Set up PRD repository with template structure
  4. 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