Repository navigation
F2b: durable safety findings, failed-run audit and partial output (#87, part 2) - #94
Merged
Merged
Conversation
… part 2) - Safety findings are saved on their attempt (schema v8, safety_finding) before the terminal write, which sends the task to needs human in the same transaction whatever outcome wins; startup recovery does the same and does not requeue. An attempt started outside ItemExecutor is covered too. Only a finding whose save failed is held in memory, as before. - A run whose agent failed on its own is inspected and audited (auditFailed); a violation or a refusing inspection is a finding. Nothing is committed. - A declared link whose snapshot status is through-link is never launched. - A writable attempt that did not complete keeps its partial output (exportPartial): D's bounded diff saved owner-only and referenced as diagnostic_ref, with retention that never deletes a referenced file. - Test: a scope pause stays approvable after a review load. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- A result that is not this attempt's no longer skips the failed-run audit and the partial-output export: both run in one place (#keepEvidence). - Tests: a run stopped while it ran is not audited (the old test stopped before launch), and an export gives up at its own deadline. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…w round 2) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Oct 1, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part 2 of #87: items 1–4. It also closes the
through-linkgap left from part 1. Part 1 merged as #92; production wiring is #91.What it adds
attempts.safety_finding) through the shutdown capability, before the terminal write. The terminal write then sends the task to needs human in the same transaction, whatever outcome wins: a stop or a stale context does not undo what the agent did. A pending cancel still closes the task. Startup recovery does the same for an attempt a crash left, and does not requeue it. The migration is idempotent.ItemExecutor/api/runnerstart or retry goes to needs human too, and admission refuses new work from needs human.RunnerDeps.auditFailed. When the agent ends badly on its own (a non-zero exit or a D stop reason, with no first reason), the same inspect-and-audit asfinishruns before the terminal write. A violation, or an inspection that refuses, is a finding. Nothing is committed. A stopped, stale, time-limited or shut-down run is not audited.RunnerDeps.exportPartialandTaskWorkspace.exportPartial(D'sexportTaskDiff). For a writable attempt that did not complete, the diff is saved as<diagnostics>/<attemptId>.diff, owner-only, through an exclusive temporary file, and stored asdiagnostic_refby the terminal write. The export has its own 60 s deadline and is never cut short by a stop. A failure adds a quoted "Partial output could not be exported" to the diagnostic.runner/diagnostics.ts)forgetDiagnostic), and only then is the file deleted.through-link(from part 1)through-linkis never launched. Preparation records a finding and fails.Design note
A task cannot change status while it has an active attempt (
transitionTaskrefuses). So the terminal write always meets a running task, and a saved finding is always acted on there. I first built an "owed" mechanism (admission and merge refusals, a pay step), then removed it as unreachable. Only a finding whose save failed is still owed, in memory (SafetyFindings), exactly as before.Test changes
findingSaveErroroption, keeping their meaning. Two described behaviour this changes and assert the new behaviour:through-linkrefusal;Validation (local; first pushed head
e07f478, later heads in the rounds below)npm run typecheck: passes.review.test.ts, which passes alone (15 of 15) at a load average of about 70.test/runner-workspace.test.ts(real Docker): 3 of 3.Review rounds (
/code-review high)#keepEvidence).• The "stopped run" test stopped before launch; it now stops during the run.
• The export deadline is tested.
forgetDiagnosticraising the owning task's state version: the Store's rule is that every durable change to an attempt raises it, and a "stale state" refusal is fail-safe (the person reloads).finishfailed was inspected a second time; now only a run that ended badly on its own is audited.The new tests for rounds 1 and 2 were checked to fail with their fix removed.
Review lessons (merge gate)
🤖 Generated with Claude Code