Repository explainer · andygsu/The-Medtech-Flywheel

The Medtech Flywheel

An agent pipeline that sources, scores and verifies medtech spin-out ideas — designed so that no machine-generated claim can ever reach a score, a shortlist, or a cheque without an independent check against a primary source, and so that the decisions that spend money or touch patients stay human.

Nine stages · three trust tiers · six agents · eleven typed connectors · one non-negotiable rule

The one rule that matters

No claim reaches a score without a Verifier pass, and no Verifier pass shares context with the Scorer that drafted the claim.

Every other convention in the repo exists to protect that sentence. The failure mode it is built against is specific and well documented: an agent chain where each step trusts the previous step's claim without re-checking it, drifting into fabricated predicate devices, invented CPT codes and phantom patents — each one fluent, plausible, and wrong.

What this actually is

Medtech idea evaluation is mostly a research problem: is there a regulatory pathway, does a billing code exist, does anyone pay enough for it, is the mechanism already patented, how big is the market really. Those questions are slow, and a language model will answer all of them instantly and confidently whether or not it knows. That is the whole problem this repository is organised around.

So the pipeline splits the work by how much it costs to be wrong. Generating ideas and drafting a first-pass score is cheap to get wrong — run it unattended, all day. Deciding that a predicate device exists is expensive to get wrong — that goes through a structurally separate agent that must produce an API record ID, not a paragraph. Deciding to spend money, sign an FTO opinion, or start an animal study is catastrophic to get wrong — no agent has a code path to it at all.

The result is a flywheel rather than a pipeline: outcomes feed back into the scoring model, killed ideas feed back into generation, and changed facts in the outside world wake dormant candidates back up.

0–8Pipeline stages
3Trust tiers
6Agents
9Rubric factors
11Typed connectors
19Gates & guards
THE KNOWLEDGE BASE rubric · candidates killed ideas calibration log signal log STAGE 0Signal scan STAGE 1Generate STAGE 2First-pass score STAGE 3VERIFY STAGE 4Verified re-score STAGE 5Hard gate check STAGE 6Human shortlist STAGE 7Diligence STAGE 8Log outcome outcomes recalibrate the rubric Every stage reads from and writes to the same knowledge base on disk. That shared state, not conversation between agents, is how work is handed from one stage to the next.
Figure 1 · The loop. Stage 3 (amber) is the mandatory verification gate; Stage 6 (plum) is the human-only judgment layer where the autonomous run stops. The green closing arc is what makes this a flywheel: what actually happened to an idea is what recalibrates the model that scored it.

Three trust tiers

The tiers are not a description of how careful each agent tries to be. They are a description of what each one is able to do. Phase 2 of the spec made that explicit: a convention an agent's prompt could violate under a bad escalation, a confused context, or a prompt injection from a scraped page is not a boundary — it has to be a capability limit.

TIER 1 · GENERATE & MONITOR Fully autonomous, 24/7 Scout · Generator · Scorer · Librarian Cheap to be wrong here: a bad idea costs tokens and a wasted verification pass. MAY WRITE signal log · candidate files scores · killed-idea log calibration log human_review_queue NEVER TOUCHES claim confidence tags human_decisions rubric.md (unapproved) a candidate's approval status TIER 2 · VERIFY Autonomous, structurally mandatory Verifier — adversarial by construction Reads the candidate file cold off disk in a fresh context. Never sees the Scorer's reasoning. MAY WRITE claim confidence tags primary-source citations stage: verified findings summary NEVER TOUCHES any factor score the composite the gate-check result a generic web search CAPABILITY BOUNDARY — ENFORCED IN CODE, NOT IN PROSE No agent process holds a write path across this line. Not the Verifier, not the orchestrating session, not claude -p. TIER 3 · JUDGE & COMMIT Human-only, always Shortlist review · FTO legal sign-off Animal-study approval · clinical review Capital allocation · rubric changes WRITE PATH scripts/human_decision.py run by a person, in their own terminal, interactively — the only writer of human_decisions HOW IT IS HELD settings.json denies Bash access to that script script exits on non-TTY stdin typed confirmation phrase
Figure 2 · The tier map. Read it as a permissions table, not a seniority chart. The interesting column is the right-hand one: what each tier is prevented from doing is what makes the tier below it trustworthy.

The residual gap, stated plainly. SQLite has no real per-table permissions, so a raw sqlite3 db/flywheel.db "INSERT INTO human_decisions ..." from any shell with file access still bypasses the CLI. The repo says so in scripts/human_decision.py rather than pretending otherwise; blocking it generically would also block legitimate read-only debugging. Moving to a real database server is where GRANT-level enforcement would replace the application-layer boundary.

The pipeline, end to end

This is the whole system in one picture. The centre column is the path an idea takes; the left column is what gets written to disk at each step (agents hand work to each other through files, never through conversation); the right column is where ideas leave the path, and the two feedback lanes that bring information back.

