feat(modes): the kernel modes - a patch series and a mailing-list reply
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.
This commit is contained in:
parent
4fc15fe1c2
commit
339f4b9b40
46 changed files with 5732 additions and 362 deletions
|
|
@ -11,18 +11,32 @@ import :Json;
|
|||
// builds, both kept as JSON with their keys in a fixed order: the dump,
|
||||
// progress.json and the prompts are made from them.
|
||||
export namespace Crafter::Review::Plan {
|
||||
// The three modes: a mailing-list reply, a kernel patch series (the
|
||||
// kernel modes, with the persona gate), and a commit range about to be
|
||||
// pushed.
|
||||
constexpr std::array<std::string_view, 3> Modes = {"reply", "series", "commits"};
|
||||
bool IsKernelMode(std::string_view mode);
|
||||
constexpr std::string_view FunctionalLens = "repo-functional.md";
|
||||
// The persona lens of the kernel modes: one instance per reviewer
|
||||
// (--reviewers), its whole pass gating its blocks, in the gate after
|
||||
// every other.
|
||||
constexpr std::string_view PersonaLens = "maintainer-persona.md";
|
||||
constexpr std::string_view PersonaGate = "Gate 4 — Personas";
|
||||
// The commit-truth lens (2026-10-31, the fp6 pipeline's repo-facts): the
|
||||
// messages and the documentation of the range.
|
||||
constexpr std::string_view FactsLens = "repo-facts.md";
|
||||
// The reasoning effort when --effort is not given (2026-10-02: the push
|
||||
// gates run at xhigh).
|
||||
// The reasoning effort when --effort is not given: the kernel modes
|
||||
// stay at max; the push gates run at xhigh (2026-10-02).
|
||||
constexpr std::string_view Effort = "xhigh";
|
||||
constexpr std::string_view KernelEffort = "max";
|
||||
// Clean reads a code unit of a lens marked `reads` needs before its
|
||||
// verdict is reused, one per round (--reads). 2026-10-06: a static lens
|
||||
// is not deterministic — a second and third read of unchanged code still
|
||||
// found defects; "3 is fine".
|
||||
// found defects; "3 is fine". A reply has no code: its paragraphs are
|
||||
// read once.
|
||||
constexpr std::int32_t Reads = 3;
|
||||
constexpr std::int32_t ReplyReads = 1;
|
||||
std::int32_t ReadsFor(std::string_view mode);
|
||||
// The key's last slot held the run's effort from 2026-09-22 to
|
||||
// 2026-10-02; it is frozen at the value every stored verdict was built
|
||||
// with, so a clean verdict bought at one effort is reused at any other
|
||||
|
|
@ -44,6 +58,9 @@ export namespace Crafter::Review::Plan {
|
|||
constexpr std::array<std::string_view, 1> BehaviourSlots = {"whole:behaviour"};
|
||||
constexpr std::array<std::string_view, 1> CodeBlocks = {"code"};
|
||||
constexpr std::array<std::string_view, 3> TruthBlocks = {"text", "doc", "slot"};
|
||||
constexpr std::array<std::string_view, 2> TextSlotBlocks = {"text", "slot"};
|
||||
constexpr std::array<std::string_view, 2> TextCodeBlocks = {"text", "code"};
|
||||
constexpr std::array<std::string_view, 2> CodeSlotBlocks = {"code", "slot"};
|
||||
|
||||
// One row of LENSES. whole: "" (none), "first-repo" (the approach) or
|
||||
// "functional" (the range exercised in the running application); every
|
||||
|
|
@ -63,6 +80,10 @@ export namespace Crafter::Review::Plan {
|
|||
// used the instrument is not evidence. perCommitSlots false: the lens
|
||||
// judges the per-commit slots in its whole pass. env: the default
|
||||
// environment; a verdict bought in any other carries it in its key.
|
||||
// kernel: a lens of the kernel modes - its whole pass and its slot
|
||||
// passes cover every whole:* slot of the artifact, a hunk of a
|
||||
// documentation file is code to it, and its keys and prompts are the
|
||||
// kernel pipeline's.
|
||||
struct Lens {
|
||||
std::string_view file;
|
||||
std::int32_t gate;
|
||||
|
|
@ -77,9 +98,11 @@ export namespace Crafter::Review::Plan {
|
|||
bool empirical;
|
||||
bool perCommitSlots;
|
||||
std::string_view env;
|
||||
bool kernel = false;
|
||||
};
|
||||
// In the order the dump and the prompts list them.
|
||||
constexpr std::array<Lens, 5> Lenses = {{
|
||||
// In the order the dump and the prompts list them: the push gates'
|
||||
// lenses, then the kernel modes'.
|
||||
constexpr std::array<Lens, 15> Lenses = {{
|
||||
{"repo-better-solution.md", 1, "first-repo", ApproachSlots, CodeBlocks, "fable", true, true, true, "code", false, true, "none"},
|
||||
{FunctionalLens, 2, "functional", BehaviourSlots, CodeBlocks, "opus", true, true, false, "functional", true, false, "browser"},
|
||||
{"repo-bug-prover.md", 3, "", {}, CodeBlocks, "opus", true, false, true, "code", false, true, "none"},
|
||||
|
|
@ -94,6 +117,23 @@ export namespace Crafter::Review::Plan {
|
|||
// once the code they describe has settled. One read: its units are
|
||||
// prose, keyed on their text and the code they describe.
|
||||
{FactsLens, 4, "", ApproachSlots, TruthBlocks, "opus", true, false, false, "text", false, true, "none"},
|
||||
// The kernel modes (reply, series). whole: "first" judges the series
|
||||
// as an approach, "all" the consistency of the whole, "persona" reads
|
||||
// it as one reviewer. better-solution's code blocks are reused and
|
||||
// need the clean reads like the other code lenses (2026-10-06.7); its
|
||||
// whole pass has no key: it runs on every hash against what is on
|
||||
// the list today. A persona's block passes are reusable, keyed with
|
||||
// the persona's name (2026-10-06.6); its whole pass runs every round.
|
||||
{"better-solution.md", 1, "first", {}, CodeBlocks, "fable", true, false, true, "code", false, true, "none", true},
|
||||
{"code-quality.md", 2, "", {}, CodeBlocks, "opus", true, false, true, "code", false, true, "none", true},
|
||||
{"minimalism.md", 2, "", {}, CodeSlotBlocks, "opus", true, false, true, "code", false, true, "none", true},
|
||||
{"bug-prover.md", 2, "", {}, CodeBlocks, "opus", true, false, true, "code", false, true, "none", true},
|
||||
{"facts.md", 3, "", {}, TextSlotBlocks, "opus", true, false, false, "code", false, true, "none", true},
|
||||
{"consistency.md", 3, "all", {}, TextCodeBlocks, "opus", false, false, false, "code", false, true, "none", true},
|
||||
{"process-docs.md", 3, "", {}, TextSlotBlocks, "opus", true, false, false, "code", false, true, "none", true},
|
||||
{"etiquette.md", 3, "", {}, TextSlotBlocks, "opus", true, false, false, "code", false, true, "none", true},
|
||||
{"conciseness.md", 3, "", {}, TextSlotBlocks, "fable", true, false, false, "code", false, true, "none", true},
|
||||
{PersonaLens, 4, "persona", {}, TextCodeBlocks, "fable", true, false, false, "code", false, true, "none", true},
|
||||
}};
|
||||
bool IsLens(std::string_view file);
|
||||
// LENSES[file]; Dyn::Error (KeyError) for a file that is no lens.
|
||||
|
|
@ -103,7 +143,12 @@ export namespace Crafter::Review::Plan {
|
|||
std::string_view title;
|
||||
std::vector<std::string_view> lenses;
|
||||
};
|
||||
const std::vector<Gate>& Gates();
|
||||
// The gates of a mode: reply runs Gate 3 alone (facts, etiquette,
|
||||
// consistency, conciseness); series Gate 1 (better-solution), Gate 2
|
||||
// (code-quality, minimalism, bug-prover), Gate 3 (facts, consistency,
|
||||
// process-docs, etiquette, conciseness); the persona gate follows them
|
||||
// when reviewers are given. commits: the push gates.
|
||||
const std::vector<Gate>& Gates(std::string_view mode = "commits");
|
||||
|
||||
// What a lens's processes get beyond the read-only tools, by the
|
||||
// consumer's lenses.<name>.environment: mcp, the server rendered into
|
||||
|
|
@ -155,6 +200,11 @@ export namespace Crafter::Review::Plan {
|
|||
Budget BudgetFor(std::string_view kind, std::string_view unitKind, std::string_view lensFile);
|
||||
|
||||
std::string_view DefaultEffort();
|
||||
std::string_view DefaultEffort(std::string_view mode);
|
||||
// A text unit that is a bare section header of the camera review
|
||||
// (`camss-milos`, `ov13b10-of`, `milos-dts-camss`, `across the three
|
||||
// series`): nothing to judge, a mechanical n/a for every text lens.
|
||||
bool IsBareHeader(const Json& unit, std::string_view text);
|
||||
// "slot", "code" or "text".
|
||||
std::string_view UnitKind(const Json& unit);
|
||||
std::string_view UnitKindOf(std::string_view unitId);
|
||||
|
|
@ -178,15 +228,18 @@ export namespace Crafter::Review::Plan {
|
|||
std::string UnitText(std::span<const std::string> lines, const Json& unit);
|
||||
// sha256 of the text's UTF-8, in hex.
|
||||
std::string Sha(std::string_view text);
|
||||
// lens_file.replace('.md', '')
|
||||
std::string LensName(std::string_view lensFile);
|
||||
// Every lens of the gates.
|
||||
std::vector<std::string> ModeLenses();
|
||||
// lens_file.replace('.md', ''); `persona:<name>` for a persona's
|
||||
// instance.
|
||||
std::string LensName(std::string_view lensFile, std::string_view persona = {});
|
||||
// Every lens of the gates, and the persona lens in the kernel modes.
|
||||
std::vector<std::string> ModeLenses(std::string_view mode = "commits");
|
||||
// The gates with their lens files. off: the lenses the config turns off;
|
||||
// only keeps (test runs), without drops (an owner ruling); an empty span
|
||||
// filters nothing, and a gate left empty disappears.
|
||||
std::vector<Gate> GatesFor(std::span<const std::string> only = {}, std::span<const std::string> without = {},
|
||||
std::span<const std::string> off = {});
|
||||
std::vector<Gate> GatesFor(std::string_view mode, std::span<const std::string> only, std::span<const std::string> without,
|
||||
std::span<const std::string> off);
|
||||
|
||||
// The whole job (null when the lens has none) and the block jobs.
|
||||
struct LensPlan {
|
||||
|
|
@ -194,13 +247,16 @@ export namespace Crafter::Review::Plan {
|
|||
std::vector<Json> blocks;
|
||||
};
|
||||
// unitsFilter: --units (empty: every unit); exclude: the functional
|
||||
// lens's path globs.
|
||||
// lens's path globs; persona: the reviewer a persona instance reads as;
|
||||
// excludeUnits: the unit ids a persona's whole pass marked not-mine.
|
||||
LensPlan PlanLens(std::string_view lensFile, const Json& units, std::span<const std::string> lines,
|
||||
std::span<const std::string> unitsFilter = {}, std::span<const std::string> exclude = {});
|
||||
std::span<const std::string> unitsFilter = {}, std::span<const std::string> exclude = {}, std::string_view persona = {},
|
||||
std::span<const std::string> excludeUnits = {});
|
||||
|
||||
// The model is part of the key (a verdict bought from one model is not
|
||||
// evidence for another); the effort is not. ident replaces the unit id for
|
||||
// a unit that is keyed on its content. nullopt: the job is not reusable.
|
||||
// a unit that is keyed on its content; a persona's block carries the
|
||||
// persona's name. nullopt: the job is not reusable.
|
||||
std::optional<std::string> ReuseKey(const Json& job, std::string_view lensFile, std::string_view unitText, std::vector<std::string> deps,
|
||||
std::vector<std::string> inForceIds, std::string_view charterSha, std::int32_t promptVersion,
|
||||
std::string_view ident = {});
|
||||
|
|
@ -223,7 +279,10 @@ export namespace Crafter::Review::Plan {
|
|||
std::vector<std::string> docs;
|
||||
std::string message;
|
||||
};
|
||||
PatchParts PartsOf(std::string_view patchText);
|
||||
// docFiles false (a kernel series): nothing is documentation - a .md or
|
||||
// .rst hunk is part of the code of its patch, as the kernel lenses read
|
||||
// it.
|
||||
PatchParts PartsOf(std::string_view patchText, bool docFiles = true);
|
||||
|
||||
// What the code keys of a range are built from, by commit number K.
|
||||
struct CommitCode {
|
||||
|
|
@ -234,14 +293,18 @@ export namespace Crafter::Review::Plan {
|
|||
std::string range;
|
||||
std::map<std::int64_t, std::string> upto;
|
||||
std::string base;
|
||||
bool kernel = false;
|
||||
};
|
||||
CommitCode CommitCodeOf(const std::map<std::int64_t, std::string>& patches);
|
||||
// kernel: the series mode's code - nothing is documentation, and the
|
||||
// message of each patch is kept for its `absent` slot (a kernel reviewer
|
||||
// looks there for a trailer or a test statement).
|
||||
CommitCode CommitCodeOf(const std::map<std::int64_t, std::string>& patches, bool kernel = false);
|
||||
|
||||
// (ident, deps) of a code unit: a hunk or a file header is keyed on its
|
||||
// file and its own normalised text, the two per-commit slots on that
|
||||
// commit's position and code, the code of the whole range, its
|
||||
// documentation files, and for `absent` whether it has a body. Every code
|
||||
// unit depends on the base.
|
||||
// documentation files, and for `absent` whether it has a body (a kernel
|
||||
// series: its message). Every code unit depends on the base.
|
||||
std::pair<std::string, std::vector<std::string>> CodeKeyParts(std::string_view unitId, const CommitCode& cc);
|
||||
std::optional<std::string> CodeReuseKey(const Json& job, std::string_view lensFile, std::string_view unitText, const CommitCode& cc,
|
||||
std::span<const std::string> inForceIds, std::string_view charterSha, std::int32_t promptVersion,
|
||||
|
|
@ -278,6 +341,14 @@ export namespace Crafter::Review::Plan {
|
|||
std::optional<std::string> WholeCodeKey(const Json& job, std::string_view lensFile, const CommitCode& cc, std::span<const std::string> inForceIds,
|
||||
std::string_view charterSha, std::int32_t promptVersion, std::string_view environment = {});
|
||||
|
||||
// The dependencies of a text unit's verdict in the kernel modes: the
|
||||
// URLs of every [n] it cites, the anchor text when it carries a dated or
|
||||
// versioned statement (otherwise every anchor-date bump would invalidate
|
||||
// every unit), and every R-unit it names verbatim. refs: the parsed
|
||||
// reference table ({"n": url} rows).
|
||||
std::vector<std::string> TextDeps(std::string_view unitText, const Json& units, std::span<const std::string> lines,
|
||||
std::span<const std::pair<std::string, std::string>> refs, std::string_view anchorText);
|
||||
|
||||
// How many clean reads a stored result stands for: one per round that
|
||||
// read its key clean.
|
||||
std::int64_t ReadsOf(const Json& entry);
|
||||
|
|
|
|||
Loading…
Reference in a new issue