Beside the push gates, crafter-review runs the pre-send review of a kernel contributor's workbench: --mode series over a format-patch export with its cover letter, --mode reply over a mail draft. The inventory partitions a cover letter, a plain mail and the camera review's shape; ten kernel lenses join the table with their gates (structure, code, artifact truth) and the persona gate - one maintainer-persona instance per --reviewers entry, its whole pass gating its blocks and pruning the units that are not theirs. A series' code units are keyed on the code like the push gates'; every text unit on its text, the references it cites and the anchor when it is dated. The references an artifact cites are prefetched through utilities/lore.py into the gate-state, with a digest in the run layer, and a persona's calibration map is its lore listing. The kernel schema carries the persona vocabulary, the kernel note kinds, the predicted review and the not-mine list; the matrix the persona holes, the thin and the modelled units; gates clean without a persona pass is GATES CLEAN. A reply's gate-state sits beside the draft and is read once; a kernel mode needs --subsystem, defaults the effort to max and the trees to work/linux,work/milos-linux, and excuses no unit from the holes. The kernel lenses and the common text ship verbatim; the table lists them after the push gates' lenses and the config template holds them off, so a repository that never turns them on changes nothing. Prompts, keys and plans were checked byte for byte against the pipeline these modes replace, on its own artifacts: two replies and a series, every system prompt, user prompt, job and reuse key identical.
118 lines
6.8 KiB
C++
118 lines
6.8 KiB
C++
// SPDX-License-Identifier: AGPL-3.0-only
|
|
// SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
|
|
|
|
export module Crafter.Review:Inventory;
|
|
import std;
|
|
import :Json;
|
|
|
|
// The partition of a frozen artifact into review units for the coverage
|
|
// contract: a commit range (a `git format-patch` export, the commits mode),
|
|
// a kernel patch series (the same export with a cover letter, the series
|
|
// mode) or a mailing-list reply (the reply mode). It is MECHANICAL: no agent
|
|
// decides what the units are. Every non-blank line of the artifact belongs
|
|
// to exactly one unit, and the inventory fails when that does not hold.
|
|
// Fixed slots give what is NOT in the text a row of the coverage matrix too.
|
|
//
|
|
// Reply mode units (ids):
|
|
// nl:intro the author's own paragraphs before the first per-file header
|
|
// nl:<file> the paragraphs under the header naming that patch file
|
|
// anchor the dated anchor line(s) opening the block
|
|
// RN reversal paragraphs ("R2. ...")
|
|
// <sec>:N numbered item N of section <sec> (camss, ov13b10, dts, x)
|
|
// <sec>:Na lettered sub-item a of item N
|
|
// x:N bullet N of the cross-series section
|
|
// refs the reference list
|
|
// whole:* fixed slots (WholeReply)
|
|
// A plain on-list mail (no "Dates: every" anchor) is partitioned
|
|
// generically instead (PartitionMail):
|
|
// hdr the header block (From/To/Cc/Subject/In-Reply-To/References)
|
|
// quote:N the N-th quoted block, with its "On ... wrote:" line
|
|
// para:N the N-th paragraph of our own text
|
|
// trailers a paragraph made only of "Tag-Name: value" lines
|
|
// Series mode units:
|
|
// cover:header the cover letter's header, cover:N its paragraph N
|
|
// pK:... as below, every hunk whole (no documentation split)
|
|
// whole:* fixed slots (WholeSeries)
|
|
// Commits mode units (ids):
|
|
// pK:subject commit K's subject
|
|
// pK:msg commit K's message body (before the trailers), when not empty
|
|
// pK:trailers commit K's trailer block, when not empty
|
|
// pK:diffstat commit K's diffstat
|
|
// pK:<file>#hdr the diff header of <file> in commit K (mode, rename, blobs)
|
|
// pK:<file>#H hunk H of <file> in commit K; a hunk of a documentation file
|
|
// that holds more than one heading-delimited part is cut into
|
|
// #H.1, #H.2, ... (DocParts)
|
|
// pK:outside fixed slot: the in-repository users and callers of what
|
|
// commit K changes, outside its diff
|
|
// pK:absent fixed slot: what a reviewer expects in commit K and does not
|
|
// find
|
|
// whole:* fixed slots (WholeCommits)
|
|
export namespace Crafter::Review::Inventory {
|
|
struct WholeSlot {
|
|
std::string_view id;
|
|
std::string_view description;
|
|
};
|
|
constexpr std::array<WholeSlot, 3> WholeReply = {{
|
|
{"whole:route", "the decision or route the mail recommends, and whether its consequences are carried through every item that depends on it"},
|
|
{"whole:asks", "the total set of actions the mail asks of the reader — is it legible as one list, free of contradictions between items"},
|
|
{"whole:absent", "what this reviewer would expect the mail to say and it does not — a precedent, a test, a dependency, a recipient, a question left open"},
|
|
}};
|
|
constexpr std::array<WholeSlot, 4> WholeSeries = {{
|
|
{"whole:order", "patch ordering, bisectability, declared dependencies and base"},
|
|
{"whole:cover-vs-patches", "the cover's claims against what the patches actually do, including testing statements"},
|
|
{"whole:recipients", "To/Cc against get_maintainer and the people who reviewed the same construct recently"},
|
|
{"whole:absent", "what this reviewer would expect the series to contain and it does not"},
|
|
}};
|
|
constexpr std::array<WholeSlot, 3> WholeCommits = {{
|
|
{"whole:order", "commit ordering and bisectability — each commit a self-contained step that leaves the repository consistent (no later commit in the range repairs an earlier one, nothing is used before the commit that adds it), the declared base"},
|
|
{"whole:absent", "what a reviewer of this repository expects the range to contain and it does not — a test, a version/changelog bump, a doc or packaging update, a migration for existing installs, a message for a body-less commit"},
|
|
{"whole:behaviour", "the user-visible behaviour of the range, exercised end to end in the running application — every behaviour the code and the messages promise, as a user sees it; the flows the range touches and the adjacent flows that share what it changes; what a user expects the range to deliver and does not get"},
|
|
}};
|
|
|
|
// [a, b) is one hunk of a Markdown file, lines[a] its @@ line: its
|
|
// partition at the headings on the new side of the diff, outside fenced
|
|
// code blocks, once the part before holds anything but headings.
|
|
std::vector<std::pair<std::size_t, std::size_t>> DocParts(std::span<const std::string> lines, std::size_t a, std::size_t b);
|
|
// The first non-blank line, stripped and cut to 90 code points.
|
|
std::string Excerpt(std::span<const std::string> lines);
|
|
|
|
struct Series {
|
|
// Every patch's lines, one after the other: what unit lines number.
|
|
std::vector<std::string> lines;
|
|
// Units ({id, lines, excerpt}), the whole slots not yet among them.
|
|
Json units;
|
|
};
|
|
// A format-patch export, a cover letter (0000-) as cover:header and
|
|
// cover:N paragraphs; splitDocs cuts a documentation hunk at its
|
|
// headings (the commits mode only); kernel words the per-patch slots
|
|
// as the series mode does (a patch in a tree, not a commit in a
|
|
// repository).
|
|
Series PartitionSeries(const std::filesystem::path& dir, bool splitDocs = true, bool kernel = false);
|
|
// A plain on-list mail: the header block, each quoted block with its
|
|
// attribution line, each paragraph of our own text, a trailer paragraph.
|
|
Series PartitionMail(std::string_view text);
|
|
// The camera review's shape when the text has its dated anchor
|
|
// ("Dates: every"), else PartitionMail.
|
|
Series PartitionReply(std::string_view text);
|
|
|
|
// A partition that broke the invariant.
|
|
class InvariantError : public std::runtime_error {
|
|
public:
|
|
using std::runtime_error::runtime_error;
|
|
};
|
|
|
|
struct Built {
|
|
// What `inventory commits <dir>` prints: {mode, artifact, hash8,
|
|
// units, invariant, count}.
|
|
Json out;
|
|
std::vector<std::string> lines;
|
|
};
|
|
// `artifact` is kept as it is spelled: the inventory records it so. mode:
|
|
// reply (a draft file), series or commits (a dir of *.patch).
|
|
Built Build(std::string_view mode, std::string_view artifact);
|
|
|
|
// `crafter-review inventory reply|series|commits <path>`: the partition
|
|
// as indented JSON on stdout. Exit 1 on a broken invariant or a bad
|
|
// command line.
|
|
std::int32_t Main(std::span<const std::string_view> args);
|
|
}
|