Closes the last three outstanding gaps from the post-wave-11
research + policy-bridge follow-ups. JouleClaw now has full parity
with NVIDIA OpenShell's agent-infrastructure primitives, with every
piece kept all-Rust, deterministic, and dep-light.
## Wave-19 — jouleclaw-routing::privacy (proposal #3)
Orthogonal sensitivity axis on top of the joules-first cascade.
NVIDIA OpenShell's Privacy Router primitive, JouleClaw-native.
Surface:
- SensitivityLevel: Public / Internal / Confidential / Restricted
- PrivacyClassifier trait — deterministic, pluggable
- HeuristicPrivacyClassifier — dep-free reference impl detecting
email / phone / SSN / credential markers / a tunable
custom-keyword list
- TierSensitivityPolicy — per JouleClass ceiling, default
locks Wire to Public-only and Model to Internal
- PrivacyRouter — wraps any inner Router, filters its plan to
permitted tiers, prepends a reasoning line carrying the
classifier verdict
17 new tests: classifier (6) + policy (4) + router (5) + the
fallback / coord-aware path (2).
## Wave-20 — jouleclaw-workspace (proposal #4)
Persistent structured workspace for long-running L6 agents.
NVIDIA-OpenShell File-System parity, all-Rust + signed.
Surface:
- Workspace<B: WorkspaceBackend> handle with put/get/has/remove
- WorkspaceBackend trait — content-addressed bytes (BLAKE3)
- MemoryWorkspaceBackend / FileWorkspaceBackend reference impls
- WorkspaceManifest — sorted entries, agent-owned, BLAKE3
content_hash over the canonical bytes
- SignedWorkspaceManifest + sign_manifest / verify_signed_manifest
using the AgentIdentity from jouleclaw-attest
- Path normalisation rejects absolute paths, `..` segments,
empty segments, NUL bytes
20 new tests: path normalisation (4) + put/get round-trip (3) +
manifest determinism (3) + sign/verify (3) + resume across
sessions (1) + file backend persistence + content-address dedupe
(2) + bad-input rejection (3) + EntryKind wire (1).
## Wave-21 — jouleclaw-policy-ipc (final follow-up)
Out-of-process transport for PolicyEngine. NVIDIA-OpenShell's
"agent process cannot in-process patch the policy" primitive.
Surface:
- PolicyServer<E: PolicyEngine> — wraps an engine, serves LD-JSON
requests on any (BufRead, Write) pair
- PolicyClient — owns a spawned child process, implements
PolicyEngine over the wire (evaluate / audit / audit_since /
policy_version / install_policy)
- jclaw-policyd binary — wires PolicyServer to stdin/stdout,
with optional --policy <path> startup
- Request / Response wire envelopes with stable LD-JSON shapes
Required one trait extension: install_policy is now a defaulted
method on PolicyEngine (defaulted to EnginePoisoned for backends
that don't support live updates), so the wire path and the
in-process path share a single trait method. InMemoryPolicyEngine
delegates the trait method to its inherent impl — same code path
for both transports.
5 unit tests (in-memory wire round-trip) + 3 integration tests
(child-process spawn → real wire round-trip → install + evaluate +
audit through the kernel boundary).
## Workspace
104 crates (+2: workspace + policy-ipc), 2,574 lib tests pass
(+42 across waves 19-21), 0 failures. The full original adoption
plan + the policy-bridge follow-ups are now shipped.