WRITESsignals/log.md WRITEScandidates/idea-XXX.md WRITESScores + gap analysis WRITESClaims: tags + sources WRITESVerified Composite WRITESGate Check result READS FROMhuman_review_queue WRITESDiligence Package HUMAN WRITEShuman_decisions WRITEScalibration-log.md STAGE 0 · TIER 1 · SCOUT Continuous signal scan FDA clearances · patents · CMS codes · rivals · literature STAGE 1 · TIER 1 · GENERATOR Produce tagged candidates Reads the rubric and the killed-idea log first Every claim it writes starts tagged unverified STAGE 2 · TIER 1 · SCORER (FIRST PASS) Draft score, for triage only Names, per factor, the source that would settle it No number here is meant to be acted on GATE A — Worth the cost of a Verifier pass? Judgment call; skipped candidates must be named STAGE 3 · TIER 2 · VERIFIER — MANDATORY Check every claim against a primary source Fresh context; reads the file cold; never sees the score A typed connector call per claim — never a web search Sets verified / unconfirmed / refuted, with a record ID STAGE 4 · TIER 1 · SCORER (RE-SCORE) Composite from verified claims only Refuted claims count against the factor, not blank Reports factors verified n/9 and core factors n/4 GATE B — At least 6 of 9 factors verified? Missing evidence is never treated as bad evidence STAGE 5 · TIER 1 · HARD GATE CHECK Apply the kill conditions Verified data only — never the Stage 2 draft numbers Reimbursement and TAM caveats checked before trusting GATE C — Did any kill condition fire? Regulatory+reimbursement floor · TAM floor · FTO blocked STAGE 6 · TIER 3 · HUMAN SHORTLIST REVIEW People decide, on a fixed cadence /shortlist compiles a source-linked packet; it never ranks candidates by preference or recommends one GATE D — Human decision: approve / reject / defer Recorded only by a person, in their own terminal STAGE 7 · TIER 1+2 · DILIGENCE LEAD Deep package — drafts, never approvals Bench evidence · failure modes · draft FTO memo for counsel Any new load-bearing claim goes back through the Verifier TIER 3 · SIGN-OFF Legal · clinical · animal study · capital The pipeline produces the packet for this decision and has no code path that can make it STAGE 8 · TIER 1 · LIBRARIAN Log what actually happened Predicted vs actual, precisely enough to cite later Records the gap; never edits the rubric off its own bat PARKED Not verified this cycle QUEUED-RESEARCH Not a kill — we simply do not know yet GATED OUT Logged in killed-ideas.md with a revive condition REJECTED BY HUMANS Reason logged verbatim yes yes no no yes reject back for another Verifier pass dead shapes are never re-proposed cleared approved outcome → calibration log → rubric proposal → a better next cycle TIER 3 BOUNDARY — THE AUTONOMOUS CYCLE STOPS HERE Below this line every advance requires a recorded human decision first.
Figure 3 · The full pipeline. Four gates (A–D), two exits (parked, gated out), one holding pattern (queued-research) and two feedback lanes. Note what the right-hand lane does: a killed idea does not disappear, it becomes an input to generation, carrying the condition under which it should come back.

The six agents

Each agent is defined by a file in .claude/agents/ that states its job, its tool list, and — at least as importantly — a What you never do section. The tool lists are the real separation: the Scorer has no network access at all, so it physically cannot verify its own claims; the Verifier has no Write tool for scores, only Edit on claim lines.

AgentTierStageJobStructurally cannot
Scout10 Watch for facts that changed — new clearances, patent expirations, code and payer-policy changes, rival activity, literature Score, generate, or set a confidence tag. A promising find is logged as a “possible verification lead”, nothing more
Generator11 Write new candidate files with device class, target, mechanism, predicate, intended use and jurisdiction Verify its own claims, score them, or re-propose a shape already in the killed-idea log without a signal that fired its revive condition
Scorer12 & 4 Apply the 9-factor rubric — once on unverified claims for triage, once on verified claims for a real composite Change a confidence tag, treat unconfirmed as true, or fill in the gate check
Verifier23 Check every claim against a typed primary-source connector and record the result with a record ID Touch any score, run in the Scorer's context, soften a refuted finding, or answer a claim with a web search
Librarian10, 5, 6, 8 Bookkeeping: killed-idea log, calibration log, flagging candidates for re-scoring, applying approved rubric changes Decide anything. It executes decisions that already exist and never edits Claims, Scores or a composite
Diligence Lead1+27 Per-candidate deep package: bench evidence, failure modes, draft FTO memo, reimbursement strategy Approve spend, greenlight an animal study, or state that FTO is “clear”. Every deliverable is explicitly a draft for sign-off

Why the Scorer and Verifier must not meet. If the Verifier can see the reasoning that produced a claim, it stops being an independent check and becomes a reviewer of an argument — and arguments are exactly what a language model is good at accepting. The repo enforces the split three ways: the Verifier runs as a fresh subagent invocation, it reads the candidate file cold off disk, and only the specific claim text — never the Scorer's trace — is in its context.

Stage by stage

Stage 0 — Signal scanning

Tier 1 Scout · /scan · runs continuously

Watches the outside world for facts that should re-open a question already in the knowledge base. It is pointed at what is already logged: unresolved claims first, then the explicit “revive condition” attached to every killed idea.

