Commit Graph

13902 Commits

Author SHA1 Message Date
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
Anthony Ettinger
544d740ab0 ci: scan pull requests for credentials and injection with ThreatCrush (#3427)
Adds a pull-request workflow that scans the diff for hardcoded
credentials,
injection, SSRF and unsafe deserialisation. Results go to the Security
tab as
SARIF and to a comment on the pull request.

### What it does on this repository

```
@profullstack/threatcrush@0.11.0 scan .
6908 files in 27.5s — 4570 finding(s): 38 high, 4061 medium, 471 low
confidence: 500 evidence, 4070 pattern
```

**None of that is a claim about your code, and I have not verified any
of it.**
`confidence: pattern` means a regex matched and nothing more; expect
false
positives in that tier. It is here because the check on this pull
request may
never run at all — GitHub withholds workflow runs from first-time
contributors,
and across 24 open requests elsewhere not one has been approved. Rather
than ask
you to approve a run to find out what it produces, that is what it
produces.

Opened alongside the question in
https://github.com/Runfusion/Fusion/issues/3426, which is the place to
say no or ask for
changes. This is only the diff, so it is there to read rather than
imagine —
closing either one is a fine answer.

**This is not a CodeQL replacement, and it is worth saying where it
differs.**
CodeQL does semantic dataflow analysis and is better at it than this is
— a
repository already running it is not missing much by closing this. Two
gaps it
does fill:

- Code scanning and secret scanning are free on public repositories, but
need
paid GitHub Code Security / Secret Protection on private ones. This is
MIT and
free on both, so the same gate can run across a mixed set of
repositories.
- CodeQL analyses a fixed set of languages, and among compiled ones it
analyses
only the language with the most source files unless it's explicitly
configured
otherwise. In a polyglot repository the rest goes unscanned by default;
this
  reads every file it is pointed at.

It is additive and report-only, so running both costs a few CI minutes
and
changes nothing else.

**It is report-only.** `failOn` is empty, so it annotates and never
fails a build.
A repository with pre-existing findings should get a report on its first
install,
not a blocked pull request — a gate that fires on everything gets
switched off
within a day. Tighten it to `critical,high` in the workflow once any
backlog is
triaged.

- `.github/workflows/threatcrush-scan.yml` — the workflow
- `.github/scripts/threatcrush-to-sarif.py` — a compatibility shim for
CLI versions
older than native SARIF output; unused once the installed CLI can emit
it itself

Permissions are least-privilege (`contents: read`, `pull-requests:
write`,
`security-events: write`). It runs on `pull_request`, not
`pull_request_target`,
so contributor code never executes with your secrets in scope. The SARIF
upload
is `continue-on-error` and degrades quietly where code scanning is
unavailable.

The CLI is pinned to `@profullstack/threatcrush@0.11.0` and installed
with
`--ignore-scripts`, and checkout runs with `persist-credentials: false`.
A
scanner that installs a floating version, runs its dependencies'
lifecycle
scripts and leaves a token in `.git/config` is asking you to trust more
than it
is worth, and none of that is needed to read a diff. Bump the pin
whenever you
like — nothing here updates itself.

Disclosure: I maintain
[ThreatCrush](https://github.com/profullstack/threatcrush).
It is free and MIT, and the workflow installs it from npm — nothing here
phones
home. If this is not something you want, closing it is the right answer,
and I
will not send another.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Added automated ThreatCrush security scanning for pull requests.
* Scan results are converted to a standardized format and uploaded for
review.
* Findings can update pull request comments and generate downloadable
reports and artifacts.
  * Supports current and legacy scanner output formats.
* Adds configurable severity thresholds and verified scanner
installation.
* **Bug Fixes**
* Invalid, incomplete, or unrecognized scan output now fails safely with
clear diagnostics.
  * Scan failures and security findings are reliably reported.
  * Improved handling of scan completion status and finding details.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: Anthony Ettinger <anthony@chovy.com>
Co-authored-by: gsxdsm <gsxdsm@users.noreply.github.com>
2026-08-23 19:46:52 -07:00
dependabot[bot]
87a3700a21 Bump sharp from 0.33.5 to 0.35.3 (#3509)
Bumps [sharp](https://github.com/lovell/sharp) from 0.33.5 to 0.35.3.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/lovell/sharp/releases">sharp's
releases</a>.</em></p>
<blockquote>
<h2>v0.35.3</h2>
<ul>
<li>
<p>Tighten verification of <code>text</code> dimensions, TIFF tile
dimensions and <code>extend</code> values.</p>
</li>
<li>
<p>Improve code bundler support by resolving path to libvips binary.</p>
</li>
<li>
<p>Increase default concurrency when use of
<code>MALLOC_ARENA_MAX</code> is detected.</p>
</li>
<li>
<p>Emit warning about binaries provided by Electron for use on
Linux.</p>
</li>
<li>
<p>Add <code>hasAlpha</code> property to output <code>info</code>.
<a
href="https://redirect.github.com/lovell/sharp/issues/4500">#4500</a></p>
</li>
<li>
<p>TypeScript: Return more precise
<code>Buffer&lt;ArrayBuffer&gt;</code> from <code>toBuffer</code>.
<a href="https://redirect.github.com/lovell/sharp/pull/4520">#4520</a>
<a href="https://github.com/Andarist"><code>@​Andarist</code></a></p>
</li>
<li>
<p>Bound <code>clahe</code> width and height to avoid signed overflow.
<a href="https://redirect.github.com/lovell/sharp/pull/4551">#4551</a>
<a
href="https://github.com/metsw24-max"><code>@​metsw24-max</code></a></p>
</li>
<li>
<p>Bound <code>trim</code> margin to avoid signed overflow.
<a href="https://redirect.github.com/lovell/sharp/pull/4552">#4552</a>
<a
href="https://github.com/metsw24-max"><code>@​metsw24-max</code></a></p>
</li>
<li>
<p>Reject infinite values when validating numbers.
<a href="https://redirect.github.com/lovell/sharp/pull/4553">#4553</a>
<a
href="https://github.com/metsw24-max"><code>@​metsw24-max</code></a></p>
</li>
<li>
<p>Bound extract region to libvips coordinate limit.
<a href="https://redirect.github.com/lovell/sharp/pull/4555">#4555</a>
<a
href="https://github.com/metsw24-max"><code>@​metsw24-max</code></a></p>
</li>
<li>
<p>Verify background colour values are numbers.
<a href="https://redirect.github.com/lovell/sharp/pull/4556">#4556</a>
<a
href="https://github.com/metsw24-max"><code>@​metsw24-max</code></a></p>
</li>
<li>
<p>Bound create and raw input dimensions to coordinate limit.
<a href="https://redirect.github.com/lovell/sharp/pull/4558">#4558</a>
<a
href="https://github.com/metsw24-max"><code>@​metsw24-max</code></a></p>
</li>
<li>
<p>Tighten recomb and affine matrix verification.
<a href="https://redirect.github.com/lovell/sharp/pull/4560">#4560</a>
<a
href="https://github.com/chatman-media"><code>@​chatman-media</code></a></p>
</li>
<li>
<p>Verify cache memory limit to avoid overflow.
<a href="https://redirect.github.com/lovell/sharp/pull/4561">#4561</a>
<a
href="https://github.com/metsw24-max"><code>@​metsw24-max</code></a></p>
</li>
</ul>
<h2>v0.35.3-rc.2</h2>
<ul>
<li>Tighten verification of <code>text</code> dimensions, TIFF tile
dimensions and <code>extend</code> values.</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="1018449164"><code>1018449</code></a>
Release v0.35.3</li>
<li><a
href="ba303a799d"><code>ba303a7</code></a>
Prerelease v0.35.3-rc.2</li>
<li><a
href="4f94fc5162"><code>4f94fc5</code></a>
Upgrade to sharp-libvips v1.3.2</li>
<li><a
href="c5e7a3ff20"><code>c5e7a3f</code></a>
Bump devDeps, fix Deno/Windows smoke tests</li>
<li><a
href="9a8d002688"><code>9a8d002</code></a>
Docs: Add changelog entry and note about transferable <a
href="https://redirect.github.com/lovell/sharp/issues/4520">#4520</a></li>
<li><a
href="8694db0bac"><code>8694db0</code></a>
TypeScript: Return more precise <code>Buffer\&lt;ArrayBuffer&gt;</code>
from <code>toBuffer</code> (<a
href="https://redirect.github.com/lovell/sharp/issues/4520">#4520</a>)</li>
<li><a
href="e000d0b5e1"><code>e000d0b</code></a>
Prerelease v0.35.3-rc.1</li>
<li><a
href="9554ca9553"><code>9554ca9</code></a>
Prerelease v0.35.3-rc.0</li>
<li><a
href="6a29fd55db"><code>6a29fd5</code></a>
Emit warning about native binaries on Linux Electron</li>
<li><a
href="540d2eada4"><code>540d2ea</code></a>
Increase default concurrency when use of MALLOC_ARENA_MAX detected</li>
<li>Additional commits viewable in <a
href="https://github.com/lovell/sharp/compare/v0.33.5...v0.35.3">compare
view</a></li>
</ul>
</details>
<details>
<summary>Maintainer changes</summary>
<p>This version was pushed to npm by <a
href="https://www.npmjs.com/~GitHub%20Actions">GitHub Actions</a>, a new
releaser for sharp since your current version.</p>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=sharp&package-manager=npm_and_yarn&previous-version=0.33.5&new-version=0.35.3)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

Dependabot will resolve any conflicts with this PR as long as you don't
alter it yourself. You can also trigger a rebase manually by commenting
`@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits
that have been made to it
- `@dependabot show <dependency name> ignore conditions` will show all
of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop
Dependabot creating any more for this major version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop
Dependabot creating any more for this minor version (unless you reopen
the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop
Dependabot creating any more for this dependency (unless you reopen the
PR or upgrade to it yourself)


</details>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: gsxdsm <gsxdsm@users.noreply.github.com>
2026-08-23 19:46:27 -07:00
Phil Larson
17aadf22ee test(core): align executor workflow prompt contract (#3517)
## Summary
- align the executor prompt regression with capability-aware workflow
creation guidance
- keep the no-creation-tool and per-tool cases covered by the adjacent
surface-specific test

## Test plan
- `pnpm --filter @fusion/core exec vitest run
src/__tests__/agent-prompts.test.ts --silent=passed-only --reporter=dot`
- `pnpm --filter @fusion/core typecheck`
- `pnpm check:changesets`


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Updated workflow guidance to prevent assigning workflows to the
current task while allowing workflow assignment for newly created or
delegated tasks.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: gsxdsm <gsxdsm@users.noreply.github.com>
2026-08-23 19:46:11 -07:00
gsxdsm
f3e248bb25 test: drop the removed subtask handler case, document the star-prompt setting
- useTaskHandlers: deletes `handleSubtaskTasksCreated delegates with addToast`
  and its `onSubtaskTasksCreated` fixture field. FN-074 removed task splitting;
  grep confirms no production reference to either symbol remains, so the case
  was asserting a deleted contract.
- settings-default-descriptions: records `githubStarPromptDismissedAt` as
  internal bookkeeping written by useGitHubStarPrompt rather than a rendered
  Settings field, which is what that guard requires of every settings key.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 19:16:53 -07:00
dependabot[bot]
bcf353de48 chore(deps): bump @capacitor/core from 7.6.1 to 8.5.0 (#3467)
Bumps [@capacitor/core](https://github.com/ionic-team/capacitor) from
7.6.1 to 8.5.0.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a
href="https://github.com/ionic-team/capacitor/releases">@​capacitor/core's
releases</a>.</em></p>
<blockquote>
<h2>8.5.0</h2>
<h1><a
href="https://github.com/ionic-team/capacitor/compare/8.4.2...8.5.0">8.5.0</a>
(2026-07-31)</h1>
<h3>Bug Fixes</h3>
<ul>
<li><strong>cli:</strong> support TypeScript 7 when loading
capacitor.config.ts (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8534">#8534</a>)
(<a
href="4c1c870941">4c1c870</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li><strong>cli:</strong> add migrator functionality for adopting
UIScene (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8544">#8544</a>)
(<a
href="984fa85ba0">984fa85</a>)</li>
<li><strong>ios:</strong> UIScene Support (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8536">#8536</a>)
(<a
href="3fa04a357c">3fa04a3</a>)</li>
</ul>
<h2>8.4.2</h2>
<h2><a
href="https://github.com/ionic-team/capacitor/compare/8.4.1...8.4.2">8.4.2</a>
(2026-07-14)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>android:</strong> explicitly grant URI permissions for image
capture intent (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8526">#8526</a>)
(<a
href="6f2d328389">6f2d328</a>)</li>
</ul>
<h2>8.4.1</h2>
<h2><a
href="https://github.com/ionic-team/capacitor/compare/8.4.0...8.4.1">8.4.1</a>
(2026-06-19)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>cli:</strong> make SPM dependency patch work on prereleases
(<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8508">#8508</a>)
(<a
href="6048e90171">6048e90</a>)</li>
<li><strong>cli:</strong> patch Capacitor SPM dependency version in
plugins (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8492">#8492</a>)
(<a
href="28bb2c6870">28bb2c6</a>)</li>
</ul>
<h2>8.4.0</h2>
<h1><a
href="https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0">8.4.0</a>
(2026-06-02)</h1>
<h3>Bug Fixes</h3>
<ul>
<li><strong>android:</strong> show only the requested system bar (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8480">#8480</a>)
(<a
href="4c6c3219af">4c6c321</a>)</li>
<li><strong>cli:</strong> revert live reload config on failure (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8485">#8485</a>)
(<a
href="1d031a4abe">1d031a4</a>)</li>
<li><strong>SystemBars:</strong> make <code>safe-area-inset-x</code>
available on API &lt;= 34 (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8424">#8424</a>)
(<a
href="e456de083e">e456de0</a>)</li>
<li><strong>SystemBars:</strong> respect <code>insetsHandling</code>
disable (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8481">#8481</a>)
(<a
href="d4ad7ffe39">d4ad7ff</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li>add method getDouble to plugin config (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/7638">#7638</a>)
(<a
href="93c72de40a">93c72de</a>)</li>
<li><strong>cli:</strong> add experimental packageOptions (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8471">#8471</a>)
(<a
href="258867b7bf">258867b</a>)</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/ionic-team/capacitor/blob/main/CHANGELOG.md">@​capacitor/core's
changelog</a>.</em></p>
<blockquote>
<h1><a
href="https://github.com/ionic-team/capacitor/compare/8.4.2...8.5.0">8.5.0</a>
(2026-07-31)</h1>
<h3>Bug Fixes</h3>
<ul>
<li><strong>cli:</strong> support TypeScript 7 when loading
capacitor.config.ts (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8534">#8534</a>)
(<a
href="4c1c870941">4c1c870</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li><strong>cli:</strong> add migrator functionality for adopting
UIScene (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8544">#8544</a>)
(<a
href="984fa85ba0">984fa85</a>)</li>
<li><strong>ios:</strong> UIScene Support (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8536">#8536</a>)
(<a
href="3fa04a357c">3fa04a3</a>)</li>
</ul>
<h2><a
href="https://github.com/ionic-team/capacitor/compare/8.4.1...8.4.2">8.4.2</a>
(2026-07-14)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>android:</strong> explicitly grant URI permissions for image
capture intent (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8526">#8526</a>)
(<a
href="6f2d328389">6f2d328</a>)</li>
</ul>
<h2><a
href="https://github.com/ionic-team/capacitor/compare/8.4.0...8.4.1">8.4.1</a>
(2026-06-19)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>cli:</strong> make SPM dependency patch work on prereleases
(<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8508">#8508</a>)
(<a
href="6048e90171">6048e90</a>)</li>
<li><strong>cli:</strong> patch Capacitor SPM dependency version in
plugins (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8492">#8492</a>)
(<a
href="28bb2c6870">28bb2c6</a>)</li>
</ul>
<h1><a
href="https://github.com/ionic-team/capacitor/compare/8.3.4...8.4.0">8.4.0</a>
(2026-06-02)</h1>
<h3>Bug Fixes</h3>
<ul>
<li><strong>android:</strong> show only the requested system bar (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8480">#8480</a>)
(<a
href="4c6c3219af">4c6c321</a>)</li>
<li><strong>cli:</strong> revert live reload config on failure (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8485">#8485</a>)
(<a
href="1d031a4abe">1d031a4</a>)</li>
<li><strong>SystemBars:</strong> make <code>safe-area-inset-x</code>
available on API &lt;= 34 (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8424">#8424</a>)
(<a
href="e456de083e">e456de0</a>)</li>
<li><strong>SystemBars:</strong> respect <code>insetsHandling</code>
disable (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8481">#8481</a>)
(<a
href="d4ad7ffe39">d4ad7ff</a>)</li>
</ul>
<h3>Features</h3>
<ul>
<li>add method getDouble to plugin config (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/7638">#7638</a>)
(<a
href="93c72de40a">93c72de</a>)</li>
<li><strong>cli:</strong> add experimental packageOptions (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8471">#8471</a>)
(<a
href="258867b7bf">258867b</a>)</li>
<li><strong>cli:</strong> capture ios_package_manager in telemetry (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8482">#8482</a>)
(<a
href="b4b297a52f">b4b297a</a>)</li>
</ul>
<h2><a
href="https://github.com/ionic-team/capacitor/compare/8.3.3...8.3.4">8.3.4</a>
(2026-05-12)</h2>
<p><strong>Note:</strong> Version bump only for package capacitor</p>
<h2><a
href="https://github.com/ionic-team/capacitor/compare/8.3.2...8.3.3">8.3.3</a>
(2026-05-08)</h2>
<h3>Bug Fixes</h3>
<ul>
<li><strong>cli:</strong> copy plugin files in CocoaPods projects (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8467">#8467</a>)
(<a
href="b2d771926a">b2d7719</a>)</li>
</ul>
<h2><a
href="https://github.com/ionic-team/capacitor/compare/8.3.1...8.3.2">8.3.2</a>
(2026-05-07)</h2>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="3ab4139bd0"><code>3ab4139</code></a>
Release 8.5.0</li>
<li><a
href="984fa85ba0"><code>984fa85</code></a>
feat(cli): add migrator functionality for adopting UIScene (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8544">#8544</a>)</li>
<li><a
href="3fa04a357c"><code>3fa04a3</code></a>
feat(ios): UIScene Support (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8536">#8536</a>)</li>
<li><a
href="4c1c870941"><code>4c1c870</code></a>
fix(cli): support TypeScript 7 when loading capacitor.config.ts (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8534">#8534</a>)</li>
<li><a
href="f368a1b1ec"><code>f368a1b</code></a>
chore(android): fix lint issues (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8542">#8542</a>)</li>
<li><a
href="1834b9740e"><code>1834b97</code></a>
Release 8.4.2</li>
<li><a
href="6f2d328389"><code>6f2d328</code></a>
fix(android): explicitly grant URI permissions for image capture intent
(<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8526">#8526</a>)</li>
<li><a
href="b789b683f0"><code>b789b68</code></a>
chore: run <code>npm run fmt</code> to fix lint errors (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8516">#8516</a>)</li>
<li><a
href="7217b5215a"><code>7217b52</code></a>
Release 8.4.1</li>
<li><a
href="6048e90171"><code>6048e90</code></a>
fix(cli): make SPM dependency patch work on prereleases (<a
href="https://redirect.github.com/ionic-team/capacitor/issues/8508">#8508</a>)</li>
<li>Additional commits viewable in <a
href="https://github.com/ionic-team/capacitor/compare/7.6.1...8.5.0">compare
view</a></li>
</ul>
</details>
<br />

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-08-23 19:00:31 -07:00
Timoteo
23b152f494 fix: normalize subscribe for callback-only runtime sessions (#3504)
## Summary

- normalize callback-only plugin sessions at the shared runtime boundary
- preserve runtime-native subscriptions and isolate subscriber failures
- strengthen ACP multi-delta, unsubscribe, and callback-delivery
coverage
- correct the task environment and unsubscribe contracts

## Why

PR #3501 fixed the generic ACP adapter, but workflow steps still call
`session.subscribe()` unconditionally. Bundled callback-only runtimes
such as Hermes and the vendored Grok/Claude/OMP ACP clients can still
return sessions without that method. Handling the compatibility once in
`createResolvedAgentSession` closes every current runtime surface
without copying the bridge into each adapter.

## Testing

- `packages/engine`: `agent-session-helpers.test.ts` — 61 passed
- `fusion-plugin-acp-runtime`: `runtime-adapter.test.ts` — 14 passed
- `fusion-plugin-acp-runtime`: `process-manager.test.ts` — 15 passed
- engine typecheck passed
- ACP runtime typecheck passed
- changeset format, FNXC date check, ESLint, and `git diff --check`
passed


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Bug Fixes**
  - Improved compatibility with callback-based runtime sessions.
- Added reliable subscriptions for text, thinking, and tool activity
updates.
  - Preserved native subscription behavior where available.
  - Prevented subscriber errors from interrupting event delivery.
  - Improved unsubscribe behavior for removed handlers.
  - Improved event delivery during deferred runtime fallback.
  - Corrected task environment values passed to runtime subprocesses.

- **Tests**
- Expanded coverage for streaming updates, fallback handling, cleanup,
and subscriber isolation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-23 19:00:06 -07:00
Phil Larson
c192971053 fix: remove irregular whitespace from lint gate (#3518)
## Summary
- replace a zero-width space in the comment-assertion gate documentation
- restore the clean-main ESLint gate without changing scanner behavior

## Test plan
- `node scripts/check-no-comment-assertions-in-tests.mjs`
- `pnpm exec eslint scripts/check-no-comment-assertions-in-tests.mjs`
- `pnpm check:changesets`
- `pnpm lint`

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Clarified the explanation for a narrowly scoped test-checking
exception.
  * No runtime behavior or user-facing functionality changed.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-23 18:59:37 -07:00
gsxdsm
72f0bbb503 docs: record dashboard api-lane PostgreSQL contention as a suite-infrastructure flake pattern
Three consecutive full-lane runs on the same tree each failed a DIFFERENT file,
every one passing in isolation, with hook timeouts arriving alongside PostgreSQL
'Failed query' warnings from two api lanes sharing one database. That is the same
class FN-9131 investigated for core's loaded PostgreSQL directory.

Deliberately not quarantined: quarantine is file-level and the failing file moves,
so it would evict healthy coverage without touching the cause. Recorded with the
evidence so the next person does not re-derive it, and so the rescue is aimed at
the lane runner's connection/concurrency budget rather than at whichever test lost
the race that run.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 18:45:31 -07:00
gsxdsm
cc19584cc4 test: stop the quality-runner self-tests from re-entering the suite
These cases live in the `api:curated` lane and spawned `pnpm --filter
@fusion/dashboard test` — the very command whose lanes they were running inside.
Under a full 15-lane run that child had to resolve pnpm through Corepack while
other lanes held the machine, and it intermittently produced nothing at all: the
lane log came back empty, the assertion read "0 lanes launched", and a test about
the orchestrator failed with no orchestrator defect involved. Seen in both
`--all --no-fail-fast` runs today; the file passed alone every time.

An earlier attempt only set COREPACK_ENABLE_DOWNLOAD_PROMPT=0, which removed the
visible Corepack line but not the failure — the child still produced no output.
That fix is replaced rather than kept.

They now invoke `node scripts/run-quality-tests.mjs` directly. Every assertion is
unchanged (lane names, the 15-lane count, fail-fast labelling, `--` passthrough,
which parseArgs already unit-tests), and the one thing the pnpm spawn uniquely
proved — that the package script actually points at this orchestrator — is now
asserted directly against package.json.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 18:34:39 -07:00
Fusion Agent
cb16f418c7 FN-183: ensure local integration branch readiness
Guarantee projects have a usable local integration branch ref across creation, import, and merge workflows.

- Add shared integration-branch readiness and repository initialization helpers.
- Wire project registration, CLI commands, central storage, and merge execution to establish the ref.
- Document the behavior and cover CLI, dashboard, core, and engine integration paths.

Files changed:
 .changeset/fn-183-integration-branch-readiness.md  |   7 +
 docs/architecture.md                               |   2 +-
 docs/cli-reference.md                              |   4 +-
 docs/getting-started.md                            |   2 +-
 docs/settings-reference.md                         |   2 +-
 .../auto-git-init-project-registration.md          |  21 +++
 docs/workspaces.md                                 |   2 +-
 packages/cli/src/commands/__tests__/init.test.ts   |  70 +++++--
 .../cli/src/commands/__tests__/project.test.ts     |  22 +++
 packages/cli/src/commands/init.ts                  |  26 ++-
 packages/cli/src/commands/project.ts               |  20 ++
 packages/core/src/__tests__/git-repository.test.ts | 190 +++++++++++++++++++
 .../__tests__/integration-branch-readiness.test.ts |  94 ++++++++++
 packages/core/src/central/central-core.ts          |  65 +++++--
 packages/core/src/git/git-repository.ts            | 112 ++++++++++--
 .../core/src/git/integration-branch-readiness.ts   | 201 +++++++++++++++++++++
 packages/core/src/index.gate.ts                    |  14 ++
 packages/core/src/index.ts                         |  14 ++
 packages/core/src/merge/task-merge.ts              |   2 +-
 .../register-project-git-readiness.test.ts         | 132 +++++++++++++-
 .../src/routes/register-project-routes.ts          |  31 +++-
 .../src/__tests__/integration-branch.test.ts       | 135 ++++++++++++++
 packages/engine/src/__tests__/merger-ai.test.ts    |  21 +++
 packages/engine/src/merge/integration-branch.ts    | 127 ++++++++++++-
 packages/engine/src/merge/merger-ai.ts             |  25 ++-
 25 files changed, 1273 insertions(+), 68 deletions(-)

Fusion-Task-Id: FN-183
Fusion-Task-Lineage: ee63d45a-3406-4064-b16f-a2fe6dc0ad86
Co-authored-by: Fusion <noreply@runfusion.ai>
2026-08-24 01:20:23 +00:00
gsxdsm
5378bca7f6 test: fix the dashboard quality runner's self-spawning tests
Running the dashboard's REAL test command (`run-quality-tests.mjs`, which shards
into 15 lanes) surfaced two failures that a plain `vitest run` never shows —
worth noting on its own, since measuring around a package's own command is how
a suite gets called green on a number the project does not produce.

`scripts/__tests__/run-quality-tests.test.ts` spawns the package's own
`pnpm --filter @fusion/dashboard test` to prove the package-command wiring. Inside
a full lane run that child inherited a Corepack environment that stopped to ask
about downloading pnpm, so it never launched, the lane log came back empty, and
the assertion read 0 launched projects. It passed in isolation only because that
shell had already resolved pnpm. Both spawn sites now set
COREPACK_ENABLE_DOWNLOAD_PROMPT=0; nothing about the assertions changed.

Also records PlanningModeModal.planning-flow as a suite-only flake rather than
forcing it green: it fails only in lane `app:backfill-3` under four concurrent
6GB shards, passes 83/83 in isolation, and picked a DIFFERENT case on each of two
runs — a render-settle timing problem, not a product defect. Recorded as a first
sighting; a repeat of the same case is an on-sight quarantine.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 18:03:38 -07:00
gsxdsm
097fa9b403 fix(i18n): route the last hardcoded dashboard copy through the catalog
`i18n-lint-baseline` was failing on eight hardcoded strings that shipped without
catalog entries: TaskDetailModal's AI-merge-review reconciliation section (title,
candidate label, dismiss action, terminal guidance) and ArtifactImageViewer's
open-task, close, loading and retry controls. ArtifactImageViewer had no
`useTranslation` at all.

Keys are authored in `en` and present-but-empty in the six machine-drafted
locales, matching the convention already used there (parity requires the key,
and an empty value falls back).

Note on the pt-BR diff size: that file carried a DUPLICATE `globalModels`
section, so re-serializing collapsed it. Verified across all seven locales that
this changed no values and removed no keys - only the nine new ones were added.
The shadowed copy was already dead at runtime, since JSON parsing keeps the last
duplicate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 17:49:01 -07:00
gsxdsm
64cb17c100 FN-9204: advertise a valid memory MCP server version
Make the built-in memory MCP server complete the SDK-validated initialize handshake.

- Include a non-empty version in fusion-memory serverInfo responses.
- Cover the real SDK handshake, malformed-response skip path, and JSON-RPC envelopes.
- Document the protocol requirement and add a patch changeset.

Files changed:
 .changeset/fn-9204-memory-mcp-handshake.md         |   7 ++
 docs/mcp.md                                        |   2 +
 .../__tests__/mcp-memory-server-spawn.test.ts      |   5 +-
 .../mcp/__tests__/memory-mcp-handler.test.ts       |   7 +-
 packages/core/src/memory/mcp/memory-mcp-handler.ts |   8 +-
 .../src/__tests__/mcp-memory-handshake.test.ts     | 120 +++++++++++++++++++++
 6 files changed, 146 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-9204

Fusion-Task-Lineage: 0f68bdd5-56fe-4fdb-867f-2a5e0ea4de65

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-23 17:17:08 -07:00
gsxdsm
28a0ebc382 docs: index three Stash memory backend docs orphaned by #3494
Add memory-backend-integration.md to Architecture & Development (plus its
missing docs-index back-link) and performance/spawn-storm-attribution.md
and research/stash-vector-search-evaluation.md to Audit Reports. All three
were added by 8fcf4bdbaa without README index entries; test:docs-index
passes and the CLI Printing Press invariant remains 2 (Audit Reports).
2026-08-23 17:17:07 -07:00
gsxdsm
c82e420ba0 fix: repair the dashboard suite and the regressions it was pointing at
Dashboard 441 failures -> 0 across 65 files, worked by three agents. As in the
engine, core and CLI sweeps, the failures were mostly pointing at real
regressions and at behavior changes whose tests were never updated.

Two behavior changes account for the bulk of it. FN-054 made Chat list-first
(the transcript and composer render only inside an explicitly opened
conversation) and FN-9193 docked the conversation list beside the thread, which
deliberately removes the in-thread Back button. Between them they updated about
a dozen of their own tests and left roughly twenty suites asserting the old
navigation - the standing rule this session added, at scale.

The single largest file was not a navigation problem at all: useChat.test.ts's
80 failures were ONE unawaited async act. `stopStreaming()` returns a durable
cancellation promise, and two cases used a concise arrow, so React opened an
async act scope nobody awaited; the queue stayed installed and all 78 later
tests in the file saw a frozen hook. A sibling case already had the corrected
form.

Product defects found and fixed:
- register-chat-routes: FN-047 dropped the null-project branch from the send
  path, so with no project selected a send began generation on a different
  ChatManager than /cancel and /stream resolve - cancel was a silent no-op.
- ChatView: an imported GitHub link was seeded into a composer that was never
  opened, so the operator landed on the conversation list with their link
  nowhere on screen; and the thread anchor effect bailed on a missing container
  WITHOUT recording state, so a conversation never anchored on open and the next
  message growth force-anchored, yanking a reader who had scrolled up.
- NewTaskModal: an unguarded `.length` on an absent `repos` payload threw during
  render and blanked the whole modal.
- styles.css: FN-9202's shared `.banner--chrome` referenced `--z-sticky`, which
  nothing defined, silently resolving sticky banners' z-index to `auto`.
- The OrcaRouter startup-sync toggle shipped with no i18n catalog entry.

The register-model-routes family - 55 failures across 8 files - was one cause:
fake routers exposing only `get` after a `router.post("/models/refresh")`
registration was added, so every file died at setup.

Also deletes Column.drop-prompt-flags-arrival.test.ts, whose drop surface FN-051
removed, retargeting its late-arriving-flags invariant onto the surviving
context-menu move rather than dropping the coverage.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 17:07:31 -07:00
gsxdsm
d6c1e27709 test: delete comment-pinning assertions in engine and desktop
Part of the repo-wide census for the new "tests assert behavior, never source
text or comments" rule.

- merger-integration-worktree: deleted "keeps direct-reuse shortcut…", whose
  sole assertion pinned a `// …Skip acquireTaskWorktree's` comment in merger.ts.
- auto-heal-review-lane-callsite-audit: deleted "the DELIBERATE-LITERAL note
  still claims…", whose sole assertion pinned a comment sentence in
  project-engine.ts. That file's two real AST/call-site cases are untouched.
- electron-builder-config: deleted a pin on "intentionally deferred", which
  exists only inside YAML comments of desktop-windows.yml.

Each of these had a comment as its entire subject, so there was no behavior to
preserve — deleting the assertion is the complete fix.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 16:56:54 -07:00
gsxdsm
6fca424852 feat: ask for a GitHub star once onboarding finishes (#3516)
## What

After an operator **finishes** onboarding, Fusion asks once whether they
want to star the repo. If they dismiss it, nothing asks again — on any
surface.

## Why

Nothing asked at the right moment. The dashboard already had a
`GitHubStarPrompt` banner, but it only fired when a task first reached
*done*, so someone who completed setup and stopped there was never
asked. The CLI (`fn onboard`) had no ask at all.

## How

**CLI — `fn onboard`**
- The ask runs *after* the completion marker is stamped, so declining
(or Ctrl-C on the question) can never cost the operator the setup work
they just did.
- It prints `https://github.com/Runfusion/Fusion`; it never opens a
browser on their behalf.
- The non-interactive auto-launch path asks nothing — that flow fires
while someone is starting a dev server, and a prompt there is exactly
the ambush
[b67e3aa](b67e3aa8bc)
removed.

**Dashboard**
- `ModelOnboardingModal.onComplete` now reports an outcome, and
`useProjectActions` fires the star prompt only for a *finished*
onboarding. Dismissing the flow does not ask: closing it is the operator
saying to leave them alone.

**One ask per operator, not per surface**
- New global setting `githubStarPromptDismissedAt`. localStorage stays
the fast local record (suppresses the prompt without waiting on a
request); the setting is the durable, cross-surface one. Both surfaces
read and write it, so answering in either retires the ask in both, and a
CLI dismissal is honoured by a dashboard opened later. The settings
write is best-effort — losing it costs at most one repeat ask on another
browser, never a broken dismissal locally.

## Verification

- `pnpm test:gate` — green, 716 tests / 29 files
- CLI `onboard` + `onboard-autolaunch` — 37 passed (new cases: asks and
stamps on accept; never asks again after dismissal, including `--force`;
silent on the non-interactive path)
- Dashboard `useGitHubStarPrompt`, `useProjectActions`,
`DashboardBanners`, `AppModals` — 72 passed (new cases: dismissal
recorded globally; a dismissal from another surface adopted; no re-read
once the local record is set; local dismissal survives a failed settings
write; finished-vs-dismissed routing)
- Typechecks clean for `@fusion/core`, dashboard `tsconfig.app.json`,
`@runfusion/fusion`
- `pnpm lint` — 0 errors (2 pre-existing warnings)

Changeset included (`@runfusion/fusion`: minor).

🤖 Generated with [Claude Code](https://claude.com/claude-code)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
  * Added a one-time GitHub star prompt after onboarding.
* Supports accepting, dismissing, or cancelling the prompt, with
responses remembered across sessions and interfaces.
* Skips the prompt during non-interactive onboarding or after a previous
response.
* Dashboard onboarding now distinguishes completed and dismissed
outcomes.
* **Bug Fixes**
* Improved prompt synchronization and loading behavior to prevent
duplicate displays.
* Preserved successful onboarding when settings cannot be saved or
retrieved.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 16:56:40 -07:00
Phil Larson
00b7078f79 fix: preserve reclaimed worktree branch provenance (#3507)
## Summary

- persist engine branch-write provenance when reclaiming an existing
task worktree
- cover branch-conflict reclaim with a regression assertion for the
branch, worktree, and provenance tuple

## Test plan

- `pnpm --filter @fusion/engine exec vitest run
src/__tests__/executor-worktree.test.ts --silent=passed-only
--reporter=dot`
- `pnpm --filter @fusion/engine typecheck`
- `pnpm check:changesets -- --strict`
- `pnpm check:fnxc-future-dates`
- `pnpm build`


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
  * Improved recovery when reclaiming existing task worktrees.
* Preserved task branch details and worktree paths during
branch-conflict recovery.
* Recorded whether branch updates originated from the system or an
operator for more reliable task state tracking.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: gsxdsm <gsxdsm@users.noreply.github.com>
2026-08-23 16:53:38 -07:00
Phil Larson
c9f3f11a72 fix: allow worktree agents to read user skills (#3506)
## Summary

- allow worktree sessions to read the standard user skill root at
`~/.agents/skills`
- keep sibling `~/.agents` files and all write/edit/Bash access outside
the exception
- canonicalize existing path components so symlinks cannot escape an
allowed skill root
- document the boundary and add a patch changeset

This extends the same host-skill consistency fixed in #2384: Fusion
should not tell an agent to load a skill and then block the skill body.

## Test plan

- [x] 15 worktree-boundary tests
- [x] `pnpm --filter @fusion/engine typecheck`
- [x] scoped ESLint
- [x] changeset and FNXC date checks
- [x] `pnpm verify:fast` (20 steps, including build and boot smoke)
- [x] CLI CI-shape test (72 tests)

## Local gate notes

`pnpm test:gate` passed all static checks, 432 engine-core tests, and
184 core unit tests. Its PostgreSQL lane could not authenticate locally
(`empty password returned by client`). The full
`pi-create-fn-agent.test.ts` run also reaches an unrelated
dashboard-chat principal assertion failure already present at the exact
`origin/main` SHA; the 15 boundary tests pass.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Worktree agents can read and search skills installed in the standard
`~/.agents/skills` directory.

- **Bug Fixes**
- Preserved worktree protections for writing, editing, and Bash
operations.
- Blocked access to unrelated files and prevented symlink-based boundary
escapes across supported path operations.
  - Improved access validation for paths that do not yet exist.

- **Documentation**
- Updated worktree boundary documentation to describe skill access and
its restrictions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-23 16:53:10 -07:00
gsxdsm
12c292ea6b test: ban asserting comment text, and fix the prompt it was hiding
Tests must assert behavior, not source text. A test that pins an FNXC block, a
date stamp, or comment prose guards documentation — and AGENTS.md tells authors
to keep those comments current, so the two rules fight and the test loses in the
worst way.

Measured today: grok-runtime-bootstrap.test.ts asserted runTaskMerge's body
contained "FNXC:GrokCliRouting 2026-07-15-10:17". FN-9167 legitimately rewrote
that function and dropped the block while leaving behavior intact; the test went
red, and the fix applied earlier in this sweep was to RE-ADD THE COMMENT to
packages/cli/src/commands/task.ts. A comment returned to shipped source not
because it documented anything true, but to appease a test. Four more such
assertions sat in dashboard CSS tests, each beside a real assertion, each adding
nothing.

- Drops the two prose pins from grok-runtime-bootstrap; its real structural
  guard (`not.toContain("mergePluginRunner")`) stays. The product comment stays
  too — it is accurate documentation, it was simply never a test's business.
- Adds scripts/check-no-comment-assertions-in-tests.mjs, wired into pretest,
  pretest:full, and test:gate:static. It flags the unambiguous case; an earlier
  draft that also matched `/*` produced 24 false positives and zero true ones,
  because a regex cannot separate comment prose from a path glob.
- Adds the standing rule to AGENTS.md, with an explicit boundary: prose,
  comments, and date stamps are never a test subject, while code-construct and
  call-site-allowlist guards (no-blocking-shellout, vi-mock resolution, durable
  write and emit-surface inventories, legacy tombstones) are a different
  category and stay.

Also carries a product fix that the agent-generation tests surfaced: the
system prompt exists in two copies, and `resolvePrompt` returns core's catalog
default, so FN-021 adding the xhigh/max thinking levels to the dashboard copy
alone left every real generation run advertising levels that stop at "high".
Core's copy is synced and both literals now say they must move together.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 16:48:56 -07:00
gsxdsm
0d11f8dbdf FN-9203: Prevent mailbox tab icons from shrinking on mobile
Keep mailbox icons and badges legible across mobile tab and sub-tab surfaces.

- Pin mailbox tab icons and badges against flex shrinking while truncating labels safely.
- Cover mailbox view, modal, and agent detail tab sizing with computed-style regressions.
- Add a patch changeset for the mobile mailbox icon fix.

Files changed:
 .changeset/fn-9203-mailbox-tab-icon.md             |  7 ++++
 packages/dashboard/app/components/MailboxModal.css | 21 ++++++++++
 .../__tests__/AgentDetailView.core.test.tsx        | 24 ++++++++---
 .../app/components/__tests__/MailboxModal.test.tsx | 32 ++++++++++++---
 .../app/components/__tests__/MailboxView.test.tsx  | 48 +++++++++++++++-------
 5 files changed, 107 insertions(+), 25 deletions(-)

Fusion-Task-Id: FN-9203
Fusion-Task-Lineage: f0bef8cb-0194-4661-aba6-8cc19f567c40
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-23 16:47:22 -07:00
ischindl
8fcf4bdbaa feat: Stash memory backend — session capture, per-chat backfill, opt-in vector search (#3494)
## Summary

Adds the **Stash memory backend** (`memory.backendType=stash`) that
connects Fusion's agent memory to the
[Stash](https://github.com/Fergana-Labs/stash) product — *knowledge
bases for the agent era* ([product site:
joinstash.ai](https://joinstash.ai)). Fusion becomes a first-class Stash
client: complete chat sessions and finished tasks are captured into
Stash, memory is recalled during chat, and Stash sessions are kept in
sync with the dashboard (including deletes and archival).

**Product:** <https://github.com/Fergana-Labs/stash> ·
[joinstash.ai](https://joinstash.ai)

## What's included

### 1. Stash memory backend (RUFU-068 / RUFU-121)
- New `StashMemoryBackend` (`memory.backendType=stash`) with `stashUrl`
/ `stashApiKey` settings (global secrets-store `stash-api-key` +
per-project override).
- **Complete-chat-session capture** keyed by ChatSession id.
- Sessions are classified into **per-project folders** (get-or-create,
`external_key fusion-<projectId>`, 1h per-process cache) and
**soft-deleted with their chat** via `DELETE /api/chat/sessions/:id`.
- Per-conversation **memory-focus** read-time scoping (new
`0066_chat_session_memory_focus.sql` migration — sequence renumbered
0059→0060→0061→0065→0066 as origin/main claimed the lower numbers);
event metadata enriched with `project` / `project_name` / `chat_title`.
- Recall queries normalized to single-keyword / explicit-OR ASCII (≤100
chars); shared normalizer export reused by per-turn recall.

### 2. Per-task executor transcript capture (RUFU-122)
Finished or failed tasks upload their executor transcript
(`agent-log.jsonl`) to Stash as a task session.

### 3. Bulk archive Stash sync (RUFU-125)
Archived task-planner chats soft-delete their Stash sessions on bulk
archival (paged). The snapshot of doomed session ids is taken *before*
the local bulk delete, and the Stash sync runs fire-and-forget so a
Stash stall can never delay local archival.

### 4. Per-chat "Preserve to Stash" backfill (RUFU-136)
A per-chat action that backfills a chat's full history into Stash, with
client-side idempotency and a pre-check that skips already-uploaded
content (fail-closed, no duplicate upload on transport failure).
- **Session-folder naming fix:** the first project folder is now named
"Fusion — &lt;project name&gt;" instead of the bare "Fusion" fallback
(the backfill now resolves the central-registry project name,
best-effort, never blocking the upload).

### 5. Opt-in semantic (vector) recall (RUFU-126)
`stashVectorSearch` setting (default `false` — **zero behavior change
until enabled**). For multi-word queries the backend tries Stash's
semantic-search endpoint first, then falls back byte-identically to the
keyword path. Definitive 404/405/501/503 responses are negatively cached
per process. Requires a patched Stash server (new endpoint +
`sentence-transformers` + embedding backfill); unpatched servers are
transparently bypassed after the first 404.

## Safety
- **Opt-in / inert by default:** the default backend remains `qmd`; the
Stash backend is inert until `memoryBackendType=stash` + `stashUrl` are
set.
- All Stash I/O is **best-effort, fail-closed, and non-blocking** — a
Stash outage never blocks chat, task completion, or archival. No
run-audit content is emitted.

## Testing
- Backfill + delete-sync suites (20/20), Stash backend suite (68/68),
executor memory / session capture suites, `memory-focus-recalling`,
description-guard — all green.
- `tsc` clean across core / engine / dashboard.
- Live verification: bulk backfill of 21/24 chats completed; the
"Preserve to Stash" action is idempotent on re-run.

## Changesets
- `@runfusion/fusion` **minor** — Stash memory backend + capture
(RUFU-068/121), per-task transcript (RUFU-122), bulk archive sync
(RUFU-125), per-chat backfill (RUFU-136), opt-in vector search
(RUFU-126)
- `@runfusion/fusion` **patch** — backfill session-folder naming fix


## Rebase Note (2026-08-23)

Rebased onto `origin/main` `3f448f7292` (v0.77.0-beta.7). Conflicts
resolved additively:
- `packages/core/src/postgres/schema-applier.ts` + test — upstream's
0062-0065 migrations (task/subtask splitting removal, AI merge review
reconciliation, task repository scope, FN-149 review convergence)
unioned with this PR's `chat_sessions.memory_focus` migration, which is
**renumbered 0065 → 0066** (upstream's FN-149 shipped 0065 canonically
on origin/main); `SCHEMA_BASELINE_VERSION` advances to `0066`.
- `packages/dashboard/app/components/ChatView.tsx` — upstream's docked
chat sidebar resize handlers unioned with the RUFU-136 "Preserve to
Stash" backfill handler.
- New commit: `settings.memory.*` stash-backend i18n keys added to all 6
secondary locales (RUFU-121/122 parity fix; `pnpm i18n:status` no longer
reports any violation introduced by this PR).

**Deploy note (operator environments that already ran a pre-rebase build
of this PR):** the memory-focus SQL may already be in the schema under
ledger row `0065`. Remap that row to `0066` (`UPDATE
fusion_schema_migrations SET version = '0066' WHERE version = '0065';`)
*before* first boot of a 0066-ceiling binary — otherwise the fresh
upstream `0065_fn_149_review_convergence_stage.sql` would be skipped as
"already applied". Clean databases (no prior memory-focus row) need no
action.

**CI note — Lint (lifecycle-column census) is red on the merge base:**
`pnpm check:lifecycle-columns --strict` fails identically on pure
`origin/main` `3f448f7292` with
`packages/core/src/db/legacy-adoption.ts: 0 -> 3` (3 column guards in
the U9b legacy-adoption table without a baseline entry or
`DELIBERATE-LITERAL` marker). Verified by running the census on a clean
origin/main checkout — inherited from the base, not introduced by this
PR. Fix belongs upstream; tracked separately.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added Stash memory integration with project configuration and optional
semantic search.
  * Added per-chat memory focus controls and a `/focus` command.
  * Added “Preserve to Stash” for uploading complete chat history.
  * Added automatic chat, task transcript, and completion-event capture.
* Added project-specific Stash session folders and archive/delete
synchronization.
* **Bug Fixes**
* Improved Stash folder naming and handling of missing branches during
no-commit tasks.
* **Documentation**
* Added setup, configuration, integration, vector-search, and
performance guidance.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Fusion <noreply@runfusion.ai>
Co-authored-by: gsxdsm <gsxdsm@users.noreply.github.com>
2026-08-23 16:46:14 -07:00
Phil Larson
1b09c39e4b test(dashboard): align room fixtures with docked sidebar (#3511)
## Summary
- detect an open conversation by its composer instead of the mobile-only
back button
- assert the persistent desktop sidebar and mobile back-navigation
contracts separately
- keep the active-header New Chat expectation aligned with shipped
behavior

## Test plan
- `FUSION_DASHBOARD_DEEP=1 pnpm --filter @fusion/dashboard exec vitest
run --silent=passed-only --reporter=dot
app/components/__tests__/ChatView.ios-keyboard.test.tsx
app/components/__tests__/ChatView.mobile.test.tsx
app/components/__tests__/ChatView.rooms.test.tsx
app/components/__tests__/ChatView.title-switcher.test.tsx
app/components/__tests__/ChatView.docked-sidebar.test.tsx
app/components/__tests__/ChatView.sessions-rooms.test.tsx`
- `pnpm --filter @fusion/dashboard typecheck`
- `pnpm exec eslint
packages/dashboard/app/components/__tests__/ChatView.rooms.test.tsx`
- `node scripts/check-changeset-format.mjs --strict`

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Tests**
- Expanded coverage for navigating between chat lists and conversation
details.
- Verified selecting a different room updates the active room and
conversation header.
  - Added responsive checks for desktop and mobile layouts.
  - Verified support for both room chats and direct conversations.
  - Confirmed mobile users see **New Chat** in the active header.
- Confirmed desktop navigation presents list and detail views without an
unnecessary back button.
  - Improved viewport isolation and cleanup between responsive tests.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-23 16:45:49 -07:00
Phil Larson
87e7369575 fix(i18n): restore JIRA settings locale parity (#3503)
## Summary
- restore the 21 JIRA settings keys in all six secondary app catalogs
- return the workspace i18n parity gate to green
- add patch release metadata

## Test Plan
- `pnpm i18n:status`
- `pnpm check:changesets`
- `pnpm --filter @fusion/dashboard build`


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Localization**
* Added Jira settings translation coverage for Spanish, French, Korean,
Brazilian Portuguese, Simplified Chinese, and Traditional Chinese.
* Standardized availability of Jira configuration labels across
supported dashboard locales, including URLs, credentials, scopes, and
issue templates.
* **Documentation**
  * Added release metadata for the localization update.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: gsxdsm <gsxdsm@users.noreply.github.com>
2026-08-23 16:45:30 -07:00