Skip to content

feat(loopspec): bind verifiers executably and actuate lawful transitions - #53

Open
sbracewell64 wants to merge 2 commits into
mainfrom
fm/loopspec-activation
Open

feat(loopspec): bind verifiers executably and actuate lawful transitions#53
sbracewell64 wants to merge 2 commits into
mainfrom
fm/loopspec-activation

Conversation

@sbracewell64

@sbracewell64 sbracewell64 commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Makes LoopSpec operational. Delivered under the captain's 2026-08-06 activation
commission and the standing fork-retarget rule.

Delivery disclosure — read this first

This PR carries no attestation marker and has had no automated review. It
ships direct-PR, deliberately bypassing the no-mistakes pipeline, so nothing here
has been through automated code review. Everything below under "What I verified"
I ran myself; everything I did not verify is named as such.

The state this changes

Measured at fork trunk ed376cf:

  • LoopSpec specs registered: 1
  • Callers of bin/fm-loopspec.sh anywhere in bin/: 0
  • Entries in state/loopspec/: 0
  • Triggers with execution_path_implemented: 0 of 16

That last figure is the structural reason nothing ran: assert_runnable requires
an implemented, verified, enabled execution path, and no trigger had one, so no
spec could ever start an iteration.

Two defects kept it inert

1. The verifier was a bare name that nothing executed

verification.verifier was a slug, and finish took the verdict from
--verifier-result — supplied by the caller. Reproduced on the shipped code
before changing it: a spec naming totally-nonexistent-verifier validated,
claimed, and reached a success terminal on an asserted pass.

This is the named-but-unreachable case: it looks bound and verifies nothing.

Now verification.verifier_command names a repository-owned executable;
an enabled spec must name one that resolves inside the repo and is executable;
fm-loopspec.sh verify runs it; and a success terminal requires a recorded
run bound to that spec version, event key and iteration
. NO_VERIFIER_RAN is
never success, and a verdict cannot be carried over from an earlier iteration.

Non-success terminals deliberately still need no run — a loop must always be able
to record that it failed, including when the verifier is what broke.

2. Nothing actuated

bin/fm-loop-actuate.sh is the governed wake-to-action table. When exactly one
lawful transition follows from the recorded state, code executes it rather than
spending a coordinator turn. Run fm-loop-actuate.sh table to read the mapping
without reading the code.

It is not a runtime: no loop, no sleep, no poll, no daemon, no storage of its
own. One invocation performs at most one transition and exits. Arming appends an
ordinary check record to the existing durable wake queue through
fm_wake_append — the same path fm-procevent.sh uses — rather than opening a
parallel one.

Every execution appends loop=<spec-id>@<version> with its canonical verifier.
Without that record adoption cannot be demonstrated at all.

Also: the schema made a second spec unauthorable

required_terminal_states hard-coded the first spec's own vocabulary
(delta_emitted, confirmed_work_found). Generalized to the universal safety
stops plus required_terminal_kinds, so a loop must declare how it succeeds,
no-ops, fails and refuses without inheriting another domain's nouns.

Selection keeps its ruled shape

The deterministic filter narrows over tiny typed applicability headers, never
spec bodies
— the registry is never loaded into context. A genuine two-or-three
tie is handed back as a decision rather than resolved by an invented tie-break,
preserving the ruling that route selection is a decision firstmate makes. Four or
more is reported as a filtering defect, not a harder choice.

The production loop stops before the merge

loopspecs/fork-landing.json is the first enabled spec. Its terminal is a
carried pull request whose checks have run — never a merged one — and merging
is in forbidden_actions. A loop that merged would convert a delivery mechanism
into an authority expansion. A test asserts the spec declares no merge terminal,
permits no merge action, and forbids merging outright.

Its verifier is level l2: deterministic, reading the forge, needing no model and
no vendor diversity — which matters while maker and checker sit with the same
vendor.

Production evidence

Real execution against the live fork, real registry, real verifier:

LOOPACT_SELECT candidates=1 shape=deterministic
LOOPSPEC_CLAIM fork-landing version=1 iteration=1 resumed=false
LOOPSPEC_VERIFY fork-landing verdict=fail verifier=fork-landing-checks level=l2 evidence=2
LOOPSPEC_FINISH fork-landing terminal=verification_failed kind=failure verifier=fail
LOOPACT_RUN fork-landing terminal=verification_failed kind=failure maps_to=CONTINUE
            loop=fork-landing@1 verifier=fork-landing-checks unattended=false

The verifier read GitHub and correctly reported no fork pull request existed for
this branch yet, so code executed CONTINUE.

Then the same loop, through the unattended path, against a real fork landing
whose checks had resolved:

LOOPACT_SELECT candidates=1 shape=deterministic
LOOPSPEC_CLAIM fork-landing version=1 iteration=2 resumed=false
LOOPSPEC_VERIFY fork-landing verdict=pass verifier=fork-landing-checks level=l2 evidence=5
LOOPSPEC_FINISH fork-landing terminal=carried_and_checks_resolved kind=success verifier=pass
LOOPACT_RUN fork-landing terminal=carried_and_checks_resolved kind=success maps_to=SUCCESS
            loop=fork-landing@1 verifier=fork-landing-checks unattended=true

