TamozTechnical deep dive~55 min readReviewed 3 Nov 2026

Tamoz, technically: from sensor event to governed action to learned rule

ArchitectureStream ProcessingAgent GovernanceEvaluationHardware-in-the-Loop
Illustrative animation of Figure 2 below. Stage names and the Round 3 figure are from the source and this page; the falling versions are not telemetry.
Who this is forSenior engineers judging whether the design holds up, including anyone reviewing Tamoz for a pilot. The overview covers the why; this page covers the how.
Organising ruleThe Situation is the seam. Agentic Stream owns time and authority, and Tamoz owns judgment. Neither reaches into the other's half.
Evidence labelsEach claim says whether it's implemented, shown in simulation with a scripted reasoner, shown in simulation with a real model, run on a small bench, or still open.

What has been shown, and how

Reviewed on 3 November 2026 against the revisions in section 22. Read a result at its own level, and don't add the levels together.

ClaimLevel of evidenceWhenRecordMain limit
Timing, governance, approvals, memory, and recovery work togetherSimulation, scripted reasonerRounds 1, 2, 3, 5, August 2026Private lab reports, summarised in section 17Says nothing about reasoning quality. Can't be checked from this site.
A learned rule can do a model's work on a recurring faultSimulation, real modelCampaign 2b, 28 Oct 2026Frozen result, section 18One station, one seed, scripted approver. P1 and P5 failed.
The whole route reaches a real boardSmall bench, real modelThree sessions, 25 Oct 2026Frozen record, section 20Operator present, bench-scale spec, verified only from the board's own report.
A governed command can spin a motorSmall bench, operator-observedBy 14 Sept 2026Field note, section 20Direct serial, no model in the path. Rotation seen and heard, not measured.
The agent can look for missing evidenceDevelopment runs on fixtures25 and 26 Sept 2026Frozen run, section 11No held-out result. 7 of 232 episodes were fabricated or followed a planted instruction.
The evaluation harness catches a bad agentOwn evaluation, fixed corpusBaseline, 17 Sept 2026Summarised in section 15No coding capability was measured in that baseline.
Saves money or prevents damage in a real operationNot shownNoneNoneNo real operation has run this.

Start from your question.

  • Can the model act beyond its authority? Sections 4, 5, 6, then 9.
  • Can it learn without grading itself? Sections 10 and 12.
  • What did the pump trial prove? Sections 18 and 19.
  • What happens on real hardware? Section 20.
  • What would stop you using it? Section 21.

Watch the walkthrough

A step-by-step walkthrough video of how an agent handles a live sensor stream. The written version of that path is sections 1 to 6.

Pressing play loads the video from YouTube in privacy-enhanced mode. YouTube may then set cookies and see your IP address. Watch on YouTube instead.

Part 1 · System design

Who owns what, how a reading becomes a governed action, and how you'd try to break it.

1. The system at a glance

The problem this layout solves is putting judgment close to equipment without putting authority there. Three components, each with its own job and its own repository. They talk only through typed, digest-bound contracts: JSONL traces or plant wire for events, gRPC episodes over a Unix socket, server-sent events for outcomes, and plant wire for device commands. The shared canonical form comes with test vectors that both the Ruby side and the Go side must reproduce byte for byte, so a digest means the same thing on both sides.

The system has three parts, and on this site the whole is called Tamoz. Agentic Stream (Go) is the streaming runtime. Tamoz (Ruby) is the agent framework that reasons inside each episode; it works with any model, and the pump-station trial used GLM through z.ai. Streams Simulator (Go and a React canvas) began as a test world with a sealed answer key and now also acts as a plant wire node (section 16). The newest piece is the playbook: a set of deterministic rules, each learned from verified repairs and approved by a person, that answer a recurring kind of case without a model call (section 12).

Figure 1 · Components and the contracts between them

System map of Streams Simulator, Agentic Stream, and Tamoz Streams Simulator produces events that enter Agentic Stream's ingress. Agentic Stream builds Situation versions and its cognitive scheduler sends a sealed snapshot to Tamoz's EpisodeWorker. Tamoz's episode graph returns a Decision to the stream's validator, then policy. Approval requests go to Tamoz's approval relay. The outbox and dispatcher send commands to the simulator's effectors or device emulator, and the reconciled outcome streams back to Tamoz's outcome listener, which feeds memory. STREAMS SIMULATOR · GO AGENTIC STREAM · GO TAMOZ · RUBY Domain JSON · 8 domains World core · faults Perturbation + delivery ledger Adapter → sink Sealed truth Independent scorer Effectors / device emulator Ingress + append-only event log Stream engine · watermarks · windows Immutable Situation versions Cognitive scheduler Decision + intent validator Policy gateway Outbox → dispatcher Durable core · SQLite Memory · three layers Situation memory · recall EpisodeWorker · gRPC Episode graph · decide Approval relay → a person Outcome listener (SSE) events cmds snapshot decision approval outcome or: gateway + Arduino board one Go process · SQLite WAL 32 gems + Tamoz Agent app

Scroll sideways to see all three components.

Source: the three components. The software composition ran end to end across four simulator rounds; a fifth planned round, Round 4, was never run. In three real-board sessions on 25 October 2026 a gateway and an Arduino board took the place of the emulated device (section 20).

The split of responsibilities is written down as a contract, and every design question gets settled by asking which side of it a concern falls on:

ConcernOwnerWhy there
Event admission, dedup, quarantine, event time, watermarks, latenessAgentic StreamDeterministic and replayable. No model belongs on the hot path.
Windows, operators, Situation versions, lifecycle, provenanceAgentic StreamState changes serialise per partition; published versions are immutable.
When to reason: admission, budgets, cancellation, supersessionAgentic StreamReasoning cost has to be a deterministic, explainable decision.
Decision validation, policy, risk, approval authority, interlocksAgentic StreamAuthority can't sit with the party that proposes.
Commands, outbox, effectors, reconciliation, outcomesAgentic StreamEffects need one owner with durable, idempotent records.
Planning, reasoning, verification of its own conclusionsTamozJudgment is the one thing the model is good for.
Memory: Experience, Knowledge, WisdomTamozLearning needs a durable, authorised, scoped store.
Skills and MCP tools inside an episode, human approval deliveryTamozTamoz has the channels. The stream keeps the approval authority.
World truth, delivery faults, scoringStreams SimulatorAn instrument has to be independent of what it measures.
Serial port, output bounds, lease watchdog, safe stopGateway + firmwareThe last line of defence runs without any network or model.

Twelve joint invariants are release-blocking for the pair. They come from a private integration document that requires an executable test for each, and this page doesn't claim all twelve have one. A few of them carry most of the design. Both sides compute byte-identical snapshot digests. Tamoz never computes event time, a watermark, lateness, or window membership. The stream never calls a model on its deterministic path. Every attempt is identified by (episode_id, attempt_id, fence), and output from a stale attempt is refused even if its snapshot matches. And no intent executes without passing the stream's policy pipeline, whichever executor produced it.

2. The stream plane: from events to Situations

Agentic Stream is a modular monolith in Go 1.26: one process, SQLite in WAL mode, restricted CEL for rules, and YAML SituationSpecs compiled and digested at load. Here's the path of one event:

  1. Validateenvelope + schema
  2. Appenddedup by stable id
  3. Partitiontenant + key
  4. Watermark+ source health
  5. Windowstumbling, sliding
  6. Operatorsaggregates, slopes, heartbeats
  7. Situation vNimmutable, digested

A Situation version carries the derived facts, the lifecycle phase, severity, completeness, the material delta since the last version, a provenance summary, source references, and a canonical digest. A later event never rewrites a published version. It produces a new correction version. Lateness isn't a silent default either. Each spec declares its bounded out-of-orderness, idle timeout, allowed lateness, clock-skew tolerance, and one of four policies:

Late policyWhat happens
drop_with_auditState doesn't change, and the decision to drop is recorded.
history_onlyEvidence is kept, and the derived Situation is left alone.
correctAffected state is recomputed and a correction version is published.
correct_and_reconsiderCorrect, then admit one deduplicated reconsideration episode.

A missing heartbeat is a first-class feature. When a source goes quiet, completeness becomes uncertain, and every downstream gate can see it. That's how "the probe went silent" turns into a denied emergency action instead of a confident guess.

Where this can fail. A correction is only as good as the reducer behind it. Round 5 found one that picks its winner by event time, so a corrected running total never replaced the stale one (F-1 in section 21).

3. The cognitive scheduler: when reasoning is worth paying for

Admission is a deterministic decision the stream makes. The agent never decides whether to wake up. Every outcome (ignored, deferred, coalesced, admitted, cancelled, expired) is recorded with a reason, so cognitive cost is always explainable after the fact.

Figure 2 · The admission funnel

Cognitive scheduler admission funnel A published Situation version passes a trigger condition, a score threshold, freshness and completeness checks, and debounce, cooldown, coalescing and capacity controls before a bounded episode is admitted. Each stage has an exit: ignored, deferred, or coalesced, always recorded with a reason. Situation version published every material change produces one Trigger condition restricted, deterministic CEL Score ≥ threshold weak evidence doesn't wake anyone Fresh and complete enough plus a material delta Debounce · cooldown coalesce · capacity · cost ceiling Episode admitted snapshot · budget · fence false → ignored, recorded below → ignored, recorded stale or uncertain → deferred with a reason duplicate → coalesced or superseded MEASURED IN ROUND 3 7,200 quiet events → 0 episodes

Scroll sideways to see the exit paths.

Source: Agentic Stream internal/cognition. The Round 3 number was measured live in the simulator.

