trusty-common 0.49.0

Shared utilities and provider-agnostic streaming chat (ChatProvider, OllamaProvider, OpenRouter, tool-use) for trusty-* projects
Documentation
{
  "artifact_version": 1,
  "crate": "trusty-common",
  "items": [
    {
      "invariants": [
        "Pure with respect to this value: no field is mutated and no file is written. For a fixed filesystem state the result is stable across calls.",
        "The ordering it induces is the ONE ordering used for both sorting and watermark membership; the two never diverge."
      ],
      "kind": "function",
      "path": "trusty_common::catchup::session_finder::PausedSession::sort_key",
      "postconditions": [
        "`None` means \"this session cannot be dated at all\", which since #5072 means EXCLUDED from a watermark-filtered digest. It does not mean \"always included\" — that was the reading `is_none_or` encoded, and it inverted a real project's digest.",
        "Both variants receive the same file-mtime fallback, so neither arm can be undatable merely because its recorded timestamp is missing or malformed. `None` survives only for a session with no file behind it."
      ],
      "preconditions": [
        "None. Every `PausedSession` value is accepted."
      ]
    },
    {
      "invariants": [
        "`kept.len() + dropped_undatable <= sessions.len()`, with the shortfall being sessions that were datable and did not postdate the watermark.",
        "No session is both kept and counted as dropped.",
        "The count is a RECEIPT, not diagnostics: a withheld session falls outside every future window once the watermark advances, so it must be reportable in the return value and not only on stderr."
      ],
      "kind": "function",
      "path": "trusty_common::catchup::session_finder::filter_sessions_since",
      "postconditions": [
        "With `watermark == None`, `kept` is `sessions` unchanged in length and order, and `dropped_undatable == 0`.",
        "With `watermark == Some(wm)`, `kept` contains exactly those sessions whose `sort_key()` is `Some(ts)` with `ts > wm`. The comparison is STRICT, so a session paused exactly at the watermark is excluded.",
        "`dropped_undatable` counts exactly the sessions whose `sort_key()` is `None`. Since #5072 an undatable session is WITHHELD, not admitted — the inverse of the `is_none_or` predicate this replaced.",
        "`kept` preserves the relative order of the input."
      ],
      "preconditions": [
        "None. Every `sessions` list and every `watermark` is accepted; an empty list and a `None` watermark are ordinary inputs, not edge cases."
      ]
    },
    {
      "invariants": [
        "Read-only: no file, directory, or session-log entry is created, modified, or removed.",
        "Referentially transparent for a fixed filesystem state — repeated calls with equal arguments return equal results."
      ],
      "kind": "function",
      "path": "trusty_common::catchup::session_finder::latest_trusty_mpm_snapshot",
      "postconditions": [
        "Returns `None` whenever `session_id` is `None`, for every `project_dir`, including one holding snapshots that would have matched before #5272.",
        "A returned path is always a snapshot the session log attributes to `session_id`; it is never selected by recency across session boundaries.",
        "A returned path is `<project_dir>/.trusty-mpm/sessions/` rooted."
      ],
      "preconditions": [
        "`session_id` is the ATTRIBUTION of the asking session, not a search hint. `None` asserts \"the caller did not identify itself\". It does NOT mean \"any session will do\" — that was the pre-#5272 reading, and it is the precondition that changed under a byte-identical signature.",
        "`project_dir` need not exist; a missing directory yields `None`, not an error."
      ]
    },
    {
      "invariants": [
        "Reads the environment but never writes it, and never caches — a region changed between two calls is observed by the second.",
        "The precedence walk itself is pure; the env read is lifted to the single call site here so [`resolve_region_from`] stays provable without mutating process-wide state."
      ],
      "kind": "function",
      "path": "trusty_common::chat::bedrock_provider::resolve_bedrock_region",
      "postconditions": [
        "Returns the first non-empty value in the strict order `explicit` > `TRUSTY_AWS_REGION` > `AWS_REGION` > [`DEFAULT_BEDROCK_REGION`] (#5652).",
        "Never returns an empty string, because the last tier is a non-empty constant.",
        "Total: there is no input for which this fails or panics."
      ],
      "preconditions": [
        "None. `explicit` may be `None`, `Some(\"\")`, or any string; an empty string at ANY tier is treated as unset rather than as a chosen region."
      ]
    },
    {
      "invariants": [
        "Pure: no I/O, no logging, no environment access.",
        "The output format is depended on by `memory_core::filter`; it is a compatibility surface, not a cosmetic choice."
      ],
      "kind": "function",
      "path": "trusty_common::credentials::redact_secret",
      "postconditions": [
        "The result is NON-REVERSIBLE: it never contains more than the first [`DEFAULT_HEAD_LEN`] characters of `secret`.",
        "When `secret` is at or under [`DEFAULT_HEAD_LEN`] CHARACTERS, no head is shown at all (#2475) — showing the head of a short secret discloses the whole value.",
        "The reported length is `secret.len()`, a BYTE count, while the head is taken in CHARACTERS. The two units differ deliberately and the char-wise `take` is what keeps a multi-byte secret from panicking.",
        "Total: never panics, for any input."
      ],
      "preconditions": [
        "None. Every `&str` is accepted, including the empty string and non-ASCII input. The caller decides whether the value is secret-shaped; this function does not gate on length."
      ]
    },
    {
      "invariants": [
        "Pure: no I/O, no environment access, `secrets` is not mutated.",
        "The result is LOWER-RISK, NOT PROVEN SECRET-FREE. It removes only values the caller already holds; a secret the process does not know passes through untouched. This is a bound on what the postconditions above claim, and it is why scrubbed text is not a licence to route untrusted text into a sink that could not otherwise hold a secret."
      ],
      "kind": "function",
      "path": "trusty_common::credentials::scrub_secrets",
      "postconditions": [
        "For every needle of at least [`MIN_SCRUBBABLE_SECRET_CHARS`] characters, the result contains NO occurrence of that needle.",
        "A needle under that length — the empty string included — is left unapplied, and text that happens to contain it is returned unchanged.",
        "Overlapping needles are applied longest-first, so a secret that is a prefix of another cannot leave the longer one's tail behind.",
        "Returns `text` unchanged when no needle survives the guard or none occurs."
      ],
      "preconditions": [
        "None. `secrets` may be empty and may contain empty or short values; those are skipped by the guard rather than rejected."
      ]
    },
    {
      "invariants": [
        "Read-only: unlike `check_already_running`, it never deletes a stale file.",
        "The path it reads is the one `write_daemon_addr` writes and `remove_daemon_addr` deletes; the three share one layout so a third trusty-* daemon cannot invent another location."
      ],
      "kind": "function",
      "path": "trusty_common::daemon_addr::read_daemon_addr",
      "postconditions": [
        "`Ok(None)` means the address file DOES NOT EXIST, and only that. It never stands in for a read that failed.",
        "`Err` means the address is UNKNOWN — a permission denial, a corrupt data directory, or any other I/O failure. Distinguishing it from `Ok(None)` is this function's reason to be fallible, and is what lets callers avoid string-matching on error messages.",
        "`Ok(Some(s))` returns the file's contents with surrounding whitespace trimmed. `s` may be empty if the file is empty or blank; this function does not validate that `s` is a well-formed address."
      ],
      "preconditions": [
        "None. `app_name` need not name a daemon that has ever run."
      ]
    },
    {
      "invariants": [
        "Read-only, and does not probe the address — a returned url means \"recorded\", never \"reachable\". Use `check_already_running` for liveness."
      ],
      "kind": "function",
      "path": "trusty_common::daemon_addr::resolve_daemon_base_url",
      "postconditions": [
        "`Some(url)` is returned ONLY from an address the named daemon actually recorded. No port, host, or scheme is ever guessed — the #2030 discovery-first rule, because a wrong guessed port fails worse than a clean skip.",
        "A returned url carries exactly one scheme: the recorded address is returned as-is when it already starts with `http://` or `https://`, and prefixed with `http://` otherwise. It is never double-prefixed.",
        "`None` is returned when the daemon never started, when the address file is empty or blank, and when it is unreadable. Callers read `None` as \"skip, not discoverable\" — it is deliberately NOT distinguishable from an I/O error here, because every one of those cases has the same correct response.",
        "Total: never panics and never returns `Err`; I/O failure collapses to `None`."
      ],
      "preconditions": [
        "None. `app_name` need not name a daemon that has ever run."
      ]
    },
    {
      "invariants": [
        "Pure: no I/O, no logging, no environment access.",
        "The output format is depended on by `memory_core::filter`; it is a compatibility surface, not a cosmetic choice."
      ],
      "kind": "function",
      "path": "trusty_common::inference::credentials::redact_secret",
      "postconditions": [
        "The result is NON-REVERSIBLE: it never contains more than the first [`DEFAULT_HEAD_LEN`] characters of `secret`.",
        "When `secret` is at or under [`DEFAULT_HEAD_LEN`] CHARACTERS, no head is shown at all (#2475) — showing the head of a short secret discloses the whole value.",
        "The reported length is `secret.len()`, a BYTE count, while the head is taken in CHARACTERS. The two units differ deliberately and the char-wise `take` is what keeps a multi-byte secret from panicking.",
        "Total: never panics, for any input."
      ],
      "preconditions": [
        "None. Every `&str` is accepted, including the empty string and non-ASCII input. The caller decides whether the value is secret-shaped; this function does not gate on length."
      ]
    },
    {
      "invariants": [
        "Pure: no I/O, no environment access, `secrets` is not mutated.",
        "The result is LOWER-RISK, NOT PROVEN SECRET-FREE. It removes only values the caller already holds; a secret the process does not know passes through untouched. This is a bound on what the postconditions above claim, and it is why scrubbed text is not a licence to route untrusted text into a sink that could not otherwise hold a secret."
      ],
      "kind": "function",
      "path": "trusty_common::inference::credentials::scrub_secrets",
      "postconditions": [
        "For every needle of at least [`MIN_SCRUBBABLE_SECRET_CHARS`] characters, the result contains NO occurrence of that needle.",
        "A needle under that length — the empty string included — is left unapplied, and text that happens to contain it is returned unchanged.",
        "Overlapping needles are applied longest-first, so a secret that is a prefix of another cannot leave the longer one's tail behind.",
        "Returns `text` unchanged when no needle survives the guard or none occurs."
      ],
      "preconditions": [
        "None. `secrets` may be empty and may contain empty or short values; those are skipped by the guard rather than rejected."
      ]
    },
    {
      "invariants": [
        "Read-only: opens a read transaction and writes nothing.",
        "Counts only ACTIVE triples — a superseded or retracted triple is excluded even though its history row survives.",
        "The sum saturates rather than overflowing `u64`."
      ],
      "kind": "function",
      "path": "trusty_common::memory_core::store::kg_redb::KgStoreRedb::count_active_triples",
      "postconditions": [
        "`Ok(n)` means the read COMPLETED and `n` is the number of currently active triples. `Ok(0)` therefore means the graph is empty, and only that (#5384). Before 0.33.0 this returned a bare `u64` and a failed read also produced `0`, which `kg_query` reported as `graph_state: \"graph_empty\"` — the false claim #4775 exists to prevent.",
        "`Err` means the count is UNKNOWN. It never means zero, and a caller must not substitute one.",
        "Every read step propagates: `begin_read`, `open_table`, `iter`, and each per-row read."
      ],
      "preconditions": [
        "The store is open. No table need be populated — `open_with_intent` creates every table on open, so a missing table is a real failure and never means \"not written yet\"."
      ]
    },
    {
      "invariants": [
        "Read-only: unlike `check_already_running`, it never deletes a stale file.",
        "The path it reads is the one `write_daemon_addr` writes and `remove_daemon_addr` deletes; the three share one layout so a third trusty-* daemon cannot invent another location."
      ],
      "kind": "function",
      "path": "trusty_common::read_daemon_addr",
      "postconditions": [
        "`Ok(None)` means the address file DOES NOT EXIST, and only that. It never stands in for a read that failed.",
        "`Err` means the address is UNKNOWN — a permission denial, a corrupt data directory, or any other I/O failure. Distinguishing it from `Ok(None)` is this function's reason to be fallible, and is what lets callers avoid string-matching on error messages.",
        "`Ok(Some(s))` returns the file's contents with surrounding whitespace trimmed. `s` may be empty if the file is empty or blank; this function does not validate that `s` is a well-formed address."
      ],
      "preconditions": [
        "None. `app_name` need not name a daemon that has ever run."
      ]
    },
    {
      "invariants": [
        "Read-only, and does not probe the address — a returned url means \"recorded\", never \"reachable\". Use `check_already_running` for liveness."
      ],
      "kind": "function",
      "path": "trusty_common::resolve_daemon_base_url",
      "postconditions": [
        "`Some(url)` is returned ONLY from an address the named daemon actually recorded. No port, host, or scheme is ever guessed — the #2030 discovery-first rule, because a wrong guessed port fails worse than a clean skip.",
        "A returned url carries exactly one scheme: the recorded address is returned as-is when it already starts with `http://` or `https://`, and prefixed with `http://` otherwise. It is never double-prefixed.",
        "`None` is returned when the daemon never started, when the address file is empty or blank, and when it is unreadable. Callers read `None` as \"skip, not discoverable\" — it is deliberately NOT distinguishable from an I/O error here, because every one of those cases has the same correct response.",
        "Total: never panics and never returns `Err`; I/O failure collapses to `None`."
      ],
      "preconditions": [
        "None. `app_name` need not name a daemon that has ever run."
      ]
    },
    {
      "invariants": [
        "Back-off doubles from [`ETXTBSY_BACKOFF_MS`] per retry and saturates rather than overflowing if the attempt ceiling is ever raised.",
        "This function blocks the calling thread during back-off. Async callers must use [`retry_on_etxtbsy_async`], which applies an identical policy."
      ],
      "kind": "function",
      "path": "trusty_common::spawn_retry::retry_on_etxtbsy",
      "postconditions": [
        "Returns the outcome of the LAST invocation of `attempt`, whatever it is.",
        "`attempt` is invoked at least once, and at most [`ETXTBSY_MAX_ATTEMPTS`] times.",
        "A retry happens if and only if the previous outcome was `Err(ErrorKind::ExecutableFileBusy)` AND attempts remain. Every other outcome — success or any other error — is returned immediately, with no further invocation and no trailing sleep.",
        "The final `ExecutableFileBusy` error is returned rather than swallowed, so exhausting the budget is distinguishable from succeeding."
      ],
      "preconditions": [
        "`attempt` performs AT MOST ONE spawn per invocation and is safe to call again after an `ExecutableFileBusy` error. The type system does not enforce this; see the section above for why the errno classification, not the signature, is what makes it hold.",
        "`attempt` must not itself manufacture an `ExecutableFileBusy` from a non-exec failure, or it would drive a retry of work that already ran."
      ]
    },
    {
      "invariants": [
        "Yields to the runtime during back-off instead of blocking a worker thread. That is the ONLY difference from the blocking twin."
      ],
      "kind": "function",
      "path": "trusty_common::spawn_retry::retry_on_etxtbsy_async",
      "postconditions": [
        "Every postcondition of [`retry_on_etxtbsy`] holds verbatim: same invocation bounds, same retry-if-and-only-if condition, same returned outcome, same final-error propagation. The two share one `step` driver so the policies cannot drift apart."
      ],
      "preconditions": [
        "Identical to [`retry_on_etxtbsy`]: `attempt` performs at most one spawn per invocation and is safe to re-invoke after `ExecutableFileBusy`.",
        "`attempt` stays SYNCHRONOUS. Only the back-off is async, because `tokio::process::Command::spawn` is itself a sync call returning `io::Result<Child>`.",
        "Must be polled inside a tokio runtime, since back-off sleeps on it."
      ]
    }
  ]
}