product-input-plan.md
c12 thread: product-input — plan
Written 2026-10-20 from a read of the agent-facing context (CLAUDE.md, goals.md, pipeline/prompts/*, .claude/skills/{analyze,brief}, briefs/TEMPLATE.md), the profile and standing code (schemas/{vocabularies,validation,problem-standing}.ts, pipeline/prompt.ts), and the Oct 12/14/19 product-session extractions. Prompt: product-input-prompt.md. Status: plan; nothing built.
The project is now used mostly as input to product work: weekly product sessions with an advisor, rulings handed to design as decision briefs. This thread makes five changes so that use is first-class. Four fix context that still reads market-first (A, B, C, E). The fifth adds a decisions ledger (D) so the project can answer "what have we decided, and what replaced what."
1. What the read found
The straddle works at the spine. The single observation stream with perspective on every item, use case → micro problem decomposition, and the two code-computed honesty rules (validation-gate.ts, problem-standing.ts) serve both lenses. goals.md puts the design lens first. Problems are consumed downstream: problem:<id> appears in design c105, c114, c116 and c118, and the Oct 19 decision brief became design c118 the same day.
Where market framing still steers agents:
- Role lines and ordering.
extract-call.mdopens "You are an analyst". All threeanalyze-*.mdprompts open "You are a market analyst". The extraction schema putsurgency,positioninganddecisionMakingbeforesessionandcandidateProblems, and candidate problems are guideline 19 of 20.analyze-overviewasks for six market sections beforeproblemSpace. The/analyzeskill is titled "Market Analyst Agent" and says "always connect back to the use-case-honing objective", which contradictsgoals.md. - Product sessions are run through sales fields. Oct 12/14/19 are declared
ciso-advisory × roadmap-planning. Each got interest 4 ("conviction") and an urgency score whose summary explains there is no deal. Mark Peterson's design opinions were tagged as positioning resonance, and a design preference ("I love it a lot better that there's both") became a value echo. Profiles can turn off interest (ratesInterest), but only theinternalprofile turns off positioning and decision-making, and nothing turns off urgency. - The advisor rule doesn't fit a co-designer. c12 confirmed that an advisor's first-hand experience counts as their own organization (Moto), labelled. Moto is one of the two organizations behind all 5 recurring problems. Today the October sessions move no standing: recomputing without them leaves every problem where it is, because Moto's support comes from Aug 20/31 and Sep 3. But the October sessions are already adding Moto first-hand items to
findings-resolution-workflow(3 sessions) andsafe-to-enforce(2). The rule counts a co-designer's preferences about the design as their organization having the problem. This fix is preventive. - Rulings are a per-call sidecar. 44
session.decisionsexist across the corpus, each inside its own call, with no supersession, no surface and no current state. The data holds both Oct 14 "V1 needs … policy groups mapped to teams" and Oct 19 "policy groups stop being a managed object" asmade, and both Oct 14 "defer frameworks" and Oct 19 "frameworks are the entry point". The decision brief sorted this by hand (§4 "Workshopped and superseded"). Nothing in the repo answers "what have we decided about policies?". - Template drift.
briefs/TEMPLATE.mdand/brieflist kinds problem / story / position; INDEX.md already usesdecision. The template's Consumers line still says "feedback.json items advanced", and that file was retired in c12.
Out of scope here, noted for later: a product-state context alongside _qpoint-context.md (that file describes Qpoint as pitched, not what is built or in design); design-native observation types (mock critique, naming / mental model, which is Q9); closing the shipped → validated-in-use loop (no problem has shipped yet); tracing engineering repos in consumers.ts; the ~19 fetched-but-untriaged meetings in data/raw/; reviewing the 25 candidates.
2. The changes
A. Role lines and agent framing (wording only)
pipeline/prompts/extract-call.mdline 1 → "You are extracting structured insights from a conversation for Qpoint's problem space: the problems users have, the decisions the team makes, and how the market receives it." MovesessionandcandidateProblemsaboveurgency/positioning/decisionMakingin the schema block. Moving keys in the prompt's example is safe: the output is parsed as JSON and validated by key, not by position.analyze-use-case.md,analyze-company.md: "You are a market analyst" → "You are an analyst". These two stages are market-lens by design and keep their content.analyze-overview.md: "synthesizing the overall state of Qpoint's market evidence" → "…of Qpoint's problem space and market evidence". MoveproblemSpaceto the top of the task list. The output schema order inschemas/output-schema.tsfollows. The site reads by key, so nothing breaks..claude/skills/analyze/SKILL.md: title "Market Analyst Agent" → "Analysis Agent". "Think through the use-case lens" → "Think through both lenses (design first)". "always connect back to the use-case-honing objective" → "always connect back to the lenses ingoals.md".
B. Turn off market blocks where they don't apply
Today only profile.counterparty === 'none' drops positioning and decision-making. Add a call-type rule beside the existing SESSION_RECORD_CALL_TYPES:
schemas/vocabularies.ts:MARKET_BLOCK_OMITmaps a call type to the blocks it omits:design-session(new, see C):interestLevel,funnelStage,urgency,positioning,decisionMaking. Next steps move tosession.todos, which already exist.document: the same set. This codifies whatprompt.tssays in prose today.working-session,roadmap-planning,build-feedback:positioningonly. A build partner's rollout timeline and approvers still matter, so urgency and decision-making stay.
pipeline/prompt.tsrenderDeclaredProfile: one line listing the omitted blocks, replacing the counterparty-only clause.schemas/validation.ts: rule 4 generalises from "internal profile" to "the profile or call type omits it". Fix messages follow the existing pattern ("positioning dropped (call type design-session)").- Site: these fields are already optional (internal calls lack them). Dashboard averages for interest and urgency simply exclude these calls. Check the call page renders cleanly with them absent.
C. A design-session call type, and what it means for standing
CALL_TYPESgainsdesign-session: "A product design session where the team, possibly with an advisor or partner as co-designer, works out what the product should do. Yields decisions, ideas and problem tags, not market signals." Add it toSESSION_RECORD_CALL_TYPES.CONVERSATION_PROFILESguidance forciso-advisorygains one sentence: in adesign-session, the advisor's opinions about the design are ideas or decisions, not pain points. Their own organization's experience is still first-hand.- Standing rule (
schemas/problem-standing.ts): items that extraction tagged from adesign-sessioncall are counted and shown as design input (a new count beside relayed and internal) and do not move standing. Curated refs (human-pinned inproblems.json) from those calls still count, because a person checked them. Reasons gain "N design-session item(s): design input, not evidence".build-index.tspasses call type intoStandingEvidence. The site's client-side recompute inuseCallData.ts(problemRollup) mirrors the rule, the same pairing c12 used for the advisor rule. - Re-triage: Oct 12, 14 and 19 →
ciso-advisory × design-sessionindata/call-classifications.json, keeping theirshownartifacts. Re-extract all three, which CLAUDE.md requires after a profile change. Expected effect: no standing change (§1.3). There are no curated refs from October, so nothing needs re-pinning.
D. Decisions ledger
A curated registry of product rulings made in conversations, the same pattern as problems.json: extraction proposes, a person promotes, the index computes, the site reads.
D1. Shape: data/decisions.json (human-curated)
{
"id": "policy-one-per-concern", // kebab, stable, cited as decision:<id>
"statement": "One policy per area of concern; the policy holds its own definition, severity, mode, exceptions and knobs.",
"status": "ruled", // DECISION_STATUSES (below)
"date": "2026-10-19", // when it took this status
"area": "policy-model", // free kebab grouping, for the ledger view
"problemIds": ["safe-to-enforce"],
"surfaces": ["policy-enforcement", "controls"],
"supersedes": ["policy-groups-mapped-to-teams"],
"source": [{ "callId": "154b2679-…", "decision": 2, "verbatim": "…", "at": "1:26" }],
"owner": "Mark Parson",
"notes": "Later statements win; the recap at 1:26–1:32 is the ruling.",
"statusHistory": [{ "status": "direction", "date": "2026-10-14", "by": "Oct 14 session" }, { "status": "ruled", "date": "2026-10-19", "by": "Oct 19 recap" }]
}
DECISION_STATUSESinvocabularies.ts:ruled(agreed, in force),direction(leaning, not final: the brief's "direction" items),open(raised, explicitly undecided),tabled(deliberately deferred),superseded(replaced by a later entry),rejected(workshopped and dropped: the brief's "do not revive" list).rejectedkeeps a dropped idea from being revived from an old transcript.supersedesis written by hand. The index computessupersededBy, and it warns when an entry is superseded but its status still saysruled/direction.- Source refs carry
verbatimas well as the index. This is the c12 re-extraction lesson: indices change, verbatims don't. - Types in
schemas/call.ts(Decision,DecisionRegistry), runtime checks invalidation.ts.
D2. Extraction proposes, linked to the ledger
session.decisions[]gains optionaldecisionId+decisionDirection(reaffirms/revises/reverses), validated against the ledger exactly asproblemIdis validated against problems (unknown ids dropped with a fix message).prompt.tsrenders a Named Decisions section (id, status, one-line statement; superseded and rejected entries included and marked) into the cached static part beside{{PROBLEMS}}. Guideline 21: tag a session decision when it restates, revises or reverses a named one. Never invent an id. A ruling that matches no named decision stays untagged and becomes a promotion candidate.- This makes supersession something the pipeline notices: a
revises/reversestag on a new call surfaces as "this may supersede X" for a person to confirm.
D3. Index and consumers
build-index.ts→data/decisions-index.json: per decision, resolved source text,supersededBy,inForce(ruled or direction and not superseded), later revisits from extraction tags (call, date, direction), consumers. Plus a list of untaggedmadesession decisions across the corpus: the promotion queue.pipeline/consumers.tsscansdecision:<id>as well asproblem:<id>and briefs.
D4. Seed (the T0-style hand pass, after C's re-extraction so indices are stable)
- Review all session decisions across the corpus: 44 today; the count changes with C's re-extraction. Use
briefs/policy-model-and-publishing.mdas the spine for policy, findings and publishing. Expect roughly 20–30 entries, including superseded and rejected ones, because the brief's §4 becomesrejected/supersededrows. - Draft in
decisions-draft.mdfor Mark's review, then writedata/decisions.json. This mirrorsproblems-draft.md→problems.json. - Retro-cite: the decision brief's §1 items (A1… D…) gain
decision:<id>tokens.
D5. Site
- New
/decisionspage, third in the nav (Dashboard · Problems · Decisions · Calls · …):- In force, grouped by
area, then each entry's statement, status pill, date, source session link, problem and surface chips, and a collapsed "replaced" chain. - Open / tabled.
- Superseded and rejected, collapsed by default.
- Not in the ledger yet: untagged
madesession decisions with copy-JSON promotion, the same idiom as candidates on/problems.
- In force, grouped by
/problems/[id]gains a Decisions card. The call page's Session Record shows a ledger chip on tagged decisions. The dashboard Direction block links "Ledger →".useCallData.tsloadsdecisions.json+decisions-index.json.
D6. Docs and skills
goals.mddesign lens gains key questions: "What is in force for each surface? What has been superseded or rejected, so it is not revived?"/analyzeloads the ledger./briefwritesdecisionbriefs that citedecision:<id>and list superseded or rejected ids in place of the free-text §4.CLAUDE.md: the ledger in the tree, data flow and conventions ("data/decisions.jsonis human-curated").
Boundary with design. Design records what a ruling changes in the design: c118 is writing dated decisions into c114's CYCLE.md. The ledger records what was decided in conversation, when, by whom, and what it replaced. To keep one source of truth per fact, design cites decision:<id> rather than restating the ruling. That needs a small addition to design's brand/pipeline.md hand-off rule 4, made as its own commit in design and only with Mark's OK (Q5).
E. Brief template and skill drift
briefs/TEMPLATE.md: Kind line gainsdecision. The Source block gains aDecisions:line (decision:<id>, status). Consumers: "feedback.json items advanced" → "problems / decisions advanced"..claude/skills/brief/SKILL.md: a "Decisions are briefs too" paragraph covering thedecisionkind, its sections, and citing the ledger.
3. Build order
- A + E (wording; no data change). Commit.
- B + C code: vocabularies, prompt, validation, standing, build-index, site recompute.
npm run indexshows no standing change on the existing corpus. Commit. - D1 + D2 schema: ledger types, vocab, validation, prompt section (renders empty until seeded), guideline 21. Commit.
- Re-triage and re-extract Oct 12/14/19 as
design-session(sequential,env -u ANTHROPIC_API_KEY). Check: no interest, urgency, positioning or decision-making on the three; session records intact; standing unchanged. Commit. - D4 seed:
decisions-draft.md→ Mark reviews →data/decisions.json. Commit. - D3 index + consumers. Commit.
- D5 site. Typecheck, build and preview on :3100 (not while the dev server runs). Commit.
- D6 docs and skills; retro-cite the decision brief. Commit. Update c12 CYCLE.md Key Changes.
Steps 2–4 are ordered so the seed is pinned against the final extractions. Seeding before the re-extract would repeat the c12 index-invalidation problem.
4. Verification
npm run index: standing identical to before (5 recurring / 10 observed); reasons show design-input counts onfindings-resolution-workflowandsafe-to-enforce.- The three October extractions validate with no interest, urgency, positioning or decision-making, and with their session records and problem tags intact.
/decisions"In force → policy-model" reads the same as the decision brief §1. Oct 14 "policy groups mapped to teams" and "defer frameworks" appear under superseded, each pointing to its Oct 19 replacement.npm run consumersreports decision tokens once design cites them, and c118 still resolves against its four problems.nuxi typecheckclean apart from the pre-existing Segments errors. All routes return 200.- A test extraction of a later product session (the Oct 21 Wednesday session, if fetched) tags at least one decision
reaffirmsorrevisesagainst the ledger.
5. Decisions for Mark
| # | Question | Recommendation |
|---|---|---|
| Q1 | Which calls become design-session? | Oct 12, 14, 19. Leave Aug 31 and Sep 3 as advisor roadmap calls: they are Mark Peterson scoping from Moto's experience, and they hold most of Moto's first-hand problem evidence. |
| Q2 | Do any design-session items move standing? | Curated (human-pinned) refs only; extraction tags count as design input. |
| Q3 | Which blocks does each call type omit (B)? | As in §2B: everything market-shaped for design-session and document; positioning only for working-session, roadmap-planning and build-feedback. |
| Q4 | Ledger statuses | ruled / direction / open / tabled / superseded / rejected. |
| Q5 | Ask design to cite decision:<id> (pipeline.md rule 4, a design commit)? | Yes, after the seed exists. |
| Q6 | Seed scope | Review all session decisions; promote what is still relevant. Superseded and rejected rows are worth keeping. |