Commit Graph

13926 Commits

Author SHA1 Message Date
Fusion Agent
47d2890031 fix(cli): make the raw logs view actually reachable, and stop it shadowing [v]
Two defects in my own previous commit, both visible in one screenshot of the dashboard.

IT DID NOTHING ON A WIDE TERMINAL. The escape was added inside the single-pane layout, which
is the NARROW one. A wide terminal renders the grid layout instead — System / Stats /
Utilities / Settings beside Logs — so the toggle flipped state and the screen did not change.
The whole point is that no chrome survives a rectangular selection, and chrome is drawn by
both layouts plus the header, so the escape has to happen before either is chosen. It now
replaces the entire frame, above the layout choice, and a test pins that ordering plus the
fact that only one place may render it.

IT SHADOWED AN EXISTING LEGEND. The Utilities panel already advertises `[v] Auto-Kill Vitest`
on the same screen. The two handlers are mutually exclusive at runtime — utility actions
require the Utilities section, this branch requires log focus — so nothing actually clashed,
but two different `[v]` legends visible at once is a UI anyone would misread. Raw mode is now
Shift+V; lowercase v stays with auto-kill.

pnpm lint 0 errors, CLI typecheck clean, dashboard-tui suites 138/138, test:gate green.
2026-08-27 00:48:09 +00:00
Fusion Agent
61f26ca4e7 feat(cli): add a raw, selectable logs view to the TUI
Reported: the logs cannot be highlighted and copied without column artifacts.

Two things cause that, and the code already named the second one: the Logs panel keeps a
border, a title and a filter row, and sits between a header and a status bar — so a
rectangular drag captures box-drawing characters and unrelated rows — while mouse reporting
is deliberately ON for that panel to drive wheel scrolling, which swallows the click-drag
before the terminal ever sees it.

`[v]` now shows the log lines alone: no border, no title, no filter row, no header, no status
bar, every line starting at column 0, and mouse reporting released so the terminal's own
selection works. One trailing hint row stays, because a full-screen view with no visible way
out is worse than one extra row. `[v]` or Esc returns, and the escape is ordered ahead of the
expanded-entry escape so the two modes cannot fight.

The rendered line shape matches the existing `[c]` single-line copy, so selecting with the
mouse and copying with the keyboard produce the same text. `[c]` remains the path for one
line; this is the path for a range, which no keyboard shortcut can express.

pnpm lint 0 errors, CLI typecheck clean, dashboard-tui suites 134/134, test:gate green.
2026-08-26 21:54:39 +00:00
Fusion Agent
4d2b42b068 fix(FN-WF): stop a successful merge aborting itself, and clear two merge-lane dead ends
Three root causes, all reported from one live multi-repository board, all ending as noise or
as a dead end an operator had to clear.

A SUCCESSFUL MERGE ABORTED ITSELF. The in-flight fence gives up ownership as soon as a card
leaves the resolved review lane — correct for a REVISE pulling the card back to
implementation, wrong for the move to the complete lane that the merge performs on success.
Measured: `all 2 sub-repo(s) landed — task → done` at 19:58:00.762, then
`Aborting active merge (left-review-lane-during-merge)`. Nothing was actually cancelled —
both repositories were already on main — but the primitive was torn down after the fact,
which is why one merge wrote `Workflow node merge requested merge` twice, 132ms apart. Fired
a few hundred milliseconds earlier it would abort a merge genuinely mid-flight. This is the
COLUMN half of what FN-184 fixed for the STATUS half, in the same file: "the fence revokes the
very merge it is guarding".

A DUPLICATE ENDED AS AN ERROR. MULT-024 was closed through the duplicate sentinel — no commits
expected, implementation must not proceed — and the merge boundary then demanded a pre-merge
node result it could not possibly have, terminalizing it with "operator action required". A
task that did exactly what was asked required human rescue. The structural proof asks "did the
planned implementation run"; it is meaningless for an authorized no-commit outcome. Exemption
narrowed by the shared `hasNonTerminalSteps` rule, so a card with unfinished work still faces
the full proof, and it waives nothing else: pre-merge approval and FN-8141's skipped-
verification guard still apply at the door.

MERGE CHECKS HAD NO RUNNER. The clean room exists to run the project's checks, and every
runner, linter and type-checker lives in devDependencies — but the install inherited an
ambient NODE_ENV=production and skipped them all. The executor said so in its own words
("the environment omitted devDependencies") and repaired itself; the clean room did not, and
its reviewer approved a merge whose tests could not run. The project already neutralizes this
for its own tests in scripts/test-changed.mjs; the lesson never reached the lane that
provisions checkouts.

pnpm lint 0 errors, test:gate green, engine typecheck clean, pipeline-smoke 93/93, and 328
tests green across the suites covering every defect reported today.
2026-08-26 21:07:12 +00:00
Fusion Agent
a6a3e5fada fix(dashboard): rescue an empty Feed when the card opens straight onto it
Reported from a live board: a task that is done, and demonstrably has journal entries,
shows "(no activity)".

Two mechanisms, each harmless alone.

`stripTaskListHeavyFields` empties `log` and KEEPS every other field, `prompt` included. So
an SSE task:updated payload for a task with a spec arrives with `prompt` present and
`log: []`.

The detail mount effect treats `"prompt" in task` as proof the prop is a complete TaskDetail
and returns WITHOUT requesting the detail. `prompt` and `log` are stripped by different
paths, so that proxy is false for exactly the payload above — the card adopts a log-less
snapshot as if it were complete.

The only rescue, refreshEmptyActivityFeed, was bound to a segment CHANGE. A card that OPENS
on Feed — `initialTab: "logs"`, which is how a deep link and the board's activity affordance
land — never changes segment, so "(no activity)" was permanent for that visit.

The rescue now runs whenever an empty Feed is visible. Its existing emptiness guard is what
keeps this cheap: a populated feed still costs no request, and a genuinely empty task asks
once, because the callback identity is stable while it stays empty.

Three regression tests: the stripped-snapshot open (fails without the fix), an honestly empty
journal that must report empty without spinning, and a prop-carried journal that must render
without re-requesting. One existing FN-8779 fixture gained a default mock implementation
because it resets the mock and queues only one — its subject is Feed layout, not request
counts, and no assertion was relaxed.

pnpm lint 0 errors, dashboard typecheck clean, TaskDetail suites 758/758, test:gate green.
2026-08-26 20:08:48 +00:00
Fusion Agent
c501ec9617 fix(dashboard): let Start work on a copied Ideas workflow, not just the built-in one
Start resolved its create-time Planning lane from the literal builtin:coding-ideas id, so a duplicated Ideas workflow fell through to a promotion that skipped the Planning hold lane and targeted the WIP lane. Column adjacency permits intake -> hold | archived only, so that move was rejected and the card stayed parked in Ideas.

Resolve the lane from traits (first declared hold column immediately after a manual intake, mirroring resolveWorkflowIntakeFacts), and promote exactly one legal forward step when no atomic lane can be proven.
2026-08-26 19:24:58 +00:00
Fusion Agent
cdef6ad7e8 fix(core): select the stale no-op merge case by its condition, not by a sentence
`merge-confirmed-finalize` carves out one case: a no-op merge confirmation with no landed
commit is not proof the work was done, so when the steps are still unfinished the run must
fall through to stale-merge cleanup and reverification instead of being consumed there.

It selected that case by comparing the blocker reason with `===` against the exact string
"task has incomplete steps". The merge-authority work then made refusals more informative, so
a card in an error state reports `task is marked 'failed': … task has incomplete steps`. Same
meaning, different sentence — and the comparison stopped matching, silently. A filter pinned
to "subject is exactly Invoice" once invoices began arriving as "Invoice — March 2026".

Nothing in the merge gate said so, because the test guarding this case lives in a file the
gate does not run. It has been red on main since that lane landed.

`hasNonTerminalSteps` states the rule the message describes and is defined from the same
`NON_TERMINAL_STEP_STATUSES` set as `getTaskMergeBlocker`, so the two cannot drift. A blocker
message is written for an operator and will be reworded again; the condition underneath it is
what callers actually mean.

The new core test pins them apart deliberately: it asserts the sentences DIFFER between a
plain card and a failed one while the rule answers the same, and that the rule agrees with the
door for every step status. A future prefix cannot re-break this quietly.

pnpm lint 0 errors, test:gate green, core + engine typecheck clean, pipeline-smoke 93/93,
ce-workflow-step-executor 53/53 (was 52/53 on main).
2026-08-26 18:59:53 +00:00
Fusion Agent
7b9f839252 fix(FN-WF): ask for the verdict in a way that covers the case that broke it
An audit of how the verdict is REQUESTED, prompted by a reviewer that answered in prose.
Prompt text only; no parser, type or lifecycle change.

This block is the last thing in a review step's system prompt, so what it says last carries
the most weight. It said this: "Backward compat fallback: if JSON is unavailable, you may
still begin output with REQUEST REVISION". The closing words of the entire prompt granted
permission to skip the required format, on a false premise — emitting JSON is never
unavailable. An imperative followed by a dispensation is a preference. The degraded path
still exists in the parser, but is now described as degraded rather than as an alternative,
and no longer occupies the final line.

It also forbade markdown fences while the parser scans fenced blocks FIRST, so "compliant"
was narrower than "parseable" for no benefit, against a habit most models have.

And the one that actually explains the incident: it offered APPROVE, APPROVE_WITH_NOTES and
REVISE, with no legal way to say "I cannot see the change I was asked to review". On the
measured multi-repo card the reviewer was told no files had changed, found nothing, and none
of the three values described its situation — approving would have been a lie. So it wrote
prose, which the gate then swallowed. The model did not go off-format by accident; it was
asked to choose from a list that did not contain its answer. That case is now explicitly
mapped onto REVISE with the search stated in notes.

A dedicated UNAVAILABLE member would model it better, and was deliberately NOT added:
`WorkflowStepVerdict` has no such value, and introducing one reaches the parser, recorded
step results, merge admission and the dashboard — out of proportion to a prompt repair, and
outside what "no negative impact" permits.

