Skip to content

refactor: run the gate's verification with Effect - #487

Merged
Sequela02 merged 7 commits into
devfrom
feat/effect-gate
Oct 18, 2026
Merged

Sequela02 merged 7 commits into
devfrom
feat/effect-gate

Conversation

@Sequela02

Copy link
Copy Markdown
Contributor

Second part of moving Tesota's coordination code to Effect 4 (after #486): the gate's verification.

What a stop did

Measured on Windows with a scratch script running the real gate on the engine, a check whose test script starts a process of its own and waits a minute, stopped once both run: the run ended 1.3-1.5 s after the stop, and the gate's handler finished at the same moment. runProcess alone stops that tree (Git's bash, npm, node and its child) in about 200 ms, and taskkill /T takes about 190 ms. So the gate went on working for over a second after the stop, building evidence for a receipt.

Change

  • settle, prove and measure are Effect.gen programs, one step per stage and per file, run with Effect.runPromise(…, { signal }). The stop interrupts between steps: no later step starts and no later progress is published. The gate no longer threads ctx.signal ?? new AbortController().signal through its stages.
  • step runs each stage: on interruption it aborts the stage's signal and waits for it, so a check's processes or Dafny's have stopped before the gate reports. The first version used Effect.promise, which does not wait; measured, the run then ended in 8 ms with both processes still alive.
  • A stop during verification settles with the receipt a stop before verification gives, now with "the operator stopped the run while Tesota verified it" and no evidence, as the owner chose. One function, stopped, builds both.
  • docs/concepts/verification.md and docs/guides/receipts.md say what a stop during verification does.

Checks

  • Stop during that check, four runs each:

    Before After
    Stop to run end 1,286-1,524 ms 211-240 ms
    The check's process and its child gone gone
  • New test in packages/core/tests/gate.test.ts: a stop while a project's check runs ends the run aborted, with the stopped receipt, and with both processes the check started gone. It fails on the gate before this change.

  • Gate tests: root 48 passed, engine 35 passed.

  • bun run check locally: root 264 passed; engine 320 passed, 3 skipped; lint and types clean. The budget fails on shell memory (115.6 MB, limit 115 MB), this machine's noise (Windows first-frame budget fails on runner noise #462); CI decides.

Verification is now an Effect the operator's stop interrupts (#408): the step under way ends with what it started, a check's processes or Dafny's, and no later step starts. The gate kept working for over a second after a stop, building evidence the receipt no longer claims; a stop during verification now settles in about 200 ms with a receipt that says the operator stopped it and claims no evidence, as a stop before verification does. Each step is awaited after its signal is aborted, so the gate never reports while a process still runs.
On Linux CI a killed orphan stays until its new parent reaps it, which kill(pid, 0) counts as alive, so the check right after the stop saw one; Windows CI saw both. The test now waits up to 10 s, far less than the minute the processes would otherwise run.
Prints each surviving process's chain of parents when a stopped check's processes outlive the stop on Windows. To be removed before merging.
…ntil #490

The diagnostic showed why Windows CI failed: Git's bash execs, which breaks the parent chain taskkill /T follows, so the stop cannot reach the check's processes there. That predates Effect and is #490. The temporary diagnostic is removed.
The gate loads with the shell, and importing Effect at its top evaluated it at startup: Linux CI measured the shell at 131.4 MB against a 128 MB limit, where other pull requests measured 119-125 MB. The gate now imports Effect's types and loads effect/Effect with its checks, the first time a run settles. The inventory test also checks namespace and dynamic imports of effect, which it missed, and docs/development.md records both lessons of this part.
The shell's measurement settles a run, which now loads Effect's runtime with the gate's checks: Linux CI measured 128.0 MB against a 128 MB limit, where pull requests before measured 119-125 MB. The owner approved 135 MB.
@Sequela02
Sequela02 merged commit 5c1804c into dev Oct 18, 2026
9 checks passed
@Sequela02
Sequela02 deleted the feat/effect-gate branch October 18, 2026 08:26
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