Readscandidate files, killed-ideas.md
Writesknowledge-base/signals/log.md
RuleIf nothing changed, write nothing — never manufacture a signal to have something to report

Stage 1 — Generation

Tier 1 Generator · /generate [n] [theme]

Produces candidates from the template, primed with the current rubric (so it knows what a strong idea needs) and the killed-idea log (so it stops re-proposing dead shapes).

Stage 2 — First-pass scoring

Tier 1 Scorer · /score idea-XXX

A triage pass whose only purpose is deciding whether a candidate is worth the cost of verification. Every number rests on an unverified claim and none of them is meant to be acted on.

The valuable output is not the score — it is the “What would settle it” column: for each factor, the specific primary source that would turn a guess into evidence. It costs nothing to fill in during scoring, it is what the Verifier works from, and it is what turns an unresolved factor into a work item instead of a permanent shrug. “More research” is not an allowed answer; a named source is.

Stage 3 — Verification the mandatory gate

Tier 2 Verifier · /verify idea-XXX · fresh context, always

Every unverified claim is routed to a typed connector and comes back with a status and a source reference — an API endpoint plus record ID, not a search URL. See the deep dive below for the routing rules and the two guards that run before any lookup.

VerifiedPrimary source directly confirms it. Citation attached
UnconfirmedSource queried, no clear answer — not evidence in either direction
RefutedPrimary source contradicts it. Stronger than unconfirmed, and may invalidate a premise

Stage 4 — Verified re-scoring

Tier 1 Scorer · /rescore idea-XXX

The composite is recomputed over verified claims only. A factor with no verified claim is left blank — not zeroed, not guessed, not carried over from the Stage 2 draft. A refuted claim is active negative evidence and pulls its factor down.

Two counts are reported alongside the score: factors verified n/9, which governs whether the candidate advances, and core factors verified n/4 (Regulatory, Reimbursement, TAM, FTO/IP), which is a diagnostic that gates nothing — it exists because a candidate with all four gate-relevant factors resolved is in a very different position from one with the same total spread across factors the gate never reads.

Stage 5 — Hard gate check

Tier 1 · /gate-check idea-XXX · mechanical, no subagent

The kill conditions, applied to verified data only. If a Verified Composite is not present, the stage refuses to run rather than falling back on Stage 2 numbers.

Stage 6 — Human shortlist review Tier 3

Humans · /shortlist compiles, it does not judge

The autonomous cycle stops here, permanently and by design. /shortlist assembles a packet: one paragraph per cleared candidate, with intended use, jurisdiction, composite, verified counts, the claims behind the best and worst factors, and the gap analysis verbatim. It ranks by composite score and explicitly does not recommend.

Two things are flagged because they look like strength and are not: a non-US launch jurisdiction, whose claims are unconfirmed for want of a connector rather than for want of an answer, and a Reimbursement factor resting on code existence alone.

Stage 7 — Spin-out diligence

Tier 1+Tier 2 Diligence Lead · /diligence idea-XXX · requires status: shortlisted

Stage 8 — Outcome logging

Tier 1 Librarian · /log-outcome idea-XXX "..."

Whatever happened — killed, funded, piloted, and why — is written back. Where the real approval timeline, real cost or real sales cycle diverges from what the model predicted, that gap is the entire input to recalibrating the rubric. The Librarian records the gap precisely and does not editorialise about which factor was “wrong”: a rubric change has to cite the row, and the row has to be worth citing.

Inside the verification gate

Stage 3 is where this repository differs from “an agent that researches ideas”. The requirement is not that the Verifier looks things up carefully — it is that “checks the FDA database” means a typed API call with a parseable response, not a search query summarised by a model. A summarised search result is not a verified claim; it is an opinion about a search result.

Two guards run before any lookup happens at all. Both exist because of specific ways a check can come back confidently wrong.

INPUT One claim line still tagged unverified GUARD 1 — Does the claim carry jurisdiction: ? An untagged claim is an underspecified one GUARD 2 — Is that jurisdiction US? Every source in this repo is a US government database GUARD 3 — Regulatory claim: is intended use stated? Class follows from the device plus its claimed indication PROCEED Route to the typed connector for this claim type One call, one parseable status, one record ID STAYS UNVERIFIED Flag the omission in the findings; do not assume US to unblock yourself UNCONFIRMED The refusal lives in code, not in a prompt: connectors/jurisdiction.py STAYS UNVERIFIED Never infer an intended use from the mechanism or the title yes yes yes no no no
Figure 4 · Pre-flight guards. Guard 2 is the sharpest one. A claim reading “CE marking under MDR Class IIa is achievable”, routed to openFDA without a jurisdiction flag, will happily match a real US 510(k) record — and the claim text says EU, the citation says FDA, and the confidence tag says verified. That is a fabricated verification, so the refusal is a function that returns unconfirmed rather than an instruction an agent could drift past.

Which connector answers which claim

Eleven subcommands, one per claim shape, so the Verifier never falls through to a web search by omission. Three of them can never return anything but unverifiable — and that is a feature, not a gap waiting to be filled.