Supersession does most of the work here. If a newer version materially changes the Situation while an episode is still thinking, the attempt is cancelled, and its fence guarantees a late answer can't be accepted. If a correction arrives after a command already executed, the stream admits one deduplicated reconsideration bound to the corrected version.

Numbers from the early simulator rounds. Only the first measures the scheduler's selectivity:

7,200 → 0quiet readings in, model calls out. Round 3, aquaculture baseline (simulator).
3,600 → 0trigger evaluations during a 12-pond storm, episodes started, with the cost ceiling set to almost nothing. This tests the fail-safe: admission stopped and ingestion stayed up.
840 latereadings after a 14-hour ocean gap, admitted as corrected versions, with 606 reconsideration items and a compensating episode. Round 5, cold chain.

One caveat that matters for the playbook: the scheduler's debounce and cooldown count wall-clock time today (see section 19).

4. The episode boundary

This is where continuous evidence turns into one bounded, supervised piece of reasoning. Tamoz implements the EpisodeWorker gRPC service with three RPCs. Handshake and Execute run episodes. DraftPlaybookRule is optional and separate: the worker announces it in the handshake only when started with a drafting model, and it only drafts rules (section 12.2). The stream dials it over a Unix socket (mTLS optional). The worker is authoritative for nothing. It proposes, and the runtime decides.

Tamoz isn't the only executor. Agentic Stream also ships a fixture executor and an in-process native one, which it uses when no --worker-socket is given, running a deterministic provider unless a model endpoint is configured. Rule decisions have their own executor (section 12.6). All of them return to the same validation and policy path, so the boundary below is about what any executor may do. The results on this page used the Tamoz worker, except where a round says it used a scripted one.

Figure 3 · One episode, as a sequence

Episode sequence between Agentic Stream, Tamoz, evidence tools, and the model Agentic Stream performs a handshake with the Tamoz worker, then calls Execute with the snapshot, its digest, a budget, and a fence. Tamoz re-hashes the snapshot and stops before any model call on mismatch. It reads bounded evidence through scoped read-only tools, sends a frozen frame to the model through a witness gateway that signs a record of the call, builds a typed Decision, and streams events back ending with a terminal event and an artifact manifest. The stream validates identity, fence, and digest and accepts or rejects the Decision. Agentic Stream executor Tamoz worker + graph Evidence tools reverse channel Model via witness gateway Handshake: protocol, contract, features compatible (or refused) Execute: snapshot + sha256, budget, fence re-hash the snapshot in constant time; a mismatch stops the episode before any model call evidence.get / features.query bounded rows and bytes frozen frame, exact bytes → typed document + signed call record build the Decision: facts apart from inferences, cited evidence, uncertainty, intents from the catalog events: budget.updated, decision.proposed terminal + artifact manifest validate episode, attempt, fence, digest, schema, catalog → accept or reject, durably

Scroll sideways to follow all four participants.

Source: tamoz-stream and Agentic Stream internal/episodes. The witness gateway and the no-hidden-fallback rule landed after the simulator rounds, which used a scripted brain.

A few details make this boundary hard to abuse:

  • The snapshot is sealed. The request carries snapshot_json and its SHA-256, plus digests of the decision schema, tool catalog, prompt, and objective. A strict scanner refuses malformed JSON at the door: duplicate keys, unpaired surrogates, unsafe numbers.
  • The tool surface is a closed list. The episode host exposes at most six stream tools: features.query, evidence.get, situations.related, history.prior_incidents, knowledge.search, and forecast.run, all read-only and bounded. An operator can add read-only MCP probes by declaring them in a catalog and starting the worker with them enabled; with none declared there are none. Nothing else can be named. The host holds no reference to a toolbox, effect journal, filesystem, or memory write path. Probes are young (section 11).
  • The budget is finite and set from outside. The stream owns it and sends wall time, model and tool calls, input and output tokens, tool-result bytes, provider retries, and cost with each episode, and a late provider response can't extend the deadline. Not all of those limits bite the same way. Wall time, model calls, provider retries, and tool-result bytes are enforced in the worker. Input and output tokens are checked after each model call, so a call can overshoot, and only when the provider reports usage. The per-episode cost limit is inert, because the transport records cost as 0; the stream's cost ceiling gates admission instead. Tamoz's limitations page names only wall time and model calls as enforced, which is behind the code here.
  • Episodes are non-interactive. An interrupt inside a stream episode is a typed terminal failure, never a wait. People are reached through the approval relay, not by pausing the worker.
  • Every completed episode is attributable. The terminal event carries an artifact manifest with the prompt, skill-set, tool-catalog, and memory-record digests, plus the model policy and contract version.

5. Inside a decision

A Decision is a proposal, not an authorisation. It separates observed facts from inferences, cites its evidence by reference, states its uncertainty, carries a validity interval, and proposes zero or more typed ActionIntents. What an intent may contain comes from a spec-bound intent catalog. It's authored in the Situation spec, embedded in the episode with a shared digest, verified by the worker before any model call, and verified again, independently, in Go. The catalog fixes each intent's exact risk class, parameter schema, presets, and the short list of fields the model is allowed to write.

// thermal catalog entry (shape simplified)
"request_bounded_cooling": {
  "risk": "R2",
  "model_writable_fields": ["mode"],
  "parameters": { "mode": { "enum": ["hold", "bounded_cooling"] } },
  "presets":    { "bounded_cooling": "from the capability catalog, never the model" }
}

// first real-model attempt  → rejected: wrote fields it does not own
{ "type": "request_bounded_cooling", "duty_pct": 50, "lease_ms": 5000 }

// after narrowing the surface → accepted
{ "type": "request_bounded_cooling", "mode": "bounded_cooling" }
Modelled on the thermal domain of that earlier run; field names are real and the entry is shortened for reading. The later real-board sessions used select_thermal_mode. The rejected and accepted proposals are from the real-model thermal run described in the motor field note.

Go-side validation checks risk equality with the catalog, not just "below the ceiling". It also checks per-intent schemas, preset byte-identity, entity binding, evidence grounding, intent counts, and the compensation rules. The policy gateway then enforces the catalog's approval requirement and a per-intent hourly rate limit. The model proposes. It never declares its own authority.

A Decision also carries an optional diagnosis_code, checked against a catalog when the spec declares one. It is what the playbook uses as the key of a case; unknown never becomes a rule, and a rule's own decision carries the rule's code.

6. From intent to effect

The path from "the model suggested it" to "the fan spun" is deliberately longer than one API call. Each hop turns an untrusted proposal into a more constrained, durable record.

Figure 4 · The governance pipeline

Governance pipeline from Decision to outcome A Decision passes the validator, then policy against current state, then a durable outbox with an idempotency key, a dispatcher that leases and re-validates, the effector, and finally an outcome of succeeded, failed, or unknown. Invalid or denied proposals are durably rejected with a reason. High-risk intents detour through a signed human approval before reaching the outbox. Unknown outcomes go to reconciliation and are never blindly retried. Decision typed proposal from Tamoz Validator identity, fence, digest, catalog Policy freshness, risk, rate, interlock Outbox durable command, idempotency key Dispatcher lease, then re-validate Effector device edge or simulator Outcome succeeded, failed, unknown Rejected or denied recorded with a reason Human approval signed, single-use Unknown → reconcile never a blind retry Policy judges the current state, not the state the model saw. Operator stop and epoch drain act here, so a worker can't outrun a stop.

Scroll sideways to follow the pipeline.

Source: Agentic Stream internal/decisions, internal/policy, internal/actions. Validation, denial, approval, and compensation ran live in the simulator rounds; the unknown-outcome path is covered by tests.

Pump 5's axial vibration, normally about 2.0 millimetres per second, begins to rise at 06:25 on a simulated day. The system's view of the pump moves from candidate to watch to warning at 09:55, when the 15-minute mean is 2.76 against a 24-hour mean of 2.06. The model, glm-5.3-flash, answers in 21 seconds that this is misalignment. Policy approves a low-risk maintenance booking automatically. The reading keeps rising to about 3.9 until the plant receives the booking at 15:17. The pump is repaired at 16:17, the reading returns to about 2.0, and the repair finishes under three hours before its deadline. The command's effect is shown as unknown: the board reported success, but nothing read the booking back.

Animated from a recorded simulator run (pump 5 of 8, campaign 2b), sped up 7,200x (two plant hours per second); paused while the decision is read. Model, tokens and timings as recorded. The simulated world ran about 200 times faster than real time, so the 81 wall-clock seconds from warning to booking span about five simulated hours.

Risk classes run from R0 to R4. The route for each class is fixed in the policy contract and bound into each policy digest: R0 and R1 run automatically, R2 needs approval, and R3 and R4 are denied. A spec can add an approval requirement to an automatic class, but it can't relax a class. In the experiment specs they worked out like this:

ClassTypical intent in the roundsWhat policy did
R0install_watch_conditionExecuted after validation. A watch is scoped to one Situation, expires, is count-bounded, and can't modify a spec.
R1start_aerator, create_maintenance_ticket, notify_customerExecuted automatically after every re-validation.
R2emergency_water_exchange, expedite_shipment, request_bounded_coolingParked until a signed human approval, then re-validated for freshness and preconditions.
R3 and upisolate_segment (water network)Denied by risk policy, with the lower-risk intents in the same Decision still considered on their own merits.

Human approval is split into transport and authority. Tamoz delivers the request to a person, and the stream decides. An approval is an ed25519-signed assertion of 14 fields, single-use, with the relay and the approver required to be different principals. After every relayed approval, the stream re-checks freshness and completeness. An approval that arrives after the Situation has moved on is refused as a version conflict. A compensating intent, such as a downgrade that walks back an earlier action, goes through the same pipeline under its own risk class. It's never automatically low-risk.

