test(audit): every defect keeps a named regression test (P10)
The audit's 24 defects must not lose their reproductions quietly; the table names the test guarding each, checks the runbook names only tools that exist, and records the mirror and its For-P12 targets in docs/testing.md. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HS8WZziDnyxunC23MUxrLp
This commit is contained in:
1 parent
a2f013955c
commit
01aff4c04e
2 files changed
+295
No files matched your search
@@ -0,0 +1,265 @@
|
|||||||
|
//! The re-audit's engineering mirror (plan P10; `docs/runbooks/re-audit.md`):
|
||||||
|
//! every defect the 2026-10-16 audit found (1 to 20), P0 (21, 22) and P3
|
||||||
|
//! (23, 24) has a named regression test somewhere in the workspace, and the
|
||||||
|
//! runbook names only tools and commands that exist.
|
||||||
|
//!
|
||||||
|
//! The list below is the single place that says which test stands guard for
|
||||||
|
//! which defect. A test renamed or deleted fails here, so a defect's
|
||||||
|
//! reproduction cannot be lost quietly. This proves the tests exist, are
|
||||||
|
//! real `#[test]`s and are not ignored; that they pass is `cargo test`'s
|
||||||
|
//! job (the runbook's step 4 runs them by name).
|
||||||
|
//!
|
||||||
|
//! SOURCE: plan/served.md 8.0 ("defect n") and P10 step 2.
|
||||||
|
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
fn root() -> PathBuf {
|
||||||
|
Path::new(env!("CARGO_MANIFEST_DIR"))
|
||||||
|
.join("../..")
|
||||||
|
.canonicalize()
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read(rel: &str) -> String {
|
||||||
|
std::fs::read_to_string(root().join(rel)).unwrap_or_else(|e| panic!("{rel}: {e}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `(defect, test name, file)`. Defect 2 is closed by D-12 and D-47 (the
|
||||||
|
/// rule it now shows is that a reversal needs no receipt of its own);
|
||||||
|
/// defect 20 (the migration scripts) was retired at the cutover and is
|
||||||
|
/// checked separately below.
|
||||||
|
const DEFECTS: [(u32, &str, &str); 23] = [
|
||||||
|
(
|
||||||
|
1,
|
||||||
|
"defect1_two_member_llc_first_year_regression",
|
||||||
|
"crates/ledger-core/tests/spec_cash_flow.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
2,
|
||||||
|
"a_reversal_needs_no_receipt_of_its_own",
|
||||||
|
"crates/ledger-cli/tests/drafts.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
3,
|
||||||
|
"get_receipt_default_has_text_and_no_bytes",
|
||||||
|
"crates/ledger-cli/tests/evidence.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
4,
|
||||||
|
"same_bytes_one_record_many_links",
|
||||||
|
"crates/ledger-store/tests/attachments.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
5,
|
||||||
|
"a_draft_waits_for_its_receipt_and_posts",
|
||||||
|
"crates/ledger-cli/tests/drafts.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
6,
|
||||||
|
"digest_since_seq_is_posting_time",
|
||||||
|
"crates/ledger-cli/tests/drafts.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
7,
|
||||||
|
"the_readme_lists_what_the_iif_writes_differently",
|
||||||
|
"crates/ledger-package/tests/package.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
8,
|
||||||
|
"add_account_warns_without_tax_category_defect_8",
|
||||||
|
"crates/ledger-cli/tests/spec_tax_policy.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
9,
|
||||||
|
"defect9_a_new_schedule_spreads_by_the_day",
|
||||||
|
"crates/ledger-core/tests/schedules.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
10,
|
||||||
|
"annotations_replay_and_project",
|
||||||
|
"crates/ledger-store/tests/attachments.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
11,
|
||||||
|
"defect11_the_directory_shows_a_members_tin_last4",
|
||||||
|
"crates/ledger-cli/tests/spec_vault.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
12,
|
||||||
|
"payment_methods_round_trip_and_classify_payments",
|
||||||
|
"crates/ledger-cli/tests/spec_1099.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
13,
|
||||||
|
"four_contributed_devices_each_take_the_lower_of_value_and_basis",
|
||||||
|
"crates/ledger-core/tests/spec_asset_basis.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
14,
|
||||||
|
"defect14_party_totals_take_a_basis",
|
||||||
|
"crates/ledger-cli/tests/spec_party_totals.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
15,
|
||||||
|
"rename_account_end_to_end_defect_15",
|
||||||
|
"crates/ledger-cli/tests/mcp_journeys.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
16,
|
||||||
|
"one_default_period_everywhere_defect_16",
|
||||||
|
"crates/ledger-cli/tests/mcp_journeys.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
17,
|
||||||
|
"the_audit_odd_cent_never_piles_up_across_closes",
|
||||||
|
"crates/ledger-core/tests/odd_cent.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
18,
|
||||||
|
"undecided_is_not_not_reportable",
|
||||||
|
"crates/ledger-core/tests/form1099.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
19,
|
||||||
|
"no_tool_takes_a_path",
|
||||||
|
"crates/ledger-mcp/src/server_tests.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
21,
|
||||||
|
"as_of_package_iif_stops_at_as_of",
|
||||||
|
"crates/ledger-package/tests/package.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
22,
|
||||||
|
"defect22_depreciation_through_mid_final_month_is_prorated_not_plugged",
|
||||||
|
"crates/ledger-core/tests/spec_assets_payroll.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
23,
|
||||||
|
"a_vendor_marked_no_1099_is_not_undecided",
|
||||||
|
"crates/ledger-cli/tests/spec_1099.rs",
|
||||||
|
),
|
||||||
|
(
|
||||||
|
24,
|
||||||
|
"defect24_an_accrual_through_another_liability_counts_once",
|
||||||
|
"crates/ledger-core/tests/spec_party_totals.rs",
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
/// Defects 1 to 24 each have a named test that exists, is a test, and is
|
||||||
|
/// not ignored (defect 20 is the retired scripts, below).
|
||||||
|
#[test]
|
||||||
|
fn every_defect_reproduction_is_a_named_test() {
|
||||||
|
let mut covered: Vec<u32> = DEFECTS.iter().map(|d| d.0).collect();
|
||||||
|
covered.push(20);
|
||||||
|
covered.sort_unstable();
|
||||||
|
assert_eq!(
|
||||||
|
covered,
|
||||||
|
(1..=24).collect::<Vec<u32>>(),
|
||||||
|
"a defect is missing"
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut missing = Vec::new();
|
||||||
|
for (defect, name, file) in DEFECTS {
|
||||||
|
let text = read(file);
|
||||||
|
let lines: Vec<&str> = text.lines().collect();
|
||||||
|
let needle = format!("fn {name}(");
|
||||||
|
let Some(at) = lines.iter().position(|l| {
|
||||||
|
l.trim_start().starts_with(&needle)
|
||||||
|
|| l.trim_start().starts_with(&format!("pub {needle}"))
|
||||||
|
}) else {
|
||||||
|
missing.push(format!("defect {defect}: no `fn {name}` in {file}"));
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
// The attributes and doc lines above the function, up to the
|
||||||
|
// previous blank line or item.
|
||||||
|
let above: String = lines[at.saturating_sub(8)..at].join("\n");
|
||||||
|
let in_proptest = text.contains("proptest!");
|
||||||
|
if !above.contains("#[test]") && !in_proptest {
|
||||||
|
missing.push(format!(
|
||||||
|
"defect {defect}: `{name}` in {file} is not a #[test]"
|
||||||
|
));
|
||||||
|
}
|
||||||
|
if above.contains("#[ignore") {
|
||||||
|
missing.push(format!("defect {defect}: `{name}` in {file} is ignored"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert!(missing.is_empty(), "{}", missing.join("\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Defect 20, the migration scripts, was retired at the cutover: there is
|
||||||
|
/// no tool for them, and none may come back as a way past the journal.
|
||||||
|
/// The defect 19 mirror (`import_local_file` and every path parameter) is
|
||||||
|
/// `no_tool_takes_a_path` above.
|
||||||
|
#[test]
|
||||||
|
fn defect_20_no_migration_tool_exists() {
|
||||||
|
let scopes = read("crates/ledger-mcp/src/scopes.rs");
|
||||||
|
for line in scopes.lines().filter(|l| l.contains("(\"books.")) {
|
||||||
|
for banned in [
|
||||||
|
"migrate",
|
||||||
|
"import_local_file",
|
||||||
|
"import_sheet",
|
||||||
|
"verify_sheet",
|
||||||
|
] {
|
||||||
|
assert!(!line.contains(banned), "a retired tool is back: {line}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The runbook names only tools and commands that exist: each
|
||||||
|
/// `books.<name>` is in the scopes table (the 8.0.3 list of tools), each
|
||||||
|
/// `wanderbooks <command>` is a command `main.rs` dispatches, and each
|
||||||
|
/// test file it names is a file.
|
||||||
|
#[test]
|
||||||
|
fn the_re_audit_runbook_names_only_what_exists() {
|
||||||
|
let runbook = read("docs/runbooks/re-audit.md");
|
||||||
|
let scopes = read("crates/ledger-mcp/src/scopes.rs");
|
||||||
|
let main = read("crates/ledger-cli/src/main.rs");
|
||||||
|
|
||||||
|
let mut tools = Vec::new();
|
||||||
|
let mut rest = runbook.as_str();
|
||||||
|
while let Some(i) = rest.find("books.") {
|
||||||
|
let tail = &rest[i..];
|
||||||
|
let end = tail
|
||||||
|
.find(|c: char| !(c.is_ascii_alphanumeric() || c == '_' || c == '.'))
|
||||||
|
.unwrap_or(tail.len());
|
||||||
|
let name = tail[..end].trim_end_matches('.');
|
||||||
|
// Prose such as "books.start's" ends at the apostrophe; a bare
|
||||||
|
// "books." (the company's books followed by a full stop) is not a name.
|
||||||
|
if name.len() > "books.".len() && !tools.contains(&name.to_string()) {
|
||||||
|
tools.push(name.to_string());
|
||||||
|
}
|
||||||
|
rest = &tail[end.max(1)..];
|
||||||
|
}
|
||||||
|
assert!(
|
||||||
|
tools.len() > 20,
|
||||||
|
"the runbook should name its tools: {tools:?}"
|
||||||
|
);
|
||||||
|
let unknown: Vec<&String> = tools
|
||||||
|
.iter()
|
||||||
|
.filter(|t| !scopes.contains(&format!("(\"{t}\"")))
|
||||||
|
.collect();
|
||||||
|
assert!(
|
||||||
|
unknown.is_empty(),
|
||||||
|
"tools the runbook names that do not exist: {unknown:?}"
|
||||||
|
);
|
||||||
|
|
||||||
|
for cmd in ["gui", "connect"] {
|
||||||
|
if runbook.contains(&format!("wanderbooks {cmd}")) {
|
||||||
|
assert!(main.contains(&format!("\"{cmd}\"")), "no command {cmd}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert!(
|
||||||
|
runbook.contains("wanderbooks gui"),
|
||||||
|
"step 6 names the viewer"
|
||||||
|
);
|
||||||
|
|
||||||
|
for step in 1..=8 {
|
||||||
|
assert!(
|
||||||
|
runbook.contains(&format!("## Step {step}.")),
|
||||||
|
"the runbook lost step {step}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// The runbook must not point at the data root or tell anyone to read it.
|
||||||
|
assert!(!runbook.contains("wanderbooks.v"), "names a database file");
|
||||||
|
}
|
||||||
@@ -3922,3 +3922,33 @@ export gate (`cpa_audit_standing`'s four conditions and its feature test,
|
|||||||
the `refuse`/`warn` split, the reason's trim); `audit_items` in Needs
|
the `refuse`/`warn` split, the reason's trim); `audit_items` in Needs
|
||||||
attention (the declared test, the attested set, the last-ended fiscal
|
attention (the declared test, the attested set, the last-ended fiscal
|
||||||
year, the three year conditions).
|
year, the three year conditions).
|
||||||
|
|
||||||
|
## P10: the re-audit runbook's mirror
|
||||||
|
|
||||||
|
`docs/runbooks/re-audit.md` is the owner's acceptance, run on his books
|
||||||
|
through the MCP alone. What CI can check of it is in
|
||||||
|
`crates/ledger-cli/tests/defects.rs`:
|
||||||
|
|
||||||
|
- `every_defect_reproduction_is_a_named_test`: a table of `(defect, test
|
||||||
|
name, file)` for the 2026-10-16 audit's defects 1 to 19, P0's 21 and 22
|
||||||
|
and P3's 23 and 24 (23 rows); each named function exists in its file, is
|
||||||
|
a `#[test]` (or inside `proptest!`) and is not `#[ignore]`d. Defect 2 is
|
||||||
|
closed by D-12 and D-47, so its row is the rule as it now stands
|
||||||
|
(`a_reversal_needs_no_receipt_of_its_own`).
|
||||||
|
- `defect_20_no_migration_tool_exists`: defect 20 (the migration scripts)
|
||||||
|
was retired at the cutover; no tool of that kind is in the scopes table.
|
||||||
|
- `the_re_audit_runbook_names_only_what_exists`: every `books.<name>` in
|
||||||
|
the runbook is in `crates/ledger-mcp/src/scopes.rs`, the commands it
|
||||||
|
names are dispatched by `main.rs`, and its eight steps are present.
|
||||||
|
|
||||||
|
The mirror proves the tests exist, not that they pass; the runbook's step 4
|
||||||
|
runs them by name. No CI job was added: the test runs in the existing
|
||||||
|
`check` job's `cargo test --workspace`. The run itself (a counted
|
||||||
|
attestation on every receipt and entry, the two CPA packages equal, the
|
||||||
|
sign-off) is the owner's and has no CI equivalent.
|
||||||
|
|
||||||
|
**For P12 (mutation targets):** the `DEFECTS` table's file/name lookup (a
|
||||||
|
`starts_with` on `fn <name>(`; the `#[test]`/`#[ignore]` window of eight
|
||||||
|
lines above it) and the scopes-line scan in `defect_20_*`. A mutant that
|
||||||
|
widens the window or drops the `ignore` check survives only if no ignored
|
||||||
|
or untested name is in the table; the table is the oracle.
|
||||||
Reference in new issue
Block a user