CLAIM TYPE CONNECTOR CALL WHAT ACTUALLY ANSWERS IT POSSIBLE RESULTS REGULATORY 510k "device name" openFDA 510(k) — cleared predicates verified refuted unconfirmed denovo "device name" openFDA De Novo grants verified refuted unconfirmed classification --product-code openFDA classification — class I/II/III verified refuted unconfirmed REIMBURSE- MENT hcpcs A1234 CMS HCPCS file — does the code exist? verified refuted unconfirmed payment A1234 --min-expected CMS fee schedule — does it pay enough? verified refuted unconfirmed coverage A1234 Medicare NCD/LCD — does a policy exist? verified refuted unconfirmed TAM procedures A1234 --expect-volume CMS utilization — a floor, not a market verified refuted unconfirmed market "claim text" No free authoritative source exists. unverifiable IP / FTO patent US1234567B2 PatentsView — filing and grant dates verified refuted unconfirmed ADOPTION adoption "claim text" Needs primary research we do not have. unverifiable CPT cpt <anything> AMA-licensed — blocked in code. unverifiable
Figure 5 · The routing map. Every call is python3 -m connectors <subcommand>, printing one JSON object. A result carries a source_ref — an endpoint plus a record ID — whenever it is verified or refuted. The four CMS-backed connectors read locally cached files that a human supplies; when the file is absent the answer is unconfirmed with instructions, never a substituted web search.

Three connectors that always say “I cannot know that”

Market size. No free, authoritative, machine-queryable source will tell you the addressable market for a device. So market returns unverifiable permanently, and only a human attaching a licensed report and editing the tag by hand can change that. But before settling for it, the claim usually decomposes: a TAM claim is three claims wearing a trenchcoat — how often the procedure happens (which is checkable), what each one is worth, and what share is addressable. Verifying one of the three and leaving two unconfirmed is far more useful than one blanket shrug.

Adoption and stakeholder preference. “Surgeons would switch for a 20% time saving”, “payers would view this as cost-neutral”. A model asked this will produce a fluent, plausible, well-hedged answer, and that answer is a synthetic stakeholder opinion — a fabricated claim in better clothes, harder to spot than an invented patent number because nothing about it looks made up. Consulting firms answer these with fifty interviews and a hundred-respondent survey. The productive move is rescoping to the checkable proxy hiding inside: does a coverage policy exist for the comparator, and how often is the procedure actually done?

CPT codes. Blocked in code, for a licensing reason rather than an epistemic one. CPT is AMA-licensed and cannot be scraped or reproduced verbatim, so check_cpt_code refuses to return a verified or refuted result under any circumstance. A claim that depends on a CPT code either gets a licensed source attached by a human or gets rescoped to HCPCS.

The reimbursement trap, made mechanical

“Is there a reimbursement pathway” looks like one question and is three. The repo splits them because answering only the first and reporting it as a pathway is how a dead product gets a green badge.

QuestionCheckWhat a “yes” actually means
Can this be described on a claim form?hcpcs A1234A code exists. Nothing more. Not that anyone pays.
Does it pay enough to be a business?payment A1234 --min-expected 42.50The rate clears a stated cost basis. A code paying $8 for a $40 consumable is a kill condition wearing a green badge.
Has a payer actually agreed to cover it?coverage A1234An NCD or LCD exists naming the code — not that it is positive. Many LCDs are non-coverage or impose limits, and that difference lives in the policy prose.

Confidence tags

Four tags, and the whole design rests on them being respected. A claim that never got a Verifier pass stays unverified forever and never contributes to a composite, no matter how obviously true it looks. “Helpfully” upgrading a tag to move a candidate along is the single most damaging thing an agent in this repo could do, because everything downstream reads the tag rather than re-deriving the fact.

never — no agent upgrades a tag to help a candidate along START unverified what the Generator wrote TIER 2 Verifier pass one typed connector call COUNTS TOWARD THE SCORE verified Primary source confirms it, and the record ID is written into the claim line CONTRIBUTES NOTHING unconfirmed Checked, no clear answer. Not evidence in either direction — “we don't know yet” ACTIVE NEGATIVE EVIDENCE refuted A source contradicts it. May invalidate a premise, not just a data point a new signal, or a newly cached CMS file, sends it back for another pass only a human, by hand, attaching a licensed source
Figure 6 · Tag transitions. The distinction that does the most work is unconfirmed versus refuted. “We looked and could not confirm it” must never collapse into “the answer is no” — one queues more research, the other can kill an idea.

The rubric and the arithmetic

Nine factors, each scored 0–5 using only verified claims, weighted and scaled to 0–100. The rubric file is explicit that v1's weights are a provisional starting guess rather than a derived result — they are meant to change, but only when logged outcomes say they should.

