buhtig 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,124 @@
1
+ # buhtig-review
2
+
3
+ Focused facet reviewers fan out over the repo's own taxonomy; each writes its findings to buhtig as
4
+ structured rows — scored, anchored to `(path, line)`, and triaged by the human in the Review tab.
5
+
6
+ {{preamble}}
7
+
8
+ The rest of this skill is four more documents, fetched the same way you fetched this one:
9
+ **`ORCHESTRATOR`** (the run lifecycle), **`FACET_REVIEWER`** (the brief a facet subagent gets),
10
+ **`API`** (every call, in the order a run uses them), **`PROVENANCE`** (a separate job with its own
11
+ brief).
12
+
13
+ ## What buhtig does for you, that you must not do yourself
14
+
15
+ | | Owner |
16
+ |---|---|
17
+ | The facet taxonomy, the contract, per-facet briefs | **buhtig** — read the review config. Never hardcode a facet list. |
18
+ | Anchor fingerprints, snippets, blob OIDs, staleness | **buhtig** — you send `path` + `line`, nothing more. |
19
+ | Whether a line is postable to GitHub (`inHeadDiff`) | **buhtig** — computed against the real diff. |
20
+ | Rendering cited code — real diff, line numbers, expandable context | **buhtig** — label a snippet `buhtig-diff:<path>#L84-L96` and it becomes the real thing. See `FACET_REVIEWER`. |
21
+ | `F<N>` numbering | **buhtig** — at synthesis, after every facet has reported. |
22
+ | Deciding what is dismissed, what goes to the author, what gets a ticket | **the human.** You can set those marks, and only when they ask you to — see `API` §10. |
23
+ | Turning a staged finding into a draft PR comment | **buhtig** — staging composes it; you never write one by hand. |
24
+ | Prose, scores, `(path, line)`, the assignment bookkeeping | **you** |
25
+
26
+ ## Execution outline
27
+
28
+ 1. **Identify scope** — changed files, ticket + acceptance criteria, touched product domains, and the
29
+ PR head SHA (`gh pr view <n> --json headRefOid`).
30
+ 2. **Start the run** with a `runKey` and that `headSha`. You get the run id and one **assignment** per
31
+ reviewable facet. Re-using the same `runKey` resumes — it never forks. A repo that has declared no
32
+ `subagentBudget` is refused here with a 422: report it and stop, rather than reviewing some other
33
+ way. What a review costs is the human's call, not yours.
34
+ 3. **Commission the briefing** — one comprehension agent over the changed surface, stored on the run.
35
+ A factual map, no findings. Every facet agent reads it instead of re-deriving the same call graph
36
+ for itself.
37
+ 4. **Pack the applicable assignments into bundles** — as many as `config.subagentBudget` allows — and
38
+ dispatch one subagent per bundle. Each is handed *only* its own facets' briefs, the briefing, and
39
+ `FACET_REVIEWER`. Mark the ones you deliberately skip `status: skipped` **with a reason** — a facet
40
+ nobody looked at must not read like a facet that came back clean.
41
+ 5. **Each subagent** updates each assignment's status, stores its report, and writes its findings.
42
+ They write directly; you do not funnel their prose through your own context.
43
+ 6. **Synthesize.** Read the current dispositions first — the human triages while the run is still in
44
+ flight, and you must never write over a resolution you did not set. Then deduplicate across facets
45
+ (merge with `mergedIntoSlugId`), set `section` on the findings that belong in the summary, write
46
+ the run's `recommendationMd` / `summaryMd` / `reviewerNotesMd`, then synthesize to assign `F<N>`.
47
+ 7. **Complete the run** and report a terse chat summary — the verdict, the blocker count, and the
48
+ coverage gaps. Do not paste the findings into chat; they are queryable.
49
+ 8. **Stay reachable.** Tell the human where the review is — disposition and posting are theirs — and
50
+ keep watching for their inline messages, on the run **and** on the PR. Completing the run does not end
51
+ that; see `ORCHESTRATOR` §8.
52
+
53
+ ## If buhtig started you
54
+
55
+ `$BUHTIG_AGENT_CONTEXT` names a briefing file, and it carries **the exact command that watches the
56
+ channel** — one command, already pointed at this worktree's subjects and already carrying your
57
+ identity. Read the briefing before anything else: it is how you learn that the human can talk to you
58
+ at all. Nothing interrupts you when they do — the message waits on the channel until you look.
59
+
60
+ ## Scoring
61
+
62
+ The scales come from the review config, **each level carrying its own definition** — read
63
+ `severities` and `priorities` off `review.config` and score against the `title`/`hint` they ship
64
+ with, rather than against what `P1` means in some other project. A repo may drop levels, reorder
65
+ them, or replace a `hint` with its own risks; it never has to restate the scale to use it.
66
+
67
+ - `severity` `P0`–`P4` — impact if the finding is real.
68
+ - `reviewPriority` `R0`–`R3` — how deeply the dimension was reviewed. `priorityNote` carries an
69
+ escalation ("R1 (escalated — persisted data)").
70
+ - `confidence` `high` | `medium` | `low` — **shown to the author**, on its own line of the composed
71
+ author-facing body, and editable by the human. Uncertainty stated plainly invites a correction; the
72
+ same finding with the hedge stripped reads as an assertion the author has to disprove.
73
+ - `blocking` — does it block merge.
74
+ - `audience` `reviewer` | `agent-internal` | `author` | `reviewer+author`. Reviewer-only findings
75
+ cannot be staged without a logged human override, which is the point.
76
+
77
+ ## The three prose parts
78
+
79
+ `bodyFinding` (the concrete issue) · `bodyWhy` (impact if true) · `bodyFix` (actionable) —
80
+ identifier-led, example-heavy.
81
+
82
+ **What the author reads is composed, not written.** buhtig builds it from `title`, `bodyFinding` and
83
+ `bodyFix`, led by `**[blocker · P1] <title>**` and a `_Confidence: High_` line. `bodyAuthor` is
84
+ read-only — there is no author-facing copy to keep in sync, so a correction to the three bodies is the
85
+ only correction there is.
86
+
87
+ `bodyWhy` is reviewer-only. It argues impact to a reviewer deciding whether the finding matters, a
88
+ decision the author is not making. To keep a whole finding off the author's screen, use
89
+ `audience: reviewer`.
90
+
91
+ ## Writing style
92
+
93
+ Follow the `/writing` skill: terse, top-down, no fluff. Identifier-led and example-heavy — pin the
94
+ real symbols and a laser-focused example (a snippet, an input→wrong-output pair, the query missing its
95
+ filter) and let those carry the finding. **No praise** in anything author-facing.
96
+
97
+ Markdown prose is stored verbatim and rendered in a browser, so:
98
+
99
+ - **Do not hard-wrap.** One physical line per paragraph or list item.
100
+ - Link code as ``[`symbol`](path/to/file.ts#L120)`` with **repo-relative** paths — buhtig rewrites
101
+ them into deep links. Do not write `../../` prefixes; there is no file to be relative to.
102
+
103
+ ## Follow-up tickets
104
+
105
+ Opt-in, and the human's. They compose the tickets in the Outbox — grouping findings, editing the
106
+ bodies, arranging the hierarchy — and mark the ones they want filed `ready`.
107
+
108
+ Your part is filing what is already composed, and only when asked:
109
+
110
+ ```call ticket.list
111
+ { "status": "ready" }
112
+ ```
113
+
114
+ …file it in the tracker, then record where it landed:
115
+
116
+ ```call ticket.update
117
+ { "id": "$TICKET_ID", "status": "filed", "url": "https://linear.app/…", "externalKey": "WEB-1235" }
118
+ ```
119
+
120
+ That one write flips every member finding to `ticketed` with the URL. See `API` §10.5.
121
+ Never mark a ticket `ready`, and never open one unprompted.
122
+
123
+ Add **one** session todo — "tally follow-ups before closing the review for PR #N" — pointing at the
124
+ `followup=wanted` findings, the Outbox, and any unresolved PR threads.