Skip to content

ShadowClaw 1.4.0

Risk Factors measured the host and stopped there. Four stress terms say how well a machine can be seen and how much pressure it is under — true about the machine, and silent about whether the thing an agent just did belongs there. Reading a credential and appending to a log file arrived identically: same host, same four numbers.

1.4.0 adds the second half. For every action the host plane attributes to an agent, shadowclaw/ktp/envelope.py computes an autonomy demand A and an environmental capacity E, and emits a Kinetic Envelope receipt carrying margin = 1 - A/E together with the supervision level that margin implies.

The unit is an action, not an agent and not a session

That is the TacticObservation the correlation plane already produces, which is also the unit a receipt is defined over — the granularity falls out of what was already there. Demand rises with five magnitudes the action can reach: privilege, reachability, irreversibility, credential reach, and configuration reach — the blast-radius signals Risk Factors held out deliberately. Capacity falls with four reducers, three of which the detector was already measuring about itself: how much of what it declared it would watch is reporting, how confidently the actor is attributed, and the adversarial_pressure reading carried straight in from Risk Factors. Only process novelty is new. See Autonomy demand and Environmental capacity for both tables.

Supervision is a floor, never an instruction

A gateway may raise its authorization tier to meet a supervision level and may never lower a tier already set; ShadowClaw emits the level and stops. silent_veto is where that discipline is easiest to lose, and it says the gateway should deny, carries KINETIC_CAPACITY_EXCEEDED in the evidence record, and stays silent to the agentic system. The sensor counts vetoes and prints the count in its run summary, which is the whole of what it does with one.

Detection does not consult any of this — the nine detection modules are checked for an import of the envelope, because a supervision level feeding back into scoring would make the detector act on its own output.

A receipt is consumable two ways, identically on both

It leaves as an OTLP log event on the path findings and Risk Factors already take, so no new transport is opened and nothing waits on a reply. It is also appended to ktp-envelope.jsonl in the ledger directory beside ktp-risk-factors.jsonl, which is what lets the oracle sidecar read receipts with --receipts and nothing else deployed. The record is flat on both paths because Risk Factors learned expensively that nested attributes break Loki's | json and render a working sensor as an empty panel — envelope.wire_record is the single definition the exporter and the file writer both call, asserted byte for byte.

Read capacity_known before the level: when Endpoint Security is unavailable, supervision is clamped to at least assisted however comfortable the margin looks, and the receipt marks that a level was raised rather than measured.

Minor rather than patch, and for the ordinary reason

This is additive. No signal, threshold, or score moved, and anything parsing 1.3.1 output reads 1.4.0 unchanged — but there is a new record shape with new attributes, and consumers can build on it.

This is also the first installer since 1.3.0 that behaves differently, which is worth stating because 1.3.1 argued the opposite: its uninstaller, dashboard JSON, and install.sh are all checkout-only assets, so a rebuilt 1.3.1 package would have installed the same sensor as the 1.3.0 one — the payload diff between those two tags shows only the version string changed under shadowclaw/. That is no longer true here. envelope.py sits inside the shadowclaw/ package and packaging/build.sh copies the whole package into the zipapp, so the payload difference from 1.3.0 is envelope.py, ledger.py, otlpevent.py, sensor.py, and settings.py. A .pkg install of 1.4.0 computes margins and writes receipts; a .pkg install of 1.3.0 or 1.3.1 does neither. Both switches, emit_ktp_envelope and ktp_envelope_log, default on.

The attribution digest is unchanged, and that is correct rather than an oversight: it covers the product and author constants and deliberately not VERSION, so cutting a release cannot disturb the tamper evidence. See Authorship.

Two operator-facing requirements outlive the release

The findings-log dashboard panel still needs Loki's 4 MB gRPC ceiling raised, on the server and on the querier's client to the query frontend, which carries a separate default the server setting does not cover; that configuration is operator-owned and lives outside this repository.

And neither ktp-risk-factors.jsonl nor ktp-envelope.jsonl rotates. The receipt file grows per attributed action rather than per poll, so on a host running agents continuously it is the faster of the two. newsyslog is the chosen answer, not made here, rather than a silent size cap — discarding the oldest receipts would leave a gap that reads like a quiet host.

Next