Impact checked before and after: the only test touching this text asserts the `## Feedback
Format` heading, which is preserved. The one failure in that file reproduces identically with
these changes stashed — it belongs to the merge-authority lane of 2026-08-23.

pnpm lint 0 errors, test:gate green, engine typecheck clean, pipeline-smoke 93/93.
2026-08-26 18:39:04 +00:00
Fusion Agent
828be7648b fix(FN-WF): stop the journal announcing aborts that never happened, and assert it
The operator journal is a deliverable. Nothing asserted it, and three defects lived there.

ABORT BREADCRUMB. `awaitAbortInFlightTaskWork` wrote `Pause abort marked` before inspecting
any surface, so a card with no session still announced an interruption: every newly created
task logged `provenance=hard-cancel` a second after creation, because creation moves the card
out of the planning lane and that move is user-sourced. Nothing was interrupted and the
operator withdrew nothing — false on both counts, and the second time this label has lied.
The in-memory marker is still claimed synchronously, before any await, because the
graph-failure classifiers depend on it; only the operator-facing line waits for evidence.

DUPLICATE APPROVAL. Landing requires TWO consecutive clean approvals of the same candidate.
Both wrote the identical sentence with the identical SHA, so a safety feature read as a
duplicated invocation and was reported as an anomaly. The line now carries its pass number.

DEAD RECOVERY. That same line is a contract: SelfHealingManager parses it with
`/AI merge review \(pass \d+\): approved …/` to recover approved SHAs. No emitter ever wrote
the parenthetical, so the parser matched nothing, `hasApprovedAiMergeReview` always answered
false, and the recovery it guards could not run. Two sides individually reasonable, coupled
through a log line nobody compared — the same shape as every other defect in this series.
Emitter and parser now agree, and a test pins them against each other so a one-sided edit
fails instead of silently killing the path again.

COVERAGE. New pipeline-smoke scenario S20 drives a task to merge on all three coding built-ins
and asserts the journal an operator actually reads: no abort claimed on an uninterrupted card,
no line written twice in a row, no approval whose own text says it verified nothing. It
reproduced the duplicate deterministically on its first run, which is the point — every
anomaly reported this week was plainly visible in that journal and invisible to this lane.

pnpm lint 0 errors, test:gate green, engine typecheck clean, pipeline-smoke 93/93.
2026-08-26 18:24:05 +00:00
Fusion Agent
ca624f0584 fix(FN-WF): a blocking gate must not approve without a usable verdict
Restores FN-6582's rule, which a later operator request had relaxed — deleting its test
along with it.

Operator decision, now carrying the reason the first reversal lacked: the only legitimate
reason to stop a task is an LLM problem; everything else is fixed at the source, or the AI
is made unable to return anything but what is expected — and if it does anyway, restart
cleanly.

Restarting cleanly already happens, twice, inside executeWorkflowStep: a malformed primary
retries on the fallback model, or self-retries once on the primary when no fallback is
configured. So `malformed` reaching this decision does not mean "one fumbled response" — it
means the reviewer failed to return a usable verdict across every attempt. That IS the
LLM-class condition an operator accepts as a legitimate stop. What it must never mean is
approval.

Measured: a reviewer reported in prose that the deliverables were absent, carried no verdict
JSON, and the gate recorded success. Unreviewed work merged on a rejection nobody could see.
A prose classifier cannot close this — that text held no rejection marker at all ("revise",
"reject", "must fix" all absent) because it was a factual statement of absence. Only the
ABSENCE of a verdict is detectable, so absence must not approve.

Advisory gates keep the relaxation: a step that was never allowed to hold a card does not
start holding one, which is where the original operator ask actually applies.

pnpm lint 0 errors, test:gate green, engine typecheck clean, pipeline-smoke 90/90.
2026-08-26 09:57:42 +00:00
Fusion Agent
24adc4bf40 fix(FN-WF): review each workspace repository against its own diff base
A workspace Code Review runs the review step once per SUB-REPOSITORY worktree.
`executeWorkflowStep` captured the reviewer's scope with the singular
`task.baseCommitSha` regardless, and that base does not resolve inside a sub-repository:
`captureModifiedFiles` returned [] and the prompt told the reviewer "(no modified files
detected for this task)".

Measured on a real multi-repo card whose executor had COMMITTED in both repositories. The
reviewer went looking, could not see the committed fixtures inside its own scope, and
reported them as never delivered — a confident, factual rejection produced entirely by a
wrong diff base. It then vanished, because prose carrying no verdict JSON is classified
malformed and passes a blocking gate. Two defects in series: one manufactured a false
rejection, the other swallowed it.

This fixes the first. The per-repo base was already recorded and already used by the
evidence capture in workspace-review-per-repo.ts; it simply never reached the reviewer.
`diffBaseCommitSha` threads it through, and a singular task with no override still uses the
task field, so the ordinary path is unchanged.

pnpm lint 0 errors, test:gate green, engine typecheck clean, pipeline-smoke 90/90.
2026-08-26 09:28:19 +00:00
Fusion Agent
b956a7c8eb fix(core): repair a renumbered migration whose ledger row outlived its column
Reported from a dev instance: `column "memory_focus" does not exist` on every chat-session
read, so the task planner chat 500s and never opens — with a startup that reports success.

A ledger row asserts "a migration with this NUMBER ran". That is not the same claim as "this
COLUMN exists" once a migration has been renumbered, and this one was renumbered four times
— 0059 -> 0060 -> 0061 -> 0065 -> 0066 — each time because an upstream batch claimed the
sequence first. A database can therefore carry a row from one numbering while a different
migration owned that number on the boot that recorded it. The applier trusts the ledger
absolutely, skips the migration, and leaves a schema that does not match it. Nothing fails at
startup; everything fails afterwards, because Drizzle's `select()` emits the binary's full
column list and one missing column breaks every read of the table.

The defence already existed one table over: `0047` task recommendations verifies its
materialized column in addition to the marker and replays its idempotent SQL. The lesson had
been learned and not generalized. Both migrations renumbered on this branch — 0066 memory
focus and 0067 session contention wait state — now carry it, and both SQL files are
`ADD COLUMN IF NOT EXISTS`, so a replay over a healthy schema costs nothing.

Two PostgreSQL regression tests reproduce the drifted state exactly (marker present, column
dropped) and prove the replay materializes the column and stays idempotent on a second pass.

pnpm lint 0 errors, test:gate green, core typecheck clean, schema-applier 80/80 against a
real PostgreSQL.
2026-08-26 09:03:59 +00:00
Fusion Agent
1c26a4bf4b fix(dashboard): report the cause of a failed query, not the statement that failed
Reported from a task chat: a screenful of column names from `project.chat_sessions` and
nothing about what broke.

That message is, by construction, the useless half. Drizzle wraps a query failure in an
error whose message is `Failed query: <the whole statement> params: …` and puts the real
PostgresError — `column "x" does not exist`, `permission denied`, `connection terminated` —
in `cause`. `rethrowAsApiError` read `error.message` alone, so the reason was dropped before
it ever reached the operator. `startup-factory` already carried a private chain walker
because field reports of exactly this shape were undiagnosable; the dashboard never got one.

The walker is now shared (`describeErrorChain` for logs, `summarizeErrorForOperator` for
operator surfaces). The inversion is keyed narrowly on the `Failed query:` wrapper, never on
guessing which message reads better: an application-authored message is deliberate prose and
still leads, so the API boundary contract and its 29 tests are unchanged. Only the
machine-generated frame is demoted to truncated context behind its cause.

This does not fix the underlying query failure — it makes it reportable. The next occurrence
will name the column or condition that failed instead of the statement that contained it.

pnpm lint 0 errors, test:gate green, core + dashboard typecheck clean, 7 new tests.
2026-08-26 08:57:31 +00:00
Fusion Agent
caae574146 fix(FN-WF): settle the restart scenario, and ban prompts that instruct denied tools
S17 ELUCIDATED. `restartPostMergeFinalization` read the task once, immediately after
restarting the engine, and treated "recovery has not finished yet" as "recovery will never
finish" — falling through to `admitAndMerge`. That fallback cannot succeed BY CONSTRUCTION:
staging deliberately replaces the row's step results with a single PENDING code-review row
and its steps with a pending stale step, precisely so the merge-confirmed recovery path is
what finalizes it. So merge admission was correctly refused and the scenario failed with
"post-merge restart parked finalization".

The outcome therefore depended on whether recovery beat one read: green in isolation
(19/19 across 8 runs) and intermittently red under full-lane load. That is a property of how
fast the suite happens to run, not of the product — the same conclusion FN-WF already reached
for S05, recorded in b39d66c00. coding-ideas-v2 surfaced it because its extra in-review
milestone lands the restart in the racy window more often.

`settleRestartFinalization` is a BOUNDED event-loop drain, the shape `settleActiveMerge`
already uses: free when recovery has already finished, and exhausting the budget still falls
through to the fallback, so a genuine hang is never masked. Three consecutive full-lane runs:
90/90, 90/90, 90/90.

NEW GUARD. `workflow-prompt-tool-availability.test.ts` rejects any built-in prompt that
instructs a `toolMode: "readonly"` node to CALL a tool its policy denies. This class has now
cost two defects that read correctly and could not be obeyed: a reviewer told to run
lint/tests/build, and a Documentation milestone told to call four writers it does not have.
Prose review cannot catch it — prompt and policy live in different files and are each
individually correct — so the guard compares them structurally. A bare mention stays legal,
because naming a denied tool is how a prompt states its own limits, and the guard carries a
test proving it rejects the exact offending shape.

Delivery notes and artifacts need no new owner: the executor's system prompt already mandates
both ("you MUST register" visual deliverables, "you MUST save" written deliverables as task
documents), independently of any plan step.

pnpm lint 0 errors, test:gate green, pipeline-smoke 90/90 x3.
2026-08-26 07:52:47 +00:00
Fusion Agent
9a54fe362d fix(FN-WF): give the Documentation milestone a way to actually persist anything
It had no writer, and its prompt did not know that.