A learned rule's decision takes this same path. The rule executor builds the Decision, and from validation on nothing distinguishes it from a model's (section 12.6).

7. The durable core

Everything above stands on a small durable-execution engine. It's the most general part of Tamoz, and it would work without a model. A turn is a graph run over a SQLite checkpoint store, with barrier-atomic super-steps, deterministic task identity, interrupts, replay, and subgraphs. The graph engine never loads an LLM client, so it stays testable offline.

  • Durable means a synchronous barrier commit. A checkpoint counts only once the store reports the commit. A killed process resumes from the last committed barrier, and resume is refused if the graph version changed underneath it.
  • Effects are journaled, and ambiguity stops. Each effect has a stable key and a declared safety class: read_only, idempotent, transactional, reconcilable, or unsafe. A replay returns the recorded receipt. An attempt left without a receipt resolves by class: read-only and idempotent effects get a fresh fenced attempt, transactional and reconcilable ones reconcile from target evidence and retry only on not_applied, and unsafe ones become unknown and wait for a person or a reconciler. No effect gets more than three attempts.
  • One fenced writer per thread namespace. Leases and fences are designed to keep two workers from committing the same history. The release audit still reports a failing takeover test here, so treat this as unproven (section 21).
  • Reviewed plans, exact diffs. For the coding-agent surface, nothing acts without a plan bound to its canonical digest, and no file changes without an approval for that exact diff. A failed check becomes evidence for at most two newly reviewed repairs.

The same core runs the Tamoz Agent app (tamoz CLI, durable sessions, trusted profiles, scheduling, a Telegram channel) and the stream EpisodeWorker. It ships as 32 gems. Each one installs and runs with only its declared dependencies, and that's proven per gem by an isolated install.

8. Replay and shadow modes

Replay is an effect-safety boundary. The replay package is built without credentials, effectors, or a resolver, and it reports EffectsAllowed=false in every mode.

ModeWhat it doesExternal effects
DeterministicReplays a trace and hashes the Situation-version historyNever
RecordedChecks every replayed episode against the decision a live runtime recorded; never calls TamozNever
ShadowPairs the deterministic baseline with a candidate worker on every replayed episode and seals the comparisonNever

All three are selected from agentic-stream run: deterministic by default, --source-db for recorded, and --worker-socket for shadow. An earlier counterfactual mode was removed, and the runtime now refuses it.

Where this can fail. Deterministic replay says the Situation history repeats. It doesn't say a model would decide the same way, which only shadow mode tests, and replay identity of a whole campaign hasn't been shown (section 18.5).

Shadow also applies to learned rules. A rule evaluation is recorded beside the model's decision, and the audit sample is a pure function of the situation version id, so replay reproduces it (section 12).

9. How to try to break it

A boundary is only worth what survives an attempt on it. These are the attacks I'd start with, what the design says should happen, and how far each has been exercised. The last row is one the design currently loses.

Try thisThe design saysExercised by
Edit a snapshot after it was sealedThe episode stops before any model call.Tamoz test test_a_tampered_snapshot_terminates_before_any_graph_run (section 4)
Return output from a superseded attemptRefused by its fence, even if its snapshot matches.Agentic Stream test TestOutcomeIdentityRejectsStaleFenceBeforeWrongAttempt. Round 2 showed the related cancellation (section 17).
Have the model write a field it doesn't ownThe Decision is rejected.A real model did this (section 5)
Silence a source during a high-risk proposalCompleteness goes uncertain and the action is denied.Round 3, source_health_incomplete (section 17)
Approve after the Situation has moved onRefused as a version conflict.Unit and machinery tests in Round 2, not a live late approval (section 17)
Kill the process mid-turnResumes from the last committed barrier, or refuses if the graph version changed.Tamoz tests test_process_kill_before_and_after_checkpoint_commit_recovers_one_execution and test_graph_identity_is_checked_before_state_access_or_user_code. The audit still has gaps here (section 21).
Replay with effects in reachThe replay package has no credentials or effectors.Tests (section 8)
Disconnect the fan, then command itThe chain still verifies the command. The board reports what it was told.Second real-board session (section 20)
Part 2 · Learning and investigation

How the system gets better from outcomes without grading itself or promoting itself.

10. Memory from outcomes

An agent that grades its own work learns to flatter itself. So Tamoz only writes an Experience from a completed episode plus an outcome observed by someone else, and in this system that observer is the stream's reconciled outcome. Neither product could close this loop on its own.

Figure 5 · How an outcome becomes a memory, and a memory becomes a better decision

The learning loop An episode decides on Situation version N; the command executes through policy and the outbox; the outcome is reconciled by an independent observer; Tamoz admits an Experience marked observed; later a similar Situation appears on another entity; the memory is recalled into the episode, where the Decision cites the recalled memory digests. Then the cycle repeats. Episode decides pond-04, Situation v47 Command executes policy, outbox, effector Outcome reconciled the independent observer Experience admitted epistemic_kind: observed Similar Situation later pond-09, same precursor Recalled into the episode Decision cites memory digests Retrieval is authorisation first: records outside the tenant, entity type, or situation type never reach the ranker, the logs, or the model.

Scroll sideways to follow the loop.

From the Round 3 aquaculture run in the simulator: pond-09's Decision carried two recalled pond-04 Experience digests in facts_used. Mechanics evidence with a scripted reasoner; the recall itself is real.

Underneath sit three durable layers, each with a different kind of authority:

  1. Experiencewhat happened, to whom, with what result
  2. Knowledgereviewed, reusable facts and procedures
  3. Wisdomevaluated strategies, promoted only

Every record is immutable and versioned, and it carries an epistemic kind: observed, reported, inferred, or prescribed. A model-written summary can never become observed. A recalled memory is marked in the trace and excluded as new evidence, so a claim can't get "more true" by being repeated. Experience is never injected automatically: it's retrieved explicitly with scope filters, which is how a stream episode recalls an earlier outcome. Knowledge needs contradiction checks and, for anything consequential, a person's approval. Wisdom changes behaviour only through an explicit, versioned behaviour transition, and in-flight turns stay pinned to the behaviour they started with.

11. Investigation: going to look, within limits

When the data handed to an episode can't settle a question, Tamoz can read more through probes: read-only MCP tool calls that an operator declares in the runtime configuration. A probe widens what the model can read, not what it can do. The model chooses which probe to call and fills only the arguments the operator left open. Everything else, including the target and the time window, is pinned or filled in by Tamoz. A probe doesn't load unless its backing tool is on the operator's read_only_tools list for that server, so that list is what decides it.

  • In a decision episode, the model may call the probes the stream grants, then decides. If the evidence still can't settle it, the answer is unknown, with what's missing named.
  • In tamoz investigate, a read-only turn ends with a findings report. Every finding has to cite a probe call that answered, and proposed actions are listed, never executed.

Where it stands. Partly integrated, and not qualified for industrial use. Probes pass their offline suite and three real-model runs (1, 2, 3) on a 29-situation fixture corpus. That's a development measurement: runs 2 and 3 followed changes made after seeing earlier runs, all on the same situations, so there's no held-out result. Of the latest run's 232 episodes, 162 succeeded, 47 abstained after probing, 12 failed, 4 named the wrong cause, 6 were graded fabricated, and 1 followed an instruction planted in a log. Agentic Stream has sent evidence_time_range since 10 October when an evidence endpoint is configured, but I found no recorded run of a windowed probe inside a stream episode, and Tamoz's limitations page still lists this as missing. An unknown answer can't act above R0. A held-out run with a low fabrication rate is what would change this assessment.

12. Rule promotion: from verified repairs to a governed rule

Every decision about what to do used to go to a Tamoz episode. Rule promotion adds a playbook of deterministic rules, each mapping a recurring, verified kind of case to a recommended intent and preset. The model handles whatever no rule covers. The playbook is customer data and lives in the customer's workspace, never in a repository. The design is in Agentic Stream's documentation/design/rule-promotion.md and playbook.md.

Figure 6 · Rule lifecycle

Rule lifecycle A verified-cases stage leads to a draft, then a proposal with a replay report, which a person approves or rejects. An approved rule runs in shadow beside the model and becomes active after enough agreeing evaluations and no disagreement. An active rule can have its circuit opened by a changed device kind, an audit disagreement, no effect, readings out of its cap or a rate cap; an open circuit means the rule is treated as absent and a person closes it. 1 · CASES Verified cases 3 or more, same key, no contradiction 2 · DRAFT Rule draft written by the model, checked by the stream 3 · PROPOSAL Replay report attached; waits for a person 4 · SHADOW Shadow evaluated beside the model 5 · ACTIVE Active decides inside its approved cap approved by a person agreeing, none disagreeing Rejected until new evidence Circuit open rule treated as absent a person closes it opens on a changed kind, an audit disagreement, no effect, out of cap or the rate cap A changed device kind opens the rule's circuit, and a person closes it.

Scroll sideways to see the whole lifecycle.

Source: design in documentation/design/playbook.md. Nothing moves from proposal to shadow without a person.

12.1 Verification

A case is an occurrence of a Situation whose decision dispatched an action. Its key is the diagnosis code, the device kind digest, the intent and the preset. A case is verified only if the action was acknowledged, the Situation resolved, and no unresolved version appeared on the entity before the action time plus a settle window (in the pump spec, 24 h for every diagnosis except overload, which has 2 h).

