Plan — Project Planning & PRD Generation

SkillDev tools

Create an execution-ready PRD and README for an HQ project.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Plan — Project Planning & PRD Generation skill

What this skill tells your AI

The instructions your AI receives, as published by indigoai-us/hq-core in .claude/skills/plan/SKILL.md and read by ahel’s review.

Create execution-ready PRDs with full HQ context awareness. Lightweight flow — batched questions, fast capture, no research subagents. For deep planning on large or strategically important PRDs, use /deep-plan instead. For adversarial spec review of an already-generated PRD, use /review-plan.

Important: Do NOT implement. Just create the PRD.

Work Mesh Live — trusted bind (do this first)

Before any other tool call that touches project work, bind the session per .claude/skills/_shared/work-mesh-live-bind.md (US-011):

bash core/scripts/work-mesh-live-bind-trusted.sh \
  --company "{co}" --project "{project}" --task "{task}"

Omit --task when unknown. This writes workspace/sessions/<sid>/meta.yaml and reconciles with observation.trustedContext (no --trusted CLI flag).

Step 0: Company Anchor (from user input)

Check if the first word of the user's input matches a company slug in companies/manifest.yaml.

How to check: Read companies/manifest.yaml. Extract top-level keys (company slugs). If the first word exactly matches one of those slugs:

  1. Set {co} = matched slug for the entire flow. Strip the slug — the remaining text is the project description
  2. Announce: "Anchored on {co}"
  3. Load policies (frontmatter-only) — For each file in companies/{co}/policies/ (skip example-policy.md), run bash core/scripts/read-policy-frontmatter.sh {file}. Note enforcement: hard titles. For hard-enforcement policies only, additionally read the ## Rule section with a targeted range. Apply as constraints throughout the PRD
  4. Scope qmd searches — If company has qmd_collections in manifest, use -c {collection} for all qmd calls
  5. Pre-load repos — Extract {co}.repos[] from manifest. Present as repo options in Batch 3 Q10
  6. Scope workers — Filter to company workers (companies/{co}/workers/) + public workers (core/workers/public/)
  7. Scope projects — Only search companies/{co}/projects/ for existing project collision check

If no match (first word is not a company slug) — proceed normally. The full input text is the project description.

Step 1: Get Project Description

If user provided input, use as starting point. If empty, ask the user: "Describe what you want to build or accomplish." Wait for response.

Step 2: Scan HQ Context

Before asking questions, explore HQ. Resolve mode from Step 0 + input:

  • company mode — a company slug was anchored in Step 0
  • repo mode — no company anchor but a target repo is mentioned or resolvable from input
  • personal/HQ mode — neither of the above (personal projects, HQ infrastructure work)

If {co} is anchored, scope all searches to that company.

Companies & Context (only if mode in (company, repo)):

  • Read agents-companies.md (roles, priorities, three-tier roster) — needed to route cross-company PRDs
  • Read companies/manifest.yaml (companies already listed there — never Glob for company discovery)
  • Skip both if already anchored in Step 0: Step 0 already loaded manifest and matched the company. Re-reading is pure waste
  • Skip entirely for personal/HQ mode: no company routing needed, no repo to map

Workers (only if mode in (company, repo) AND the description plausibly needs a worker — otherwise skip):

  • Read core/workers/registry.yaml (workers already indexed there — never Glob for worker discovery). Skip if the description is clearly code/infra work not matching a worker skill
  • If anchored: filter to company workers (companies/{co}/workers/) + public workers (core/workers/public/)
  • Skip entirely for personal/HQ mode

Existing Projects:

  • If anchored: qmd search "prd.json" --json -n 20 -c {co} (scoped) or search companies/{co}/projects/ directly
  • If not anchored: qmd search "prd.json" --json -n 20 — existing projects across all companies and personal
  • If {co} is anchored and a candidate project slug is already clear from the input, prefer live Board/presence from hq mesh daemon / Desktop live read. Do not call deleted hq mesh session check|watch. Presence is automatic; optional hq mesh session note only for a discrete milestone.

Knowledge (use single qmd hybrid query, not Grep, not vsearch+search pair):

  • If anchored + company has qmd_collections: qmd query "<description keywords>" -c {collection} --json -n 10
  • If not anchored: qmd query "<description keywords>" --json -n 10 — hybrid BM25 + vector + re-ranking for related knowledge, prior work, workers

Company Policies (anchored only):

  • Already loaded in Step 0 (frontmatter-only). Do NOT re-read here. Note constraints from that scan

