Task
Given one piece of content (required) and, optionally, its paired assistant_message (this
turn's AI reply) and prev_message (the last paragraph of the immediately previous
assistant reply — not the previous human turn), classify using references/CATEGORY_TAXONOMY.md
and references/TOPIC_TAXONOMY.md. This makes no CawPlan API calls and needs no cawplan auth —
it is a pure reasoning check against uid.core-product's current classify rules, not a lookup.
Workflow
- Read
references/CATEGORY_TAXONOMY.md,references/TOPIC_TAXONOMY.md, andreferences/PRODUCTION_CLASSIFY_PROMPT.md(full production snapshot) if you haven't already this session. When the curated docs and the snapshot disagree, follow the snapshot. new_featureis the last resort topic. When more than one topic plausibly fits, do not pick it — prefer the specific one (design_uifor anything about how something is displayed, including a NEW node/panel/screen whose ask is what it shows;integration_apifor wiring or for a field an external system must carry;security,infra,refactor,bug,investigation). A new screen or a new field does not by itself make itnew_feature.- Prepare
assistant_messagethe same way production does before reading it — don't reason over raw untruncated text:- Normalize literal
\n/\tescapes and line endings to real whitespace. - Strip
[REDACTED]placeholders (upload-time redaction — not real bracketed content like[Done]/[QA Testing], which must stay). - Strip markdown noise within each paragraph (table rules,
---horizontal rules, heading/bold markers, emoji). - Split on blank lines into paragraphs; keep only the first 3 paragraphs.
- Join those paragraphs with
\n\n, then cap at ~1200 runes (head cut with...if longer) — mirrorsClassifyAssistantSnippet/AISessionClassifyAssistantMaxRunes.
- Normalize literal
- Prepare
prev_messagewhen provided (same paragraph split + per-paragraph sanitize as step 2, but take only the last paragraph; cap at ~500 runes) — mirrorsClassifyPrevAssistantTail/AISessionClassifyPrevMaxRunes. When omitted, treatprevas empty; bare follow-ups ("commit & push", "直接改") may be ambiguous without it. - Route categories exactly like production (see
CATEGORY_TAXONOMY.md):- Primary signal:
content. Always read this first. prev: use ONLY on short bare follow-ups (typically ≤12 Han chars or ≤6 English words) to distinguishdecision(human names/repeats the concrete action the assistant offered) vsapproval(generic go-ahead: "直接改", "可以", "do it"). Never useprevfor any other category; never treat it as a prior human requirement.assistant_message: use for category ONLY whencontentis a bare hand-off (URL, file path, screenshot path, log path) with no intent words. Do not infer category from what the assistant already did or verified.
- Primary signal:
- Determine every category from the taxonomy that clearly applies, then sort by the priority
order in the reference doc (highest → lowest). Use the exact snake_case leaf names
(
direction_constraint,rejection_rollback,question_clarification,other_meta, … — not shortened forms likedirection/rejection/question/other). Don't invent a secondary category just to fill the list. When only one applies, the list has one element. - The first element of that sorted list is the primary category.
- Pick exactly one topic from
TOPIC_TAXONOMY.mdusingcontent+ preparedassistant_messageonly — never useprev_messagefor topic. Apply ASKING vs CHANGING, barecommit & push→git_ops, and Slack-heavy hints from the reference doc. - Write one short
topic_reasonsentence andtopic_confidence(0.0–1.0 perTOPIC_TAXONOMY.md) mirroring production.
Output
Report:
category— the primary category (single value, first element ofcategories).categories— the full priority-ordered list (may be a single value).topic— exactly one value from the 17-topic list inTOPIC_TAXONOMY.md.topic_reason— one short sentence explaining the topic pick.topic_confidence— float 0.0–1.0 (how sure you are about the topic pick).- One short sentence explaining the primary category pick, citing the specific phrase in
content,prev_message, or preparedassistant_messagethat drove the decision — this is what makes a caller's downstream disagreement (e.g. vs. an already-persisted cloud category) reviewable rather than opaque.
References
references/PRODUCTION_CLASSIFY_PROMPT.md— full prompt exported from uid.core-productreferences/CATEGORY_TAXONOMY.md— curated category routing + examplesreferences/TOPIC_TAXONOMY.md— curated topic routing + examples
Sync snapshot after prompt ships:
node skills/cawplan-internal-qa-coding-humaninputs/scripts/sync-classify-prompt-from-core-product.mjs