FN-9178: Classify awaited core run-audit emitters

Document and ratchet which core run-audit writers may remain lifecycle-coupled.

- classify awaited emitters by bounded-isolation safety and preserve transactional boundaries
- characterize hostile sink behavior across store- and data-layer call sites
- fail closed when new awaited audit writers lack an explicit classification

Files changed:
 AGENTS.md                                          |   1 +
 docs/run-audit.md                                  |   6 +
 .../core-run-audit-emitter-isolation.test.ts       |  71 ++++-
 .../excluded-awaited-run-audit-layer-sites.test.ts | 332 +++++++++++++++++++++
 .../excluded-awaited-run-audit-store-sites.test.ts | 236 +++++++++++++++
 5 files changed, 645 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-9178

Fusion-Task-Lineage: 25fed6a5-4f2f-4d4b-8724-838eff4323c8

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
gsxdsm
2026-08-20 00:28:59 -07:00
parent f5192a5d15
commit 649b901bbd
5 changed files with 645 additions and 1 deletions

View File

@@ -83,3 +83,9 @@ This applies to executor, run-auditor, self-healing, merger, PR reconciliation,
### Core emit-seam policy
Core best-effort emitters use `packages/core/src/run-audit/emit-bounded-run-audit.ts`. This is a deliberate copy of the engine seam because `@fusion/core` cannot import `@fusion/engine`; it synchronously invokes a valid sink, then absorbs throws, rejection, timeout, and late settlement without making telemetry lifecycle-load-bearing. Transactional writers and explicitly awaited durability/ordering writers remain unbounded. `packages/core/src/__tests__/core-run-audit-sink-health.test.ts` and `core-run-audit-emitter-isolation.test.ts` respectively enforce hostile-sink behavior and source routing.
### Awaited core exclusion decision
FN-9178 classified the remaining awaited sites with hostile-sink characterization tests. `task-deleted-outbox:catch-up`, `:reconciliation-fallback`, `:lease-fenced`, `:retention-pruned`, and recall-capture audit events are class A (bound-safe) candidates. `task:workflow-switch-torn` and `task:reconcile-phantom-committed-reservation` are class B: a future bounded seam must return `recorded`, `failed`, `timed-out`, or `absent`, because their throw/result payload depends on audit outcome. `task:bypass-review`, `task:resume-step`, and both resurrection-blocked records are class C and intentionally unbounded: they claim persistence before return, destructive cleanup, or a forensic throw.
All `recordRunAuditEventWithinTransaction(tx, ...)` calls and the `recordRunAuditEventBackend(tx, ...)` transactional call are permanently out of scope. Their audit row shares a transaction with the mutation it describes; bounding would split that atomicity. The full matrix and evidence pointers are in the FN-9178 `decision` task document; `excluded-awaited-run-audit-store-sites.test.ts`, `excluded-awaited-run-audit-layer-sites.test.ts`, and the core routing ratchet pin this boundary.