Repo Policies (if repo resolved):

  • If target repo identified, list files in {repoPath}/.claude/policies/ (if dir exists), then for each run bash core/scripts/read-policy-frontmatter.sh {file}. For hard-enforcement policies, additionally read the ## Rule section

Target Repo (if repo specified or discovered):

  • If anchored: company repos already pre-loaded from manifest. Present as options
  • If target repo has a qmd collection (e.g. my-app): qmd query "<description keywords>" -c {collection} --json -n 10 — hybrid search for related code, patterns, existing implementations
  • Present: "Found related code: {list of relevant files}"

Present:

Scanned HQ:
- Mode: {company | repo | personal/HQ}
- Company: {co} (anchored) | TBD | n/a
- Workers: {relevant list or "skipped"}
- Existing projects: {list or "none matching"}
- Relevant knowledge: {if any}
- Policies: {count loaded, or "none"}
- Category: [company-specific | cross-company | personal | HQ infrastructure]

Step 2.5: Infrastructure Pre-Check

Before generating the PRD, verify infrastructure exists for the target company/repo:

  1. Company: If project targets a company, read companies/manifest.yaml. If company has knowledge: null, flag: "Company {co} has no knowledge repo. Create one? [Y/n]" — if yes, create embedded repo at companies/{co}/knowledge/ with git init, and update manifest.yaml.

  2. Repo: If repoPath specified and doesn't exist locally, flag: "Repo not found at {path}. Clone it or create new?" Add to manifest.yaml if missing.

  3. qmd collection: If company has qmd_collections: [] in manifest, flag and offer to create collection.

Fix any gaps before proceeding.

Step 3: Get + Validate Project Name

Ask the user for project slug (or infer from description). Then:

  1. If {co} already set by Step 0: use it directly (skip company detection) If NOT set: determine company from context (infer from description, repo, or ask the user)
  2. Check if companies/{co}/projects/{name}/ exists (also check personal/projects/{name}/ for personal/HQ)
    • If exists: ask the user "Project exists. Continue editing or choose different name?"
  3. Validate slug format (lowercase, hyphens only)

Step 3.5: Brainstorm Detection

Now that {co} and {slug} are resolved, check if a brainstorm file exists:

companies/{co}/projects/{slug}/brainstorm.md

If found:

  1. Read it. Extract YAML frontmatter (status, source_idea_id)
  2. If status: "promoted" — warn the user: "This brainstorm was already promoted to a PRD. Open existing prd.json instead?"
  3. Pre-load brainstorm content into interview context for Step 4:
    • Batch 1 (Problem/Success): pre-fill from brainstorm's ## Context, ## Recommendation. Present as confirmations ("Based on brainstorm: {X}. Confirm or modify?") instead of open-ended questions
    • Batch 2 (Users/Current State): pre-fill audience and current solution from brainstorm context if mentioned
    • Batch 3 (Scope/Constraints): pre-fill from ## What We Don't Know + any constraints mentioned. Surface unknowns as explicit questions to resolve. Pre-fill non-goals from brainstorm's rejected approaches
    • Batch 4 (Data/Architecture): pre-fill from brainstorm's recommended approach's tech choices, data model mentions
    • Batch 5 (Integrations): pre-fill from brainstorm's identified external services
    • Batch 6 (Quality/Shipping): pre-fill from brainstorm's identified workers, repos
    • Batch 7 (E2E): unchanged — brainstorm doesn't cover testing specifics
  4. Effect: interview batches collapse to confirmations rather than open-ended questions. User answers faster, stories are better anchored to the evaluated approach

If not found: proceed normally (no change to existing behavior).

Step 3.6: Open Session Journal

Spec: core/knowledge/public/hq-core/journal-spec.md. Open a session journal at the project_dir so research, decisions, and dead ends survive context compaction:

.claude/skills/_shared/journal.sh open plan "{project_dir}"

Where {project_dir} = companies/{co}/projects/{slug}/ or personal/projects/{slug}/ for personal/HQ. The helper:

  • Creates {project_dir}/journal/{ISO8601}-plan.md with frontmatter (status: active, skill: plan)
  • Writes a session-scoped pointer under .claude/state/active-journal.d/ so this session's autocapture hook + later steps append to this file
  • Stays open across /handoff boundaries — only /handoff and /checkpoint close it

The autocapture PostToolUse hook appends ## Auto-capture lines for any Agent / WebFetch / WebSearch / AskUserQuestion calls. Step 4 (interview decisions) and Step 8.5 (resolved/deferred questions) append curated entries via the same helper.

