Add /cpa:product-review command - #78
Conversation
Evaluates plugins from a product perspective across nine tenets: USCDI V3 clinical data model alignment, placement conventions, coded data capture (SNOMED/LOINC/RxNorm/ICD-10), use of native Canvas primitives over parallel systems, alert fatigue, configurability of clinical logic, audit/attribution, terminology consistency, and overlap with the §170.315 criteria Canvas is ONC-certified for. Writes a timestamped report to .cpa-workflow-artifacts/ and routes next steps via AskUserQuestion. Does not auto-fix USCDI or ONC findings — always confirms first, because they touch the designated record set and compliance posture. Wires the new command into the /cpa:security-review and /cpa:wrap-up workflow references so it appears in the standard chain. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Clarify that the §170.315(b)(11) CDS concern under Tenet 9 is about plugin-authored clinical guidance (hardcoded titration schedules, default thresholds, shipped code lists representing clinical opinions) — not about plugins that surface fields users populate with their own clinical content. Adds a "plugin-authored vs. plugin-surfaced" classification with flag / do-not-flag examples and a simple test: "if the plugin's shipped content/defaults were removed, does any clinical opinion remain?" Notes that moving defaults out of code (Tenet 6) often resolves the Tenet 9 concern as a side effect. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Expands the placement tenet to make two distinctions explicit:
1. provider_menu_item vs global — both live outside a patient chart, but
provider_menu_item is for settings-ish work (configuration, catalog
management, user preferences, admin actions) while global is for
panel-level clinical activities (worklists, rollups, population
dashboards). Quick test: does opening this UI show patient clinical
data as its primary content? yes → global; no → provider_menu_item.
2. Mixed-scope applications (one app doing two jobs):
- Patient-scoped apps with handlers that mutate non-patient state
(catalog/template/preference CRUD behind a chart button) — split
into a patient_specific action app and a provider_menu_item manager
app.
- Global-scoped apps whose every handler takes a patient_id and
operates on one patient — move to patient_specific, or surface the
one-patient drill-down as a distinct app linked from the panel.
Adds a "one app, one job" test: list each application's endpoints in
patient-specific vs. non-patient-specific columns; if both have entries,
the app should probably be split.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@andhines - would love your eyes on this from a product perspective - anything I missed? I ran it against a handful of plugins to confirm it aligns with my general thinking. It might be overly sensitive in areas - but figure its better to flag/have a conversation. |
|
Yes I'll take a deeper look today. I scanned briefly and noticed two
things. First thing is high level, shouldn't this be skill applied along
the way, not just a review command? Would be great to guide correct
decisions along the way not just invoke on review. Second, tactical thing,
it seems our data model is characterized as USCDI v3 but it's so so so so
so so much more than that and includes operational and financial stuff,
need to characterize that too.
…On Mon, Apr 20, 2026 at 3:04 PM Kristen ONeill ***@***.***> wrote:
*kristenoneill* left a comment (canvas-medical/coding-agents#78)
<#78?email_source=notifications&email_token=AATYZNLLBGRAW65RSFLFO5T4W2NGPA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTIMRYGQ2TOMZSGQZKM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJNLQOJPWG33NNVSW45C7N5YGK3S7MNWGSY3L#issuecomment-4284573242>
@andhines <https://github.com/andhines> - would love your eyes on this
from a product perspective - anything I missed? I ran it against a handful
of plugins to confirm it aligns with my general thinking. It might be
overly sensitive in areas - but figure its better to flag/have a
conversation.
—
Reply to this email directly, view it on GitHub
<#78?email_source=notifications&email_token=AATYZNLLBGRAW65RSFLFO5T4W2NGPA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTIMRYGQ2TOMZSGQZKM4TFMFZW63VHNVSW45DJN5XKKZLWMVXHJNLQOJPWG33NNVSW45C7N5YGK3S7MNWGSY3L#issuecomment-4284573242>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AATYZNKMXPQ62S7WZ4NZLB34W2NGPAVCNFSM6AAAAACX7746J6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHM2DEOBUGU3TGMRUGI>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
--
Andrew Hines
Founder, Canvas Medical
(415) 610-5175
220 Montgomery Street, Suite 991
San Francisco, CA 94104
--
Disclaimer: This e-mail and any attachments may contain confidential
information. If you are not the intended recipient, any disclosure,
copying, distribution or use of any information contained herein is
strictly prohibited. If you have received this transmission in error,
please immediately notify the Security Officer
***@***.***>, and destroy the original transmission
and any attachments without reading or saving.
|
Two updates based on feedback:
1. Add the product-review skill under canvas-plugin-assistant/skills/.
Mirrors the existing skill+command pattern (plugin-api-server-security,
custom-data-patterns, etc.): the skill contains the nine tenets as
coding-time rules that can be applied inline during plugin development;
the /cpa:product-review command remains the end-to-end workflow with
environment validation, report generation, and next-step routing.
Skill structure:
- SKILL.md — when to invoke, index of the nine tenets, relationship
to other skills and the command, do-not-auto-fix boundary
- product_review_context.txt — full tenet rules with detection
heuristics, flag criteria, and priority order for inline
application
2. Broaden Tenet 1 from "Clinical Data Model / USCDI V3" to
"Designated Record Set / Clinical Data Model". USCDI V3 is the
required subset; the DRS under HIPAA is broader and includes
billing/encounter records, care coordination communications,
authorizations/consents, utilization/case management, imported
external data once incorporated, and patient-generated health data
used for care decisions.
Tenet 1 now includes:
- The DRS test ("if it's used to make a decision about the patient,
it belongs in the DRS")
- The USCDI V3 table (existing, as the required subset)
- A broader DRS categories table (new — billing, care coordination,
authorizations, etc.)
- An explicit excluded table (psychotherapy notes, QA/peer review,
business planning, de-identified data, personal memory aids,
litigation holds)
- HIGH-priority flags for psychotherapy notes (escalate to
Compliance — not DRS, not a regular Note either) and for
parallel billing/claims paths
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
@andhines broadened to evaluate based on what is typically considered a part of the designated record set. When it asked me skill vs command - the examples of the skills it gave as a reference/to differentiate didn't seem like parallels - but makes sense. |
Distinguish between two concepts that were previously conflated: 1. Actor — who actually performed the action. Must be captured in Canvas's audit trail. For session-authenticated calls, the logged-in Staff; for API-key / service-account / webhook calls, the integration bot. Never silently attributed to a clinician who did not actually perform the action. 2. Routing / assignment — fields a caller supplies that name a clinician for business reasons (provider_id on a note, assignee on a task, prescriber_id on a carried-forward prescription). Legitimate for integrations to set — they tell Canvas "file this under Dr. X" but do not attest that Dr. X authored the content. The distinction determines severity: - NOT HIGH: API-key-authenticated endpoints that create or route records on behalf of a named clinician (bulk import, scheduling, CCM dashboards, task routing, unsigned note creation attributed to a provider), as long as the audit trail stamps the integration bot as the real actor. The customer is responsible for using such integrations only where real attestation is not required. - HIGH: API-key-authenticated endpoints that trigger attestation events as a named clinician — electronic signing, signing-adjacent commits (push_charges, commit where Canvas treats it as clinician certification), and shadow-override patterns where displayed data is edited via side-channel metadata while the underlying record stays untouched. - MEDIUM: CustomModel writes that capture no actor at all, missing Canvas-side audit for high-impact operations, API-key on PHI-bearing endpoints without a bot-stamped audit entry. Golden patterns documented for both clinician-driven and integration-driven flows. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Evaluation: ran the new tenets against 10 plugins in
|
| Plugin purpose | Scope | UX surface |
|---|---|---|
| Provider mobile launcher (no patient/note context) | provider_companion_global |
Provider companion home |
| Provider mobile patient view | provider_companion_patient_specific |
Companion patient page |
| Provider mobile note view | provider_companion_note_specific |
Companion note view |
2. Tenet 7 detection has some false-positive risk worth softening
Tenet 7 (commands/product-review.md:299-345) actually has good nuance already — it distinguishes actor from routing, has a "Not a Tenet 7 flag" carve-out for routing-only API-key endpoints, etc. The risk is in the Detect heuristics at :309-317: greps over .save()/.create()/Effect/etc. will surface every native-effect emission, and a reviewer may read the surfaced grep hits as findings even though the rule's logic would clear them.
Rather than tightening the rule, the better posture is to encourage attribution where an actor is reachable:
- For handlers extending
StaffSessionAuthMixin, the staff is right there in the session — capture and pass it through to whatever the handler emits, even if the platform also stamps it. - For
CronTaskand other actor-less contexts, default to a canvas bot fallback until a plugin-specific fallback actor is available.
A line under the Detect block — "if the handler is StaffSessionAuthMixin and emits native Effects, the platform attributes the dispatching staff; do not flag merely because actor capture isn't visible in the source" — would help the reviewer interpret the grep hits correctly.
3. Add a "confirm-and-document" surfacer for cascade / auto-finalize patterns
Three plugins in the sample finalize clinical or billing writes from system-driven event handlers without a provider-driven trigger:
bmi_coding_automation/protocols/bmi_diagnosis.py:180,189—originate() + commit()ofDiagnose/UpdateDiagnosisonVITALS_COMMAND__POST_COMMITclaim_coding_agent/protocols/agent.py:30-40—AddBillingLineItem.apply()onPERFORM_COMMAND__POST_ORIGINATEchronic_care_management_activity_tracker/handlers/ccmat_monthly_cron.py:236,272,316— Note + Diagnose + billing emitted from a monthly cron
These aren't necessarily anti-patterns — sometimes "when action A happens, action B should also happen" is the desired design. But they're worth surfacing so the developer confirms intent and documents the cascade in the README. Suggested behavior: when the command sees a .commit() (or equivalent finalization) emitted from a system-driven event handler, surface as a "confirm-and-document" item rather than a HIGH finding.
4. Tenet 6 needs a clinical-content vs. UI-mechanics rubric
Tenet 6 (commands/product-review.md:277-296) currently says "hardcoded threshold → flag, hardcoded code list → flag." That works for clear-cut cases but produces noise on UI knobs that happen to be numeric.
From the sample:
- Should flag:
hcc_capture/protocols/condition_annotations.py:10-1090(1000+ ICD-10 codes inline),bmi_coding_automation/protocols/bmi_diagnosis.py:80-131(22 BMI bands),claim_coding_agent/protocols/agent.py:32-38(hardcoded CPT 99213 + units + modifiers),chronic_care_management_activity_tracker/handlers/ccmat_monthly_cron.py:36,310-321(CCM minute thresholds + CPT 99490/99439) - Borderline: 1-year DOB fuzzy-match window in
register_patient_companion, patterns-via-secret inhigh-risk-medications - Should not flag:
_VITALS_MAX_PANELS = 12inclinical_summary_companion, 4-digit phone narrowing inregister_patient_companion
Suggested rubric to add near the top of Tenet 6:
Flag a hardcoded value when it encodes a clinical, regulatory, or billing rule that a non-engineer would expect to be content/settings (CMS thresholds, code lists, medical-society cutoffs, billing rates). Don't flag UI mechanics or implementation knobs (page sizes, retry counts, polling intervals, fuzzy-match windows that are heuristics rather than clinical thresholds). When in doubt: would a clinician or biller want to change this without filing an engineering ticket?
5. Consider a manifest-accuracy tenet (or a Tenet 8 extension)
claim_coding_agent's manifest description reads "Example plugin using LLM inference to manage claim coding in real time" and declares OPENAI_SECRET_KEY as a required secret, but protocols/agent.py:23-24 instantiates LlmOpenai and never calls it — the plugin actually emits a hardcoded CPT 99213 with no LLM in the path. That's a real product issue (misleading description for installers, declared secret that isn't used) but no current tenet covers it.
Suggested addition (either under Tenet 8 or as a new small tenet):
Manifest accuracy. The plugin's manifest description should match its actual behavior. Flag when:
- declared
secretsare imported but never read- the description references a capability (LLM, external API, scheduled job) that the code doesn't exercise
- declared
componentsreference dead classes
6. Reference data duplicated between command and skill
The PR adds both commands/product-review.md (573 lines) and skills/product-review/product_review_context.txt (323 lines). Most of the bulk in the command file is reference data — USCDI/DRS tables (product-review.md:51-133), ONC criteria list (product-review.md:378-440) — and the skill exists specifically to hold the rule set as inline-applicable context. Two copies of the same reference data is a maintenance hazard (two places to update on the next ICD release / criterion change).
Suggested: trim the command file to the workflow steps (validate env, orient, walk tenets, generate report, route next steps) and reference the skill for the rule data — e.g., "See product-review skill context for the USCDI/DRS table." Keeps one source of truth for the rule definitions.
Happy to discuss any of these or open separate issues if it's easier to track. Items 1, 4, and 6 are the ones I'd flag as most likely to bite reviewers immediately; the others are sharpening.
|
@kristenoneill I recommend updating https://github.com/canvas-medical/coding-agents/blob/main/canvas-plugin-assistant/CLAUDE.md to get the tenets broadly applied |
|
Further guidance, mostly from |
Summary
Adds
/cpa:product-review— a new command undercanvas-plugin-assistant/commands/that evaluates a plugin from a product perspective. Complementary to/cpa:security-review(engineering concerns); this one surfaces product judgments a human needs to make.The command checks nine tenets:
provider_menu_item/global/patient_specific/portal_menu_item).The command writes a timestamped report to
.cpa-workflow-artifacts/product-review-*.mdand usesAskUserQuestionto route next steps. It explicitly does not auto-fix USCDI or ONC findings — always confirms first, because they touch the designated record set and compliance posture.Also updates the workflow reference tables in
wrap-up.mdandsecurity-review.mdso the new command appears in the standard chain.Test plan
/cpa:product-reviewagainst a plugin with a clean bill of health → verify✅ PASSverdictCustomModelfields that duplicate USCDI concepts → verify Tenet 1 flags with file:line references.cpa-workflow-artifacts/product-review-<timestamp>.mdAskUserQuestionnext-steps prompt appears after findings🤖 Generated with Claude Code