plan.md
c12 Plan — Micro Problems (draft, pre-kick-off)
Drafted 2026-09-21. Status: planning only — nothing built, no CYCLE.md, not on CYCLES.md. Companion: lens-analysis.md (the "why"). Kick-off waits on the decision queue in §5.
1. Context
Mark's ask: the tool was conceived as a market analyst; it is now used to build design briefs that feed product work. Shape it to gather design-grade insight without losing the market-shaped work. Treat market-analyst as the source of truth for the problem space, used to draft micro problems (the design methodology's term: a wicked macro problem given tangible form as addressable pieces) that in turn tell stories, set priority, write briefs, and inform the product. Analyse the existing lens, recommend changes, plan the cycle. Plan first; ask; suggest what he may not be considering.
Mode: archaeology → assemblage. The problems are already in the corpus; the pieces (perspective, gate, session records, brief template, personas) already exist. c12 surfaces the former and composes the latter into a new grain.
What I verified (read-only)
- Corpus: 6 phase-2 calls processed, 7 entries in
data/call-classifications.json(the Aug 7 "Mark | Qpoint Catch-Up" was classifiednulltoday, 2026-09-21 — uncommitted, left untouched). 0 of 7 use cases pass the gate.data/feedback.jsonhas never held an item. - The design need is visible in artifacts written by hand:
briefs/cam-dashboard-directives.mdis organized around "what the dashboard should answer" (user questions); bob-wirec21.inventory/design-brief.mdis user stories in question form + decisions-as-constraints + open questions, assembled from a session record and Mark's notes. Neither had data to draw on at that grain. - Design has a page vocabulary this repo lacks (c90/c92: Fleet Overview, Teams/Users/Devices, Inventory, Sessions, Session Details, actor detail pages;
c92/detail-pages-guide.mdstates purpose per page).PRODUCT_AREAShere is capability-level and predates it. - Design c55 personas are hypothesis-first and unlinked to this corpus (11 personas, page × persona matrix, "no relevant calls yet" at the time).
- The strongest voice is archived: Cam's 9 Cisco build-partner calls are phase-1 schema only (
archive/phase-1/); the gate cannot see them. - Only transcripts enter the pipeline.
inbox/(Cam's chat, QControl-as-Signal docs) has no path in. - Hand-off framing is stale: design
CLAUDE.mdstill describes this repo as "Customer intelligence & ICP data." - Patterns to reuse by analogy:
use-cases.json+useCaseId+direction+computeValidation()(registry curated by a human, extraction tags evidence, standing computed in code); c11's triage declaration (a human states the nature of the input; the prompt gets it as a dynamic block; the static prefix stays cached).
2. Design (lean)
A. Registry. data/problems.json — curated by Mark, extraction never writes it. Record: id, statement (the pain, one sentence, in the user's frame — canonical), question (the mirror image: the question the user asks of the product; required to promote a candidate — if it cannot be written, the product cannot address it), personaIds[], situation, useCaseIds[] (may be empty — a signal), surfaces[], status (candidate → observed → recurring → briefed → in-design → shipped → validated-in-use | retired, each transition dated), origin { callId | docId, date, speaker, perspective }, notes.
B. Extraction — four optional fields, no new observation type.
Observation.problemId?— tag any observation (pain-point, feature-request, use-case-evidence, concern…) to a registered problem, plusproblemDirection?: has | challenges | variant(has= they have it;challenges= evidence it is not real/ready;variant= a different shape of it).CallData.candidateProblems[]—{ statement, question?, personaHint, situation, speaker, perspective, verbatim, nearestProblemId? }. The archaeology output Mark curates into A; extraction proposes both forms when it can.Observation.surface?— from a newPRODUCT_SURFACESvocabulary invocabularies.ts(hand-synced from design's page registry; single source stays here).Observation.artifactRef?—{ repo: design | bob-wire | qdash, slug }when the reaction is to something shown; only allowed when triage declared it (C).CallData.language[]?—{ term, meaningAsUsed, speaker, perspective, verbatim }. Small; skip if Mark says no (§5 Q9).- Prompt: registry rendered into the static (cached) part like
{{USE_CASES}}; nothing per-call except C's shown-artifacts line in the dynamic block.
C. Triage — one more optional field. shown?: string[] (artifact slugs) on the classification entry. /extract asks "anything on screen?" with Enter = none. The prompt's "This Conversation" block lists them; artifactRef outside that list is stripped by finalize.ts.
D. Standing is computed. schemas/problem-standing.ts computeStanding(problemId, calls) → { standing: candidate | observed | recurring, counts: { companies, firstHand, relayed, internal, challenges }, reasons[] }. observed = ≥1 first-hand has from a non-internal source; recurring = ≥2 distinct companies. Used by build-index.ts (writes data/problems-index.json), the site, and analyze. Same discipline as validation-gate.ts: the model is told the standing and narrates around it.
E. Intake expansion. npm run ingest -- <file.md> --source <sourceType> --type document --date … --speaker … writes data/raw/<docId>.txt + hand-authored .meta.json (source: 'document'), classification entry, then the normal extract path. CALL_TYPES gains document; MeetingSource gains document. Same prompt; the profile block says "this is a written document, not a transcript; speaker is the author." Date backfill skipped as for sagetap.
F. Legacy reconnect (decision Q6). Batch re-extract Cam's 9 phase-1 calls as build-partner × working-session with legacy: true on the index entry; market KPIs and the use-case gate exclude legacy by default (flag to include), the problem layer includes it. Raw transcripts copy from archive/phase-1/data/raw/; the archive itself stays frozen.
G. Registries. data/personas.json seeded from design c55's persona one-pagers (id, name, orgSize, role, jobs[], hypothesisSource, status). PERSONA_TYPES stays the coarse attendee tag; Attendee.personaId? links when clear.
H. Briefs. INDEX.md gains kind (problem | story | position) and problems columns; TEMPLATE.md Source block gains a Problems line (ids + standing at time of writing); /brief <problem-id | topic> reads the registry and standing first. A story uses the same template with ## Narrative replacing ## Goal/## Success Criteria: persona, situation, the sequence of problems, verbatims, the moment the product answers. Stories can name the fixture world they should seed.
I. Loop closure. npm run consumers scans ../design/cycles/*/{CYCLE.md,*-prompt.md,*-plan.md} and ../bob-wire/cycles/*/briefs/*.md for briefs/<name>.md and problem:<id> mentions → data/consumers.json; build-index.ts advances briefed / in-design (never backwards; shipped stays manual). pipeline.md hand-off rule 4: a design or bob-wire cycle that works a problem cites problem:<id> in its initial prompt or CYCLE.md.
J. Site. /problems page (table: statement, persona, surface, use case, standing, companies, first-hand count, status; row → observations grouped by call with perspective pills); dashboard first row becomes problems observed / recurring / briefed / shipped, sales KPIs second row; call page shows candidateProblems with a "register" hint; Insights gains a surface facet. useCallData.ts interface copies updated (known gotcha).
K. Docs — the identity rewrite. This is where the redefinition lands in the docs every agent reads, not just in the data: CLAUDE.md Project Overview restated (a design tool first — the source of truth for Qpoint's problem space, drafting micro problems that tell stories, set priority, and write briefs; market analysis is a critical part of it), with "What this project does" gaining the problem layer as step 3; goals.md two lenses (Market: unchanged; Design: the key questions from lens-analysis §7.7); README.md "How to Interpret" gains problems/standing/document intake; CLAUDE.md architecture + skills; /extract, /analyze, /brief skills; design CLAUDE.md Sister Projects re-framed ("source of truth for the problem space; start at data/problems.json and briefs/INDEX.md"); pipeline.md stage 2 artifact adds the problem registry + rule 4.
Explicitly not doing: removing any market instrument; a defect-tracker hand-off (bugs and deployment blockers stay observation types and are listed on the site as not tracked here; a /defects ship-off to Linear/GitHub/Slack is shelved until a formal tracker exists — follow-up); an MCP server (noted as follow-up); a per-problem LLM map stage (computed tallies first; add a map only if the registry passes ~25 entries); OAuth (c3 stays parked).
3. Threads (ordered)
- T0 — Archaeology (no code). Read the 6 processed calls, the Cam brief, the c21 brief, c55
page-persona-analysis.md, c92detail-pages-guide.md. Hand-writeproblems-draft.md: 10–15 micro problems in the §2A shape, each with the observations that evidence it (call id, speaker, perspective), plus the persona and surface lists it implies. Review with Mark. Gate: if the shape needs changing, change §2 before T1. Also produces the firstPRODUCT_SURFACESandpersonas.jsonseed lists. - T1 — Registry + extraction + triage. §2A–D.
vocabularies.ts(PRODUCT_SURFACES,PROBLEM_STATUSES,PROBLEM_DIRECTIONS, render helpers),call.ts,validation.ts(new fields,artifactRef∈ declaredshown),prompt.ts({{PROBLEMS}}static; shown-artifacts dynamic),extract-call.md(guideline 18: problems; 19: candidates; 20: language),extract.tstriageshown,classifications.ts,finalize.ts,build-index.ts(problems-index.json),problem-standing.ts. Pilot: re-extract Tiled (prospect × demo) and Mark P Aug 31 (advisory × roadmap) against the T0 registry; confirm cache still reads; confirm candidates are new material, not restatements of registered problems. - T2 — Site + analyze. §2J; analyze Map A/overview told each problem's standing (
analyze-overview.mdgains a "problem space" section: recurring problems with no brief, briefed problems with challenge evidence, surfaces with no first-hand problems). - T3 — Intake expansion. §2E document ingest (pilot:
inbox/chat-from-cam.mdasbuild-partner × document), and §2F legacy reconnect if Q6 is yes (batch; compare Cam-brief claims against the re-extracted candidates as the acceptance test). - T4 — Briefs, loop, docs. §2G–I, K. Retrofit the two existing briefs with
kind+ problem ids; write one story from the T0 registry as the worked example (candidate: the "sensor coverage → personal-account exposure" arc from the Aug 31 / Sep 3 Mark P calls + Tiled); runnpm run consumersand confirm c21 / c78 / c81 / c92 are found.
Each thread = its own commit(s), dated Key Changes entry, and where a mid-thread prompt arrives, <thread>-prompt.md / <thread>-plan.md per the convention.
4. Execution order
- Mark answers §5 (or picks the recommendations).
cycle-manager: kick off c12 (CYCLE.md,CYCLES.mdentry). Commitc12: kick off (micro problems). Also commit or discard the pendingcall-classifications.jsonedit first — it is Mark's, not c12's. - T0 → review → freeze §2 shape.
- T1 (pilot on 2 calls) → T2 → T3 → T4. Re-extract the corpus under the new prompt at the end of T1 (
--force, 6 calls), not before. - Outcome + close; note follow-ups (MCP server, digest, per-problem map stage, silence-as-signal).
5. Decision queue (clarifying questions)
Unlocking decisions (gate T0/T1):
- Who forms the problems? ✅ Confirmed 2026-09-21: extraction does its best to identify candidate problems from each call (
candidateProblems[]); Mark and the agent then refine together and promote candidates to full problems inproblems.json— problems that are addressable and solvable by the product. Extraction tagsproblemIdonly against promoted problems. - Problem ↔ use case. ✅ Confirmed 2026-09-21: decomposition — a problem lists the use cases it belongs to (many-to-many, optional), use cases roll problems up, and a problem with no use case is a signal that the registry is missing a hypothesis. Distinctions to hold: problems are demand-side (the user's wicked problem decomposed), use cases are supply-side (our capability hypotheses); the link is where demand meets hypothesis. The registry holds the problem, never the solution —
surfaces[]is the one deliberately solution-shaped field (where it would be answered). Granularity rule of thumb: a micro problem is answerable by one surface's data + affordances in one sitting; if it needs several, it is a use case or a story. Standing (evidence, computed) and status (lifecycle, human) are separate axes. - Statement form. ✅ Confirmed 2026-09-21: both, as two fields.
statementis the pain form and is canonical (title, id, story voice);questionis the product-facing mirror ("Who has the sensor installed, and who doesn't?") and is required at promotion — the addressability test./problemsshows the pain as the row title with the question beneath; briefs use the question in Goal / Success Criteria and the pain in Evidence; stories use the pain. feedback.json. ✅ Confirmed 2026-09-21: retire it; product-feedback observations keep their types and severity, lifecycle lives on the problem. This is a design tool first (market analysis is a critical part); no formal bug integration at this stage. Bugs and deployment blockers surfaced in calls are listed on the site as not tracked here; a rudimentary ship-off (Linear / Slack / GitHub) is shelved as a follow-up until a formal tracker exists.
Canon/detail decisions (can be made during work):
- Document intake now or later? Recommend: now, lean (T3) — it is what makes "source of truth" true, and
inbox/already has material. - Phase-1 Cam calls. ⏸ Deferred by Mark 2026-09-21 — "not at this time"; take up later. The case, for when it comes back:
- For reconnecting: Cam's nine Cisco calls are the only usage-based, first-hand, build-partner, agent-era evidence anyone has;
unreviewed-mcp-surface(P15) goes from the thinnest promoted problem to the best-evidenced, andunknown-agent-fleet(P1) gains a second build-partner voice; the Cam brief's Source block becomes machine-checkable instead of hand-assigned; cost is nine calls on the Batches API, well under a dollar, and alegacy: trueflag keeps market KPIs and the use-case gate clean by default. - Against, for now: it blurs the deliberate phase-2 restart (Aug 2026) and the archive's "frozen at
phase-1-final" promise; the calls predate the pivot's vocabulary, so extraction would be reading old conversations through new categories (category squeeze risk); Cam's prototype reactions are about his dashboard, not a shipped Qpoint surface, so some "usage-based" would need hand-review; it adds a flag every consumer must remember to respect; and six phase-2 calls already produce four recurring problems — the registry is not starved yet. - Middle path if wanted later: re-extract only the three or four Cam calls the brief cites most (Feb 24, Mar 23, Mar 30) rather than all nine.
- For reconnecting: Cam's nine Cisco calls are the only usage-based, first-hand, build-partner, agent-era evidence anyone has;
- Stories. Recommend: a brief kind (
kind: story), same directory and index,## Narrativesection. Alternative: a separatestories/artifact with its own index. - Personas. ✅ Confirmed 2026-09-21 ("let's try it out, we may shift"):
data/personas.jsonhere, seeded from c55 + P12 end user/developer; a person may map to two personas. Surfaces (23 page families) likewise — try, then shift as they get used. 9a. T1 pilot result (2026-09-21): see CYCLE.md — both calls PASSED; tags,challenges, session tags,artifactRef(9 on the Sep 3 call), surfaces, and candidates all exercised; cache held (14,128 read on call 2). Re-extracting a call invalidates its curated ref indices — the two pilot calls now rely on tags;curatedAgainstwarns for the rest. - Language capture. Recommend: yes, as a small optional
language[]block. Cheap; skip if it feels like scope creep. - Shown-artifacts at triage. Recommend: yes — the same "declare, don't infer" concession c11 made; Enter = none keeps it free when nothing was shown.
- Dashboard re-shaping. Recommend: problems first row, sales KPIs second — design reader first. Alternative: a separate
/problemsentry point and the dashboard unchanged.
T0 review decisions (Mark, 2026-09-21)
- The 15 promoted problems stand as drafted. Merges considered (sensor coverage ↔ fleet compliance state; personal accounts ↔ unsanctioned services) rejected: different questions.
- Advisor first-hand counts toward standing, labelled — advisors are first-class sources. Implemented in
schemas/problem-standing.ts(source type travels with the company; the site prints "Moto · CISO Advisory"). A person-levelorgon theknown-entities.jsonsource override keys an advisor's company-less calls to one organization. - Registry changes:
governance-evidence-reportingandsession-record-governanceadded touse-cases.json;account-identity-controladded as the rewrite ofgateway-bypass-detection, which is parked with a note. - Variant evidence does not move standing. Found while wiring the index: three "adjacent" refs counted as recurring under the first rule.
variantitems are shown and counted separately; onlyhasitems from first-hand, non-internal sources qualify. Hand count and index now agree (4 recurring, 11 observed).
6. Risks
- Registry drift. Problems can proliferate into a backlog. Mitigation: standing is computed;
candidatewith no first-hand evidence after N calls is visibly stale;retiredneeds a reason. - Double-tagging load on extraction.
problemIdon top ofuseCaseIdand category. Mitigation:problemIdis optional and only for registered problems; candidates are a separate block; pilot on two calls before the corpus re-extract. - Surface vocabulary goes stale as design's pages move (c92 renamed
/teams→/teams-users-devicesin a week). Mitigation: keep surfaces coarse (page families, not routes); hand-sync note invocabularies.ts. - Legacy reconnect blurs the phase-2 restart. Mitigation:
legacyflag, excluded by default from market KPIs and the gate. - Consumers scan is heuristic (grep for ids and filenames). Mitigation: it only advances to
briefed/in-design;shippedstays manual with a date. - Static prompt grows (registry + personas + surfaces). Mitigation: all static, cached; measure
cache_read_input_tokensin the T1 pilot.
7. Verification
npx tsc --noEmitclean (root + site).- T0:
problems-draft.mdreviewed; every problem cites ≥1 observation by call id and perspective. - T1 pilot: Tiled re-extract tags ≥3 registered problems first-hand; Mark P Aug 31 tags problems with perspective
first-handfor his own experience andrelayedfor CISO-board claims;artifactRefonly appears whereshownwas declared; cache read >0 on call 2. - T2:
/problemsrenders standing + counts identical todata/problems-index.json; dashboard first row is problem KPIs. - T3:
inbox/chat-from-cam.mdingests asbuild-partner × document, all observationsfirst-hand/relayed(never usage-based unless the doc says they ran it); legacy Cam calls (if Q6) appear withlegacy: true, excluded from Avg Interest, included in problem standing. - T4:
npm run consumersfinds bob-wire c21 and design c78/c81/c92 forcam-dashboard-directives.md/ the c21 brief; one story brief exists with a Source block;goals.mdhas two lenses; designCLAUDE.mdSister Projects re-framed.