Skip if: journal helper unavailable (fail-soft).

Step 4: Discovery Interview

Ask questions in batches. Users respond with shorthand: "1a A, 1b: build a dashboard, 1c B"

Each question has lettered options for fast answers + free text override. Present one batch at a time, wait for response, then present next batch.

Before Batch 4: Classify project type from description + Batch 1-3 answers:

  • Code project (has repoPath, or code/app/API/feature keywords) — ask all batches
  • Content/knowledge/report — skip Batches 4, 5; skip 6g/6h. Note: "(Batch 4 skipped — non-code project)"
  • Personal/HQ tooling — skip 5b, 5c, 6g, 6h

Dynamic Question Enrichment

Use the context gathered in Step 2 (company policies, repo policies, manifest, repo scan) to enrich questions with specific details rather than asking generic versions. This makes questions faster to answer and surfaces constraints the user might forget.

From company policies (companies/{co}/policies/):

  • Policy mentions feature flags / rollout — pre-fill 5c with the required approach, present as confirmation
  • Policy mentions PII / GDPR / compliance — always surface 5b regardless of keywords, note the policy
  • Policy mentions brand voice / design system — pre-fill 2c option C with the specific system name
  • Policy mentions specific deploy procedures — add context to 6a (quality gates)
  • Any enforcement: hard policy that constrains architecture, auth, or integrations — surface as a constraint in the relevant batch header (e.g. "Note: company policy requires Clerk auth for all new features")