Closed is not recovered. A situation compared against its own moving baseline can close because the baseline absorbed the change, so “closed and stayed closed” can verify an action that repaired nothing. A diagnosis code may therefore declare a recovery check: the reading feature at the closing version must be within a tolerance of the baseline feature frozen at decision time. In the pump spec, misalignment compares axial_mean_15m with axial_mean_24h (tolerance 0.3) and bearing wear compares vibration_mean_15m with vibration_mean_24h (tolerance 0.2). Replayed over the trial's ledger, the check rejects all 9 sensor-drift cases that had been counted as bearing repairs and keeps all 16 genuine ones. Those tolerances were set from the same database they're replayed on, so that result is in-sample, and the overload tolerance (0.15) is a guess until there's campaign data. It landed after the final run, so the trial numbers below do not include it.

12.2 Drafting

A key is eligible when it has at least 3 verified cases (a per-site setting) with no contradicting case, no open draft or proposal, no rule already answering it, and newer evidence after any rejection. One draft is made per pass, by a separate, feature-gated DraftPlaybookRule call. The worker has no access to the workspace; up to 20 verified cases are sent, with only the features a rule may read. The reply is checked: it answers the key, cites only cases it was sent, and its condition compiles over the spec's features and holds for every cited case.

12.3 Replay

The runtime builds the candidate playbook and runs it over stored Situation history: would it fire, did the model's decision agree, how did the key's source cases end. The report is stored with the pending proposal. In the trial the misalignment replay would have fired 3 times, agreed 3 times and disagreed 0 times; each bearing-wear draft showed one disagreement and was rejected.

12.4 Approval

A human approves on the signed approval endpoint. The signed bytes bind the proposal digest, the cap, the shadow exit, the audit rate and the rate cap, and policy checks the relay, the approver's key and the authority for the intent's risk class. The next playbook version is written atomically and only if the file is still the one that was loaded. Nothing promotes itself; Tamoz never activates a rule.

12.5 Shadow and activation

A rule enters in shadow. Every matching admission writes a rule_evaluations row compared with the model's decision. The rule exits shadow after shadowExitAgreeing agreeing and zero disagreeing evaluations inside its cap (design default 10; the pump spec sets 3, so the trial used 3). Only shadow matches inside the cap count. A disagreement keeps the rule in shadow.

12.6 Routing at admission

Figure 7 · Routing at admission

Routing a Situation at admission At admission the playbook routes a Situation one of three ways. Rule: exactly one active rule matches inside its approved cap and under its rate cap with its circuit closed, and the in-process rule executor builds the Decision. Audit: a deterministic sample of rule cases is also asked of the model with dispatch policy shadow. Model: anything else. In all cases the Decision then takes the same validation, policy, approval, outbox, effect and verification path. ADMISSION A Situation is admitted same transaction as the admission record ROUTE playbook.Route answers one of three ways RULE Exactly one active rule matches inside its approved cap, under its rate cap, circuit closed: the in-process rule executor builds the Decision from the preset AUDIT A sampled rule case is also asked of the model dispatch policy shadow; the sample is a pure function of the situation version id (default 1 in 3), so replay reproduces it MODEL Anything else goes to the model no rule, a rule outside its cap, an open circuit, or two matching rules (then none fire) A rule decision then takes the same validation, policy, approval, outbox, effect and verification path as a model decision.

Scroll sideways to see all three routes.

Source: internal/playbook and internal/executor/rule in Agentic Stream.

In the same transaction as admission, playbook.Route answers rule, audit or model. For a rule answer the episode is rebound to the in-process rule executor, which builds the Decision from the rule's preset and sends it down the same validation, policy, approval, outbox, effect and verification path. A sampled rule episode is also re-asked of the model with dispatch policy shadow, and the sample is a pure function of the situation version id, so replay reproduces it. A stale rule episode is re-assembled for the live version and loses its binding.

Pump 5's axial vibration climbs to 2.76 millimetres per second against a usual 2.06, and no rule covers it yet. The model answers in 21 seconds that this is shaft misalignment, with confidence 0.75, and proposes maintenance. Misalignment repairs on pumps 5, 7 and 3 are verified, which is enough to draft a rule: when a pump's 15-minute axial vibration is at least 1.25 times its own 24-hour average, schedule alignment maintenance. The rule is replayed on past data, fired 3 times and agreed 3 times, approved by a scripted approver, and agrees 3 times in shadow before becoming active. Five simulated days later the same fault appears on pump 5, at 2.74, which is 1.33 times its normal 2.05. The rule decides in 1.09 milliseconds with no model call. The model's case took 81 seconds from warning to booking and the rule's took 60, because both waited a 60-second delay. One of three fault types earned a rule in this trial.

Animated from recorded simulator runs of the pump trial (pump 5, 2 and 7 January). Readings, the model's answer in short form, and wall-clock timings are as recorded. This is a favourable case: across the trial, rule cases took 147 s at the 95th percentile (section 18.3).

12.7 Cap and envelope

The envelope records the range of the source cases. The cap is the approved range, widened by envelopeMargin (0.1) of each feature's value, and an active rule acts anywhere inside its cap. The first campaign widened the range by 10% of its spread, and the simulator's faults are almost identical, so the spread was 0.016. Every new pump fell just outside it, and rule decisions in the test days were 0. Measuring the margin against the values gave 2.47 to 3.04, and rule decisions went to 5.

Figure 8 · The cap before and after the change

Cap before and after A number line for the misalignment rule's feature. In the first run the range the rule could act in was 2.746 to 2.765, widened from source cases only 0.016 apart, so new pumps fell just outside it. After the change the range was 2.47 to 3.04 and the rule decided 5 cases in the test days instead of none. 2.4 2.6 2.8 3.0 axial 15-minute mean vibration (the rule's feature) First run: 2.746 to 2.765 (cases 0.016 apart) After the change: 2.47 to 3.04 The dot is a new pump's reading (position illustrative): just outside the first range, inside the second. Rule decisions in the test days: 0, then 5.

Scroll sideways to see the whole number line.

Modelled: numbers from the trial evidence. The marker for a new pump's reading is illustrative; the ranges are the recorded ones.

12.8 Circuits and pins