#FactorWhat it measuresWeightVerification path
1Regulatory pathwayClass, predicate or De Novo availability, review burden15%connector openFDA
2Reimbursement pathwayCode exists, pays enough, and is covered15%connector CMS files
3TAMAddressable market from primary data, not aggregator blogs15%partial volume only
4FTO / IPBlocking patents, expiry timelines, workarounds15%connector PatentsView
5Moat / defensibilityWhat stops a fast-follower once the idea is public10%judgment no source
6Mechanism & clinical riskPlausibility; what bench or animal evidence must show10%judgment no source
7Capital intensity & time-to-revenueCost and calendar time to first dollar10%judgment no source
8Competitive intensityExisting players, funding, launches, recalls5%judgment no source
9Strategic fit & portfolio balanceHero bet versus cash-generative spoke5%judgment no source
VERIFIEDcounts, with its source UNCONFIRMEDcontributes nothing REFUTEDcounts against Factor score 0 – 5 no verified claim → left blank, not zero × weight 15 / 10 / 5 % COMPOSITE Σ (score ÷ 5 × weight) scaled to 0 – 100 over scored factors only THE THRESHOLD — GOVERNS EVERYTHING Factors verified: n / 9 Fewer than 6 → queued-research, never a kill 6 or more → on to the Stage 5 gate check THE DIAGNOSTIC — GATES NOTHING Core factors verified: n / 4 Regulatory · Reimbursement · TAM · FTO — the only four the kill conditions ever read Reported alongside the composite, so an idea never looks more solid than its evidence.
Figure 7 · The arithmetic. The second counter is a deliberate piece of restraint: a candidate at 4/4 on the gate-relevant factors but 5/9 overall is still queued-research. Whether the core count should replace the 6/9 threshold is a rubric question, and rubric questions are decided by humans, not by the agent that would benefit from the change.

The gates

“Gate” here means something narrower than “step”: a point where a candidate, a claim, or a decision is tested and can be stopped. Some are decisions in a prompt; the important ones are functions that return a refusal. Below is the Stage 5 hard gate drawn out, then a catalogue of every gate and guard in the system.

INPUT A candidate that has been through a Verifier pass Is a Verified Composite present? Stage 2 draft numbers are never a fallback Are at least 6 of 9 factors verified? Missing evidence is not adverse evidence KILL 1 — Is FTO blocked? A live, enforceable patent covers it with no workaround KILL 2 — Is TAM below the 2/5 floor? Only if TAM is genuinely resolved — see the caveat below KILL 3 — Regulatory AND reimbursement both below 2/5? Both, not either — one weak leg is survivable CLEARED Queued for human shortlist review The candidate does not advance — a person picks it up STOP AND SAY SO Gate-checking on unverified data is the failure, not a shortcut QUEUED-RESEARCH Distinct from a kill, and tracked separately. Never conflate them KILL — AUTOMATIC Regardless of every other score, however strong KILL Logged with the verified facts that drove it, plus a revive condition KILL The Generator reads this log and will not re-propose the shape yes yes no no no no no yes yes yes TWO THINGS TO CHECK BEFORE TRUSTING A FACTOR SCORE AT THIS GATE Reimbursement may have been scored on a code-existence check alone. If the verified claims cover hcpcs but not payment or coverage, the factor means “a code exists”, not “the device gets paid for” — say so rather than letting it pass as a pathway. TAM may rest on a Medicare procedure volume. That is a floor on US volume, not a market size — the TAM floor must not be applied as if resolved.
Figure 8 · Stage 5, drawn out. Note the asymmetry: three ways to die, one way to clear, and “cleared” only means “a human should now look at this”. The gate has no path that advances a candidate toward money.

Every gate and guard, in one table

#GateFires whenOutcomeWhat it prevents
1Verification triage Stage 2→3A candidate would fail a floor even on generous unverified claimsParked, and named in the cycle reportSpending verification effort on ideas already dead on their own optimistic numbers
2Jurisdiction tag present Stage 3A claim carries no jurisdiction: fieldStays unverified; omission flaggedSilently defaulting an unstated claim to US
3Jurisdiction supported codeA claim is about the EU, UK or anywhere non-USunconfirmed, with the reason recordedCiting a real US 510(k) record as evidence for an EU pathway claim
4Intended use stated Stage 3intended_use: is blank and a regulatory claim is being checkedRegulatory claims stay unverified; Factor 1 unscored“Verifying” a device class in the abstract, which is meaningless rather than merely weak
5Typed connector only Stage 3Any claim checkA parseable status plus a record ID, or an explicit “no connector for this”A summarised web search being recorded as a primary-source check
6CPT hard block codeAny CPT lookup, alwaysunverifiable, unconditionallyScraping or reproducing AMA-licensed code descriptions
7Structurally unverifiable codeMarket-size or adoption/preference claims, alwaysunverifiable → treated as permanently unconfirmedA model's plausible guess about market size or clinician behaviour entering the record as evidence
8Missing cached file codeA CMS data file the connector needs is not in data/unconfirmed, naming the file and its sourceSubstituting a web search or a hand-typed table for a primary dataset
9Only verified claims score Stage 4Composite computationUnverified and unconfirmed claims contribute nothing; factors go blankAn idea looking more solid than its evidence
106-of-9 threshold Stage 4/5Fewer than six factors carry a verified claimqueued-research — explicitly not a killConflating “we don't know yet” with “the answer is no”
11FTO blocked Stage 5A live, enforceable patent covers the mechanism with no workaroundAutomatic kill, regardless of all other scoresBuilding on ground somebody else owns
12TAM floor Stage 5TAM scores below 2/5 on verified dataKill, logged with a revive conditionPursuing a real device into a market too small to matter
13Regulatory + reimbursement floor Stage 5Both score below 2/5KillA product that is both hard to clear and impossible to get paid for
14Tier 3 boundary Stage 6A candidate clears the gate check/flywheel-cycle stops; a packet is compiled, not a recommendationAn autonomous run walking a candidate into a shortlist, a budget or a study
15Human decision write path codeAnything tries to record an approvalOnly scripts/human_decision.py writes it — non-interactive stdin refused, confirmation phrase typed, Bash access denied in settingsAny agent code path reaching a Tier 3 outcome
16Two-queue separation schemaRouting a question upwardescalation_queue for model-to-model synthesis; human_review_queue for anything a person must decideA Tier 3 judgment being quietly answered as a Tier 1/2 one “for a second opinion”
17Rubric edit convention + queueAnyone wants to change a weight, floor or factorWritten proposal → queue → human decision → Librarian applies it citing a calibration rowAn agent tuning the scoring function that judges its own output
18Diligence precondition Stage 7/diligence is run on a candidateRefuses unless status: shortlisted — i.e. a human already said yesDeep work, and its implicit momentum, being spent ahead of the human decision
19Append-only history Stage 8Any edit to the killed-idea or calibration logsAppend; a revived idea gets a new linked entry, never an erased oneLosing the record of what was believed and when — the only thing calibration can be computed from

