feat(audit): fit the audit tools into the agent surface (P8)

After P5 merged first: a close leads to the audit and the period's
attestation, an audit run to its workpaper and the claims behind it, the
attest tools to the attestations and the CPA package; a refusal for want of
a standing audit is the guard audit_required with books.audit as its
remedy; the audit prompt runs the audit tools. policy.cpa_package_requires_audit,
unset, refuses once the books hold an audit run and warns before, so a
book that has not begun the programme is not stopped from its first handoff
by a rule it has not met; set to refuse, it holds from the start.
bookspec states B-45 (convention) in its checker.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HS8WZziDnyxunC23MUxrLp
This commit is contained in:
swaitsandClaude Fable 5.1 committed 2026-10-29 16:03:53 -06:00
1 parent 45bcce679b
commit 4774bd9abd
14 files changed
+139 -33

No files matched your search

+9 -1
View File
@@ -683,7 +683,15 @@ impl BooksServer {
.find(|q| q.name == named || q.id.to_string() == named)
.map(|q| q.id)
.ok_or_else(|| format!("no period {named:?}: books.list_periods lists them"))?;
let (a, _) = store.attest_period(period, claim).map_err(err)?;
let (a, _) = store.attest_period(period, claim).map_err(|e| match e {
ledger_store::StoreError::AuditRefused(why) => serde_json::json!({
"code": "audit_required",
"message": why,
"remedy_tool": "books.audit",
})
.to_string(),
other => other.to_string(),
})?;
Ok(Json(attest_out(&store, &a)?))
}