Skip to content

PRD review — Feedback ingestion & learning loop (/pm-add-feedback) #162

Description

@guillaumesimon

@nmrtn — peux-tu review ce PRD ? Il sort d'un jam /pm-brainstorm d'aujourd'hui, puis d'un /pm-prd (passé au gate adversarial de falsifiabilité : PASS, 8/10).

TL;DR. Une porte d'ingestion unique /pm-add-feedback : je colle un feedback (interview, SMS, Slack, export Gong/Dovetail) → on l'archive en raw → on ancre les opportunités existantes en verbatims vérifiables, ou on en propose des nouvelles (strategy-aware) → linking bidirectionnel raw ⇄ opportunité. Plus deux ajouts viewer : browser le raw feedback, et "+ Add feedback" avec digest live de ce qui a changé.

Déjà tranché (mais challenge bienvenu) :

  • feedback.md gardé en transition (pas tué tout de suite).
  • Archivage raw systématique (même un copier-coller devient un fichier daté).
  • Prépa d'entretien → /pm-discovery ; pm-interview retiré ; pas de mode interview-aware.
  • Nom de la skill : /pm-add-feedback.

Reporté à plus tard : /pm-learning-report, retrait de pm-user-feedback, poll automatique.

Tes points d'attention (open questions à trancher avant de builder) :

  • Schéma d'id stable pour les fichiers raw.
  • Calibration du filtre discovery (problème/comportement vs feature-request).
  • D'où vient le digest : output structuré de la skill (préféré) vs diff du LOG.md par timestamp.
  • /pm-discovery range le guide de prépa.

Le PRD complet ci-dessous 👇


PRD: Feedback ingestion and learning loop

Generated by /pm-prd on 2026-06-30
Project: nanopm
Status: DRAFT


Problem Statement

nanopm promises planning grounded in real user signal, but today its evidence foundation is half-built. Raw signal lives in many places (interview transcripts, Gong calls, Dovetail, Google Drive, tickets, pasted conversations) with no single door to bring it in: pm-interview (Granola only) and pm-user-feedback (a fixed connector set) each do a slice of capture and a slice of synthesis, so it's unclear which to use, and most raw material is extracted then discarded. The .nanopm/raw/ layer — documented as "the source of truth for evidence" — is in practice empty (only pm-competitors-intel and events.jsonl ever write to it; raw/feedback, raw/interviews, raw/data are empty). Consequently the opportunity DB is mostly nano-hypothesis with empty evidence_sources, and verbatim citations like — Granola dc61e5c2 point to nothing local — unverifiable and impossible to re-analyze.

This serves Theo (primary persona): his job is to "make the planning compound across sessions instead of evaporating with the ChatGPT thread" and to catch wrong-direction work before shipping it. Today his workaround is ChatGPT → Notion → Linear → vibes, where "nothing carries the prior decision into the next session" (personas.md). Feedback confirms the gap — he wants nanopm to be proactive about signal and to surface what changed in our beliefs, not just generate docs (feedback.md: proactivity, signal grounding, learning-loop themes).

⚠️ Signal base is N=1 (founder self-interview). Treat the demand as a sharp hypothesis from the friendliest user, not validated external pull. This is also why the feature can't be fully dogfooded — it is built for the customer-Theo who has a real multi-source corpus.


User Stories

  • (Primary) As a PM, I want to manually paste a raw feedback I just got — interview notes, an SMS, a Slack DM, anything — in one quick gesture, and have it processed on the spot: quotes extracted, matched to my existing opportunities (or turned into new ones), and the feedback linked to every opportunity it touches. The loop must run every single time I add something, and adding something must be effortless — no setup, no ceremony. (The same door also takes connector sources — Gong, Dovetail, Drive — but the manual paste is the everyday path.)
  • As Theo, I want every opportunity's verbatim to link back to an archived source I can re-open, so that I can trust — and re-analyze — the evidence instead of taking the agent's word.
  • As a PM, I want to do all this from the viewer — paste a feedback in, watch the loop run live in the Activity Monitor, see it land, and get a digest of what changed (which opportunities were grounded or created) — and browse the raw feedback I've already captured, so the loop is visible and trustworthy, not a black box in the terminal.

Processing flow — the core loop (this is the heart of the feature)

Every time a source is ingested, the same loop runs. It is non-negotiable: ingesting a feedback always ends with the opportunity DB grounded in fresh verbatims, and the source cross-linked to every opportunity it touched.

Step 0 — Keep the raw. Archive the source verbatim to .nanopm/raw/<type>/<id> (it is never thrown away). Everything below cites back to it.