From repo scan (target repo's CLAUDE.md, package.json, existing patterns):

  • Repo uses specific auth (Clerk, NextAuth, Supabase Auth) — pre-fill 4b option A with: "Uses existing auth ({system}) — no changes needed"
  • Repo uses specific ORM/DB (Prisma, pgClient, Supabase) — add hint to 4a: "This repo uses {ORM}. Describe entities in those terms"
  • Repo has analytics/tracking (PostHog, Segment, Mixpanel, GA) — pre-fill 6g option B with the system name
  • Repo has monitoring (Sentry, Datadog, CloudWatch) — pre-fill 6h option B/D with the service name
  • Repo has existing test commands — pre-fill 6a with detected commands
  • Repo has existing design system / component library — mention in 2c option C

From manifest (companies/manifest.yaml):

  • Company has services: [stripe, ...] — if project might involve payments, surface in 5a as a hint
  • Company has vercel_team — enrich 5c with "deploys via Vercel to {team}"
  • Company has existing integrations — list them as option B context in 5a

Presentation: Weave enrichments into the question text naturally. Don't add a separate "detected context" dump — make each question smarter:

// Generic (bad):
4b. Auth / permissions model?
    A. Uses existing auth — no changes needed

// Enriched (good):
4b. Auth / permissions model? (repo uses Clerk via @clerk/nextjs)
    A. Uses existing Clerk auth — no changes needed

If a policy or repo context fully answers a question, present it as a confirmation rather than an open question:

5c. Rollout strategy? → Company policy requires feature flags for all new features.
    Confirming: B. Feature flag (env var)  [Y/n]

Batch 1 — Problem & Success 1a. Core problem or goal? 1b. What does success look like? (measurable metric or verifiable state) 1c. Who benefits? (list all beneficiaries)


Batch 2 — Users & Current State 2a. Who are the primary users? A. Internal / admin only B. External customers / end users C. Both internal and external D. Developer tooling / no direct end user (free text to specify roles and technical level, e.g. "Geoff — CEO, non-technical")

2b. What exists today? (current solution, even if it's a spreadsheet or nothing) A. Nothing — greenfield B. Existing feature being replaced or upgraded C. Manual process being automated D. Third-party tool being replaced (free text to describe what's being replaced and why it's insufficient)

2c. Are there reference designs, mockups, or brand constraints? (skip if non-UI) A. Figma file exists (provide file/node ID) B. Visual reference / screenshot (describe or link) C. Follow existing design system exactly (name which one) D. No design constraints — AI chooses E. Not a UI project (skip) Conditional: auto-skip with E for pure backend/CLI/data projects


Batch 3 — Scope & Constraints 3a. What's in scope for MVP? 3b. Hard constraints (time, tech, budget)? 3c. Dependencies on other projects? 3d. What is explicitly NOT in scope? (non-goals — things users might ask for but we won't build) (free text list, or "none")


Batch 4 — Data & Architecture (conditional: code projects only) Trigger: project has repoPath or description contains DB/schema/API/model keywords. Auto-skip for content/knowledge/reports/social.

4a. Key data entities? (tables, columns, domain objects this project touches) (free text, e.g. "new depletions table, adds sku_id FK to line_items" — or "no DB changes")

4b. Auth / permissions model? A. Uses existing auth — no changes needed B. New role or permission level needed (describe) C. New auth provider or login method D. No auth (public or internal tool)

4c. Architecture approach? A. Follow existing patterns in the repo exactly B. New pattern needed (describe) C. No opinion — let workers decide

4d. Performance requirements? (conditional: only if real-time/scale/latency/throughput keywords in description) A. Standard — no special requirements B. Latency target: [specify, e.g. "< 2s page load"] C. Throughput target: [specify, e.g. "1000 req/s"] D. Mobile / low-bandwidth optimization needed Default: A


Batch 5 — Integrations & Security (conditional: projects with external service interaction) Trigger: description contains API/webhook/OAuth/third-party/Stripe/Slack/integration keywords. Auto-skip for fully internal projects.

5a. External integrations or third-party APIs? A. None — fully self-contained B. Existing integrations (already wired up, just using them) C. New integration needed — list: which service, what data flows, are credentials already set up?

5b. Sensitive data or security considerations? (conditional: only if user/payment/PII/customer keywords) A. No PII or sensitive data B. PII handled (email, name, payment info) — existing compliance approach applies C. New compliance requirement (HIPAA, GDPR, etc.) D. Rate limiting or abuse protection needed E. User-generated content with moderation needs

5c. Rollout strategy? (conditional: only for production-deployed projects with real users) A. Ship to all users immediately B. Feature flag (specify: env var, LaunchDarkly, user segment) C. Staged rollout (% of users or specific cohort) D. Internal only first, then broader rollout Default: A


Batch 6 — Quality & Shipping 6a. Quality gates? (detect repo from scan, suggest commands) A. pnpm typecheck && pnpm lint B. npm run typecheck && npm run lint C. None (no automated checks) D. Other: [specify]

6b. Based on scan: "Should this use {relevant workers}?" 6c. Does this need a new worker or skill? 6d. Repo path? (e.g. repos/private/{name}, or "none" if non-code) 6e. Branch name? (default: feature/{project-name}) 6f. Base branch? (default: main, or staging for {your-repo}, etc.) — Pure Ralph creates feature branch from this

6g. Analytics / event tracking needed? (conditional: deployable UI projects only) A. No — not a user-facing feature B. Yes — use existing tracking system (name it) C. Yes — new tracking events needed (list key events, e.g. "depletion.filter.applied") D. Not sure — include tracking stub only Default: A

6h. How do we know it's working in production? (conditional: production-deployed projects only) A. Manual testing only B. Existing monitoring covers it (no changes needed) C. New health check or monitoring alert needed (describe) D. Success metric visible in existing dashboard (name it) Default: B for existing repos, A for greenfield


Batch 7 — E2E Testing (recommended for deployable projects) For each user story targeting a deployable repo, specify E2E tests:

7a. What E2E tests should verify each story works? - For UI: "Page loads", "User can complete [action]", "Form shows validation errors" - For API: "Endpoint returns expected response", "Error cases handled" - For CLI: "Command runs successfully", "Opens correct URL" - For integration: "Full flow from [A] to [B] works" - Leave empty for non-deployable projects (knowledge, content, data)

Append interview decisions to journal

After the interview batches complete:

.claude/skills/_shared/journal.sh append "{project_dir}" decisions "Interview decisions: project type — {classification}; scope — {what's in / what's out}; notable answers — {2-3 bullets}"

Live Path Watch hook

Before generating the PRD, detect whether this project plausibly replaces, hardens, or builds alongside an existing live production surface. Purpose: prevent silent regressions on routes that already serve real users.

Trigger the hook when ANY of the following match:

  • Project description contains a full URL (https://...) or a known production hostname (check companies/{co}/manifest.yaml dns_zones and any existing project's metadata.replacementFor.liveUrls)
  • repoPath matches a repo that has prior PRDs declaring metadata.replacementFor (grep companies/{co}/projects/*/prd.json for replacementFor)
  • Description matches replacement/hardening language: rebuild, replace, harden, v[0-9]+, migration, rewrite, safeguard, regression, silent, prevent + live noun

On match, ask via AskUserQuestion:

  • question: "This PRD looks like it touches a live surface. Declare it so heartbeats and canaries can protect it from silent regression?"
  • header: "Live Path Watch"
  • options:
    • label: "Yes — declare live URL(s)" — follow up with a free-text prompt for the URL list (one per line), then set metadata.replacementFor = { liveUrls, description, detectedFrom: "hook" } and add livePathWatch to any story whose acceptanceCriteria mention the matched URLs
    • label: "No — not a live-surface project" — record the dismissal in metadata.openQuestions as "LivePathWatch hook fired but was dismissed: {reason}" (free text)
    • label: "User already answered" — skip (user populated replacementFor earlier in interview)

If user picks "Yes": also add a canary E2E test to the highest-priority story: "curl -sS <liveUrl> returns 200 and contains none of {forbiddenTokens}".

Policy core/policies/hq-live-path-watch-on-replacement-prds.md (hard enforcement) blocks PRD generation when the hook matches but the user neither declared replacementFor nor explicitly dismissed. The hook MUST run before Step 5.

Step 5: Generate PRD

Create companies/{co}/projects/{name}/ folder with two files. Use personal/projects/{name}/ only for personal/HQ projects.

Primary: companies/{co}/projects/{name}/prd.json

This is the source of truth. /run-project and /execute-task consume this file.

{
  "name": "{project-slug}",
  "description": "{1-sentence goal}",
  "branchName": "feature/{name}",
  "userStories": [
    {
      "id": "US-001",
      "title": "{Story title}",
      "description": "{As a [user], I want [feature] so that [benefit]}",
      "acceptanceCriteria": ["{Specific verifiable criterion}"],
      "e2eTests": [],
      "priority": 1,
      "passes": false,
      "files": [],
      "labels": [],
      "dependsOn": [],
      "notes": "",
      "model_hint": "",
      "worker_preference": [],
      "livePathWatch": []
    }
  ],
  "metadata": {
    "createdAt": "{ISO8601}",
    "goal": "{Overall project goal}",
    "successCriteria": "{Measurable outcome}",
    "qualityGates": ["{commands from Batch 6a}"],
    "repoPath": "{repos/private/repo-name or empty}",
    "baseBranch": "{main or staging or master}",
    "relatedWorkers": ["{worker-ids from scan}"],
    "knowledge": ["{relevant knowledge paths}"],
    "audiences": ["{from Batch 2a — user roles + technical level}"],
    "currentSolution": "{from Batch 2b — what exists today}",
    "designRef": "{from Batch 2c — Figma ID, reference, or empty}",
    "nonGoals": ["{from Batch 3d — explicit out-of-scope items}"],
    "dataModel": "{from Batch 4a — key entities/tables or empty}",
    "authModel": "{from Batch 4b — auth approach or empty}",
    "architectureNotes": "{from Batch 4c — approach or empty}",
    "performanceRequirements": "{from Batch 4d — targets or empty}",
    "integrations": ["{from Batch 5a — service name, type, credentialsReady}"],
    "securityNotes": "{from Batch 5b — PII/compliance notes or empty}",
    "rolloutStrategy": "{from Batch 5c — ship strategy or empty}",
    "analyticsEvents": ["{from Batch 6g — event names or empty}"],
    "monitoringNotes": "{from Batch 6h — prod monitoring plan or empty}",
    "openQuestions": ["{remaining unresolved questions — Step 8.5 resolves these before Step 9}"],
    "decisions": [],
    "replacementFor": null
  }
}

decisions[] schema: Appended by Step 8.5 as {question, answer, decidedAt, decidedBy}. Optional — absent means empty. Additive and backwards-compatible; existing PRDs without the field are unaffected.

worker_preference[] schema: Optional ordered list of preferred worker IDs (strings) per story. Used by /execute-task Layer 2 worker selection (core/settings/orchestrator.yaml → worker_selection). When non-empty AND any pinned worker can fill a role slot in the resolved sequence, that worker wins and the LLM picker is skipped. Default: empty array — fully auto-select. Example: ["acme-backend", "acme-qa"].

Populating files: For each story, infer file paths from the description + acceptance criteria + target repo structure. If repoPath is set, search the repo (via qmd or Glob) to find existing files the story will modify, and predict new files it will create. Paths are repo-relative (e.g. src/middleware/auth.ts, not absolute). Best-effort — empty is fine for stories with unclear scope.

Derived: companies/{co}/projects/{name}/README.md

Shortened here. Read the whole file on GitHub.

Signals

GitHub stars
84
Forks
15
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
plan-indigoai-us
Source
github.com/indigoai-us/hq-core