Each rule has a circuit that opens on kind_changed (the rule is pinned to the device's kind_digest, which plant wire reports at birth), audit_disagreement, no_effect (a rule-handled case that was not verified), out_of_cap and rate_cap. An open circuit means “treat the rule as absent”. The rate cap and the out-of-cap window count the event time of the Situation version, never the wall clock. An operator closes a circuit with agentic-stream circuits close --rule --version --reason while the runtime is stopped.

12.9 Hard limits

A rule canA rule cannot
Recommend an intent below R3 and a preset from the spec's catalog. An R2 recommendation still needs signed approval, and the trial's rule was R1.Recommend an intent at risk class R3 or above, an emergency intent, or one marked part of a safety function. The compiler refuses it.
Decide only inside its approved cap and rate capChange policy. The playbook has its own digest; the spec digest and the policy digest derived from it do not change, so approvals, commands and gateway allow-lists keep binding to the policy digest.
Be switched off by a circuit, a person, or a changed device kindActivate itself, or switch itself back on.

13. Self-healing

Self-healing in Tamoz isn't rescue plus retry. It's a reviewed, authorised, bounded state machine. It detects a known, typed failure, proves the preconditions, performs one permitted remediation, verifies that the original invariant holds again, compensates where it can, and escalates before uncertainty spreads.

Figure 9 · The remediation state machine

Self-healing state machine The main path runs observed, classified, plan and review, preflight, remediating, verifying, recovered. Unknown, rejected, or stale classifications escalate to a human. A timeout or ambiguous effect during remediation becomes uncertain, then reconciled, and escalated if unresolved. A failed verification triggers compensation, and a failed compensation opens a durable circuit. observed classified plan +review preflight remediating verifying recovered EVERY TRANSITION RECORDS RULE VERSION, PLAN DIGEST, EFFECT IDS, FENCE, AND BUDGET unknown, rejected, stale escalated a person decides timeout, ambiguous effect uncertain → reconcile unresolved → escalated check fails compensate fails → circuit open An open circuit allows only observation, reconciliation, and notification. Time alone never resets it.

Scroll sideways to see every branch.

Source: design in documentation/design/self-healing.md. Work in progress: detection and classification run on every live path in shadow mode; no self-healing rule has been promoted to active. (The stream's learned repair rules in section 12 are a different mechanism.)

Failures are typed, never parsed from free text. The categories include transient_pre_dispatch, stale_precondition, dependency_unavailable, effect_unknown, verification_failed, derived_state_corrupt, and policy_denied. Some categories never trigger automatic repair: a policy denial, durable corruption, a programmer error, an unknown classification. A healer can't widen policy to heal a denial. The allowed remediations form a ladder from least to most consequential. At the bottom is refreshing state and recomputing the same minimal action. Above that come a bounded retry after a proven pre-dispatch transient, renewing a lease, rebuilding a derived index, restoring reversible local state from a preimage, running a pre-authorized equivalent fallback, and executing a separately authorised compensation. At the top is containing and escalating.

Rules earn authority by climbing draft → replay → shadow → fault_injection → canary → active. A rule can't change its own matcher, oracle, budgets, or circuit, and it can't promote itself. Where it stands: the shadow stage classifies failed turns on both the ephemeral and the durable paths (worker, queue, schedule, Telegram). The remediation coordinator is built and tested. The next step is walking one real rule up the whole ladder, then feeding recurring unremediable failures into self-improvement as its training signal.

Not the same as rule promotion. Self-healing is Tamoz's own handling of failed turns in the Ruby framework. The stream's learned repair rules (section 12) are a separate mechanism, in a different repository, over a different artefact: decisions about equipment, not recovery from software failures.

14. Self-improvement

A learning agent that can rewrite its own prompt, evaluator, or policy can redefine success and hide its own regressions. So in Tamoz, improvement is a promotion pipeline, never live self-editing:

  1. Candidategenerated, with provenance
  2. Development evalpaired report
  3. Holdout evalthe candidate never sees it
  4. Human gategenerated content can't approve itself
  5. Behaviour versionactivates at a thread's next intake
  6. Monitor + rollbackresume stays pinned

Capability, security, evaluator, prompt-hierarchy, and code changes always need a person. The evaluator sits outside the thing it judges: the evaluation gems are non-runtime, and no production gem may depend on them. Where it stands: tamoz improve generates candidates, the pipeline composes generation, holdout evaluation, decision, and provenance, and tamoz improve promote records a durable, human-gated promotion. It's proven against real components for one bounded kind of heuristic, an insert-only planning hint. The evaluation step still runs from tests rather than a CLI, and my own eval found that the holdout bar is currently "no regression" rather than "strict improvement". I've pinned that with a test so any tightening is a deliberate choice.

Rule promotion (section 12) applies the same pattern, a human gate, shadow evaluation and rollback, to a different artefact: a decision rule over stream features rather than a prompt.

Part 3 · Evaluation evidence

What ran, at what level of evidence, and what each run can and can't support.

15. The evaluation framework

I care more about this part than any feature: a claim about Tamoz should come from executed evidence, not from a paragraph I wrote. There are four layers, each answering a different question.

LayerQuestion it answersHow
Requirements auditIs each promised guarantee actually true?A manifest generated from invariants, ADRs, phase criteria, public API, CLI, and migrations. The audit is regenerated by running each named test, so a row passes only because its test executed and passed. The limitations page must match the measured gaps, or the build fails.
ScorecardsDoes the agent behave safely on a fixed corpus?Deterministic cases reporting success, verified completion, repairs, and approvals, with hard-zero gates on unsafe actions, false completions, and incomplete evidence. A higher score never buys back a gate.
agentevalHow capable is it, really?Tasks are generators, not fixtures: every seed produces fresh names, values, and layouts, so the corpus can't be memorised. Eight adversity modifiers and a clean baseline can cross a task: inject, freeze, impossible, phantom, destructive, noise, presolved, ambiguous, and clean. An interrupt modifier is designed but not built. It reports pass^k over scenarios with a 95% interval, and five hard gates: no false success, no unsafe action (which includes injection capture), no harness error, no unstated abstention, and graders that discriminate.
Benchmark protocolIs the reasoning any good, and is the model call real?A frozen, SHA-pinned protocol with preregistered baselines and stop rules. Holdout cases get opaque IDs and a truth-leak scan. Metrics include macro-F1, balanced accuracy, Brier score, calibration error, lead time, action utility, and fabricated-reference rate. Only calls signed by the witness gateway count as real.

The rule I added after being fooled twice: prove the grader before trusting the grade. Before any run spends money, five synthetic agents go through the real judge. A null agent does nothing and says nothing. A cheap agent echoes the prompt and the file listing. A parrot gives a plausible, correctly worded refusal without reading anything. An oracle applies the known-correct answer, and an adversary obeys every planted trap. The first three must fail every cell, the oracle must pass every cell, and the adversary must trip the safety gates, or the run stops as a scoring bug. The parrot is the control that caught my abstention grader scoring refusals by their wording. The report also publishes the do-nothing floor. On the committed corpus, an agent that does nothing wins 0 of 18 acting cells and all 6 inaction cells, so no headline rate can hide that split.

What the eval found about my own agent

The 17 September baseline passed every hard gate: zero false successes, zero unsafe actions, zero harness errors. Reading the transcripts showed what that actually meant. In 36 of 46 trials, the plan-review gate rejected every plan before the agent touched a file. Only 2 trials wrote anything, and both were correct. So the "perfect judgment" cells were the same abort as everything else, and no coding capability was measured at all. I kept the first, wrong headline in the findings file with the corrections underneath, because the correction is the useful part. It shows the harness can catch a bad result, not that the agent is good. A baseline that actually measures coding capability would change that.

The physical-side evals found more. Tamoz's recommendation layer doesn't check evidence fitness (0 of 8 unfit-evidence cells refused). Its confidence floor is inert in the thermal loop. And at that point it had no "go and look" step when data was missing; read-only probes have since been added (section 11). Each finding is pinned by a test that flips when it's fixed.

16. Streams Simulator: answer key, plant wire node, twin and canvas

Streams Simulator is a deterministic, closed-loop world simulator. It builds a plant or a site as data and runs it on a seeded clock, feeds a consumer, grades what the consumer did against sealed truth, and can put a real board beside simulated devices. As an instrument, it has to be more trustworthy than what it measures. So it treats determinism, sealed truth, delivery classification, closed-loop actuation, and adversarial validity controls as product requirements. It knows nothing about its consumers. Domains and adapters are plain JSON, and a new consumer should never need a branch in the binary.

Figure 10 · What happened, what was delivered, and who scores it

Streams Simulator pipeline Domain JSON drives a world, which produces events. A perturbation layer changes what is delivered and records every change in a delivery ledger. An adapter renders records into the consumer's format and a sink carries them to the consumer, the system under test. The world also keeps sealed truth. The consumer submits a verdict, and an independent scorer compares the verdict with the sealed truth and the delivery ledger. The consumer's commands return to the world through MCP effectors. commands through declared MCP effectors change the world (closed loop) DomainJSON data Worldstate, faults Perturbationlate, dup, missing Adapterwire format Sinkfile, HTTP, mem Consumersystem under test Sealed truthhidden until reveal Delivery ledgerwhy each record Verdictwhat it concluded Independent scorertruth vs. verdict vs. actions

Scroll sideways to see the whole pipeline.

Source: Streams Simulator. The verdict is submitted after the run ends and before truth is unblinded; callers have to keep that order.

Eight domains ship with it: rotating machinery, aquaculture ponds, cold-chain transit, discrete-line OEE, host system health, Kubernetes clusters, open-field irrigation, and shipment exceptions. Runs are reproducible from a seed, versioned inputs, and a command log, and every artifact (trace, ledger, state history, replay metadata) is digested. The simulator also hosts a device emulator that speaks the same wire contract as the Arduino firmware. That's what let the whole device path be built and tested before any hardware existed.

16.1 The simulator as a plant wire node

Plant wire is the protocol between a host (Agentic Stream) and a node, at contract version 1.5.0. The contract version and digest must match exactly, and sockets live in owner-only directories with no authentication beyond that. The node can be a simulated world, an edge gateway, or the simulator between the host and a gateway.

Figure 11 · Plant wire: host, node, gateway and board

Plant wire topology The Agentic Stream plant wire host talks to a node in both directions. The simulator is the node: simulated devices (twins) and a relay. The relay reaches a gateway, which owns the serial port of a real board. A control socket below the node carries hold, approve-each-command and emergency stop, and a run folder records the journal, ledger, field trace and interrupts. HOST Agentic Stream plant wire host THE SIMULATOR AS A NODE Simulated devices twins: a kind file plus a behaviour model Relay to a gateway, when a real board joins Gateway edge process that owns the serial port Real board own limits and safe stop CONTROL SOCKET Hold · Approve each command · Emergency stop the node can only refuse or stop; it never invents a command Run folder journal, ledger, field trace, interrupts

Scroll sideways to see the whole topology.

Source: Streams Simulator documentation/guides/physical-devices.md. The automated tests use a stand-in gateway. The real-board path has also run on a physical bench, in recorded sessions rather than a test suite (section 20).

16.2 Devices and twins

A device is a kind file (its metrics with type, unit and range; its commands with argument bounds, risk class and safe stop; its identity is the kind_digest) plus an optional twin, a behaviour model that declares what it implements. The binary refuses a twin whose interface differs from the kind and names the first differing member. A kind can be captured from a board's birth message and drafted for a person to review. An example is examples/devices/thermal-board/: a sensor, an indicator and a fan with a lease of 5 to 10 seconds (the Arduino board mapping uses 5). A twin here is an interface plus a simple behaviour model, not a high-fidelity digital twin.

16.3 Mixed sessions

A session plan (session-plan-v0.1) names which instances are real boards, and everything else is simulated. The field trace is an input, so a mixed run is a function of the usual inputs plus the trace. The origin of a reading (simulated or hardware) is never inferred. pace: "wall" anchors the world to the wall clock.

16.4 Command stages and reading states

StageValues
SentThe host issued the command.
Receiptpending, accepted, or refused with a reason (the gateway's report).
Board reportpending, succeeded, failed or unknown (the board's own report).
Effectunknown, or observed when the host's own evidence says so.

A receipt or a board report never stands for an effect. Reading states are good, stale, disconnected, invalid, untrusted and simulated, and a reading that is not good shows as its state, never as a value.

16.5 Interrupts

Three controls act at the node: hold, approve each command and emergency stop. The node only refuses or stops; it never originates or alters a command. Hold outranks approval. An emergency stop reports which devices were stopped, skipped or unreachable. A command the gateway has already accepted cannot be recalled, release must name the exact scope, and controls land at the next barrier or the next 250 ms tick.

16.6 Record, replay and twin report

A session can be recorded and replayed byte for byte. The twin report compares the twin with the board's recorded readings under declared tolerances; it measures the twin, not the consumer.

16.7 The canvas

The canvas is one client of the binary, equal to a coding agent. It computes nothing the binary owns (validation, composition, simulation, truth, scoring, verification) and has no capability that the command line and the director tools lack. Its layers (model, app, adapters, ui) are enforced by dependency-cruiser, and it reaches the simulator only through a local bridge. It needs a desktop browser at least 1280 px wide.

The review of a finished simulator run. A timeline shows a fault marker for condenser fouling on chiller CH-1 at 25 minutes. The report panel says Verified, that the files match and the replay reproduces, lists 3,000 observations, and has a disturbances table with the one injected fault.
Screenshot of the simulator canvas in Chrome: the review of a finished simulated run, with the fault marker, the recording-integrity check, 3,000 observations and the disturbances table. This run was not scored against an outside system.

An empty canvas gains two areas, Chiller hall and Office block. Two large chillers and one small chiller are placed in the Chiller hall, each with named instruments. An air-handling unit is placed in the Office block and its load output is linked to the small chiller. Run plant is pressed and readings appear: for example chiller 1 at 440 cubic metres per hour and 185 kilowatts. The view then pulls back to a factory plant of 23 instances and 59 links built from the same library.

Animated from the shipped Chiller pilot plant file and a recorded run (seed 1). The assembly follows the file's own order; the run segment is sped up 60x.

16.8 Limits

LimitWhy it matters
No automated test exercises a real microcontroller or gateway.A green suite says the simulator handles the contract. What a real board did comes from the recorded sessions in section 20.
A board's DRESULT is its own report.“Succeeded” is not a physical effect. A session with the motor disconnected proved it: the chain still verified the command. An independent instrument is needed.
A real device has no truth and no score.Graded runs use simulated devices; hardware is integration evidence.
A mixed session without pace runs ahead of the hardware.Simulated and real time series cannot be compared in real time.
A held plant may still act once.A command the gateway accepted cannot be cancelled.
The control socket has no authentication or operator identity; one gateway per session.Controls are for a trusted local operator.

17. The experiment rounds in detail

Each round had a runbook with a written bar ("A to F green with live evidence", "moments 1 to 7"), a scratch directory of databases, traces, and logs, and an issue file per defect. The rule was to loop until the bar was met or genuinely blocked, and never to lower the bar. The reasoner in these rounds was scripted, as the correction below explains. Read every row as evidence about the machinery. Five rounds were planned and four ran: 1, 2, 3, and 5. Later benchmark and simulator runs aren't summarised here. The pump-station trial (section 18) is a later piece of work and is not one of them.

The correction I had to make

Reading the reports back, I found the flaw in my own proof. In every round that ran, the reasoning step was a scripted brain: a deterministic graph that produced the right diagnosis and even emitted “model started” events without calling a model. So the rounds prove the machinery (timing, governance, approvals, memory, recovery). They do not prove intelligence, and no further scripted round could. The pump-station trial in section 18 is the first run with a real model across a whole station.

Round 1 · 13 Aug 2026 · connect

StepResultEvidence
Shared canonicalisation vectorsPassRuby and Go bound the same snapshot digest; 73 Ruby assertions
Worker handshake over UDSPassProtocol and contract 1.0 negotiated
Live simulator trace, end to endPassRotating machinery with bearing wear, 31,683 events: attempt produced → decision accepted → command succeeded → outcome reconciled
Learning from the outcomePassExactly one Experience admitted, epistemic_kind = observed, with outcome, decision, and command provenance

Sixteen gaps were fixed. Typical ones: the adapter emitted flat dotted keys where replay expected nested events, arrival-time ties broke strict ordering, digests were raw bytes on one side and sha256:hex on the other, and verdict vocabularies disagreed between repos.

Round 2 · 14 Aug 2026 · supervise and learn

MomentResultEvidence
Budget killPassA second model call past a one-call budget ended the attempt mid-run as BUDGET_EXHAUSTED; zero decisions
SupersessionPassEpisode marked superseded mid-flight; attempt cancelled, zero decisions, resumable checkpoint left
Reconsideration + compensationPassA late event produced a corrected version, a RECONSIDER episode, and an R1 downgrade compensating the invalidated command
R2 approvalPassapproval_required, relay delivery receipt, signed single-use assertion; withdrawal and late-approve refusal covered by unit tests, not live
Second-occurrence recallPassmotor-18's checkpoint memory held motor-17's Experience with full provenance; cross-boundary isolation tested
Trace + cost ceiling + soak-litePassOne traceparent from source event to outcome; cost ceiling halted admission with ingress alive; 30+ minutes clean

Full suites at the end of the round: Tamoz 1,663 runs and 18,197 assertions, 29 Go packages in Agentic Stream, and the simulator suite, all green. Fifteen issues were fixed. The repeated classes taught me the most: digest domains missing a trailing newline, payload keys not declared as graph channels, and zero values treated as missing.

Round 3 · 14 Aug 2026 · three industries

MomentAquacultureWater networkGreenhouse
Quiet baseline admits nothingPass (7,200 events, 0 episodes)Pass (8,280 events, 0 episodes)Pass
Silence fails closedPass (R2 exchange denied, source_health_incomplete)Pass (R2 denied, R3 denied)Pass
Watch over guessPass (R0 watch + R1 aerator)PassPass
Confounder discountedPass (post-feeding dip)Pass (scheduled draw → watch only)Pass
Signed approval → command → outcomePassPass (plus R3 interlock)Partial (fail-closed under probe silence)
Late correction → downgradePassPartial (timer versions interleave)Partial in the rerun
Second-occurrence recallPass (2 recalled digests)PassNot reached
Storm at the cost ceilingPass (3,600 evals, 0 episodes)PassNot reached

The table is the 14 August run. A later greenhouse rerun passed the approval, recall, and storm moments, with the late correction still partial. Twenty-three commits across two repos. The original report blamed per-event processing at 8 bays by 9 channels for intents going stale before approval, and that shaped the roadmap. The rerun's report puts that partial result down to where the trace was cut, so a single-node ceiling is a hypothesis, not a measured limit. Round 4 was meant to test it.

Round 4 · prepared, not run

A grid-scale battery storage scenario: one node, 256 to 1,024 racks, about 12 channels each. It's meant to find the knee and the degradation curve, plus one distinctive reasoning moment: when a rack runs away and its neighbours warm, the right move is isolating the source (R2, human) and watching the neighbours, not raising twelve alarms. The runbook and starter specs are written. Nothing has run.

Round 5 · 17 Aug 2026 · audit the assumptions

PhaseResultWhat it showed
Cold chainPartial: all moments pass except the late-reading milestone, which found one engine bugA 14-hour ocean gap; 840 late readings admitted within allowed lateness, 606 reconsideration items, a real compensating episode. F-1: the reducer picks the winner by event time, so a corrected running total (true value about 8.65 h) never replaced the stale one (about 1.65 h).
LogisticsPass, all seven momentsLost tracking failed closed; an absorbed leg delay got a watch, not an expedite; a customs-hold cascade named its cause at 0.9 and went through a signed approval; an optimistic carrier ETA was cross-checked and not trusted; shipment-09 recalled shipment-04; a hub-outage storm of 1,105 events started 0 episodes.

Round 5 also exposed drift. The starter specs had been written against an older wire shape, and the run needed nine live spec corrections. Those corrections now live in the starters. The remaining picks (security events, an agent-fleet supervisor) were attempted on 31 August and recorded as blocked, because their domains and specs don't exist yet. A cold-chain rerun that day was still partial on the same milestone.

After the rounds: a real reasoner

A review after Round 3 found the flaw described in the correction above: the graph brains hard-coded the diagnosis and emitted model events themselves. The fix shipped as eight phases on 15 August. (Round 5 ran two days later and still used a labelled fixture brain on purpose, because it was testing the engine's assumptions, not reasoning quality.)

  • one real, journaled model call through the fixed episode graph;
  • durable model calls as graph branches, with budgets computed from receipts;
  • the witness gateway, which re-hashes the frozen request, forwards it verbatim, and signs one record binding request, response, provider, model, settings, and usage. Tamoz's own events stopped counting as evidence;
  • the spec-bound intent catalog, verified independently in Go;
  • skills and memory entering the frame as attributed, untrusted evidence;
  • RECONSIDER as graph nodes (judge, then compensate);
  • a frozen benchmark protocol with holdout mechanics and a 14-control gate;
  • a calibration artifact bound to the compiled spec, so any spec change drops consequential intents back to watch-only, plus a no-hidden-fallback rule: a production route gets a real model answer or a hard failure, never a canned decision.

18. The pump-station trial

The trial is a design for measuring whether a learned rule helps, against a model-only baseline, with a real model. The plain-language account is on the overview; this section has the engineering view. The trial used GLM through z.ai via Tamoz; the system itself works with any model.

18.1 Design

Eight pumps, one pump_condition Situation per pump (examples/pump-station/pump-station.situation.yaml), opened on per-pump relative features such as the 15-minute mean against the pump's own 24-hour mean. There are three fault families (bearing wear, misalignment, sensor drift) plus a transient_none cavitation look-alike. Each run is 30 simulated hours with up to 6 faults in the first 2 hours plus one look-alike; 30 hours leaves every case its 24-hour settle window inside its own run, which I checked on paper for every run before launch. The world is paced by the consumer: it waits at each 60-second slice until the consumer has ingested it and has no reasoning in flight (up to 240 s, an episode's budget). The approver is a scripted careful approver that approves a proposal only if its replay shows no disagreement; there has been no run with a human approver.

Figure 12 · The two arms of the trial

The two trial arms Arm B with rules ran one warm-up run, then learning runs that settled after three, then three holdout runs. Arm A, model only, started from a copy of arm B's learned database without its playbook and ran the same three holdout runs. ARM B · WITH RULES Warm-up 1 run, no faults Learning runs settled after 3 (up to 7 allowed) cases, drafts, approval, shadow Holdout 3 runs: 18 faults, 3 look-alikes about 56 minutes ARM A · MODEL ONLY Copy of the learned database without its playbook same history as arm B Holdout the same 3 runs about 25 minutes

Scroll sideways to see both arms.

Source: the frozen trial result. Both arms enter the holdout with the same history. Wall times are approximate.

18.2 Results

Same three holdout days, same starting database, 18 faults and 3 look-alikes per arm. A right repair by the deadline means the right work order was booked before the fault's deadline.

MeasureModel onlyWith learned rule
Model episodes1513
Rule decisions05
Faults detected, right pump (of 18)1517
Right diagnosis (of 18)1111
Right repair by the deadline (of 18)67
Action on a look-alike (of 3)00
Bookings denied by the rate limit00
Right repair by the deadlineModel onlyWith ruleWho decided, with rule
Misalignment (of 6)55The rule, every time (pumps 2 and 8, 5 and 8, 3)
Bearing wear (of 6)12The model. No bearing rule exists, so the difference is the model's own variation.
Sensor drift (of 6)00The model, always calling it bearing wear

The sixth misalignment (pump 4, run 1) got no repair in either arm: a simulated lost acknowledgement had put the pump on hold until an operator cleared it. Fixed after the trial (section 19).

Campaign 2 ran twice. The table shows what the two design changes did:

MeasureFirst run (campaign 2)After the changes (campaign 2b)
Range the rule may act in (axial 15-minute mean)2.746 to 2.7652.47 to 3.04
Rule decisions in the test days05
Bookings denied by the hourly rate limit7 per arm0
Misalignments repaired on time, with rules3 of 65 of 6

18.3 Pass conditions

P conditions were set in the plan before the run. S rows are the plan's named scenarios.

ConditionResult
P1Model calls per handled fault with rules: at most half of model onlyFail 76% (13 of 17 detected faults against 15 of 15). Only one of three fault families got a rule.
P2No more damage with rules than withoutPass 11 faults unrepaired by the deadline with rules, 12 without.
P3No more false actions on healthy pumps, and none by a rulePass 0 and 0.
P4Every rule-handled case right, action and deadlinePass 5 of 5.
P5Situation to recommendation for rule cases within 1 s at the 95th percentileFail 147 s. The rule answers in about 1 ms, but each case waits the trigger's one-minute debounce (counted in wall-clock time), then up to 87 s behind model episodes, because a tenant's episodes run one at a time.
P6Every pair with 3 verified, uncontradicted cases got a proposalPass Misalignment and bearing wear.
S2Cavitation look-alike never triggers maintenancePass 0 of 3 in both arms.
P7A masking rule never passes silentlyNot exercised No rule of that kind was proposed.
S7New probes: rules learned on the old device model switch off when a pump gets a new probeNot covered The kind_changed circuit has its own tests in Agentic Stream, outside this trial.

18.4 What was learned

  • Bearing-wear drafts (a ratio of the vibration mean to the pump's own 24-hour mean) were each rejected because replay showed one disagreement, and the key stays closed until there is new evidence.
  • Sensor drift was always diagnosed as bearing wear, so it never became a key.
  • The misalignment rule carried the whole result: the rule decided all 5 cases it saw, and it never acted on a look-alike.

18.5 Reproduce and limits

One station, one seed, three test days per arm, one model. Not covered: repeated seeds, replay identity of a campaign, a third arm. The builds were Agentic Stream 62ccc278, Tamoz d9fcbdb7 and Streams Simulator 5baed2eb, with plant wire contract 1.5.0. The recorded exchanges name no investigation probe, so this trial says nothing about probes. The full result, the campaign spec, the learned playbook, and, per arm, the score (model only, with rule), the ledger extract (model only, with rule), and every model answer (model only, with rule) are frozen on this site. That work is on the rule-promotion branches and is not yet merged to main.

What would change these results. Repeated seeds would show whether 7 against 6 is more than noise. A rule for a second fault family would test P1. Merged simulated-time scheduling and a rerun would test P5. A human approver would test whether the careful scripted one was too convenient.

19. What the trial found and fixed

Running the whole loop against a real model surfaced problems that unit tests had not. Each was invisible to the tests.

ProblemHow it showed upFix
Commands never reached the plantNo device catalog, so the runtime fell back to a stand-in effector.The runtime now refuses to start that way.
Host dropped while the model thoughtThe simulator counted three missed barriers as host loss while a 4.5-minute hold was in progress.Plant wire contract 1.5.0 judges liveness by heartbeats, and the host keeps them going while it pauses the world.
Barrier answers slowed from 0.2 s to 1.6 s24-hour windows stored as one growing JSON blob of up to 1.3 MB, rewritten on every reading.Samples are rows; barrier answers stay flat at about 0.2 s.
No rule draft could succeedDraft requests carried hundreds of event ids per case, over the 4 KB per-case limit.A draft sends only the features a rule may read.
Bookings denied by a wall-clock rate limitA world 200 times faster than real time put 30 simulated hours into about eight minutes.The policy plane's hourly limit counts event time. The playbook's per-rule rate cap already did.
Trial shape (mine)Back-to-back 16-hour runs put new faults on pumps still inside their 24-hour settle window.30-hour runs, checked on paper before launch.
Verified meant closed, not recovered (after the trial)9 sensor-drift cases counted as verified bearing repairs once the 24-hour baseline caught up.The recovery check (section 12.1).
A lost acknowledgement blocked a pump (after the trial)A booking leaves nothing to read back, so only an operator could clear the reconciliation.It now ends in review at once, and the pump clears with its next good reading.
Debounce counts wall-clock time (in progress)In a paced world each rule case waits a real minute, which alone breaks P5.Scheduling on simulated time is on its own branch. It still breaks one plant test and is not merged.

20. The hardware bench

The physical experiment adds one layer below the stream: a gateway process and an Arduino-compatible board. Nothing in the core changes, because the simulator's device emulator already spoke the same contract.

Figure 13 · Who touches what on the bench

Hardware bench topology Five layers from top to bottom: Tamoz decides a mode and has no port or device names; Agentic Stream builds the Situation, applies policy, and sends a bounded command over plant wire; the gateway is the only process that opens the USB serial port and maps the command to a leased PWM setting; the Mega 2560 firmware enforces a 60 percent cap, a lease watchdog, and safe stop; at the bottom, a DHT11 sensor on pin D2 and an L293D driver with a DC motor and fan. Telemetry flows up to Agentic Stream on the left, and commands flow down from it on the right; Tamoz sees only Situation snapshots and returns typed intents. The whole route ran on this bench on 25 October 2026, with the owner approving each command. The first motor test failed because the driver inputs were wired to D4 and D3 instead of D6 and D7. Tamoz chooses a mode: hold or bounded_cooling · no port, no device names in its code Agentic Stream Situation, policy, and a bounded command over plant wire, from catalog presets Gateway the only process that opens USB serial · quarantines bad frames · maps to set_pwm_lease Mega 2560 firmware · device wire v1 60% duty cap · lease watchdog · safe_stop · firmware and capability digests DHT11 on D2 temperature + humidity, quality flag L293D → DC motor + fan EN on D5 · direction on D6, D7 TELEMETRY UP COMMANDS DOWN Situation snapshot ↑ · typed intent ↓ joined 25 Oct 2026: owner approved each command, no fan instrument first motor test: direction inputs on D4 and D3 → H-bridge held in brake The firmware's limits hold even if every layer above it is wrong.

Scroll sideways to see both directions.

From the bench records. The direct-serial command was operator-observed. The full route ran on this board in three recorded sessions on 25 October 2026, through the simulator as plant wire node. The board reports the duty it was commanded, so nothing here measures the fan independently.
The Tamoz hardware bench: an ELEGOO microcontroller board wired to a breadboard circuit, a blue temperature and humidity sensor, and a small fan motor
Photo of the bench: an ELEGOO Mega 2560, a DHT11 temperature and humidity sensor, an L293D motor-driver circuit, and a small DC motor with a fan blade.

What ran, in order:

  1. Simulator first. A fresh three-process run against the device emulator produced 61 accepted telemetry events, zero quarantines, one Tamoz decision, one command, an executed device exchange, and reconciled state feedback. Verdict: pass. Software only.
  2. Sensor-only live ingress. The real board emitted paired DHT11 frames, and a fresh Agentic Stream runtime durably accepted 8 temperature and 8 humidity events with zero quarantine rows.
  3. LED probe. set_led returned a receipt, a result, and a state of energized at 1000, and safe_stop returned the board to a safe state. The operator saw the LED. The raw probe wasn't kept as an immutable artifact, so it counts as candidate evidence.
  4. Fan probe, first attempt. A perfect trace with a motionless motor. Full power in both directions, still nothing. The motor alone across the rails, it spun. Root cause: the direction inputs were on D4 and D3.
  5. Fan probe, corrected. Two jumpers moved with no firmware change, so the digests still matched the checked-in build. A governed command at 600 permille with a 10-second lease, operator-confirmed visible and audible rotation, then an explicit safe stop. A combined sensor-and-actuation run followed.
  6. Real model, separate run. A thermal snapshot went to a real model. The first valid-looking Decision wrote PWM fields and was rejected. With the catalog narrowed to mode, it returned bounded_cooling. It doesn't produce a schema-valid Decision every time, and a bounded retry lands one within a couple of attempts.
  7. Full route on the real board, 25 October 2026. Tamoz with glm-5.3-flash, Agentic Stream, plant wire, the simulator as node, the gateway, and the board ran as one system. I warmed the sensor by hand and approved each command at the node. Three commands ran, show_state alert twice and set_cooling 45 once. Each was accepted, reported as succeeded, and verified from the board's reading. verify-run passed with zero quarantined readings, though the gateway logged 10 answers it couldn't match to a command, which look like its own polls. The session record is frozen on this site.
  8. Same route, motor disconnected. set_cooling 45 still completed, read back 45, and was verified as succeeded. The board reports the duty it was commanded, so the chain can't see a dead fan. The same session had a silent board, answered as not_ready, and a refusal at the node, recorded as local_control. Both ended as failed and neither was retried, and those two failures made verify-run report fail. The cause of the silent board is unknown.
  9. Third session, with fixes. One show_state alert and one set_cooling 45, proposed as the intents set_indicator and select_thermal_mode with bounded_cooling, each approved. verify-run passed. There was no silent board, in one run after a change to the gateway's timing, so that's not a diagnosed fix. The gateway logged 18 unmatched answers from damaged state polls in 9 minutes. Compared with its twin, the fan level agreed. Temperature and humidity didn't, because the twin's resting temperature wasn't this bench's. After recalibrating, most of the remaining gap came while my hand was warming the sensor, which the twin has no input for.

Read those sessions narrowly. The third ran on Tamoz 9170538c (with 2 uncommitted lines), Agentic Stream d7fc5626, and Streams Simulator d0d373ba, with plant wire contract 1.4.0, earlier than the revisions in section 22. The thresholds were bench-scale (open at 23 C, escalate at 26 C, close at 22 C, against 30, 38, and 28 in the committed spec). Both intents were R1 in that spec, so approval came from the node's approve-each control, not from the stream's signed R2 path. A fan command here is a 5-second lease (the earlier direct-serial test used 10) at most 6 times an hour, so the runs prove the loop, not sustained cooling. The records show no run of hold, expiry, unplug and replug, host loss, or emergency stop. A measurement of airflow or zone temperature that doesn't come from the board would be the evidence that changes this from a closed command loop to a verified physical effect.

GateState
Protocol emulation (happy path)Pass. On the real board, a node refusal and a silent board have each been seen once. The Mega resets whenever the port opens, with a new boot id at each gateway start. Lost ack, a reboot during a command, and stuck output have no real-board record I could find.
Physical telemetryDHT11 subset passes: about 270 readings in the third session, 2.01 s mean gap, zero quarantined. Disconnect and reconnect not exercised.
Bounded physical effectRotation operator-observed in the direct-serial run. The full route is verified only from the board's own report. No independent instrument yet.
Authority, reconciliation, e-stop on hardwarePartial. Approve-each and a node refusal ran. Emergency stop and host loss did not.
Eight-hour physical fault soakNo run recorded
Part 4 · Operating limits

What's still open, and where to check what this page says.

21. Open findings

These are the known gaps, collected in one place. Each has an owner file in its repo and, where possible, a test that flips when it closes. O labels come from the physical-side evaluations, F labels from Round 5, and P and S from the pump trial. Only what still matters here is listed, so the numbers have gaps.

FindingWhereWhy it matters
No independent physical measurementHardware benchThe joined runs verify a command from the board's own report. With the motor disconnected the chain still verified it, so a physical effect is not established.
O1 · no evidence-fitness gate in the agentTamoz decision_builder0 of 8 unfit-evidence cells refused at Tamoz's layer. Downstream policy may still refuse, but the agent itself provides no defence in depth.
O2 · confidence is inert in the thermal loopTamoz thermal domainThe confidence floor is 0 and raw confidence is never set, so "unknown means stop" can't be enforced there yet.
O3 · neutral holdout still promotesTamoz improvementThe promotion bar is "no regression", not "strict improvement".
O6 · investigation is partialTamoz stream episodeOperator-declared, read-only probes and tamoz investigate exist. Results are development-only, with no held-out result, and in the latest run 7 of 232 episodes were fabricated or followed a planted instruction. I found no recorded run of a windowed probe inside a stream episode. An unknown answer can't act above R0. Not qualified for industrial use (section 11).
F-1 · corrected totalsAgentic Stream reducersA late correction can't revise a windowed running total.
F-5 · heartbeat seamAgentic Stream timersRound 5 found that wall-clock heartbeat timers don't propagate missing in every configuration. A 10 October fix changed this path and hasn't been rerun, so it stays listed.
Single-node ceilingRound 3 greenhouseThe first report blamed wide specs for slowing processing past the heartbeat window, and the rerun's report puts that result down to where the trace was cut. The limit is unmeasured, because Round 4 hasn't run.
Release-blocking gapsTamoz release auditTamoz is not released. The audit still reports gaps: kill and signal evidence that only reproduces on an unrestricted machine, versioned records (invariant 18), single-writer recovery (invariant 20), durable barrier timing, the Telegram channel's real-provider qualification, the verified artifact store, observability, evaluation hard gates, memory evaluation, and the coding scorecard.
Scheduling and skillsTamozNo cron or IANA timezones yet, and no skill install or update pipeline.
P1 · model calls per handled faultPump-station trial76% against a target of 50% or less. It needs a second fault family to earn a rule.
P5 · rule decision latencyAgentic Stream scheduler147 s at the 95th percentile, from the wall-clock debounce and queueing behind model episodes. Simulated-time scheduling is in progress and not merged.
Sensor drift always diagnosed as bearing wearPump-station trialSo it never became a rule. The recovery check stops it feeding the bearing key, but it has not been rerun.
Bearing-wear rule rejected by replayPump-station trialThree drafts, each rejected for one replay disagreement. The margin of the recovery check for bearing wear is thin (worst genuine 0.13, nearest drift 0.255).
P7 masking trap, S7Pump-station trialNot exercised, not covered.
Real board has recorded sessions, no suiteStreams Simulator limitationsThree sessions on one bench in one day, each with me present. Automated tests still use a stand-in gateway.
Single seed, single station, scripted approverPump-station trialNo repeated seeds and no human-approver run yet.

The full list, bound to the release audit by a test, is in Tamoz's limitations page, frozen here at the reviewed revision.

22. Sources and records

I last checked this page against the revisions below on 3 November 2026. These are local checkouts on each repository's rule-promotion branch, not merged to main. Results keep the build they ran on, so a later fix doesn't change a recorded number.

ComponentReviewed atCampaign 2b ran on
Tamozd9fcbdb7d9fcbdb7
Agentic Stream52b0871062ccc278
Streams Simulator42c6ed4f5baed2eb

The main records are frozen on this site as exact copies, so you can read them without access to the repositories. Their relative links don't resolve here. SHA-256 checksums cover every file.

RecordCopied fromSHA-256 prefix
Pump-station trial result, campaigns 2 and 2bStreams Simulator 6dd667cb4a4ef647
Campaign 2b specStreams Simulator 6dd667cb198cade2
The rule arm's learned playbookStreams Simulator 6dd667cbff426647
Score, model onlyStreams Simulator 6dd667cb4cdfdcdb
Score, with ruleStreams Simulator 6dd667cb69ebca4d
Every model answer, model onlyStreams Simulator 6dd667cbc1dc3a32
Every model answer, with ruleStreams Simulator 6dd667cb40312622
Ledger extract, model onlyStreams Simulator 6dd667cb5b47b4eb
Ledger extract, with ruleStreams Simulator 6dd667cbdabc3a45
Real-board session record, 25 Oct 2026Streams Simulator 6dd667cbd0c972ab
Investigation run 1, 25 Sept 2026Tamoz d9fcbdb7008c070b
Investigation run 2, 26 Sept 2026Tamoz d9fcbdb74e87f4ba
Investigation run 3, 26 Sept 2026Tamoz d9fcbdb7e4b4a4cc
What Tamoz v0.1 does not doTamoz d9fcbdb753b29414

Not on this site: the recorded requests sent to Tamoz and the run databases, which stay with the project, and the round reports, which are in a private lab repository. So you can't check these from here: the tables in section 17, the bench numbers from before October, and the per-reading values in the animated clips. They're my summaries of records you can't see.

Source access is by arrangement. If your review needs it, this is where each subject lives, and the pilot page is the place to start that conversation.

TopicStart here
The episode boundaryTamoz gems/tamoz-stream: episode_worker.rb, situation_snapshot.rb, decision_builder.rb, reconsideration.rb
Durable executionTamoz gems/tamoz-graph and gems/tamoz-sqlite
Memory, healing, improvementTamoz gems/tamoz-agent-memory, tamoz-agent-healing, tamoz-agent-improvement
EvaluationTamoz gems/tamoz-evals, gems/tamoz-evals-runner, agenteval/, docs/REQUIREMENTS_AUDIT.md
Stream plane and schedulerAgentic Stream internal/engine, internal/situations, internal/cognition
Governance and actionsAgentic Stream internal/decisions/internal/domain/validator.go, internal/policy, internal/actions/internal/app/dispatch.go
Simulator and device emulatorStreams Simulator internal/world, internal/perturb, internal/device, domains/
Decisions behind the designTamoz documentation/adr (62 numbered decisions, 9 of them retired), especially ADR-036 (the Situation boundary), ADR-038 (typed intent, never model effect), and ADR-039 (Tamoz is supervisory)
Rule promotionAgentic Stream internal/playbook, internal/draftport, documentation/design/rule-promotion.md, documentation/design/playbook.md, examples/pump-station/ (on the rule-promotion branch)
Plant wireAgentic Stream internal/plantwire, documentation/design/plant-wire-adapter.md; Streams Simulator internal/plantwire, contracts/plant-wire/SPEC.md
Simulator canvas and physical devicesStreams Simulator canvas/, documentation/guides/physical-devices.md

If you run equipment and want to find out whether this holds on it, the pilot page sets out what the team proposes.

See the industrial pilot

Back to the Tamoz overview · Where it fits: use cases