A workflow step running `toolMode: "readonly"` is limited to read/grep/find/ls, fn_web_fetch
and a few read-only task reads; `fn_task_create` is explicitly DENIED there. The prompt asked
for four tool calls — fn_task_done(summary=…), fn_task_document_write, fn_artifact_register,
and creating follow-up tasks. It could make none of them. Every run produced a well-formed
report and persisted NOTHING. And because this milestone replaced `completion-summary`, which
used the working contract, cards quietly lost their agent-authored summary and fell back to
the deterministic backfill.

This is the same failure the reviewer prompt was fixed for — a session instructed to do what
its tool policy forbids — on a node nobody re-checked.

Both durable outputs now travel by PROJECTION, the only channel a writer-less node has.
`summaryTarget: "task"` persists its prose as the card summary. New
`recommendationsTarget: "task"` reads a trailing {"recommendations":[…]} payload, normalizes
it through the SAME rules the store boundary enforces (relocated to
tasks/recommendation-validation.ts so a second producer cannot drift from a copied regex),
and projects it to task.recommendations — the Recommendations tab, where an OPERATOR turns a
proposal into a task. An in-review agent proposes; it never creates board rows. Normalization
drops bad entries rather than throwing: a stray character in a suggestion must not wedge a
card whose code is already approved.

`summaryTarget` also removes this node's verdict requirement, so a reporter can no longer emit
the REVISE that held the merge door and bounced the card with nothing to do.

The guard that should have caught all of this asserted a PROMPT STRING —
`prompt.includes("fn_task_done(summary=")` — as proof a summary gets written. It was green
throughout. It now asserts the projection contract, including inside optional-group templates,
because the executing node of a group is its template child.

pnpm lint 0 errors, test:gate green, core + engine typecheck clean, pipeline-smoke 90/90.
2026-08-26 07:31:40 +00:00
Fusion Agent
56ee1622df fix(FN-WF): make Documentation a reporter, and refuse every bounce with no work
Observed on a live card (mult-021), where the log tells the whole story: Documentation
returned an advisory REVISE asking for implementation work, the card was "moved back to
in-progress for remediation", and 467ms later Code Review started again. No step was ever
created, no executor session ran, and the demand was never implemented — the card merged
when the second Documentation pass happened to pass.

Two separate defects produced that.

FIRST, the reporter could hold the merge. An advisory REVISE records `advisory_failure`,
and `resolveRequiredPreMergeStepIds` included the Documentation group, so
`evaluatePreMergeApprovals` read it as "not-approved". `gateMode: "advisory"` only stops
the node blocking traversal; it says nothing to the merge door.

SECOND, the reporter could bounce. `requestPreMergeOptionalStepFix` accepts
`advisory_failure`, and under this workflow's named-remediation policy the resulting
`sendTaskBackForFix` reopens NOTHING. With no pending step the foreach answered
`already-expanded` and the walk replayed the review lane over an unchanged tree. The
budget was 1/10, so it could have burned ten rounds of two model calls each.

New opt-in `reportingOnly` on an optional group states the contract once — no approval to
withhold, no remediation to request — and both doors read it. It is set only on
Documentation, so advisory gates that DO own remediation (browser verification) keep their
behaviour exactly.

Plus the general invariant that would have caught both: under `stepReopenPolicy: "none"`,
a bounce that appended no named steps is refused and logged on the card. Only the gates
that can APPEND work may send a card back. Code Review REVISE and the deterministic
verification failure still produce named fix steps — unchanged, still covered.

pnpm lint 0 errors, test:gate green, core + engine typecheck clean, pipeline-smoke 90/90.
2026-08-26 06:54:08 +00:00
Fusion Agent
8328b458b0 fix(FN-WF): prove fix steps reach the card, and clear the V2 rework's leftovers
FIX STEPS, asserted on `task.steps` rather than on a spy. A failing FINAL verification
and a Code Review REVISE each append pending named steps carrying their gate provenance,
and the card is re-dispatched to run them; completed implementation steps stay done,
because remediation appends and never reopens. A review failure with NO REVISE verdict
appends nothing — a transport error must not manufacture work. And no node id other than
those two gates can reach the appender, which is what keeps a red test INSIDE a step the
step's own problem: the executor fixes it there instead of littering the checklist.
The new tests drive the real routing seam and the real appender against the real built-in
registry — an injected IR is resolved away by workflow id and would have proved nothing.

CATALOG. `builtin-workflows-lifecycle.test.ts` never received an EXPECTATIONS entry when
V2 was registered, so its catalog-coverage assertion has been red on main since. The merge
gate does not run that file, which is why it survived. Its trail is identical to
builtin:coding-ideas by design: a read-only review lane changes what happens inside the
working columns, not where the card goes.

REGISTRY. The description still advertised "verify … summarize", steps that no longer
exist, and the layout still positioned four deleted nodes plus drew Documentation to the
LEFT of Code Review — so the editor rendered the review lane backwards against its own
edges. Both now match the graph.

AUDIT. `implementation-only-leakage` no longer flags `testing|verification`. That regex
belonged to the revision where a review gate ran the tests; testing came back to the
executor, so the planner emits that step on purpose and every V2 card was reporting
leakage against its own intended plan. Documentation and delivery are still flagged.

pnpm lint 0 errors, test:gate green, core + engine typecheck clean, 227 tests across the
touched files.
2026-08-26 06:06:56 +00:00
Fusion Agent
3cfb5119ea fix(FN-WF): stop V2 planning a Documentation step it already runs in review
Documentation is not a task step on this workflow.

Restoring the default planning prompt to bring `Testing & Verification` back also
restored `### Step {N}: Documentation & Delivery`, because the abandoned
`planning-implementation-only` seam stripped both in ONE anchored block, from the testing
heading to `## Documentation Requirements`. Nobody chose that; it was collateral.

The result was the same work done twice. The executor's step saved a delivery note,
registered artifacts and created follow-up tasks; the in-review Documentation milestone
then did the identical three tool calls again. Both wrote task document `docs`, so the
review pass silently overwrote the executor's.

`stripDocumentationDeliveryStep` removes ONLY the documentation block and deliberately
keeps `Testing & Verification`, which the executor owns and must keep planning. It is
applied to V2's own copy of the planning prompt, so `builtin:coding` and
`builtin:coding-ideas` keep the shared template byte-identical. If the base prompt is
reworded and the anchors stop matching, the strip degrades to an appended prohibition
rather than breaking planning at runtime.

Repository documentation survives as implementation work: the executor updates a doc its
own change made wrong, inside the step that made it, so Code Review sees it in the same
diff it approves. Whether a change warrants that is the executor's judgement, not a stage.

pnpm lint 0 errors, test:gate green, core typecheck clean, 2 new tests plus a shared-template
non-regression assertion.
2026-08-26 05:59:29 +00:00
Fusion Agent
0c3fe18347 fix(FN-WF): make a red verification create named fix steps, not an empty bounce
The FN-3345 deterministic verification gate runs testCommand/buildCommand after every
planned step succeeds and before the in-review handoff. Both of its bounces went through
`sendTaskBackForFix` regardless of the workflow's `stepReopenPolicy`.

Under `none` — declared by `parse.implementationOnlySteps` + `preserveRemediationSteps`,
selected today only by builtin:coding-ideas-v2 — that call reopens nothing, because
send-task-back-for-fix.ts guards the reopen on `reopen-trailing`. So a card bounced back to
implementation with ZERO pending steps, the foreach answered `already-expanded`, and it
walked on to Code Review with the failing command unaddressed. The verification was
measured, logged, and then silently discarded.

The bounce shape now lives in executor/bounce-verification-failure.ts. `none` routes to
`appendReviewRemediationSteps`, which derives one named step per file in the failing output,
widens the PROMPT.md File Scope to those files, re-dispatches the executor, and parks for a
human after three waves. `reopen-trailing` keeps its exact prior call, so builtin:coding and
builtin:coding-ideas are byte-identical.

This revives the `Verification` branch of appendReviewRemediationSteps, caller-less since the
graph's `verification` node was removed — which is why the gap was invisible: the code was
present, correct, and dead.

pnpm lint 0 errors, test:gate green, engine typecheck clean, 5 new behavioural tests.
2026-08-26 05:03:49 +00:00
Fusion Agent
b723c35fc9 feat(FN-WF): give testing back to the executor and the plan
Testing belongs to whoever can actually run it. That is the executor.

RESTORED — the planner emits "Testing & Verification" again. An earlier revision in
this series routed V2 planning through `planning-implementation-only`, whose contract
STRIPS that step region and replaces it with "Do NOT emit a Testing & Verification
step", on the theory that a review-column gate would run the checks instead.

Nothing ever did. The deterministic gate was not routed by its node kind and reported
PASS in ~46ms without executing anything; and once that was fixed, a review node runs
`toolMode: "readonly"`, where `bash` is denied and `fn_run_verification` is not in the
allowlist — so a reviewer cannot run lint, tests or build no matter what its prompt
says. Measured on real cards: 19s and 23s "reviews" that silently read the diff alone,
and a plan bounced for "implementation steps include testing and verification work
that must be handled as review-column gates" AFTER the gate it named was deleted. The
planner was forbidden from planning tests while nothing else ran them.