The human boundary

Two queues, deliberately not one. Conflating them is the exact failure the split exists to prevent: an escalation queue's worst case is wasted tokens and a hypothesis to redo, while a human review queue's worst case is a real capital, legal or clinical decision made by something that cannot be held responsible for it.

TIER 1 & TIER 2 Agents Scout · Generator · Scorer · Verifier · Librarian · Diligence QUEUE 1 escalation_queue local models → Claude GATED, CAPPED A synthesis pass Worst case: wasted tokens QUEUE 2 human_review_queue any tier may add to it — no tier may resolve it TIER 3 · A PERSON, NOT A PROCESS scripts/human_decision.py Exits on non-interactive stdin · requires a typed confirmation phrase · run in own terminal THE ONLY PLACE AN APPROVAL EXISTS human_decisions answer returns to the agent that asked TIER 3 BOUNDARY no agent holds this path: not in any tool list, denied in settings.json
Figure 9 · Two queues. An idea that clears Stage 5 goes to human_review_queue and never through escalation_queue — no code path routes a Stage 6 item through a model first “for a second opinion”, because that would quietly convert a Tier 3 judgment into a Tier 1 one.

Changing the rubric is itself a Tier 3 decision

The rubric decides what gets killed and what gets funded, which makes editing it adjacent to allocating capital. So it follows the same propose-then-approve path — and the standard for approval is a citation, not an argument.

