March Docs

Diagnose

Diagnose: the findings forge diagnose reports, for a program to run on itself (design section 5.3; R3 of specs/plans/2026-09-28-observe-recon-shell-plan.md).

Each finding is a pure function over two observe SNAPSHOT envelopes taken a window apart. run takes those snapshots of the running program (through the same in-process query Recon uses); findings takes any two envelopes, so the checks are tested on fixtures with no live node.

forge/lib/diagnose.ml is the same list in OCaml, for forge. Both are tested against forge/test/fixtures/diagnose (expected.txt names each fixture's findings), so a threshold changed in one place and not the other fails a test. Change them together.

Types

typeFindingFinding = { id : String, severity : String, rows : List(Int), next : String }#

Functions

fncoveragecoverage(before : Json.JsonValue, after : Json.JsonValue) : List(String)#

Reports actor or crash sections truncated in either SNAPSHOT envelope.

fnfindingsfindings(before : Json.JsonValue, after : Json.JsonValue) : List(Finding)#

Every finding over two SNAPSHOT envelopes (as the observe socket or observe_query returns them), before taken a window ahead of after. Nil means none fired; probes this backend cannot run (cluster suspicion, lost global names) are not in the list at all.

fnids_ofids_of(fs : List(Finding)) : List(String)#

\

fnrunrun(_c : Cap(Actor.Introspect), window_ms : Int) : List(Finding)#

Run the findings on this program: two snapshots window_ms apart, with this green thread asleep between them.

    match Diagnose.run(c, 1000) do
      Nil -> ()
      fs -> List.each(fs, fn f -> println(f.id ++ ": " ++ f.next))
    end