What was stripped is the mature contract: real automated tests only ("typechecks and
builds are NOT tests"), per-step test authoring, a final lint/tests/typecheck/build
pass ordered before delivery, an explicit duty to update tests that encode behaviour
the task changes, and standing up a test framework when the project has none. Plan
Review no longer rejects a plan for containing any of it.

CHANGED — Code Review judges the TESTS rather than claiming to run them. It rules on
four things: they exist for the behaviour that changed; they are real runner-executed
assertions; they assert BEHAVIOUR and never a comment or date stamp; and they cover
the invariant, not only the reported repro. Then it reviews the code for what tests
miss. Telling a session to do what its tool policy forbids invites the one failure
worse than a missing check — a fluent claim that the check passed.

DELETED — `builtin:review-gated-coding`, rather than left deprecated. It SHARED the
documentation-delivery node with V2, so every change made for V2 silently changed a
second workflow nobody was maintaining. Its own success path could never complete
anyway (`workspace-review-seal-required`).

Tests updated to the reversals they now describe, each naming the measurement that
reversed it. Deleting the workflow also cleared a pre-existing remediation-loop
failure.

pnpm lint 0 errors, test:gate, verify:fast, engine-pipeline-smoke 90/90, and three
consecutive full runs: 142.7s, 140.9s, 135.2s of the 175s budget.
2026-08-26 04:32:59 +00:00
Fusion Agent
e71ccb9d70 feat(FN-WF): show the in-review stage as a badge, not a step list
An in-review card now renders its stage through the running-gate badge alone —
Code Review, then Documentation, then Merging — with no progress bar, no counter,
and no expandable step list.

This reverts the review-lane progress section added earlier in this series. That
change was a correct fix for the complaint at the time (the review lane showed
nothing at all), but with the lane reduced to two milestones in a fixed order the
badge already answers "where is this card", and a list of two rows plus every
finished implementation step is noise on a board.

It also removes a defect for free rather than by repair. The list is built from
`task.enabledWorkflowSteps`, which is FROZEN on the card at planning time, so a card
planned before its workflow changed rendered a milestone that no longer exists as
permanently `pending` — a ghost row that could never resolve. Removing the deleted
`verification` group created exactly that on in-flight cards. No list, no ghost, and
no reconciliation pass to write and maintain.

Cost, stated rather than hidden: a NON-BLOCKING gate that failed is no longer
visible from the board — Documentation cannot hold a card, so a failed delivery note
now merges silently and must be read on the card itself. Blocking failures are
unaffected: a Code Review REVISE moves the card back to in-progress, which is the
most visible signal the board has.

Tests updated to the new truth, not around it: the review-lane assertions now expect
`.card-progress` and `.card-steps-list` to be absent.

pnpm lint 0 errors, typecheck, test:gate, and 738 tests across every suite that
touches card progress (TaskCard, ListView, taskProgress, board-mobile, live-ticker).
The full dashboard suite's 22 failures are pre-existing and unrelated — ChatView,
voice dictation, model menus, process supervision — with no card or progress test
among them.
2026-08-26 03:19:40 +00:00
Fusion Agent
8b64b88bfd feat(FN-WF): make the V2 review lane Code Review -> Documentation -> merge
One gate that can hold a card, one milestone that reports, then the merge.

REMOVED — the separate deterministic `verification` group. It duplicated the
executor's own verification, it showed a green badge on projects that had
configured no command, and it split merge evidence across two authorities that
could disagree. Code Review now runs lint/test/build itself, so exit codes still
decide and a single node owns the verdict. Its prompt is APPENDED to rather than
edited, leaving the shared reviewer used by builtin:coding and
builtin:coding-ideas exactly as it was.

The evidence rule is the point: the reviewer must quote each command with its exit
code and output tail, and a verdict with no execution evidence is invalid. A
reviewer free to assert "tests pass" in prose reproduces the false green a silently
passing gate produced mechanically — and the fluent version is harder to spot.
Absent commands are reported, never treated as failure: a project that never
configured verification has never been refused a merge on that basis.

REMOVED — `completion-summary` as its own milestone. Documentation writes the card
summary in the same pass as the delivery note. One model call, not two.

CHANGED — Documentation now runs AFTER the review, which is the ordering its own
author intended ("runs after passing verification and code review") and which the
review seal previously forbade. It is legal because it no longer writes the
repository: it is advisory, read-only, and records a Fusion-side delivery note,
artifacts, follow-ups and the summary. Repository documentation belongs to the
executor during implementation — a docs change is a code change, and writing it
after approval put it outside the diff the reviewer signed off.

It also cannot veto any more. As a blocking gate it bounced a task whose own plan
forbade implementing anything, and that card looped through the review lane every
five minutes indefinitely.

The seal invariant got STRONGER, not weaker: no node other than the reviewer itself
writes anywhere in the review lane, so nothing can change after an approval. The
test asserts exactly that, and names the reviewer exclusion rather than filtering it
away silently.

pnpm lint 0 errors, test:gate, verify:fast, engine-pipeline-smoke 90/90, and three
consecutive full runs: 137.4s, 141.0s, 144.6s of the 175s budget. The 3 remaining
core failures are pre-existing and reproduce without this diff.
2026-08-26 01:16:30 +00:00
Fusion Agent
28a8205645 fix(FN-WF): run the Verification gate instead of silently passing it
Your Verification step completed in 46ms and reported PASS without executing
anything. It had never run.

`GateNodeRunner` recognised exactly two executable shapes, `prompt` and
`scriptName`. A gate carrying `workflowAction: "deterministic-verification"`
matched neither and fell through to the method's closing `return success`. The
code that runs testCommand/buildCommand was never reached — so the strictest gate
in the review lane was decorative, and it was supplying the merge evidence a task
is allowed to rely on.

The existing unit tests were green throughout, because every one of them called
`runDeterministicVerificationGate` directly. Testing a function proves the
function; it does not prove the graph calls it. The new wiring suite asserts the
routing itself and fails when the fix is removed — verified by removing it.

DRY: `verification-gate.ts` re-derived the command list and re-ran the loop, a
second implementation of a rule that `runExecutorDeterministicVerification`
(FN-3345, run-implementation.ts) already owned. The two had already drifted — the
copy treated "no command configured" as a hard failure while the original treats it
as not-applicable. The gate now delegates, so timeouts, per-command logging, and
settings precedence can only be fixed in one place.

NOT in this change, and deliberately so: recording an unrunnable gate as `skipped`
rather than `passed`. It is the right model and it was implemented end-to-end, but
`pre-merge-approval` clears a `skipped` step only for an audited operator bypass,
so it made every task on a project without a test command unmergeable — 25 of 90
smoke tests. Narrowing the acceptance left one unexplained failure (S09 sentinel,
120s timeout). Shipping that half-understood would trade a visible false green for
an invisible merge deadlock. FN-189 owns it with the full evidence.

pnpm lint 0 errors, test:gate, engine-pipeline-smoke 90/90, and three consecutive
full runs: 150.9s, 152.8s, 154.5s of the 175s budget.
2026-08-25 23:40:38 +00:00
Fusion Agent
ea869ff38f fix(FN-186): give pipeline-smoke tasks process-unique ids and drain execution on teardown
S05 now covers builtin:coding-ideas-v2. 5/5 consecutive full lanes.

Two harness defects, both of which made a CORRECT engine refusal look like a flake.

1. Task ids collided. The serial lived on the harness instance and reset with it, so
   every test's first task was `FN-182-S05-1`. The engine's process-wide state —
   `executingTaskLock`, `activeSessionRegistry.pathsForTask`, worktree registrations —
   is keyed by task id, so a straggler from the previous test answered for the NEXT
   test's identically-named task and handed it a worktree under the PREVIOUS fixture.
   The serial now lives on the module.

2. Teardown forgot in-flight work instead of waiting for it. `ProjectEngine.stop()`
   clears timers but does not await an execution already inside `execute()`, and the
   harness then called `activeSessionRegistry.clear()` — which hides a live session
   rather than ending it. `dispose()` now drains `executingTaskLock` and the registry
   for its own task ids, bounded, and THROWS on expiry: a straggler that outlives the
   budget is a real defect, and a silent continue would restore the leak.

Throughout this, the product was right. The executor detected the foreign worktree,
refused it (`outside_worktrees_dir`), retried, exhausted its budget and failed
visibly. That refusal is the desired behaviour and was never the bug — the harness
was manufacturing the condition.

Budget re-baselined 150s -> 175s for attributable growth: a 7th file (the remediation
drive) and S05 on V2, one of the longest scenarios. Five runs at 140.1-148.4s left
under 2s of headroom against the old ceiling, which is a flake waiting to happen. The
standing rule is unchanged and now has three precedents: growth must be nameable, or
it is a regression to fix rather than a budget to raise.

pnpm lint 0 errors, test:gate, verify:fast, engine-pipeline-smoke 90/90, and five
consecutive full runs: 146.0s, 142.6s, 148.5s, 144.8s, 146.3s of the 175s budget.
2026-08-25 21:42:36 +00:00
Fusion Agent
b39d66c002 test(FN-WF): settle at the manual-merge hold instead of guessing from a snapshot
`driveToManualMergeHold` returned on the first turn that merely LOOKED parked
(`column === "in-review" && reviewPassed`). That is a snapshot, and a review-column
workflow invalidates it one turn later: a Code Review REVISE appends remediation
steps and sends the card back to in-progress, so the caller's merge then hit the
engine's correct refusal ("task is in 'in-progress', must be in 'in-review'").

The engine was right and the driver was wrong. Suppressing that refusal would have
reproduced FN-175 exactly, which is why the earlier attempts to swallow it were
reverted rather than kept.

It now returns immediately on an authoritative `manual-required` work item, and
otherwise keeps turning until the observable signature (column, status, step
statuses, review statuses) stops changing across consecutive turns. That is a
property of the graph rather than of how fast the suite happens to run — which is
why the scenario was intermittent only under full-lane load.

S05 is deliberately NOT extended to builtin:coding-ideas-v2 in this change. It
passes 22/22 when its file runs alone but fails in the full lane, and the evidence
says the cause is harness isolation, not the product: the task is handed a worktree
belonging to a DIFFERENT fixture (observed .../fusion-pipeline-smoke-eXXRLy/...,
expected .../fusion-pipeline-smoke-K2iaTm/...). The engine detects this and refuses
it — `outside_worktrees_dir`, retried, budget exhausted — which is the correct
behaviour. Shipping that as a red scenario would be shipping a known flake, so the
coverage waits for the isolation fix.

pnpm lint 0 errors, test:gate, verify:fast, and three consecutive full runs:
139.2s, 135.1s, 139.9s of the 150s budget.
2026-08-25 20:40:10 +00:00
Fusion Agent
bf147d6ade test(FN-WF): prove Code Review remediation produces named steps that run and merge
You asked why I could not prove it. Because I kept trying to prove it THROUGH S05,
which asserts a different property — no merge without a current approval — and
reaches it by racing the background auto-merge. That race is the source of its
intermittency, and it has nothing to do with remediation.

The behaviour itself does not need that race. `pipeline-remediation.pipeline.test.ts`
drives it explicitly, turn by turn, and asserts three things in order:

  1. a Code Review REVISE appends a step carrying `remediation` metadata — named
     work derived from the reviewer's findings, not a bare bounce;
  2. no step is left pending — the appended work is actually executed, which is the
     failure mode that previously left it `pending` forever;
  3. `mergeDetails.mergeConfirmed` — the loop terminates instead of merely looking
     alive.

Five consecutive runs, five passes.

REVERTED in the same change: the `workflow-graph-foreach` relaxation that let a
sequential region grow past its pinned step count. I justified it with a measured
failure, but that measurement came from a configuration since fixed elsewhere and no
longer reproduces — with the growth removed the full lane passes 89/89, including
this new drive. An engine change to a core execution primitive that no failing test
requires is dead weight on a hot path, so it goes rather than staying "just in case".
A future case that genuinely needs growth must arrive with a test that fails without it.

pnpm lint 0 errors, test:gate, verify:fast, and three consecutive full runs:
133.1s, 136.0s, 134.2s of the 150s budget.
2026-08-25 19:46:49 +00:00
Fusion Agent
4750b689ea refactor(FN-WF): classify workflow gates structurally, not by display name
Three defects of the same family, all of which let a LABEL decide BEHAVIOUR.

1. `workflowNodeRequiresWorktree` matched `/(?:^|\b)(?:review|verification)(?:\b|$)/i`
   against `config.name`. A deterministic verification gate — exit codes only, no
   mutation path — was therefore classified write-capable purely because it is
   called "Verification", and the review seal refused it on every post-approval
   replay. It now keys on `reviewKind`, `workflowAction` and the optional-group id.

2. The review seal's `isCodeReview` also matched `/code review/i`, so its central
   question — "is this THE review that seals the tree?" — depended on a name an
   operator may change. Renaming the gate to "Final Review" would have silently
   stopped it being recognised while every other gate kept being sealed against it.
   That is why the rename was blocked; it no longer is.

3. `getRunningOptionalGateBadge` gated on a closed list of three step ids, so gates
   a workflow adds showed no badge at all: the operator watched an apparently idle
   card until "Merging" appeared at the end. It now asks whether the running step
   is a lane-owned gate.

Also: task cards arrive in the review lane with their step list EXPANDED, as they
already were in in-progress. The initial state is computed once per mount and a
column move remounts the card, so a card the operator had open collapsed itself
exactly when its review gates started running.

Lifecycle-column ratchet ceilings lowered to the measured counts (todo 64→12,
in-progress 197→72, in-review 213→28). They had drifted so far above reality that
the ratchet was inert for the thing it exists to stop — the TaskCard guard that hid
review-lane progress was one of those tolerated sites, and it had no way to notice.

Tests updated to the new truth rather than around it: the seal ratchet now asserts
a deterministic gate must NOT be write-capable, and the badge tests assert the
expanded list.

pnpm lint 0 errors, test:gate, verify:fast, dashboard 695, core 38, engine 8, and
three consecutive smoke runs: 122.4s, 126.3s, 124.8s of the 150s budget.
2026-08-25 12:31:43 +00:00
Fusion Agent
0c2f204acc fix(FN-WF): render the review-lane progress breakdown on task cards
TaskCard already switched to the FULL pipeline once a card reached its review
lane — and then suppressed the rendering of what it had just computed, because
`showProgressSection` still required `task.status === "executing" || isWipColumn`.
The operator saw nothing for the stage those gates were promoted into.

FN-7676 hid the breakdown in Planning because enumerated implementation steps are
a premature planning artifact there. That reasoning does not extend to in-review,
where builtin:coding-ideas-v2 runs Verification, Documentation & Delivery and Code
Review as real, advancing work.

The previous commit fixed ListView on the same reasoning and I assumed TaskCard was
already correct because its scope switch flipped. It flipped and the render gate
dropped it one line later.

Both the scope switch and the render gate now resolve the lane through
`isReviewColumnRole`, by trait rather than the hardcoded `in-review` id, so a
renamed board behaves the same.

Two TaskCard tests asserted the old absence and are updated to the new truth: the
running-gate badge remains a distinct additive affordance and is not replaced by
the bar, while the expandable step list still stays collapsed until opened.

Dashboard 661 tests, test:gate and verify:fast green.
2026-08-25 10:45:13 +00:00
Fusion Agent
f22ebca62a test(FN-WF): treat a revoked merge gate as the deferral it is, and stop the engine before clearing globals
Two harness correctness fixes, both found chasing the S05 flake.

REVOKED GATE. `MergeGateRevokedError` escaped the graph dispatch and failed the
scenario. It is a DEFERRAL, not a failure — FN-180's own contract, and the reason
it carries a dedicated error type so callers cannot convert a gate lost mid-merge
into a retry or a failed park. It fires when a merge admitted on an earlier turn
reaches its ref-advance fence after a REVISE has already returned the card to
in-progress: the engine refusing correctly while the driver races it. The dispatch
now swallows ONLY that type, by NAME rather than by import, because importing
merger-errors.js would break the pre-FN-180 differential run the harness self-test
enforces.

TEARDOWN ORDER. `dispose` reset the shared mock registry and cleared
`activeSessionRegistry` BEFORE stopping the engine, stranding in-flight sessions on
default scripts mid-teardown and hiding them from the liveness checks the stop path
consults. Both are process-global, so the damage landed on whichever file ran next.

Together these took S05 on builtin:coding-ideas-v2 from failing 3 runs out of 3 to
2 out of 6 — a real reduction, and not zero, so it is still not shipped. S05 stays
on its original workflows, where the lane is green four consecutive full runs:
122.4s, 126.6s, 124.0s, 116.9s of the 150s budget.

builtin:coding-ideas-v2 remains at 18 of 19 scenarios plus the multi-repository
workspace drive.
2026-08-25 05:38:46 +00:00
Fusion Agent
19c3981a50 feat(FN-WF): cover S07 on V2 by releasing its operator park in recovery
Named remediation parks an unactionable review rejection as `awaiting-approval`
with `paused: true` — deliberately, because there is no actionable finding to
derive work from, so a human must decide. S07's recovery driver only re-drove the
graph, and a drive cannot move a paused card, so the declared recovery could never
reach a merge and the scenario read as a wedge.

The recovery now performs the operator's half of its own contract ("operator
retry, or the cause disappears") before driving: it releases an EXPLICIT
awaiting-approval park and then approves through the restored graph session. The
merge that follows is still fully asserted, so this widens no assertion.

builtin:coding-ideas-v2 covers 18 of 19 scenarios plus the multi-repository
workspace drive. Three consecutive full runs: 123.6s, 125.7s, 126.1s of 150s.

S05 stays on its original workflows. It passes 22/22 when its file runs alone but
fails intermittently under full-lane load, and settling in-flight merges at every
graph dispatch — before and after, with a 10x larger drain bound — did not remove
it. That points at cross-file interference rather than the merge race it first
resembled, and an unexplained flake is not something to ship.
2026-08-25 04:22:49 +00:00
Fusion Agent
eba8c1052d feat(FN-WF): let a foreach cover steps appended after expansion
A sequential foreach region pinned its step count at expansion and never revisited
it, so work appended afterwards never received an instance. That is what made
named remediation unusable: `review-remediation-steps` derives fix-it steps from a
reviewer's findings and appends them to `task.steps`, and every one of them stayed
`pending` forever — the merge boundary's foreach coverage never completed and the
card terminalized with `merge-boundary-unproven`.

The region now re-reads the live step list per iteration, exactly as the existing
status probe already did, and extends its bound when the list has grown. Growth is
the ONLY relaxation: the pin still governs every step it already covers, a
shrinking list is ignored, and `pinnedStepCount + 64` stops a pathological appender
spinning the region. The worktree-isolated path keeps the strict pin, because its
instances are allocated up front.

Other workflows are unaffected by construction — with no appended steps the bound
never moves and the loop is byte-identical.

builtin:coding-ideas-v2 accordingly enables named remediation on BOTH review gates:
a rejected review now returns the card to in-progress carrying steps that name what
must be fixed, with the PROMPT.md File Scope widened to the files they touch,
instead of an unchanged checklist.

Three consecutive full runs: 122.1s, 124.5s, 122.9s of the 150s budget.

S05 and S07 stay on their original workflows: with named remediation live, S05 is
intermittent on V2 under full-lane load and S07's park oscillates instead of
settling. Both are visible, neither is shipped green.
2026-08-25 03:46:32 +00:00
Fusion Agent
f193c196e3 fix(FN-WF): seal on gate presence, and settle in-flight merges between turns
REVIEW SEAL. The already-satisfied carve-out tested the result's STATUS, which is
unanswerable at that point: the optional group writes a fresh `pending` row when it
STARTS, overwriting the terminal record before the check runs. Measured on S13, the
replayed documentation gate showed `pending` with `priorAttempts=failed/failed/...`
and its earlier `passed` was simply gone, so the carve-out never fired and a
conflicting merge left the card cycling instead of retrying.

Presence of a result row is the correct signal, and it is exact rather than lax:
these gates run UPSTREAM of Code Review, so a current approval proves the gate
already ran in this episode, while a gate that has genuinely never run has no row
at all and is still refused. S13 ("scripted merger resolves a conflict") now passes
on builtin:coding-ideas-v2.

HARNESS RACE. `runProductionTurn` now drains any in-flight merge before dispatching.
A REVISE returns the card to in-progress, and a merge admitted on an earlier turn
then hits its ref-advance fence and is correctly revoked with "task is in
'in-progress', must be in 'in-review'" — the engine behaving properly while the
driver raced it. The drain is a bounded event-loop yield, not a wall-clock wait, so
it costs nothing when no merge is in flight and cannot mask a hang.

builtin:coding-ideas-v2 now covers 18 of 19 scenarios plus the multi-repository
workspace drive. Three consecutive full runs: 129.0s, 122.5s, 125.1s of 150s.

S05 ("code review revisions require a current approval") stays on its original
workflows: it remains intermittent on V2 under full-lane load, and a flake is not
something to ship.
2026-08-25 03:11:56 +00:00
Fusion Agent
d976ed4118 fix(FN-WF): remove duplicate V2 edges and match the review seal on group ids
Two defects, and the first explains most of what looked intractable.

DUPLICATE EDGES. The V2 IR re-pushed `completion-summary -> code-review`,
`code-review -> merge-gate` and the code-review rework, all of which it already
inherits, so the graph carried each of them twice. A duplicated success edge out
of a review gate is a second competing traversal of the same lane. Pushing only
the genuinely new edges fixed S05 ("Code Review REVISE twice, then approve") and
S17 ("restart recovery resumes each recorded stage exactly once") on
builtin:coding-ideas-v2 together — both had been chased through remediation
policy, rework targets and mock routing, and neither was ever about those.

REVIEW SEAL ID MATCH. The already-satisfied carve-out compared the failing node's
own id against recorded results, but a gate runs as its optional group's inner
template node (`documentation-delivery-step`) while its result is recorded under
the group (`documentation-delivery`). The comparison therefore never matched, and
the carve-out was dead code for every optional group — precisely the shape it
exists to protect.

builtin:coding-ideas-v2 now covers 18 of the 19 declared scenarios plus the
multi-repository workspace drive. Three consecutive full runs: 124.7s, 131.5s and
127.3s against the 150s budget.

S13 ("scripted merger resolves a conflict") remains on its original workflows: it
still replays the documentation gate after a conflicting merge, and the base S05
showed one cross-file failure at full-lane scale that does not reproduce when the
file runs alone. Neither is shipped green.
2026-08-25 02:28:20 +00:00
Fusion Agent
324c67d16c fix(FN-WF): make V2 rework converge, and cover S07
Root cause of the stalled rework: named remediation (`review-remediation-steps`)
is UNAVAILABLE to a foreach-executed workflow. The parse node preserves an
appended step and then answers `already-expanded`, because the foreach is PINNED
to the step list it first expanded — so a step appended afterwards never receives
an instance and stays `pending` forever. The merge boundary's foreach coverage
then never completes and the card terminalizes with `merge-boundary-unproven`
("no pre-merge node result recorded"), measured on S05 as
`steps=["Implement deterministic pipeline output:pending"]` in the review lane.

`implementationOnlySteps` + `preserveRemediationSteps` on the parse node is the
pair that selects that mechanism, so V2 no longer sets it and keeps the inherited
"reopen-trailing" policy, which re-runs instances the foreach already owns. The
planner constraint is unaffected: it lives in the seam PROMPT, while
`implementationOnlySteps` only audits leakage by its own design.

Code Review rework accordingly returns to `code-review` as the inherited graph
does. Stated cost: a Code Review REVISE no longer regenerates the documentation.
Verification rework still re-enters `verification` and replays the doc node with
it, because a failing test needs re-running rather than new implementation steps.

Also fixes the smoke mock: gate routing intercepted the writable Code Review
Remediation session and returned a bare approval, skipping the branch that
completes the steps a REVISE reopened.

S07 ("unactionable Code Review rejection") now passes on builtin:coding-ideas-v2,
bringing it to 15 of 19 scenarios plus the multi-repository workspace drive.
S05 still does not converge and stays on its proven workflows.

Lane green twice: 6 files, 82 tests, 19/19 scenarios, 115.1s and 118.4s of 150s.
2026-08-25 01:58:00 +00:00
Fusion Agent
ca171502f7 fix(FN-WF): show review-lane gate progress on task rows
`TaskCard` already switches to the full pipeline once a card reaches its review
lane, but `ListView` resolved progress with `scope: "implementation"`
unconditionally — and `shouldShowTaskProgress` suppressed the review column
outright. Implementation scope hides exactly `verification`,
`documentation-delivery` and `code-review`, so a list row showed "-" or a stale
count for the stage the operator was watching.

That default was written when those steps existed only as invisible gates.
builtin:coding-ideas-v2 promotes them into first-class review-lane work, so the
rule now hides the very thing it was asked to surface. Both call sites resolve the
lane through `isReviewColumnRole` — by trait, not by the hardcoded `in-review` id,
so a renamed board behaves the same.

Regression coverage asserts both directions: implementation scope still hides the
gates, and the full pipeline surfaces Verification, Documentation & Delivery and
Code Review.

Dashboard 250 tests, smoke lane 6 files / 81 tests / 19/19 scenarios, test:gate and
verify:fast green.
2026-08-25 01:40:26 +00:00
Fusion Agent
d866617f40 test(FN-WF): complete every pending step in the smoke executor mock
The mock marked only step 0 done. A review gate that appends named remediation
work (`review-remediation-steps`) adds steps beyond the first, and a workflow whose
parse node disables trailing-step reopening depends on exactly that mechanism to
give a bounced card something to execute — so those steps stayed pending forever.
The mock now completes every pending step, as a real executor does.

This is necessary but not sufficient for S05 on builtin:coding-ideas-v2: the
remediation step IS appended and still ends pending
(`["Implement deterministic pipeline output:done",
   "Fix: The disposable fixture needs the scripted remediation commit.:pending"]`),
so the bounced card is not re-dispatched through an executor session that can
complete it. S05 and S07 therefore stay on their proven workflows rather than
shipping red.

Lane green: 6 files, 81 tests, 19/19 scenarios.
2026-08-25 01:30:20 +00:00
Fusion Agent
cfe65527ca fix(FN-WF): make the smoke mock honest, and match V2 remediation to its reopen policy
The pipeline-smoke executor mock routed a gate turn by its TOOL SURFACE. Code
Review is a writable inline-fix review, so on a review-column workflow it arrives
with the task-update tool, fell through to the implementation branch, and ended by
emitting a blanket APPROVE — silently discarding the scenario's scripted verdict.
Measured: S07 scripts `codeReviewModes: ["empty-revise"]` and the persisted result
was `code-review:passed:APPROVE:code`, which then sealed the tree and blocked the
replay of Documentation & Delivery. Two failures downstream of one mislabel.

Gate turns are now routed by the step they name (`Execute the workflow step "X"`),
which is present on every gate turn and absent from the implementation session.
Non-review gates approve without consuming review verdicts.

This matters beyond the two scenarios it fixes: the mock was manufacturing false
greens. S05 on builtin:coding-ideas-v2 passed only because its scripted
"revise twice, then approve" was being auto-approved, so the workflow's rework path
was never exercised at all. Making the mock honest reveals that path as genuinely
broken, and S05/S07 accordingly move back to the workflows where they are proven.
A green that came from a mislabel is worse than a red.

Also aligns V2's code-review remediation with `review-remediation-steps`. That is
not cosmetic symmetry: the workflow sets the parse node's `implementationOnlySteps`
+ `preserveRemediationSteps`, which `resolveStepReopenPolicy` reads as reopen
policy "none". The two are a matched pair — with trailing-step reopening disabled,
the inherited `pre-merge-remediation` returns the card to in-progress with every
step already done and nothing to execute. The earlier revert of this change blamed
the wrong cause: the empty `git merge --squash` ref came from the merger mock
resolving `task.branch`, since fixed at the harness.

Lane green: 6 files, 81 tests, 19/19 scenarios, 107.7s and 107.1s against 150s.
Remaining V2 gap, stated rather than hidden: the Code Review REVISE -> rework path
does not converge ("did not persist completed implementation-step projection"), so
S05, S07, S13 and S17 stay on their original workflows.
2026-08-25 01:21:22 +00:00
Fusion Agent
975d8a0ed2 test(FN-WF): stop non-review gates consuming a scenario's scripted review verdicts
Two places in the pipeline-smoke mock treated any readonly, non-Plan-Review turn
as a Code Review, so on a review-column workflow the Documentation & Delivery gate
ate the verdict scripted for Code Review. S07 scripts
`codeReviewModes: ["empty-revise"]` to exercise an unactionable Code Review
rejection; the card instead died with `documentation-delivery: failed: REVISE`
before Code Review ever ran.

- `emitReview` classified everything that was not Plan Review as "code".
- The executor script forces `emitReview(context, "code")` whenever a readonly
  session coincides with scripted `codeReviewModes` — and a documentation gate is
  readonly too, so it took that branch as well.

Both now identify the executing step from the workflow-step system prompt
("You are a workflow step agent executing: <name>") and exclude the known
non-review gates. Detection is by EXCLUSION rather than an allow-list on purpose:
the real reviewer prompt does not carry the literal "Code Review", so allow-listing
silently approves every genuine review instead — measured, it turned S07 green on
`builtin:coding-ideas` for the wrong reason.

S07 on builtin:coding-ideas-v2 now gets past that misattribution and reaches the
review seal instead, which is a different and still-open problem, so the scenario
stays on its original workflows. Lane is green and faster than the previous
matrix: 6 files, 82 tests, 19/19 scenarios, 97.2s and 100.3s against the 150s
budget.
2026-08-24 21:20:23 +00:00
Fusion Agent
94f660e672 fix(FN-WF): stop a failed merge stranding review-column tasks, and widen V2 coverage
Two review-seal defects, both found by running builtin:coding-ideas-v2 through the
whole scenario matrix rather than the nominal path alone.

1. A DETERMINISTIC verification gate was sealed as write-capable. It needs a
   worktree because it runs the project's test/build commands there, but it only
   reads the tree — `verification-gate.ts` has no mutation path.
   `workflowNodeRequiresWorktree` conflates "needs a worktree" with "writes", and
   its inline-fix branch matches on the node NAME (`/review|verification/i`), so a
   gate named "Verification" was refused after any approval.

2. A gate that already `passed` or was `skipped` was refused on replay. A
   post-approval requeue — a merge conflict, a transient merge failure — walks the
   graph back through gates whose output is already inside the approved tree.
   Refusing them converts a retryable merge into a terminal wedge; re-running them
   would rewrite the tree the review approved. "Already produced, already
   reviewed" now resolves as satisfied. A gate with no result still hits the
   refusal, which is the case the seal exists for.

Measured by pipeline-smoke S13, where a conflicting merge left the card cycling on
documentation-delivery with `workspace-review-seal-required` instead of retrying.

Coverage: builtin:coding-ideas-v2 now runs 16 of the 19 declared scenarios plus
the multi-repository workspace drive, up from 1. The duration budget is
re-baselined 90s -> 150s, and the workload growth is itemised in docs/testing.md:
17 added scenario executions and a second project shape, 124.95s measured against
76.9s for the smaller matrix. Three consecutive full runs: 116.9s, 115.6s, 119.8s.

NOT covered, deliberately and stated rather than hidden: S07 (unactionable review
rejection), S13 (scripted merge-conflict resolution) and S17 (restart resilience)
still run on the original workflows only. S07 and S13 do not converge on V2, and
S17 produced one intermittent post-merge failure in four full-lane runs — a flake
is not something to ship or to paper over, so those three stay uncovered until
they are understood.
2026-08-24 16:21:30 +00:00
Fusion Agent
f4487b4b31 test(FN-WF): prove the pipeline end to end on multi-repository workspaces
The smoke lane now drives a workspace task on builtin:coding-ideas-v2 from the
Ideas intake to `merged-done`, alongside the existing single-repository coverage.
6 files, 65 tests, 19/19 scenarios, 77.1s of the 90s budget.

Two fixture defects stood between the harness and that proof, both of the same
shape: a workspace task legitimately has NO task-level `branch` — each repository
owns one under `workspaceWorktrees[repo].branch`.

- The scripted merger was handed `task.branch ?? ""`, so it ran
  `git merge --squash` on an empty ref ("merge:  - not something we can merge"),
  surfacing only as the generic "Workspace repository repo1 could not land".
- Resolving the branch at INSTALL time was still wrong: the merge is attempted in
  the same turn as the first install, before acquisition has created any
  per-repository worktree. The scripts now receive an async getter that reads the
  live task when the merger actually runs, so ordering cannot make it stale.

This also corrects an earlier misattribution recorded in the previous commit: the
land failure was NOT a missing `repositoryScope`. A probe showed the scope
confirmed, the review evidence recorded, and `workspaceWorktrees.repo1.branch`
populated — the harness simply never passed that branch to the merger.

The workspace path is now measured, not inferred: plan, plan-review, parse,
verification, documentation-delivery, completion-summary, code review
("All 1 modified in-scope sub-repo(s) approved") and the per-repository land all
run, with `mergeDetails.mergeConfirmed` asserted on the persisted row.
2026-08-24 15:29:07 +00:00
Fusion Agent
ec37920593 fix(FN-WF): document the V2 remediation gap and the workspace land precondition
Two investigations, both concluded with evidence rather than a shipped guess.

REMEDIATION. builtin:coding-ideas-v2 inherits Coding (Ideas)' `code-review-remediation`
(`pre-merge-remediation`, a send-back that appends no work) while its own
`verification-remediation` uses `review-remediation-steps`, which derives NAMED steps
from the reviewer's findings, appends them as a numbered wave, widens the PROMPT.md
File Scope, and parks for a human instead of bouncing when findings are out of scope,
unactionable, or a fourth wave. Aligning the two was attempted and REVERTED: with the
named path on code review, S05 ("REVISE twice, then approve") fails reproducibly on
this workflow — the card reaches merge without a usable branch and `git merge --squash`
runs with an empty ref ("not something we can merge"). A bounced card that cannot merge
is worse than a bounced card with an unchanged checklist, so the asymmetry is pinned by
a test that states the constraint: change it together with a green S05, never alone.

WORKSPACE. The land failure behind "Workspace repository repo1 could not land" is the
SAME empty-ref signature, and it is a fixture limitation rather than a product defect:
the harness states `repositoryScope` directly, so no acquisition ever populates
`workspaceWorktrees[repo].branch`, and the per-repo land has no branch to squash. The
production path populates it; the fixture must too before the end-to-end workspace
drive can be asserted.

What the workspace work already proved stands: a workspace task clears plan,
plan-review, parse, verification, documentation-delivery and code review
("All 1 modified in-scope sub-repo(s) approved"), which is the direct end-to-end
confirmation that the session-boundary fix works — the write-capable documentation gate
now runs in a multi-repository project instead of dying with "Refusing to start coding
agent in incomplete worktree".

Everything committed here is green: smoke 63 tests / 19/19 scenarios / 72.7s of 90s,
test:gate, verify:fast, both typechecks, changesets.
2026-08-24 14:33:50 +00:00
Fusion Agent
c8b2b10732 test(FN-WF): add multi-repository workspace support to the pipeline smoke harness
The smoke lane was single-repository only, so the workspace path — the one that
actually broke in production — was never driven end to end. Adds:

- `createPipelineWorkspaceFixture`: a real workspace project whose ROOT is a plain
  container (no Git metadata) holding per-repository checkouts with their own
  origins and a `.fusion/workspace.json`. The single-repo fixture cannot express
  this shape, because there the root and the repository are the same directory —
  which is why a node resolving the root as a worktree still worked by accident.
- `PipelineGitFixture.integrationRepoDir`: integration git (`rev-parse main`,
  ancestry, status, worktree prune) now targets a repository rather than the
  project root. Single-repo fixtures answer `repoDir`, so nothing changes there.
- `PipelineSmokeHarness.create(pg, { workspace: true })` and an optional confirmed
  `repositoryScope` on `createPipelineTask`, which workspace acquisition requires
  before any write-capable node runs.
- The executor mock now resolves the repository it can commit in. Its
  `existsSync(cwd/.git)` guard skipped the whole implementation block on a
  workspace session (cwd is the task directory), so no commit existed and Code
  Review reported "No changes — not reviewed" on an untouched scoped repository.

Measured with these in place, a workspace task on builtin:coding-ideas-v2 now
clears plan, plan-review, parse, verification, documentation-delivery and code
review ("All 1 modified in-scope sub-repo(s) approved"). That is the direct
end-to-end confirmation that the FN-158-shaped session-boundary fix works: the
write-capable documentation gate runs in a workspace instead of dying with
"Refusing to start coding agent in incomplete worktree".

It then fails at the workspace LAND step with "Workspace repository repo1 could
not land". The underlying cause is written to the task log rather than stdout and
is not yet identified, so the end-to-end workspace drive test is deliberately NOT
committed: shipping it red would put a permanently failing test in the lane, and
weakening it to assert only the progress reached would be appeasement. Mono-repo
coverage is unchanged and green (63 tests, 19/19 scenarios).
2026-08-24 14:18:50 +00:00
Fusion Agent
d061081b61 chore(FN-WF): retire builtin:review-gated-coding via the registry deprecation list
Adds it to `DEPRECATED_BUILTIN_WORKFLOW_IDS` — the registry's own retirement
mechanism, and the reason `isBuiltinWorkflowToggleEligible` and
`validateEnabledBuiltinWorkflowIds` exist. The workflow disappears from new
selection while `getBuiltinWorkflow` keeps resolving it, so any task that already
selected it still runs. Built-ins cannot be deleted, and deleting this one would
strand those tasks.

It is obsolete because builtin:coding-ideas-v2 supersedes it and because its own
success path could never complete: `code-review -> documentation-delivery` puts a
write-capable node after a passed review, which the graph refuses with
`workspace-review-seal-required`.
2026-08-24 10:33:36 +00:00
Fusion Agent
9e76393cfa fix(FN-WF): make review-column workflows actually merge
A required pre-merge step is not necessarily a content review. Review-column
workflows also require a deterministic verification gate (exit codes) and a
documentation/delivery gate; neither records a `reviewInputFingerprint` because
neither binds a diff. `evaluatePreMergeApprovals` compared them against the merge
content anyway, classified both as `unprovable-content`, and `canMergeTask`
answered "task has no provable approval for the content being merged" — an
unsatisfiable gate, so NOTHING could ever merge on such a workflow. Cards reached
the merge, were refused, and looped through verification-remediation.

The carve-out is narrow: a step that is neither `code-review` nor a
`reviewKind: "code"` result AND recorded no fingerprint of its own is not
diff-bound and passes on its status. A content review that DID record a
fingerprint is still compared, and a code review missing one is still refused, so
FN-180's guarantee is untouched. Reverting the carve-out fails the new tests.

builtin:review-gated-coding carried the identical latent defect and never reached
its merge to expose it.

Proven end to end: pipeline-smoke now drives S01 on builtin:coding-ideas-v2 from
the Ideas intake through promotion, planning, plan review, implementation,
verification, documentation, summary and code review to `merged-done` —
63 tests, 19/19 scenarios, 74.7s against the 90s budget. S01 keeps that workflow
permanently, because all five defects fixed in this effort passed structural
review and only a real card reaching `merged-done` exposed them.
2026-08-24 10:07:22 +00:00
Fusion Agent
3efdc42ad4 fix(FN-WF): repair the review-gated planning seam, prompt, and workspace gate boundary
Four defects found by pointing the FN-182 pipeline-smoke harness at a review-gated
workflow. Three of them also affected builtin:review-gated-coding, where they had
been latent because that graph dies earlier on the review seal.

1. `planning-implementation-only` is a PROMPT key, never an executable seam.
   `resolveSeamName` accepts exactly seven seam names and throws
   `Unsupported workflow seam` otherwise, so the `plan` node threw on every task:
   the graph failed at `plan`, the card bounced to todo, and the board reported
   "Execution dispatch refused — task is still unplanned" — pressing Start
   appeared to do nothing. The seam is now `planning`; only the prompt differs.

2. The seam prompt contradicted itself. It was the full triage prompt — whose
   template MANDATES `### Step {N-1}: Testing & Verification` and
   `### Step {N}: Documentation & Delivery` — plus one appended line asking for
   neither. The template won, so tasks emitted both steps and ran them in
   in-progress, duplicating the review gates. The template region is now removed
   and replaced by an explicit prohibition. The parse node's
   `implementationOnlySteps` is not a backstop: it only audits, by design.

3. `requireImplementationOnlySteps` was inert when set on an already-built
   plan-review node: the prompt is assembled by `planReviewOptionalGroupNode`
   and no engine code reads the flag, so the reviewer never received its
   criterion. Both derived workflows now call `applyImplementationOnlyStepReview`.

4. Write-capable graph nodes declared no session boundary on workspace tasks, so
   the single-repo assertion resolved the task DIRECTORY (a container of per-repo
   worktrees, no `.git`) as a worktree and refused: "Refusing to start coding
   agent in incomplete worktree", failing the gate before a verdict and requeuing
   the task. FN-158 gave Code Review the `workspace-task-dir` boundary but not the
   generic prompt path. Extracted as a pure `resolveGraphNodeSessionBoundary`.

Also reorders coding-ideas-v2 to `verification -> documentation-delivery ->
completion-summary -> code-review -> merge`. The summary escapes the review seal
(readonly) but still acquires a worktree, and any node between the review and the
merge invalidates FN-180's review-diff fingerprint.

Known incomplete: builtin:coding-ideas-v2 still does not converge end to end —
pipeline-smoke S01 reaches merge and is refused with "task has no provable
approval for the content being merged". Not yet root-caused; the workflow must be
treated as unusable until it is.
2026-08-24 06:39:28 +00:00
Fusion Agent
b818eb20ad feat(FN-WF): add the Coding (Ideas) V2 workflow with review-column gates
Selectable built-in `builtin:coding-ideas-v2`. It clones the Coding (Ideas) IR
without mutating it, so the manual `ideas` intake (`autoTriage: false`) and the
whole board shape are unchanged, and moves testing and documentation out of the
planner's implementation checklist into visible review-column gates:

  in-progress : steps            = implementation only
  in-review   : verification -> documentation-delivery -> code-review
                -> completion-summary -> merge-gate -> merge

Ordering is load-bearing, not cosmetic. `execute-workflow-graph.ts` refuses any
write-capable node once a Code Review APPROVE exists, so that a passed review
seals the tree and nothing unreviewed reaches main. `verification-step` and
`documentation-delivery-step` are both write-capable and therefore run BEFORE
the review; `completion-summary` is `toolMode: "readonly"` and runs after it, so
the card blurb describes the state that was actually approved.

Both remediation loops re-enter at `verification`, never at `code-review`: a
REVISE replays verification AND documentation-delivery, so the docs and
changeset are regenerated to include what the review demanded before it re-reads
them. Documentation stays both current and reviewed.

The planner is switched to the `planning-implementation-only` seam so it stops
emitting "Testing & Verification" and "Documentation & Delivery" steps, which
would otherwise duplicate the gates under identical names.

Adds a ratchet running the production `workflowNodeRequiresWorktree` classifier
over the success chain: it reports zero offenders here and correctly flags
`documentation-delivery` on builtin:review-gated-coding, whose post-review
ordering deadlocks every task once its review approves.
2026-08-24 05:59:49 +00:00
Fusion Agent
5990ebb752 fix(FN-184): stop an in-flight merge aborting on its own merging status
FN-180's in-flight revoke watcher read `runAiMerge`'s own `status:"merging"`
stamp as a blocking pre-merge verdict: `merging`/`merging-pr` are members of
HARD_BLOCKING_TASK_STATUSES and daemon/dashboard/serve all wire the unoptioned
`getTaskMergeBlocker`. The merge aborted itself within the same second, the
drain catch cleared the stamp, and the sweep re-admitted the task every
`pollIntervalMs` forever. The abort branch spends no `mergeRetries`, so nothing
bounded the loop: no task merged, on any project, and no card was ever parked.

Fixed at both seams, because the watcher alone leaves the merge dying later:
- `ProjectEngine.wireTaskPauseMergeInterruption` evaluates the blocker against a
  verdict view that neutralizes `isMergeActiveStatus` for the owned task.
- `assertMergeGateStillOpen` (merger-ai) re-reads the task from the store at the
  ref-advance fence, so it observes the same stamp and revoked the very merge it
  guards. Same neutralization applied.

Genuine verdicts still abort: failed/pending pre-merge step results, `paused`,
`needs-replan`, and the scheduler's `queued` (deliberately not neutralized —
MERGE_CONFIRMED_TRANSIENT_STATUSES would have swallowed it). A merge-active
stamp on a different task never enters the branch.

Replaces the FN-180 source-grep coverage with behavioral tests driving the real
production blocker through the handler. Proven differential: reverting the
neutralization fails exactly the `merging` and `merging-pr` cases (2 of 11).

Fusion-Task-Id: FN-184
2026-08-24 04:45:58 +00:00
Fusion Agent
bde81ad4ff feat(FN-182): add deterministic AI-free pipeline smoke lane
Opt-in `pnpm smoke:pipeline` lane replaying 19 declared scenarios across
builtin:coding-ideas and the builtin:coding non-regression floor, driving the
real engine: disposable local Git repositories, throwaway PostgreSQL store,
production graph dispatch, ProjectEngine merge admission, real worktree
acquisition, and deterministic mock-provider scripts under testMode.

Each scenario declares one closed terminal state (merged-done, inert-intake,
parked, manual-hold, no-op-merge); an undeclared terminal fails the run, and
five wedge detectors (W1-W5) reject contradictory parks, finalization loops,
severed sessions, unreachable waits, and quiescence without progress.

Differential proof: on the pre-FN-180 tree (95ea06b48) exactly S05, S06, S09,
S10 and S16 fail across both workflows with behavioral assertions, and pass
after FN-180 — the FN-175/FN-177 incident classes are reproduced mechanically.

The declared duration budget is re-baselined 70s -> 90s at landing. The harness
did not degrade: the identical branch measured 61.8-64.1s against the
pre-integration main and 73.2-80.2s against the same main after 65 upstream
commits, with growth in transform, import and test phases the lane does not own.
docs/testing.md records the measurements, the cause, and the file-consolidation
lever to reach for before the budget is touched again.

Excluded from engine-default and engine-core; the merge gate is unchanged and
CI runs the lane non-blocking after merge.

Fusion-Task-Id: FN-182
2026-08-24 04:19:21 +00:00
Fusion Agent
8e8e3233c6 Merge remote-tracking branch 'origin/main'
# Conflicts:
#	docs/dashboard-guide.md
#	packages/core/src/__tests__/postgres/schema-applier.test.ts
#	packages/core/src/__tests__/task-merge.test.ts
#	packages/core/src/merge/task-merge.ts
#	packages/core/src/postgres/schema-applier.ts
#	packages/core/src/task-store/merge-queue-ops.ts
#	packages/dashboard/app/__tests__/App.keyboard-shortcuts.test.tsx
#	packages/dashboard/app/components/ChatView.css
#	packages/dashboard/app/components/ChatView.tsx
#	packages/dashboard/app/components/__tests__/ChatView.core-contracts.test.tsx
#	packages/dashboard/app/components/__tests__/ChatView.core-interactions.test.tsx
#	packages/dashboard/app/components/__tests__/ChatView.core.test.tsx
#	packages/dashboard/app/components/__tests__/ChatView.draft.test.tsx
#	packages/dashboard/app/components/__tests__/ChatView.message-edit.test.tsx
#	packages/dashboard/app/components/__tests__/ChatView.mobile-render.test.tsx
#	packages/dashboard/app/components/__tests__/ChatView.mobile.test.tsx
#	packages/dashboard/app/components/__tests__/ChatView.new-chat-default.test.tsx
#	packages/dashboard/app/components/__tests__/ChatView.rooms.test.tsx
#	packages/dashboard/app/components/__tests__/ChatView.scroll-to-top.test.tsx
#	packages/dashboard/app/components/__tests__/ChatView.sessions-rooms.test.tsx
#	packages/dashboard/app/components/__tests__/ChatView.thinking-level.test.tsx
#	packages/engine/src/__tests__/executor-step-session.test.ts
#	packages/engine/src/__tests__/merge-abort-clears-transient-status.test.ts
#	packages/engine/src/__tests__/merger-ai-cleanup.test.ts
#	packages/engine/src/__tests__/merger-merge-lifecycle.test.ts
#	packages/engine/src/__tests__/workspace-merger.test.ts
#	packages/engine/src/merge/auto-merge-finalization.ts
#	packages/engine/src/merge/merger-ai.ts
#	packages/engine/src/project-engine.ts
#	packages/engine/src/run-audit/run-audit-catalogue.ts
#	packages/engine/src/self-healing.ts
#	packages/engine/src/worktree/review-diff-fingerprint.ts
#	packages/i18n/locales/es/app.json
#	packages/i18n/locales/fr/app.json
#	packages/i18n/locales/ko/app.json
#	packages/i18n/locales/pt-BR/app.json
#	packages/i18n/locales/zh-CN/app.json
#	packages/i18n/locales/zh-TW/app.json
2026-08-24 03:55:34 +00:00
gsxdsm
456f7b370b docs(test-failures): retract the connection-exhaustion cause, record the failed reproduction
Measured 14 backend connections against max_connections=100, so the api-lane
hook timeouts are not connection exhaustion; the PostgreSQL Failed query lines
are a torn-down reconciler polling after the fact. Full 15-lane run at 23,584
tests reproduced nothing, and the DDL admission gate never degraded, so that
mechanism is unsupported too. Records what a future attempt must capture.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 20:08:43 -07:00
gsxdsm
68f5c45ef0 chore(dashboard): commit e2e screenshot baselines regenerated by the browser lane
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 19:48:34 -07:00