EVIDENCE calibration-log.md predicted vs actual outcomes PATTERN A systematic gap not one wrong prediction ARGUMENT A written proposal rubric-proposals/*.md QUEUED, NOT APPROVED queue_rubric_ proposal.py Human decision — approved / rejected / deferred Does the proposal cite a calibration row? APPROVED The Librarian edits rubric.md and adds a changelog entry citing the calibration row. A normal git commit — versioned like code. DEFERRED OR REJECTED The rubric does not change. The argument stays on file, intact, for when the evidence it needs finally exists. approved not yet
Figure 10 · The rubric loop. Five proposals currently sit in knowledge-base/rubric-proposals/ and the calibration log has no rows in it, because no candidate has been through Stage 8 yet. The repo's own reading: deferred is a well-founded answer to every one of them — the log's emptiness is information, not an obstacle to route around.

The known structural limit

The most useful thing this repository does is state, in its own README, the reason it cannot currently finish a lap. Only three of the nine factors have any verification path at all. The other six are not under-resourced — five of them are judgments rather than facts, and no database anywhere will resolve them.

THE NINE FACTORS, BY WHETHER ANY SOURCE CAN SETTLE THEM 1RegulatoryopenFDA 2Reimburse-ment · CMS 3TAMvolume only 4FTO / IPPatentsView 5Moatjudgment 6Mechanismjudgment 7Capitaljudgment 8Competitivejudgment 9Strategic fitjudgment CEILING TODAY: 3 OF 9 6 of 9 — the threshold to leave queued-research Anything short of it parks at queued-research, forever WHAT THIS MEANS IN PRACTICE No candidate can reach “cleared” on its own, so the Stage 6 human review never receives a packet. It is not sealed — a human can attach a licensed source and edit a tag by hand — but there is no autonomous path to a shortlist. WHY IT IS NOT FIXED BY LOWERING THE BAR Approving the pending TAM and coverage proposals raises the ceiling but does not reach six. Factors 5–9 have no primary source anyone could query. The core-factor count exists to gather evidence for which end to change.
Figure 11 · The ceiling. A pipeline that reports “no candidate cleared” because it genuinely cannot verify enough is behaving correctly. The tempting fix — relax the threshold so something gets through — would convert an honest blockage into a stream of under-evidenced shortlists, which is precisely the outcome the whole design exists to avoid.

The Core factors verified: n/4 readout is the instrumentation for deciding this properly: it distinguishes “we know nothing about this candidate” from “we know everything the kill conditions actually read, and nothing else”. Whether that should replace the 6/9 rule is written up in knowledge-base/rubric-proposals/2026-08-21-core-factor-threshold.md and parked for a human.

The candidate file is the shared state

Agents do not pass results to each other through conversation. They read and write the same markdown file on disk, in sequence, across separate invocations. That is what makes the Verifier/Scorer separation real rather than a naming convention — and it means the file itself is the audit trail: who claimed what, who checked it, against which record, and on what date.

SECTION OF THE CANDIDATE FILE WRITTEN BY CONSTRAINT Frontmatter id · device class · target · mechanism · predicate GENERATOR stage / status also flipped by the Librarian intended_use · launch_jurisdiction required; Factor 1 is unscorable without it GENERATOR no one may infer one later to unblock a check Claims one line per factual assertion, each with a tag GENERATOR → VERIFIER Scorer, Scout and Librarian never touch a tag Scores (Stage 2) draft numbers + “what would settle it” gap analysis SCORER Verifier never reads or writes these Verified Composite (Stage 4) composite, factors verified n/9, core n/4 SCORER Librarian and Verifier stay out Gate Check (Stage 5) which kill condition fired, or cleared THE gate-check STEP Scorer and Verifier never fill this in Human Review Notes (Stage 6) strategic fit, portfolio balance, the actual call HUMANS ONLY no agent writes a line here, ever Diligence Package (Stage 7) bench evidence · failure modes · draft FTO · reimbursement DILIGENCE LEAD new claims route back to the Verifier Outcome (Stage 8) what happened, and why — feeds the calibration log LIBRARIAN never an approval status set by an agent
Figure 12 · Section ownership. Six agents write to one file and none of them may write to another's section. The Scorer and the Verifier both edit the same file and still cannot influence each other, because they touch disjoint parts of it in separate contexts.

What a claim line looks like

StageThe same claim, as it evolves
Stage 1- [ ] A 510(k)-cleared hydrocolloid dressing predicate exists — jurisdiction: US — confidence: unverified — source: Generator's best guess
Stage 3- [x] A 510(k)-cleared hydrocolloid dressing predicate exists — jurisdiction: US — confidence: verified — source: api.fda.gov/device/510k · K123456 (fda.check_predicate_510k) — matched on device_name, decision date on record
Stage 4Factor 1 may now carry a score. Until that middle line existed, it could not.

A worked example

From the spec, and worth reading because it shows the pipeline producing a modest, useful answer rather than a heroic one.

StageWhat happens
0 · ScoutNo new signal needed; the existing rubric applies.
1 · Generator“Hydrocolloid wound dressing, repackaged for canine/feline post-surgical use, sourced from an expired-patent human product.”
2 · ScorerRegulatory 5/5 (veterinary device, no premarket review), moat 2/5 (commodity). Flags “patent expired” as unconfirmed.
3 · VerifierChecks the specific product's patent family — confirms expiry, upgrades the claim. Confirms no antimicrobial or drug component, so it stays device-class rather than drug-class.
4 · Re-scoreComposite lands in the high 60s. Clears the gates; low moat.
6 · HumansFlagged as a “cash-generative spoke, not a hero bet” — approved at low priority and low budget.
7 · DiligenceSourcing agreements and fur-adhesive reformulation logged as the one available moat lever.
8 · OutcomeBecomes the template for “expired-patent human device + veterinary repackage” — future Generator runs can propose variants of the pattern faster, and the Scorer can pre-fill confidence on similar claims.

That last row is the flywheel doing its actual job: the value is not the dressing, it is that the next twenty ideas of this shape cost a fraction as much to evaluate.

Running it

Every pipeline stage is a slash command in a Claude Code session opened on the repo. They map 1:1 to stages, so a stage can be run or debugged on its own.

CommandStageWhat it does
/flywheel-cycle [theme]0–5One full autonomous cycle: scan, generate, score, verify, re-score, gate-check. Stops hard at Stage 6.
/scan0Scout pass; then routes any signals through the Librarian to flag affected candidates
/generate [n] [theme]1New candidates, checked against the killed-idea log
/score idea-XXX2First-pass triage scoring
/verify idea-XXX3Verifier in a fresh context, connector per claim
/rescore idea-XXX4Composite from verified claims only
/gate-check idea-XXX5Kill conditions on verified data
/shortlist6Compiles the human review packet. Does not recommend
/diligence idea-XXX7Deep package — requires status: shortlisted
/log-outcome idea-XXX "…"8Records predicted vs actual into the calibration log

The connector and database layer

CommandPurpose
pip install -r requirements.txtOne dependency: requests
python3 init_db.pyCreates db/flywheel.db from db/schema.sql. Safe to re-run
python3 -m connectors 510k "device name"Any connector call; prints one JSON object with status, source_ref, detail
python3 -m pytest tests/33 tests, mostly asserting that guards refuse rather than answer
python3 scripts/queue_rubric_proposal.py listRubric proposals awaiting a human
python3 scripts/human_decision.py listhumans only Run in your own terminal — never through an agent
docker-compose up --buildSame image, runs init_db.py at build time

Every connector call exits 0 even when the lookup fails — a failed or unconfirmed result is a normal answer, not a CLI error, so callers read the status field rather than the exit code. Anything jurisdiction-specific takes --jurisdiction and defaults to US.

The data/ directory is deliberately empty in git. Four connectors read cached CMS releases from it; none are checked in, because a stale copy would look authoritative while answering last year's question. Until a file is there, its connector returns unconfirmed and says exactly what is missing. A fabricated cache file would be indistinguishable from a real one to every agent downstream, which makes it the single most dangerous thing anyone could put in that directory.

The data model

SQLite is the intended source of truth; the markdown files are the working surface agents actually use day to day. The two are not synced yet — that is stated as an open item rather than implied to be done.

TableHoldsWritten by
candidatesIdea, class, target, mechanism, intended use, jurisdiction, stage, status, compositeTier 1
claimsClaim text, type, jurisdiction, status, source_ref, who verified it, whenTier 2
killed_ideasKill reason and tags, so the Generator can be steered off the patternTier 1
calibration_logPredicted value, actual value, and what the gap impliesTier 1
escalation_queueTier 1/2 questions gated up to a synthesis pass. Never a route to a human decisionTier 1
human_review_queueAnything a person must decide, plus a detail pointer to the full argumentany tier
human_decisionsapproved / rejected / deferred, who decided, and their notehumans only
perspectives, insightsStage 7 diligence output, scoped per candidateTier 1

Repository map

PathWhat lives there
docs/spec.mdThe original architecture spec — stages, tiers, agent roster, worked example
docs/phase2-spec.mdAddendum: structural tier enforcement, typed connectors, the SQLite data model
docs/research/Competitive review of a commercially-sold medtech assessment, benchmarked against the rubric
CLAUDE.mdDay-to-day operating rules for anyone — human or agent — working in the repo
knowledge-base/rubric.mdThe live 9-factor rubric, weights, floors, changelog
knowledge-base/rubric-proposals/Written arguments for proposed changes, pending human decision
knowledge-base/killed-ideas.mdAppend-only: every gated idea and its revive condition
knowledge-base/calibration-log.mdAppend-only: predicted versus actual, the input to every rubric change
knowledge-base/signals/log.mdStage 0 output — what changed, and which candidates it affects
knowledge-base/candidates/One file per idea; _template.md is the format and carries the rules inline
.claude/agents/The six agent definitions, each with its tool list and its “never” section
.claude/commands/One slash command per stage, plus /flywheel-cycle
.claude/settings.jsonDenies Bash access to the human-decision script from any session
connectors/The typed lookups, the jurisdiction guard, the shared cache loader, the result type
db/, init_db.pySchema and migrations for the structural boundary
scripts/human_decision.py (human-only) and queue_rubric_proposal.py (agent-runnable)
tests/pytest suite, largely asserting that guards refuse

What the design refuses to do

Read together, the constraints have a shape. Almost every one of them makes the system slower and less impressive in exchange for making its output believable.

It refuses to…Because
Let a scoring agent verify its own claimA checker that has seen the argument is reviewing a case, not checking a fact
Accept a summarised search result as verificationThat is an opinion about a search result, not a primary source
Answer a non-US claim from a US databaseThe citation would be real, and about a different regulatory regime
Score a device class without a stated indicationClass is a property of the device plus its claimed use — the question is otherwise malformed
Treat “could not confirm” as “no”One queues research; the other kills an idea. Collapsing them destroys the difference between ignorance and evidence
Guess a market size or a clinician preferenceThe answer would be fluent, plausible, and fabricated — the hardest kind of error to catch
Report a reimbursement pathway from a code lookupA code that exists, pays $8, and has no coverage policy is a code, not a pathway
Let an agent record a human decisionNot because it would decide badly, but because nobody could be accountable for the decision afterwards
Let an agent tune the rubric that scores its workA model that can adjust its own grading function will, eventually, describe its own priors as findings
Lower its threshold to produce a shortlist“Nothing cleared” is a true answer. A stream of under-evidenced shortlists is a false one

The point of all of it

A pipeline like this is not trying to be right more often than a person. It is trying to be wrong in ways that are visible — every claim carrying a tag, every tag carrying a record ID, every gap named as a specific document somebody would have to go and get. An idea that arrives at a human with three verified factors, six honest blanks and a list of what each blank would cost to fill is worth more than a confident score with nothing underneath it.

Generated from the repository at andygsu/The-Medtech-Flywheel. Sources: docs/spec.md, docs/phase2-spec.md, CLAUDE.md, README.md, the six agent definitions, the ten slash commands, connectors/, db/schema.sql, scripts/ and the knowledge base.