PRD Source Write: $ARGUMENTS
Thin dispatcher. Resolves the configured PRD source and delegates to the matching vendor PRD
writer, which owns the concrete create/update, the lifecycle-role application, and the marker-based
dedupe. When the supplied PRD body already contains the canonical ## Lisa Usage ledger, the
vendor writer must preserve that managed section on update instead of dropping it or reformatting it
ad hoc. This skill only routes — it never talks to a source API itself.
See the config-resolution rule for the full configuration schema and the PRD lifecycle roles.
Input contract
Callers pass a single structured spec:
operation: create_or_update # the only operation; create unless the marker already exists
title: "<PRD title>"
body: "<full PRD markdown — the entire spec>"
initial_role: draft | ready # default: draft. ready = picked up by lisa-intake's PRD scan
dedupe_key: "<stable-key>" # e.g. project-ideation's idea key
marker: "[lisa-project-ideation] idea=<stable-key>" # embedded in the PRD body for dedupe
origin: { tool: project-ideation | research | manual }
source_ref: "<optional existing PRD ref to force an update>"
ideation_ledger_payload: # optional; forwarded unchanged to the vendor writer
selected_marker: "<same value as marker>"
automation_id: "<Codex/Claude automation id or unavailable>"
automation_memory_path: "<path or unavailable>"
repo: "<org>/<repo or detected repo identity>"
prd_ready: true|false
persona_names: ["<derived persona name>"]
persona_evidence_refs: ["<file/doc/table/release ref>"]
selected_idea: "<selected idea title/key>"
rejected_overlap_candidates: ["<issue refs/titles considered and rejected>"]
expected_empirical_verification_artifact: "<artifact ref or unavailable>"
initial_role semantics are uniform across vendors (the role STRINGS resolve per vendor from
config-resolution):
draft(default) → the PRD is created in the source'sdraftPRD role. It waits for a human (or a laterreadypromotion) before any intake claims it.ready→ the PRD is created in the source'sreadyPRD role (prd-ready), so the PRD-side oflisa-intake/ the*-prd-intakescanner auto-claims it on the next cycle.
Omitted means draft — the not-ready default. This matches the ticket-side build_ready contract
in ready-role-filing: on both sides of the pipeline, entering a queue is an explicit claim and
omission is the safe direction. (The ticket side reached that position by removing a per-vendor
legacy default; the PRD side never had one to remove.)
Workflow
Resolve the source. Read
.lisa.config.local.jsonfirst (if present), then.lisa.config.json. Local overrides global per key. Usejq— never hand-parse JSON.local_source=$(jq -r '.source // empty' .lisa.config.local.json 2>/dev/null) global_source=$(jq -r '.source // empty' .lisa.config.json 2>/dev/null) source="${local_source:-${global_source}}" if [ -z "$source" ]; then echo "Error: 'source' is not set in .lisa.config.json. A PRD source (notion / confluence / github / linear) is required to create a PRD. Run /lisa:setup:notion (or :confluence, :github, :linear)." >&2 exit 1 fiValidate the value and dispatch (pass the spec verbatim):
notion→ confirmnotion.workspaceIdandnotion.prdDatabaseIdare present, then invokelisa-notion-write-prd.confluence→ confirmatlassian.cloudIdand (confluence.spaceKeyorconfluence.parents.draft/.ready) are present, then invokelisa-confluence-write-prd.github→ confirmgithub.organdgithub.repoare present, then invokelisa-github-write-prd.linear→ confirmlinear.workspace(and team for project placement) is present, then invokelisa-linear-write-prd.jira→ stop and fail loudly:"source=jira is not a supported PRD source — config-resolution defines no JIRA PRD lifecycle roles. Use notion / confluence / github / linear, or set source accordingly."(JIRA is a destination tracker, not a PRD source.)- Any other value (including
file) → stop and report:"Unknown PRD source '<value>'. Expected one of: notion, confluence, github, linear."
Surface the vendor writer's output unchanged. It returns the created/reused PRD ref + URL, the applied role (
draft/ready), the dedupe marker, and whether it was created or reused. Downstream callers (research, project-ideation) parse this — do not paraphrase.
When ideation_ledger_payload is present, this shim still does not render or interpret it. Forward
the object verbatim to the selected vendor writer so source-specific rendering remains behind the
configured writer and the dispatch layer never bypasses source selection.
Rules
- Never bypass dispatch — a vendor-neutral caller calling a
*-write-prdskill directly defeats the per-project source switch (exactly thetracker-writediscipline, mirrored). - Never drop or duplicate an existing managed
## Lisa Usagesection. Writer-specific preservation and fallback behavior belongs in the vendor writers and follows thelisa-lisa-usage-accountingcontract. - Never accept a source outside
{notion, confluence, github, linear}.jiraandfilefail loudly. - Never mutate the spec between layers. The vendor writers define their own create/dedupe contract.
- Never drop, rename, or vendor-render
ideation_ledger_payload; it is a pass-through payload for the configured writer. - Never invent a PRD lifecycle role string — resolve every role from
config-resolutionper vendor. - Idempotency is the vendor writer's job (marker search before create); this shim only routes.