Crafter.Review/interfaces/Crafter.Review-Tools.cppm

44 lines
2.4 KiB
Text
Raw Permalink Normal View History

feat(pipeline): the pure pipeline, checked against its goldens The modules that turn a frozen range into passes and passes into a verdict: :Schema, :Tools (the DENY, git and base lists, a leaf, so the config and the pool both read them), :Plan, :Artifact, :Inventory, :Dispositions, :State, :Normalize, :Stream, :Prompt, :Config, and the URL half of :PgWire. Units, jobs, results, the config and the claude stream stay JSON from end to end, so every key keeps its place; :Text gives JSON values truthiness, get, ==, membership and Str(), and throws Dyn::Error under a name for each kind of unexpected data. Exactness where the bytes are seen: - the stream classifiers are hand-written scanners with case-insensitive folds (the Kelvin sign is a k), Unicode \b and \s, and `.` stopping at \n; the SQL call detection takes `<exe> sql` with any path before it; - config problems carry the JSON scanner's and the UTF-8 decoder's own texts, positions included; - a float total is Neumaier's compensated sum, and the build passes -ffp-contract=off: -march=native would fuse a*b+c; - `crafter-review inventory` and `config` print what the goldens record, byte for byte (the fixture and 14 configs, broken ones included); a message names this binary as the command to run. tests/Goldens: the recorded answers over the fixtures next to them (the commits fixture, a rich versioned series with CRLF, a folded subject, Markdown headings in and out of fences, the code-key rewrites); the suite compares 2304 results as DumpFile writes them, so a key out of order fails too. All agree. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 06:48:55 +01:00
// SPDX-License-Identifier: AGPL-3.0-only
// SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts®
export module Crafter.Review:Tools;
import std;
// The tool lists every pass is started with: what is denied whatever the
// allowlist says, the read-only git verbs, the base allowlist, and the
// Playwright MCP server's tools by name. A leaf of its own: the config checks
// its extra tools against DENY and the pool builds every command line from
// these, so with the lists in either of them the two would import each
// other.
export namespace Crafter::Review::Tools {
// The Playwright MCP server, as --mcp-config names it.
constexpr std::string_view McpServer = "playwright";
constexpr std::array<std::string_view, 24> McpTools = {
"browser_navigate", "browser_navigate_back", "browser_snapshot", "browser_click", "browser_type", "browser_fill_form",
"browser_select_option", "browser_press_key", "browser_hover", "browser_drag", "browser_drop", "browser_handle_dialog",
"browser_wait_for", "browser_take_screenshot", "browser_console_messages", "browser_network_requests", "browser_network_request",
"browser_evaluate", "browser_tabs", "browser_resize", "browser_close", "browser_find", "browser_emulate_media", "browser_file_upload",
};
// browser_run_code_unsafe runs arbitrary Node code in the server's
// process.
constexpr std::array<std::string_view, 1> McpDenied = {"browser_run_code_unsafe"};
// mcp__playwright__<tool> for each.
std::vector<std::string> McpToolNames();
std::vector<std::string> McpDeniedToolNames();
// Never, whatever the allowlist says: writes, the network beyond the
// browser, the agent tools, package managers, stacks, a database client
// that commits (psql: the supabase environment's helper is the one way
// in, every call rolled back).
const std::vector<std::string>& Deny();
constexpr std::array<std::string_view, 22> GitReadOnly = {
"diff", "log", "show", "grep", "blame", "ls-tree", "ls-files", "cat-file", "rev-parse", "rev-list", "hash-object", "describe",
"merge-base", "name-rev", "shortlog", "for-each-ref", "branch", "tag", "status", "worktree list", "remote", "count-objects",
};
const std::vector<std::string>& BaseAllow();
// Does Deny() override this allowlist entry? `Bash(psql -h x:*)` falls
// under `Bash(psql:*)`, `Bash(psqlx:*)` does not.
bool Denied(std::string_view tool);
}