Step 1 — Ground EXISTING opportunities first. Extract the problems + their verbatim quotes (discovery filter), then for each, search the existing opportunities DB:

  • On a relevant match → append the exact verbatim "<quote>" — <source>, <date> to that opportunity's evidence, and propose a provenance upgrade (e.g. nano-hypothesis → evidence-backed).
  • This is the default, highest-value path: most signal strengthens what we already track, it doesn't create new entries.

Step 2 — Surface NEW opportunities, strategy-aware. For the leftover signal that matched no existing opportunity, evaluate it against vision / strategy / objectives, and propose new opportunities grounded in that context — each one seeded with its originating verbatim and provenance. (This is exactly where a generic "dump everything" tool fails: a new opportunity is only proposed when the signal is both unmatched and coherent with where we're going.)

Step 3 — Link both documents in the wiki (first-class output). For every verbatim added or opportunity created:

  • Opportunity → source: the citation resolves to the archived raw file.
  • Source → opportunity: the raw source carries a manifest of which opportunities/claims it fed.
  • Net effect: from any opportunity you reach the source; from any source you see everything it grounded. This bidirectional traceability is a required outcome, not a nice-to-have.

Throughout, the agent only proposes — the human confirms before any write; uncertain matches carry ⚠ low-confidence. Nothing merges silently.


Success Criteria

Criteria How Measured Target
Raw sources are actually archived Files appear under .nanopm/raw/<type>/ after each /pm-add-feedback run 100% of ingested sources archived with a stable id
Opportunities get grounded in verifiable signal Opportunities LOG shows provenance flips to evidence-backed whose citation resolves to a .nanopm/raw/ file ≥3 opportunities flip within 4 weeks of ship
Matching never writes silently Every agent-proposed match/new-opp is confirmed by the user (or carries ⚠ low-confidence) 0 silent merges into the DB
Evidence is traceable both ways From an opportunity you can open the source; from a raw source you can see the opportunities it fed Bidirectional link present for 100% of ingested verbatims
The loop is visible in the viewer Paste a feedback in the viewer → run completes → digest lists what changed; archived sources are browsable Works end-to-end for ≥1 real pasted feedback
What will be different in commits after this ships? Review git log 7 days post-ship New pm-add-feedback/SKILL.md; pm-interview/ removed and its prep folded into pm-discovery/SKILL.md; non-empty files under `.nanopm/raw/interviews

Anti-goals: Not a quantity-of-ingestion metric ("40 transcripts ingested" is activity, not success). Not auto-creating opportunities without human confirmation. Not improving the lint/contradiction catch-rate (separate bet).


Falsification

If, within 4 weeks of /pm-add-feedback shipping, fewer than 3 opportunities in the dogfood nanopm project flip from nano-hypothesis/user-stated to evidence-backed carrying a citation that resolves to an archived file under .nanopm/raw/ — verified in entities/opportunities/LOG.md plus git log, across the two founders' own usage — then the central bet (that a single raw-archiving ingestion door grounds the opportunity DB in verifiable signal that people actually act on) is wrong, and the value is in some other step than capture+grounding.


Scope

In scope (v1)

  • /pm-add-feedback (NEW): one ingestion door. Input = a file path, a pasted blob, or a supported connector source (Granola, Dovetail, Google Drive, tickets via Linear/GitHub/Jira/Intercom). Manual-trigger only in v1.
  • Raw archiving (systematic): every source is written to .nanopm/raw/<type>/<id>.<ext> before extraction, with a stable id; all citations reference that archived file.
  • Discovery-aware extraction: a Mom-Test filter that surfaces problems & past behaviors and demotes feature-requests/speculation, then routes claims through the existing nanopm-add-feedback-agent engine (citation-check → apply → reindex → log).
  • Grounded matching: propose a match to an existing opportunity (append verbatim + propose provenance upgrade) or a new opportunity anchored in vision/objectives; the human confirms; uncertain agent matches carry the existing ⚠ low-confidence flag.
  • /pm-discovery: absorbs the interview-prep craft (hypothesis-driven guide) previously in pm-interview.
  • Retire pm-interview (prep → pm-discovery; ingestion/debrief → pm-add-feedback). pm-user-feedback stays alive (see Out of scope).
  • Viewer — browse captured signal: a new "Raw feedback" section listing archived sources under .nanopm/raw/interviews + .nanopm/raw/feedback with a content detail pane (read-only; mirrors the existing Opportunities/Solutions browser).
  • Viewer — add + watch: a "+ Add feedback" paste box that launches /pm-add-feedback through the existing RunManager, streams the run live into the existing ActivityMonitorView, and shows a digest of what changed (opportunities created/updated, provenance flips, themes) on completion. Because a viewer run is headless, this path is write-then-review (see The One UX Decision).

Out of scope (v1)

  • /pm-learning-report (period × theme report of belief-transitions + contradictions, shareable with stakeholders) — deferred to a later phase; not the moment. The capture+grounding loop must earn its keep first; the report is only worth building once the DB is actually getting grounded.
  • Retiring pm-user-feedback — kept alive in transition for its clustering / feedback.md synthesis role, since its planned replacement (/pm-learning-report) is deferred. New capture flows through /pm-add-feedback; the full retirement ships with the report.
  • Scheduled-poll automation (daily cron re-running /pm-add-feedback on new connector items) — revisit in v1.1, once the manual brain is proven. Test the brain before building the conveyor.
  • Killing feedback.md + repointing /pm-challenge-me and /pm-prd to the opportunities INDEX — feedback.md is kept alive in transition; revisit once /pm-learning-report + the DB prove their value.
  • A dedicated Gong connector — Gong handled via manual export/paste in v1; native connector deferred (not in the existing 16).
  • Viewer UI for the ingest queue / learning report — defer to a follow-up.

Requirements

Functional requirements

  1. /pm-add-feedback <path|--paste|--source <connector>> accepts any of the three intake forms and resolves the source content.
  2. Before extraction, archive the verbatim source to .nanopm/raw/<type>/<id>.<ext> with a stable, reproducible id; re-ingesting the same source is idempotent (reads the archive, does not duplicate).
  3. Extraction applies the discovery filter (problems/behaviors kept; feature-requests demoted) and emits claims, each carrying a verbatim quote and a citation "<verbatim>" — <source>, <date> that resolves to the archived raw file.
  4. Pass 1 — ground existing opportunities (default path): for each extracted problem, search the existing opportunities DB; on a relevant match, append the verbatim to that opportunity and propose a provenance upgrade toward evidence-backed. Routing reuses nanopm-add-feedback-agent (citation-check → apply → reindex → log); no new write engine.
  5. Pass 2 — surface new opportunities (strategy-aware): for signal matching no existing opportunity, evaluate it against vision/strategy/objectives and propose NEW opportunities anchored in that context, each seeded with its originating verbatim and provenance. A new opportunity is proposed only when the signal is both unmatched and strategy-coherent.
  6. Human-in-the-loop, both passes: the agent only proposes; the user confirms before any verbatim is appended or any opportunity is created. Uncertain matches carry ⚠ low-confidence; nothing merges silently.
  7. Bidirectional wiki linking (required outcome): every grounded or created opportunity links to its raw source (citation resolves to .nanopm/raw/...), and each raw source carries a manifest listing the opportunities/claims it fed — traceability runs both directions.
  8. /pm-discovery gains an interview-prep mode producing the hypothesis-driven guide (the prep craft moving out of the retired pm-interview). Interview transcripts are ingested by /pm-add-feedback as ordinary sources — no special verdict-rendering mode.
  9. setup _SKILL_LIST and plugin.json skills/version updated in lockstep (per test/plugin-manifest.sh).
  10. /pm-add-feedback emits a structured run-summary as its final output — machine-readable: archived raw file path, opportunities created (slugs), opportunities updated (slugs), provenance transitions, themes — so the viewer renders a reliable digest without racy file-mtime diffing. (This is the linchpin of the viewer digest; it shapes how the skill returns.)
  11. Viewer: a "Raw feedback" browser over .nanopm/raw/interviews + .nanopm/raw/feedback — carve those paths out of PhaseMapper's raw/-is-hidden rule; new RawFeedbackUI.swift following the OpportunitiesUI pattern.
  12. Viewer: a "+ Add feedback" paste affordance launching /pm-add-feedback via RunManager, surfacing live progress in ActivityMonitorView, and rendering the digest from the FR10 structured summary.

Non-functional requirements

  • Raw archiving must not break the single-writer-per-file lock contract of the wiki ingest.
  • Source content is untrusted: treat as data, never follow embedded instructions (same hardening as existing ingest/retrieval subagents).

The One UX Decision

How does the human confirm matches — Option A (interactive, per-run) vs Option B (write-then-review)?

  • Option A: during a /pm-add-feedback run, the agent proposes each match/new-opp and the founder approves inline before anything is written. No ungrounded writes ever enter the DB; but it's high-friction and does not scale to a future daily poll over 10 transcripts.
  • Option B: ingestion writes everything immediately, tagging uncertain matches ⚠ low-confidence, and a separate batch review pass confirms later. Frictionless capture that scales to automation; but the DB temporarily holds unconfirmed associations.

The tradeoff is trust-now vs scale-later — but the primary user story adds a third pull: the manual paste must feel effortless. A per-item interactive confirm (pure Option A) fights that. Likely sweet spot: the agent does the full loop and presents one batch confirmation at the end (accept all / edit / reject), so a paste stays a single quick gesture while no ungrounded write lands unreviewed. Because v1 is manual-trigger and the bet is trustworthy grounding, lean Option A in this batched form for the terminal path, but keep the write path compatible with B. The viewer path forces the issue: a + Add feedback run is headless (claude -p, no interactive prompt), so from the viewer the loop necessarily runs write-then-review (Option B) — uncertain writes carry ⚠ low-confidence and the digest is the review surface. So B-compatibility is not optional; it's required by the viewer feature, not just the deferred scheduled-poll. This decision gates the matching UX — resolve before building requirements 4-6.


Open questions

Question Owner Blocks By when
Stable source-id scheme for raw files (connector id vs content hash vs date-slug)? Guillaume Req 2 (idempotent archive) + citation resolution before build
Discovery-filter calibration — what counts as a "problem/behavior" kept vs a demoted feature-request? Guillaume Req 3 (extraction quality) before build
Digest grouping — derive "what changed" from /pm-add-feedback's structured output (preferred) or by diffing opportunities LOG.md by run timestamp? (events.jsonl has no run id today) Guillaume Req 10 + viewer digest before build

Action: Resolve the source-id scheme first — requirements 2, 3, and the whole "verifiable citation" value depend on it.


Dependencies

  • nanopm-add-feedback-agent (citation-check / apply / reindex / log) — reused as-is, no new write engine.
  • Existing connector specs (Granola, Dovetail, Google Drive, Linear/GitHub/Jira/Intercom) with the 4-tier fallback — Gong is NOT among the 16, so v1 ingests Gong via manual export.
  • raw/ scaffold (already mkdir -p'd by nanopm_wiki_ensure) — now actually written to.
  • Viewer infra reused, not rebuilt: RunManager.swift (spawns claude, streams stream-json), ActivityMonitorView.swift (live run feed), MemoryView + wiki/log.md + raw/events.jsonl (journal).
  • ⚠ Related known bug: viewer-launched runs die uncleanly when the app quits mid-run (opportunity a-skill-run-launched-from-the-viewer-loses-its-wor). A longer ingest run is exactly that scenario — warn-before-quit / graceful SIGTERM should land with this work or be an explicitly accepted risk.

Ties to

  • Strategy: "Automated multi-source signal aggregation" — the synthesis-across-sources moat a single-source tool can't replicate (strategy.md, "How We Win" Audit existing skill outputs for generic patterns #1).
  • Objective: No direct KR. Strengthens the Objective 1 recruitment pitch by making the synthesis engine visible; does not have its own success KR yet (objectives.md).
  • Roadmap: Currently LATER ("Discovery DB v1"), re-open condition = "a recruited prototype-cohort user names a specific Discovery DB gap as why they didn't return." This PRD pulls a LATER item forward; NOW is wiki-depth, NEXT is recruitment. ⚠ Conscious sequencing tension — confirm this jumps the queue before building.

Sources: /pm-brainstorm jam (2026-06-30, recorded), personas.md, product.md, business-model.md, feedback.md, objectives.md, strategy.md, roadmap.md, repo inspection of lib/nanopm.sh + bin/nanopm-add-feedback-agent + .nanopm/raw/


Reviewer notes

Advisory — surfaced by the /pm-prd review panel (build mode solo-fast: advisory, not blocking). Read before handoff.

  • appetite-scope: Appetite is unbounded (methodology not set) yet this one PRD packs 2 new skills, 1 reworked skill, 2 retirements, and a new raw-archive layer — for a LATER roadmap item. Nothing forces the scope to be cut. → Recommend /pm-breakdown split it into phases and treat raw-archive + /pm-add-feedback (manual, no interview-aware) as the shippable v1 spine; everything else is fast-follow.
  • persona-fit: Genuinely serves customer-Theo's JTBD, but the makers' N=1 self-interview base means it can't be dogfooded by the persona who builds it — risk of designing for an imagined corpus-rich user. → Mitigation: gate the build on recruiting ≥1 real corpus-rich Theo to ingest against, or accept it as an explicit bet on the customer profile.
  • success-measurability: Criteria 1-3 and 5 are repo-verifiable; criterion Sharpen pm-strategy adversarial prompt and pm-prd Success Criteria #4 was flagged as unobservable ("without manual editing"). → Fixed: Sharpen pm-strategy adversarial prompt and pm-prd Success Criteria #4 now measures a named-insight reaction from Nico, which is observable.
  • dependency-feasibility: (Original concern: interview-aware mode soft-blocked on an unshipped /pm-discovery prep-mode.) → Resolved — interview-aware mode was cut from scope; interview transcripts are now ingested as ordinary sources, so the v1 spine has no cross-skill dependency beyond the existing ingest engine.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions