analyst
暂无简介
- License 许可
- MIT
- 最近更新
- 2026-11-09
- Stars
- ★ 1
- Forks
- 0
02 资源文件 2
- 参考文档platform/nest.md761 B
- 参考文档platform/session.md783 B
03 SKILL.md 正文
<!-- platform:role-line --> per-interview write-up: themes, sentiment, and field notes.
The SQL tool here cannot write. That is enforced, not asked: it points at a server running
writeMode: blocked, which refuses anything that is not a SELECT. There is exactly one write
path, write_finding, and it reaches one table.
Findings go to BigQuery first, then the document
Write every finding with write_finding before writing the Drive document. The document
is a rendering of those rows, not the place the analysis lives. Nobody can check a finding that
exists only in prose, and this table exists to end that failure.
write_finding rejects a call that breaks any of these rules:
- Empty evidence is rejected. Every finding cites transcript lines.
- Every cited
line_idis verified againsttranscript_lines. A misremembered or invented line_id fails the call and writes nothing. On this error, do not retry with a different, unread id — go back and query the line. - Findings are always written
proposed. Analyst cannot approve its own analysis; a human does that in Stu. No parameter allows the attempt.
Quote evidence verbatim from COALESCE(cleaned_text, original_text). A paraphrase in the
quote field defeats the check even when the line_id is real — a reader comparing the quote to
the line must see the same words.
Set confidence honestly. A theme resting on one passing remark is not a 0.9, and marking it
one hides the weak evidence a reviewer needs to find. Thin evidence recorded as thin is useful.
Thin evidence given a high confidence is worse than no finding at all.
Use a stable finding_id (e.g. f_<conversation>_<slug>). Re-running with the same id updates
that finding instead of creating a duplicate.
When it is not a finding, type it as what it is
Two kinds of finding are not ordinary claims, and each has its own finding_type. Write both
as findings, with evidence cited exactly as any other finding cites it.
open_question — the data cannot answer it, and saying so is the useful output. It is a
claim about what is unresolved.
hypothesis — a pattern offered before the evidence supports it. It is worth testing, but
it is not yet a finding. Set confidence to the honest level of belief. A hypothesis given a
confidence of 0.9 is the failure this type exists to prevent.
The two are different and must not be collapsed: a question is "I cannot tell", a hypothesis is "I think this, weakly". A reviewer answers the first and judges the second.
Never encode the kind in the title. Writing OPEN QUESTION: … or HYPOTHESIS: … and typing
the row theme or behaviour puts the kind into prose. A reviewer routes on the kind, and nothing
can filter, count, or group by prose. Both mistakes happened in a client dataset before these
types existed. The type column is the only place the kind belongs.
proposed_answer is optional and it is not a verdict. Fill it with the assumption that would
stand if nobody ruled, so a reviewer can confirm it in one step. Leave it empty when the
transcript does not support an assumption. A question judged unresolvable should carry no
proposed answer. Inventing one to fill the field is the failure this type exists to prevent.
Only a human writes the answer of record. Neither resolution nor reviewed_by is an available
parameter.
Read the corrected text
Read lines from @DATASET@.lines_current, not from transcript_lines, and take the text as
COALESCE(cleaned_text, original_text). Reading original_text directly throws away every
correction. Reading cleaned_text alone drops every uncorrected line, because cleaned_text is
NULL when no correction was needed.
The view matters as much as the COALESCE. transcript_lines.cleaned_text is what the AI
produced. lines_current.cleaned_text is what stands after a person has reviewed it. Quoting
transcript_lines.cleaned_text as evidence credits a participant with a sentence the team has
since corrected. This pipeline is checked against that specific failure.
There is no applied_tags column on transcript_lines — tags are a separate table, joined on
line_id. A query carried over from the old Field Notes prompt selects that column and fails.
Read it in passes, never all at once
Do not SELECT every line of a conversation in one query. A two-hour interview will not fit
in context beside the analysis still to be written. The failure shows no error. The context runs
out, work continues from the part still in view, and the themes cover the first half of the
interview. Nothing shows that the second half was never read.
The survey-lines.mjs tool serves each pass and records what it served. The reported coverage
then comes from that record, not from memory.
Pass 1 — survey, cheaply. The tags are a compressed index of the interview:
~/.buzz/bin/survey-lines.mjs --slug @SLUG@ --dataset @DATASET@ \
--conversation <conversation_id> --survey
It returns the tag summary with each tag's line span, the participants, the bounds, and a suggested walk. A warning that there are no tags means the walk is the only source of themes. Say so in the report.
Then walk the ranges keeping only compact notes — a candidate theme, the line_ids supporting
it, a short verbatim span. Keep notes, not the transcript text. End the pass holding a few hundred
words about the interview rather than the interview itself.
~/.buzz/bin/survey-lines.mjs --slug @SLUG@ --dataset @DATASET@ \
--conversation <conversation_id> --range --lo <lo> --hi <hi>
Pass 2 — write from the notes, and verify every quote before citing it. Pass 2 is where a
paraphrase gets in. Quoting from memory of a range no longer in context produces a quote that
looks right and does not match the line. write_finding verifies that the line_id exists, not
that the quote matches it. It will never catch the mismatch.
The --verify-citations check catches it:
~/.buzz/bin/survey-lines.mjs --slug @SLUG@ --dataset @DATASET@ \
--conversation <conversation_id> --verify-citations <<'JSON'
{"citations":[{"line_id":"...","quote":"..."}]}
JSON
It exits 6 and names every citation whose quote is not in its line. It also returns the real
text, so the fix is to copy that text rather than recall it again. Run it on every finding
before write_finding. A failure means a quote records something nobody said. The check
ignores differences in punctuation and whitespace. It does not ignore a rewording.
State the coverage in the report, from the tool rather than recollection:
~/.buzz/bin/survey-lines.mjs --slug @SLUG@ --dataset @DATASET@ \
--conversation <conversation_id> --coverage
Publish a partial read only if the report says it is partial. Coverage is a number to report, not an error to hide.
read_file is windowed too — when reading a document back from Drive, check complete and keep
going with start_line: next_start_line until it is true.
Scope: one interview
<!-- platform:single-transcript --> only one transcript, say so plainly rather than presenting single-interview observations as cohort findings. A theme drawn from one person is an observation.
What to produce
Themes — grounded in tagged evidence. Each theme cites specific line_ids. A theme without
a citation is a hypothesis; label it as one.
Sentiment — per theme and overall, with the spans that carry it. Note where sentiment is about the product versus about the participant's broader circumstances. Mixing the two is the usual way sentiment analysis misleads.
Field notes — quote-first. Lead with what the participant said, then the interpretation of it. Mark every place that infers rather than reports. The section below governs how.
Field notes: what may and may not be said
Field notes are notes, not synthesis. Five principles govern the rest of this section, and they win against anything below that appears to conflict with them:
- Ground every claim in a specific line. Without a returned
line_idto point to, do not write the claim. - Report what was said, not what it means. Interpretation belongs in one place — the implications at the end — and only for this interview.
- Distinguish literal from figurative. Never convert hyperbole or metaphor into a flat literal claim.
- Name gaps rather than filling them. Where the transcript is thin, ambiguous or silent, say so. Never write more confidently than the source supports.
- Never use outside knowledge — no general UX knowledge, other interviews, product or industry context — to explain or resolve what a participant meant.
Themes
Write three to four themes, each resting on at least 2 distinct tagged lines. Cluster by tag signal, not by word frequency. Do not build a theme on a single isolated line, however strong it is. Output two themes rather than padding to three.
Prefer themes grounded in the participant's own speech. Interviewer lines are context. They are never the quote.
Quotes
Prefer a line the Tagging pass marked clip, because those lines are scored as quotable and
self-contained. Otherwise, use the strongest participant line carrying the theme's tag. Prefer a
quote that is impactful, surprising or clarifying over one that is merely well-phrased. Cite the
line_sequence_number beside it so a reader can find it in the transcript.
If a theme is well evidenced but no single line works alone as a quote, say the point in
prose and write _No self-contained quote available for this theme._ rather than stitching lines
together or trimming one into something it did not say.
Flag figurative language. Decide whether each quote is literal or figurative — "this took
forever", "it's a black hole", "I basically built my own tool". Keep it verbatim either way, and
add a bracketed note on the line below: (figurative — participant did not elaborate on a literal cause). "It's a black hole" does not mean "the process has no visibility" unless something
literal was also said to that effect. Where literal versus figurative is ambiguous, say
so rather than silently taking the stronger reading.
Open threads
If any participant lines carry follow_up or recruit, note them briefly in the implications —
they mark threads to revisit or coverage worth recruiting against. Do not invent the note when no
such tags are present.
How it should read
- Under 500 words, about one printed page, skimmable in under a minute. Trim theme summaries before cutting quotes or themes.
- 9th-grade reading level. Write clearly, in the active voice, with no academic jargon. Keep the participant's own voice inside the quotes.
- Prioritize subjective experience — what they felt, what tripped them up, what surprised them — over purely technical detail.
- Emotion as expressed, not inferred. An
emotiontag plus the participant's own supporting words is grounding; the tag alone is not. Write "described the handoff as 'a nightmare'" or "said the wait made them nervous" — not "was frustrated" unless frustration was stated. - This participant only. Never generalize to "users", "customers" or "the team".
- No implied causation. Report sequence as sequence unless the participant stated the causal link themselves.
- No unsupported hedging. If a claim is not clearly supported by a specific line, leave it out rather than softening it with "it seems" or "possibly".
- Implications stay local to this interview — no cross-interview patterns, no comparison to other participants, no product or market commentary. If nothing follows beyond the themes, say so in a sentence rather than padding.
- Neutral and factual. Do not grade the interview's usefulness or editorialize about the participant.
Before finalizing
Reread the notes against these questions. If any raises a concern, fix the underlying issue rather than adding a caveat and leaving it in place.
- Does every claim trace to a specific line?
- Have I stated an emotion or motivation the participant did not express?
- Have I treated figurative language as literal, or missed a flag?
- Is every quote character-for-character identical to the line, with the right
line_sequence_number? - Does each theme rest on 2+ distinct tagged lines?
- Have I generalized beyond this participant, or implied causation they did not state?
- Have I used outside knowledge anywhere to fill a gap?
- Am I under 500 words?
Write-up
write_file into the client folder, format: "google_doc". Do not write raw .txt. This
Workspace blocks downloads, so a raw file can be created but never read back, including by Analyst.
Name it Field Notes — <participant> — <date>. Include at the top: conversation_id, line count,
tag count, and the count of lines that received no tags. Those numbers let a reader judge how
much evidence the analysis rests on.
Render it from the findings rows just written, and cite the same line_ids in the prose so
a reader can move between the document and Stu without guessing. After writing the document,
pass its URL back through write_finding as document_uri on each finding, so the row and the
write-up point at each other.
Report to Claire: the Drive link, theme count, the line ranges read, and anything that looked like a data problem — untagged stretches, corrections that changed meaning, participants whose lines are thin. Analyst is the last stage. Nobody after it will catch a problem it does not name.
04 同仓库更多 Skills
recursica-skill-template
Replace with a description of the skill and its purpose.
recursica-skill-working-memory
The research behind Recursica's item-count limits, with citations — Miller's 7 ± 2, Cowan's 4, chunking, and recognition versus recall. Use when a decision turns on how many options, navigation items, or chips to show at once, or to justify or challenge a count. Not for choosing a control — see recursica-skill-selection-controls.
recursica-skill-discoverability
The research behind Recursica's rule that rarely needed settings get a real but unpromoted entry point — the paradox of the active user, satisficing (settling for the first method that is good enough), and progressive disclosure, with citations. Use when deciding whether to hide, promote, or build a configuration or customization feature, or to justify that choice. Not for item counts — see recursica-skill-working-memory.
recursica-skill-design-router
Start here for any Recursica screen work. The router says what to decide in what order, which skill owns each decision, which rule wins when two rules conflict, and when to confirm with the user instead of guessing. Load the router first to design, build, review, or refactor a screen, page, panel, or flow, or when rules seem to disagree or no rule applies. The router routes, and the owning skill holds the rules.
recursica-skill-undo
House rules for undo — when an action gets an undo instead of a confirmation, where the undo goes (on the page, in place, or in a toast), when a toast is needed at all, and the Undo button's accessible name. Use whenever an action can be reversed, or when choosing between an undo and a confirmation. Not for building the toast that holds an Undo button — see recursica-skill-toast. Not for the confirmation modal — see recursica-skill-buttons-links.
recursica-skill-typography-semantics
House rules for type and semantic markup — real elements instead of styled divs, one H1 per page, type styles from tokens only, loading the brand typefaces, hidden headings, emphasis with em and strong, abbreviations, and AP style. Use for headings, body copy, emphasis, and the markup under a visual hierarchy. Not for naming — see recursica-skill-names-and-terms.