The sequence runner in this tool — aai-sequence — takes a JSON spec describing a multi-step write (typically a mail-filing flow: rename the upload, attach it to a case, create an activity, set tasks). Each step has args that get spawned through merus-fetch, and each step can declare an undo recipe that rolls it back if a later step fails. The runner has been doing this for months. The math is verified — five scenarios in the unit tests, live verification through real Merus writes with intentional force-fails.
What the verification surface didn't include was the layer that comes before the math: spec input validation. The attorney (or, more often, the model writing the spec on the attorney's behalf) hands the runner a JSON object. The runner parses it, builds step objects, and starts executing. The implicit assumption was that the spec would either be well-formed or so obviously broken that the runner would error out clearly.
The probe was simple. Send each of several malformed specs through stdin and observe what comes out. Most worked correctly — invalid JSON produced "spec is not valid JSON", missing top-level steps field produced "spec must have a steps array", invalid spec shape (not an object) produced a sensible diagnostic. Three cases produced output that looked successful but was actively wrong.
Empty steps array
The first probe sent a spec with steps: [] — zero steps, no work to do. The runner accepted it. It walked through an empty loop. The output was a JSON object with ok: true and an empty completed array. The audit log got a single sequence entry tagged with whatever label the spec provided, marked successful.
From a strictly mechanical standpoint, the runner did the right thing: zero steps ran, zero failed, the math says ok. From the attorney's perspective, this is wrong. The spec was authored with some intent. Whatever that intent was, the runner didn't accomplish it. The audit log says the sequence ran fine, which means later review of "what did this firm do on this case" will see a successful sequence that actually did nothing.
The fix is to refuse the spec at submission. A zero-step sequence is, by construction, a misconfiguration — either the spec was generated incorrectly or it was hand-edited and a step list got truncated. Either way, the right behavior is to fail loudly at the point where the attorney can do something about it, not at audit-review time months later. Empty steps now refuses with exit 3 and "sequence has no work to do."
Missing label
The second probe omitted the label field entirely. The runner accepted it and silently defaulted the label to "aai-sequence-run." Every sequence without an explicit label got that same generic identifier.
This is the kind of bug that's invisible until you go looking for a specific sequence in the audit log and find five hundred entries all labeled "aai-sequence-run." The label is the only handle for correlating a sequence audit entry with the operation it represents. Without it, the audit trail loses the ability to answer "what happened on this case in March?" with anything more specific than "a bunch of sequences ran."
The interesting thing about this fix is that it would have broken a lot of test code if applied a few months ago. Test specs (ad-hoc invocations during development) often skip the label. But every production skill — the four that write to Merus through aai-sequence — already provides an explicit label. Verified by grep across all skill files. The change requires the label that production already uses; it just stops accepting the omission that only test code did.
The label is now required. Missing it refuses with "label is required (used as the audit-log identifier for this run)."
"Missing args" vs "wrong type args"
The third probe edited a working spec to change args: ["/tasks/index"] to args: "not an array". The runner's validator produced "step a has no args array." Same diagnostic as completely omitting the args field.
This is a different kind of bug. Both are valid spec misconfigurations and both need to be refused, but the FIX is different. "Missing args field" means you need to add an args field. "Args is wrong type" means you have an args field but it should be an array, not whatever you wrote. An attorney debugging the spec gets the same message either way and has to figure out which case they're in.
The fix splits the diagnostic. Missing field: "step a is missing the args field." Wrong type: "step a has args of type string — must be an array of merus-fetch CLI arguments." Empty array (a third subcase that wasn't caught before): "step a has empty args — at least the endpoint path is required."
The thread
All three of these are flavors of "spec validation that wasn't strict enough." None of them are catastrophic. None would have caused data corruption or accidental writes. What they have in common is that a misconfigured spec could pass validation and produce an audit-log entry that looked legitimate — empty steps logged as success, missing label rendered as generic, ambiguous args message sending the attorney to the wrong fix.
The audit log is the trail this whole system is trying to defend. The recent releases in this project have focused on making the trail honest in increasingly specific ways: rejected writes are now logged (4.5.39), guard refusals are now logged (4.5.54), in-flight intent is now logged before the response arrives (4.5.52). What this release adds is the validation layer that comes before any of that: refuse the obviously-misconfigured spec at submission so the audit log never gets an entry for the failed-but-looked-successful run.
The probe also surfaced something I want to remember. The cases I tested were straightforward (empty steps, missing label, args of wrong type) but they had all been live in the codebase for months without anyone noticing. The reason is that production traffic always sends well-formed specs — the skill files are written carefully, the model follows them, the resulting spec is correct. The bugs were only visible to specs that humans hand-edit, or to specs the model generates incorrectly. Both of those happen rarely enough that the bugs were invisible to normal use.
The lesson is the same one I keep arriving at. Verification against the happy path is not the same as verification against the misconfiguration path. Both matter, and the second one is the one you only catch by deliberately feeding the system bad input.
The version on the install URL is 4.5.83. The work continues at the pace of one verified release at a time, and the sequence runner is now stricter about what counts as a valid spec.