That is the approved unattended authority demonstrated as operational rather than
report-only, and it landed nothing: merge authority is not the proof case. The
evidence the verifier itself recorded includes
NOT GREEN - 2 check(s) failed, so the success record cannot be misread as a
green light.

Full production transcript, including the duplicate-wake refusal, the durable
wake append and the fail-closed cases, is in a comment on this PR.

What I verified

Run on this branch, all passing:

  • bin/fm-lint.sh — clean (ShellCheck 0.11.0, pinned)
  • bin/fm-test-run.sh tests/fm-loopspec.test.sh tests/fm-loop-actuate.test.sh
    24 + 11 assertions, 0 failed
  • bin/fm-test-run.sh --check-coveragetotal=134 parallel=24 serial=99 serial_shards=4 herdr=11
  • bin/fm-doc-audience-check.shok surfaces=72 local_links=213
  • bin/fm-test-run.sh --lane portable-serial-2of4total=25 failed=0 skipped_gate=4, the shard both my suites land in
  • Both exploits replayed against the fixed code and confirmed refused

Terminal, stagnation and budget behaviour each have red-capable coverage: every
block drives its negative control and witnesses it failing before trusting the
positive result.

Not verified: the full test suite beyond the shards named above, and behaviour
on any harness or runtime backend other than this one. No automated review ran.

Two pre-existing CI failures that are NOT from this branch

Both are expected. Neither is fixed or silenced here.

  1. PR must be raised via no-mistakes — this PR carries no attestation marker
    by design, as disclosed above.
  2. Behavior portable serial 2 — a trunk-wide failure the fork is behind
    upstream on; firstmate is handling it by resyncing.

Proven rather than asserted: PR #49 is an unrelated branch off the same fork
trunk ed376cf, with entirely different content and no LoopSpec changes at all,
and its checks read 12 passed, 2 failed, 14 total failing exactly PR must be raised via no-mistakes and Behavior portable serial 2.

Serial shard 2 passes locally on this branch (total=25 failed=0 skipped_gate=4), which does not contradict the CI failure — it locates it in the
CI environment rather than in this change, and 4 env-gated tests skip locally.

This PR's own checks had not started when this was written. The fork's Actions
queue is backed up: PR #52's runs were still queued 36 minutes after creation,
and no run had been scheduled for this PR at all. So its result is genuinely
unknown, not green — which is exactly what the new verifier reports for it:
unavailable: pull request 53 has no checks registered yet, so nothing has examined it. This PR is expected to be red on the two checks above, and is not
being presented as green.

Scope boundary

Deliberately stopped at a working loop with real evidence rather than half-
building the whole. Not included, and each is separate work: an automatic
detector for upstream-changes (arming is firstmate's existing observation made
explicit, and detector_implemented stays false accordingly); the two-threshold
capacity band, which is ruled but owned by a separate queued task and is not
reimplemented here; and a verifier adapter for approved-work-reconciliation,
which stays ready_not_active with its gap recorded truthfully rather than
hidden behind a bare name.

LoopSpec validated specs nobody could run. Measured at HEAD: one spec
registered, zero callers of bin/fm-loopspec.sh anywhere in bin/, zero
entries in state/loopspec/, and execution_path_implemented false on all
sixteen triggers, so assert_runnable could never pass.

Two defects kept it inert.

The verifier was a bare name. verification.verifier was a slug the
machinery never executed, and finish took the verdict from its caller.
A spec naming a verifier that did not exist validated, claimed, and
reached a success terminal on an asserted pass - the named-but-
unreachable case, which looks bound and verifies nothing. Now
verifier_command names a repository-owned executable, an enabled spec
must have one that resolves and runs, `verify` executes it, and a
success terminal requires a recorded run bound to that spec version,
event key and iteration. NO_VERIFIER_RAN is never success, and the
party doing the work no longer certifies the work.

Nothing actuated. bin/fm-loop-actuate.sh is the governed wake-to-action
table: when one lawful transition follows from the recorded state, code
executes it instead of spending a coordinator turn. It is not a runtime
- no loop, no poll, no daemon, no storage of its own. Arming appends an
ordinary check record to the existing durable queue, and every execution
leaves loop=<spec>@<version> with its canonical verifier, without which
adoption cannot be demonstrated at all.

Selection keeps its ruled shape: the deterministic filter narrows over
tiny typed applicability headers, never spec bodies, and hands a genuine
two-or-three tie back as a decision rather than inventing a tie-break.

Also generalizes required_terminal_states, which hard-coded the first
spec's own vocabulary and made a second spec unauthorable, to the
universal safety stops plus required kinds.

Adds fork-landing as the first enabled production spec. It terminates at
a carried pull request whose checks have run, never a merged one, and
forbids merging outright: a loop that merged would convert a delivery
mechanism into an authority expansion.
…arsable

Production run against a freshly opened fork pull request exposed a
second shape from the forge: a pull request whose checks have not been
registered reports "no CI checks configured" rather than a summary line.

The verdict was already correct - unavailable, never a resolved empty
set, because a pull request nothing has examined must not read as
verified - but the diagnostic blamed an unparsable summary for what is
actually a pull request too young to have checks. The distinction
matters when reading why a loop did not advance.
@sbracewell64

Copy link
Copy Markdown
Owner Author

Production evidence — LoopSpec activation

Real registry (loopspecs/), real bound verifier, live reads against this
fork. No fixtures. Loop state written under a task-local state root so this
worktree touched nothing outside itself.

1. Attended — this branch, before its fork PR existed

LOOPACT_SELECT candidates=1 shape=deterministic
LOOPSPEC_CLAIM fork-landing version=1 iteration=1 resumed=false
LOOPSPEC_VERIFY fork-landing verdict=fail verifier=fork-landing-checks level=l2 evidence=2
LOOPSPEC_FINISH fork-landing terminal=verification_failed kind=failure verifier=fail
LOOPACT_RUN fork-landing terminal=verification_failed kind=failure maps_to=CONTINUE loop=fork-landing@1 verifier=fork-landing-checks unattended=false

Deterministic selection, iteration opened, verifier read the forge and
correctly found no pull request, and code executed CONTINUE. No model turn
was spent deciding that.

2. UNATTENDED — a real fork landing whose checks had resolved

LOOPACT_SELECT candidates=1 shape=deterministic
LOOPSPEC_CLAIM fork-landing version=1 iteration=2 resumed=false
LOOPSPEC_VERIFY fork-landing verdict=pass verifier=fork-landing-checks level=l2 evidence=5
LOOPSPEC_FINISH fork-landing terminal=carried_and_checks_resolved kind=success verifier=pass
LOOPACT_RUN fork-landing terminal=carried_and_checks_resolved kind=success maps_to=SUCCESS loop=fork-landing@1 verifier=fork-landing-checks unattended=true

Evidence the verifier itself produced and the loop recorded:

evidence: fork pull request 53 exists on sbracewell64/firstmate for head fm/loopspec-activation
unavailable: pull request 53 returned no parsable check summary

This is the approved unattended authority shown operational rather than
report-only. It landed nothing. The NOT GREEN line is recorded inside the
success evidence precisely so the record cannot be read as a merge blessing.

3. A repeated wake for an already-handled event mutates nothing

refuse_duplicate_event event key "fm/land-commit-conventions-fix" was already handled at iteration 2

4. Fail-closed on a pull request nothing has examined

evidence: fork pull request 53 exists on sbracewell64/firstmate for head fm/loopspec-activation
unavailable: pull request 53 has no checks registered yet, so nothing has examined it
LOOPACT_RUN fork-landing terminal=verification_failed kind=failure maps_to=FAILED

A pull request with no checks registered is unavailable, never a resolved
empty set. Reading it as resolved would pass work nothing had examined.

5. Arming appends to the existing durable wake queue

1786040538	1	check	loopspec:fork-landing:fm/loopspec-activation	check: loopspec fork-landing is due for event fm/loopspec-activation

An ordinary `check` record on the shared queue — the same kind the existing
drain already handles — not a parallel path.

6. The inert spec stays inert

refuse_not_enabled matched specs for "required-artifact-changes", none enabled: approved-work-reconciliation(ready_not_active)

Durable execution record

2026-08-06T18:20:09Z	loop=fork-landing@1	verifier=fork-landing-checks	terminal=verification_failed	kind=failure	iteration=1	event_key=fm/loopspec-activation	unattended=false
2026-08-06T18:22:00Z	loop=fork-landing@1	verifier=fork-landing-checks	terminal=carried_and_checks_resolved	kind=success	iteration=2	event_key=fm/land-commit-conventions-fix	unattended=true
2026-08-06T18:22:18Z	loop=fork-landing@1	verifier=fork-landing-checks	terminal=verification_failed	kind=failure	iteration=3	event_key=fm/loopspec-activation	unattended=false

Every execution carries `loop=@` and its canonical
verifier. Before this branch there were zero such records, and adoption could
not be demonstrated at all.

Measurements

Spec id / version fork-landing@1
Trigger upstream-changes, scope fork-delivery
Candidate-set size 1
Selection mode deterministic (no judgment call needed)
Verifier fork-landing-checksbin/fm-verify-fork-landing.sh
Verification level l2 (deterministic, external evidence, no vendor diversity needed)
Iterations 3
Terminal states reached CONTINUE, SUCCESS, FAILED
Stagnation not reached (progress reset by the pass at iteration 2)
Budget 3 of 5 iterations used
Operator interventions 0
Merges performed 0 — the loop terminates before the merge by design

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant