71b09e677dbd4a204409830e8a8def8651af01ec
2923 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7e537989dc |
Merge remote-tracking branch 'origin/main'
# Conflicts: # packages/core/src/__tests__/settings-defaults.test.ts # packages/dashboard/app/components/ChatView.tsx |
||
|
|
cdef6ad7e8 |
fix(core): select the stale no-op merge case by its condition, not by a sentence
`merge-confirmed-finalize` carves out one case: a no-op merge confirmation with no landed commit is not proof the work was done, so when the steps are still unfinished the run must fall through to stale-merge cleanup and reverification instead of being consumed there. It selected that case by comparing the blocker reason with `===` against the exact string "task has incomplete steps". The merge-authority work then made refusals more informative, so a card in an error state reports `task is marked 'failed': … task has incomplete steps`. Same meaning, different sentence — and the comparison stopped matching, silently. A filter pinned to "subject is exactly Invoice" once invoices began arriving as "Invoice — March 2026". Nothing in the merge gate said so, because the test guarding this case lives in a file the gate does not run. It has been red on main since that lane landed. `hasNonTerminalSteps` states the rule the message describes and is defined from the same `NON_TERMINAL_STEP_STATUSES` set as `getTaskMergeBlocker`, so the two cannot drift. A blocker message is written for an operator and will be reworded again; the condition underneath it is what callers actually mean. The new core test pins them apart deliberately: it asserts the sentences DIFFER between a plain card and a failed one while the rule answers the same, and that the rule agrees with the door for every step status. A future prefix cannot re-break this quietly. pnpm lint 0 errors, test:gate green, core + engine typecheck clean, pipeline-smoke 93/93, ce-workflow-step-executor 53/53 (was 52/53 on main). |
||
|
|
b956a7c8eb |
fix(core): repair a renumbered migration whose ledger row outlived its column
Reported from a dev instance: `column "memory_focus" does not exist` on every chat-session read, so the task planner chat 500s and never opens — with a startup that reports success. A ledger row asserts "a migration with this NUMBER ran". That is not the same claim as "this COLUMN exists" once a migration has been renumbered, and this one was renumbered four times — 0059 -> 0060 -> 0061 -> 0065 -> 0066 — each time because an upstream batch claimed the sequence first. A database can therefore carry a row from one numbering while a different migration owned that number on the boot that recorded it. The applier trusts the ledger absolutely, skips the migration, and leaves a schema that does not match it. Nothing fails at startup; everything fails afterwards, because Drizzle's `select()` emits the binary's full column list and one missing column breaks every read of the table. The defence already existed one table over: `0047` task recommendations verifies its materialized column in addition to the marker and replays its idempotent SQL. The lesson had been learned and not generalized. Both migrations renumbered on this branch — 0066 memory focus and 0067 session contention wait state — now carry it, and both SQL files are `ADD COLUMN IF NOT EXISTS`, so a replay over a healthy schema costs nothing. Two PostgreSQL regression tests reproduce the drifted state exactly (marker present, column dropped) and prove the replay materializes the column and stays idempotent on a second pass. pnpm lint 0 errors, test:gate green, core typecheck clean, schema-applier 80/80 against a real PostgreSQL. |
||
|
|
1c26a4bf4b |
fix(dashboard): report the cause of a failed query, not the statement that failed
Reported from a task chat: a screenful of column names from `project.chat_sessions` and nothing about what broke. That message is, by construction, the useless half. Drizzle wraps a query failure in an error whose message is `Failed query: <the whole statement> params: …` and puts the real PostgresError — `column "x" does not exist`, `permission denied`, `connection terminated` — in `cause`. `rethrowAsApiError` read `error.message` alone, so the reason was dropped before it ever reached the operator. `startup-factory` already carried a private chain walker because field reports of exactly this shape were undiagnosable; the dashboard never got one. The walker is now shared (`describeErrorChain` for logs, `summarizeErrorForOperator` for operator surfaces). The inversion is keyed narrowly on the `Failed query:` wrapper, never on guessing which message reads better: an application-authored message is deliberate prose and still leads, so the API boundary contract and its 29 tests are unchanged. Only the machine-generated frame is demoted to truncated context behind its cause. This does not fix the underlying query failure — it makes it reportable. The next occurrence will name the column or condition that failed instead of the statement that contained it. pnpm lint 0 errors, test:gate green, core + dashboard typecheck clean, 7 new tests. |
||
|
|
9a54fe362d |
fix(FN-WF): give the Documentation milestone a way to actually persist anything
It had no writer, and its prompt did not know that.
A workflow step running `toolMode: "readonly"` is limited to read/grep/find/ls, fn_web_fetch
and a few read-only task reads; `fn_task_create` is explicitly DENIED there. The prompt asked
for four tool calls — fn_task_done(summary=…), fn_task_document_write, fn_artifact_register,
and creating follow-up tasks. It could make none of them. Every run produced a well-formed
report and persisted NOTHING. And because this milestone replaced `completion-summary`, which
used the working contract, cards quietly lost their agent-authored summary and fell back to
the deterministic backfill.
This is the same failure the reviewer prompt was fixed for — a session instructed to do what
its tool policy forbids — on a node nobody re-checked.
Both durable outputs now travel by PROJECTION, the only channel a writer-less node has.
`summaryTarget: "task"` persists its prose as the card summary. New
`recommendationsTarget: "task"` reads a trailing {"recommendations":[…]} payload, normalizes
it through the SAME rules the store boundary enforces (relocated to
tasks/recommendation-validation.ts so a second producer cannot drift from a copied regex),
and projects it to task.recommendations — the Recommendations tab, where an OPERATOR turns a
proposal into a task. An in-review agent proposes; it never creates board rows. Normalization
drops bad entries rather than throwing: a stray character in a suggestion must not wedge a
card whose code is already approved.
`summaryTarget` also removes this node's verdict requirement, so a reporter can no longer emit
the REVISE that held the merge door and bounced the card with nothing to do.
The guard that should have caught all of this asserted a PROMPT STRING —
`prompt.includes("fn_task_done(summary=")` — as proof a summary gets written. It was green
throughout. It now asserts the projection contract, including inside optional-group templates,
because the executing node of a group is its template child.
pnpm lint 0 errors, test:gate green, core + engine typecheck clean, pipeline-smoke 90/90.
|
||
|
|
56ee1622df |
fix(FN-WF): make Documentation a reporter, and refuse every bounce with no work
Observed on a live card (mult-021), where the log tells the whole story: Documentation returned an advisory REVISE asking for implementation work, the card was "moved back to in-progress for remediation", and 467ms later Code Review started again. No step was ever created, no executor session ran, and the demand was never implemented — the card merged when the second Documentation pass happened to pass. Two separate defects produced that. FIRST, the reporter could hold the merge. An advisory REVISE records `advisory_failure`, and `resolveRequiredPreMergeStepIds` included the Documentation group, so `evaluatePreMergeApprovals` read it as "not-approved". `gateMode: "advisory"` only stops the node blocking traversal; it says nothing to the merge door. SECOND, the reporter could bounce. `requestPreMergeOptionalStepFix` accepts `advisory_failure`, and under this workflow's named-remediation policy the resulting `sendTaskBackForFix` reopens NOTHING. With no pending step the foreach answered `already-expanded` and the walk replayed the review lane over an unchanged tree. The budget was 1/10, so it could have burned ten rounds of two model calls each. New opt-in `reportingOnly` on an optional group states the contract once — no approval to withhold, no remediation to request — and both doors read it. It is set only on Documentation, so advisory gates that DO own remediation (browser verification) keep their behaviour exactly. Plus the general invariant that would have caught both: under `stepReopenPolicy: "none"`, a bounce that appended no named steps is refused and logged on the card. Only the gates that can APPEND work may send a card back. Code Review REVISE and the deterministic verification failure still produce named fix steps — unchanged, still covered. pnpm lint 0 errors, test:gate green, core + engine typecheck clean, pipeline-smoke 90/90. |
||
|
|
8328b458b0 |
fix(FN-WF): prove fix steps reach the card, and clear the V2 rework's leftovers
FIX STEPS, asserted on `task.steps` rather than on a spy. A failing FINAL verification and a Code Review REVISE each append pending named steps carrying their gate provenance, and the card is re-dispatched to run them; completed implementation steps stay done, because remediation appends and never reopens. A review failure with NO REVISE verdict appends nothing — a transport error must not manufacture work. And no node id other than those two gates can reach the appender, which is what keeps a red test INSIDE a step the step's own problem: the executor fixes it there instead of littering the checklist. The new tests drive the real routing seam and the real appender against the real built-in registry — an injected IR is resolved away by workflow id and would have proved nothing. CATALOG. `builtin-workflows-lifecycle.test.ts` never received an EXPECTATIONS entry when V2 was registered, so its catalog-coverage assertion has been red on main since. The merge gate does not run that file, which is why it survived. Its trail is identical to builtin:coding-ideas by design: a read-only review lane changes what happens inside the working columns, not where the card goes. REGISTRY. The description still advertised "verify … summarize", steps that no longer exist, and the layout still positioned four deleted nodes plus drew Documentation to the LEFT of Code Review — so the editor rendered the review lane backwards against its own edges. Both now match the graph. AUDIT. `implementation-only-leakage` no longer flags `testing|verification`. That regex belonged to the revision where a review gate ran the tests; testing came back to the executor, so the planner emits that step on purpose and every V2 card was reporting leakage against its own intended plan. Documentation and delivery are still flagged. pnpm lint 0 errors, test:gate green, core + engine typecheck clean, 227 tests across the touched files. |
||
|
|
3cfb5119ea |
fix(FN-WF): stop V2 planning a Documentation step it already runs in review
Documentation is not a task step on this workflow.
Restoring the default planning prompt to bring `Testing & Verification` back also
restored `### Step {N}: Documentation & Delivery`, because the abandoned
`planning-implementation-only` seam stripped both in ONE anchored block, from the testing
heading to `## Documentation Requirements`. Nobody chose that; it was collateral.
The result was the same work done twice. The executor's step saved a delivery note,
registered artifacts and created follow-up tasks; the in-review Documentation milestone
then did the identical three tool calls again. Both wrote task document `docs`, so the
review pass silently overwrote the executor's.
`stripDocumentationDeliveryStep` removes ONLY the documentation block and deliberately
keeps `Testing & Verification`, which the executor owns and must keep planning. It is
applied to V2's own copy of the planning prompt, so `builtin:coding` and
`builtin:coding-ideas` keep the shared template byte-identical. If the base prompt is
reworded and the anchors stop matching, the strip degrades to an appended prohibition
rather than breaking planning at runtime.
Repository documentation survives as implementation work: the executor updates a doc its
own change made wrong, inside the step that made it, so Code Review sees it in the same
diff it approves. Whether a change warrants that is the executor's judgement, not a stage.
pnpm lint 0 errors, test:gate green, core typecheck clean, 2 new tests plus a shared-template
non-regression assertion.
|
||
|
|
b723c35fc9 |
feat(FN-WF): give testing back to the executor and the plan
Testing belongs to whoever can actually run it. That is the executor.
RESTORED — the planner emits "Testing & Verification" again. An earlier revision in
this series routed V2 planning through `planning-implementation-only`, whose contract
STRIPS that step region and replaces it with "Do NOT emit a Testing & Verification
step", on the theory that a review-column gate would run the checks instead.
Nothing ever did. The deterministic gate was not routed by its node kind and reported
PASS in ~46ms without executing anything; and once that was fixed, a review node runs
`toolMode: "readonly"`, where `bash` is denied and `fn_run_verification` is not in the
allowlist — so a reviewer cannot run lint, tests or build no matter what its prompt
says. Measured on real cards: 19s and 23s "reviews" that silently read the diff alone,
and a plan bounced for "implementation steps include testing and verification work
that must be handled as review-column gates" AFTER the gate it named was deleted. The
planner was forbidden from planning tests while nothing else ran them.
What was stripped is the mature contract: real automated tests only ("typechecks and
builds are NOT tests"), per-step test authoring, a final lint/tests/typecheck/build
pass ordered before delivery, an explicit duty to update tests that encode behaviour
the task changes, and standing up a test framework when the project has none. Plan
Review no longer rejects a plan for containing any of it.
CHANGED — Code Review judges the TESTS rather than claiming to run them. It rules on
four things: they exist for the behaviour that changed; they are real runner-executed
assertions; they assert BEHAVIOUR and never a comment or date stamp; and they cover
the invariant, not only the reported repro. Then it reviews the code for what tests
miss. Telling a session to do what its tool policy forbids invites the one failure
worse than a missing check — a fluent claim that the check passed.
DELETED — `builtin:review-gated-coding`, rather than left deprecated. It SHARED the
documentation-delivery node with V2, so every change made for V2 silently changed a
second workflow nobody was maintaining. Its own success path could never complete
anyway (`workspace-review-seal-required`).
Tests updated to the reversals they now describe, each naming the measurement that
reversed it. Deleting the workflow also cleared a pre-existing remediation-loop
failure.
pnpm lint 0 errors, test:gate, verify:fast, engine-pipeline-smoke 90/90, and three
consecutive full runs: 142.7s, 140.9s, 135.2s of the 175s budget.
|
||
|
|
8b64b88bfd |
feat(FN-WF): make the V2 review lane Code Review -> Documentation -> merge
One gate that can hold a card, one milestone that reports, then the merge.
REMOVED — the separate deterministic `verification` group. It duplicated the
executor's own verification, it showed a green badge on projects that had
configured no command, and it split merge evidence across two authorities that
could disagree. Code Review now runs lint/test/build itself, so exit codes still
decide and a single node owns the verdict. Its prompt is APPENDED to rather than
edited, leaving the shared reviewer used by builtin:coding and
builtin:coding-ideas exactly as it was.
The evidence rule is the point: the reviewer must quote each command with its exit
code and output tail, and a verdict with no execution evidence is invalid. A
reviewer free to assert "tests pass" in prose reproduces the false green a silently
passing gate produced mechanically — and the fluent version is harder to spot.
Absent commands are reported, never treated as failure: a project that never
configured verification has never been refused a merge on that basis.
REMOVED — `completion-summary` as its own milestone. Documentation writes the card
summary in the same pass as the delivery note. One model call, not two.
CHANGED — Documentation now runs AFTER the review, which is the ordering its own
author intended ("runs after passing verification and code review") and which the
review seal previously forbade. It is legal because it no longer writes the
repository: it is advisory, read-only, and records a Fusion-side delivery note,
artifacts, follow-ups and the summary. Repository documentation belongs to the
executor during implementation — a docs change is a code change, and writing it
after approval put it outside the diff the reviewer signed off.
It also cannot veto any more. As a blocking gate it bounced a task whose own plan
forbade implementing anything, and that card looped through the review lane every
five minutes indefinitely.
The seal invariant got STRONGER, not weaker: no node other than the reviewer itself
writes anywhere in the review lane, so nothing can change after an approval. The
test asserts exactly that, and names the reviewer exclusion rather than filtering it
away silently.
pnpm lint 0 errors, test:gate, verify:fast, engine-pipeline-smoke 90/90, and three
consecutive full runs: 137.4s, 141.0s, 144.6s of the 175s budget. The 3 remaining
core failures are pre-existing and reproduce without this diff.
|
||
|
|
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. |
||
|
|
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. |
||
|
|
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.
|
||
|
|
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.
|
||
|
|
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.
|
||
|
|
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.
|
||
|
|
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`. |
||
|
|
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. |
||
|
|
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.
|
||
|
|
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.
|
||
|
|
68c466a6ab |
FN-9209: Gate chat focus behind an experimental flag
Make per-conversation chat memory focus opt-in while preserving stored focus values for compatibility. - Add the chatFocus experimental setting, exports, documentation, and release changeset. - Hide and disable focus controls and commands across chat and task-planner composers when the flag is off. - Apply persisted focus scopes to memory recall only when enabled, with regression coverage for both flag states. Files changed: .changeset/fn-9209-chat-focus-experimental-flag.md | 7 ++ docs/memory-backend-integration.md | 6 +- docs/settings-reference.md | 3 +- .../core/src/__tests__/settings-defaults.test.ts | 9 +- packages/core/src/config/experimental-features.ts | 7 ++ packages/core/src/index.gate.ts | 2 +- packages/core/src/index.ts | 2 +- packages/core/src/types.ts | 7 ++ packages/dashboard/app/components/ChatView.tsx | 37 ++++--- .../dashboard/app/components/SettingsModal.tsx | 1 + .../app/components/TaskPlannerChatTab.tsx | 62 ++++++++--- .../__tests__/ChatView.chat-focus-flag.test.tsx | 122 +++++++++++++++++++++ .../__tests__/ChatView.focus-chip.test.tsx | 2 +- .../TaskPlannerChatTab.chat-focus-flag.test.tsx | 108 ++++++++++++++++++ .../__tests__/TaskPlannerChatTab.test.tsx | 5 +- .../app/components/__tests__/chat-commands.test.ts | 7 +- .../app/components/__tests__/focus-command.test.ts | 13 ++- packages/dashboard/app/components/chat-commands.ts | 11 ++ .../chat-memory-focus-reachability.test.ts | 16 ++- packages/dashboard/src/chat.ts | 30 ++--- 20 files changed, 394 insertions(+), 63 deletions(-) Fusion-Task-Id: FN-9209 Fusion-Task-Lineage: d58296be-a5f9-4b8c-bf4a-03f7f9100efe Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
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 |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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 [ |
||
|
|
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>
|
||
|
|
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 — <project name>" 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> |
||
|
|
38edc2366b |
fix(core): restore executor workflow creation guidance (#3513)
## Summary - restore explicit executor guidance for assigning workflows to tasks the agent creates - keep the existing prohibition on rerouting the task currently being executed - restore parity between both built-in executor prompt variants and their regression test ## Test plan - `pnpm --filter @fusion/core exec vitest run --silent=passed-only --reporter=dot src/__tests__/agent-prompts.test.ts` - `pnpm --filter @fusion/core typecheck` - `pnpm check:changesets` - `pnpm exec eslint packages/core/src/agents/agent-prompts.ts` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Executor workflow guidance now appears only when task creation or delegation capabilities are available. * Built-in executor prompts provide clearer task-assignment instructions based on available capabilities. * Custom executor prompts remain unchanged. * Removed outdated workflow-setting guidance when task-management capabilities are unavailable. * **Tests** * Added coverage for task creation, delegation, and capability-specific workflow guidance scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
9838f42076 |
fix: repair core and CLI suites, plus a PG table-registry omission
Core 32 failures -> 0 (5,981 passing); CLI 46 -> 0 (2,021 passing). Three agents per package, root-cause fixes only. One product defect, same class as FN-9059 and found the same way — by a test that leaked state between runs: `projectTableNames` was missing SEVENTEEN tables the schema declares (current_plan_evidence, spec_locks, spec_drift_reports, symbol_locks, configuration_revisions, chat_tags, chat_session_tags, mission_lineage_stops, task_verification_requests, unplanned_execution_blocks, workflow_agent_capacity_leases and the six task_lifecycle_* tables). That list drives BOTH the PG test-harness per-test reset and production health compaction, so those tables were never truncated between tests (a plan-evidence version counter carried forward, making whole-file runs disagree with isolated ones) and never VACUUM/ANALYZEd in production. Registered, with project-table-registry.test.ts as a ratchet — verified it fails on an unregistered new table naming the offender. Everything else was drift behind deliberate changes: branch-write provenance, FN-073 dependency validation, the FN-9191 pre-merge merge gate, U11's triage/ planning lane merge, refinement workflow coming from the ORIGIN selection, async-converted provider registration, a barrel mock missing exports a guard added, and several source-pinned inventories broken by module moves. Tests for removed features were deleted with their removing commit cited. Also fixes a vitest config gap where @fusion/core/mcp-builtin-servers resolved only to dist/, which was breaking test COLLECTION in unrelated CLI files and had been misread as transient cross-agent noise. Quarantines mission-store.pg's concurrent-claim race (second sighting): it holds a transaction open, sleeps 250ms and asserts the rival has not settled, which fails under parallel load. An A/B against the registry change above looked causal on one run and did not reproduce on three — that coincidence is the flake itself, and rescue needs a real lock-wait probe rather than a longer sleep. Core's config now inlines its exclude array, because check-quarantine-ledger.mjs cannot resolve a variable reference and silently reported the ledger unpaired. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
bc82d8e0e1 |
fix(core): thread review lanes through merge readiness (#3514)
## Summary - thread resolved review lanes through `isTaskReadyForMerge` - preserve required pre-merge step filtering - add coverage for a renamed review lane ## Test plan - `pnpm --filter @fusion/core exec vitest run --silent=passed-only --reporter=dot src/__tests__/task-merge.test.ts` - `pnpm --filter @fusion/core typecheck` - `pnpm check:lane-wiring` - `pnpm check:changesets` - `pnpm exec eslint packages/core/src/merge/task-merge.ts packages/core/src/__tests__/task-merge.test.ts` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Custom review lanes are now honored during merge-readiness checks and auto-merge processing. * Renamed workflow lanes correctly determine whether tasks can merge. * Tasks resumed from a paused state are routed and evaluated using the appropriate review lane. * The default `in-review` lane remains supported when no custom review lanes are configured. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: gsxdsm <gsxdsm@users.noreply.github.com> |
||
|
|
febe375b14 |
fix(core): preserve merge finalization review lanes (#3508)
## Summary - Forward project review lanes and required pre-merge steps through merge-confirmed finalization. - Cover custom review-lane and required-step blockers in the merge finalization tests. - Correct future-dated FNXC stamps that were blocking the shared lint gate. ## Test Plan - `corepack pnpm --filter @fusion/core exec vitest run src/__tests__/task-merge.test.ts --silent=passed-only --reporter=dot` - `corepack pnpm --filter @fusion/core typecheck` - `corepack pnpm check:lifecycle-columns` - `corepack pnpm check:lane-wiring` - `corepack pnpm check:fnxc-future-dates` - `corepack pnpm check:changesets --strict` - `git diff --check` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Confirmed merge finalization now preserves the selected review lane and applies its resolved review requirements. - Required pre-merge steps are correctly enforced for both durable and non-durable merges. - **Tests** - Added coverage for review-lane handling and pre-merge blockers across merge paths. - **Documentation** - Added release notes documenting the merge finalization fix. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
3533fc8a47 |
docs: pin the hybrid step-storage contract (the "steps: [] no-op" is not a bug)
An investigation reported that under PostgreSQL `updateTask(id, { steps: [] })`
silently no-ops while a non-empty array writes fine, and worked around it in
fixtures. Reproduced and traced: the write is literal and correct — the row and
task.json both hold `[]`. What actually happens is that an empty array means
"plan not parsed yet", not "this task has no steps", so all four read paths
re-derive steps from PROMPT.md when the stored array is empty: getTaskImpl, the
two list hydrations (reads.ts), and updateStep's auto-init, whose range error
already says outright that "its steps are defined in PROMPT.md".
No product change: removing the re-derivation would strand every task whose plan
lives only in PROMPT.md. Instead both halves of the contract are now pinned by a
PG test and documented at the write site, so the next reader sees the mechanism
instead of re-diagnosing it as a lost write. To make a task genuinely stepless,
remove the step headings from PROMPT.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
455bdbc007 |
fix: repair the engine suite and the product regressions it was pointing at
Six parallel agents worked the 150 remaining failures. Engine suite: 297 failing tests at baseline |
||
|
|
f2eda4819d |
docs: make a behavior change own the tests that assert the old behavior
Fusion agents keep shipping behavior changes that leave stale tests behind, and targeted verification structurally cannot catch it: it runs the tests for the files the agent TOUCHED, while the assertions encoding the old behavior live in files it did not. Measured on one full engine suite run (2026-08-24): 297 failing tests, ~135 of them from exactly five such changes — the FN-158 pre-merge-gate guard (~70 fixtures across 13 files), the branch-write provenance guard (18 from ONE shared fixture), a workflow-IR reorder (10 stale topology assertions), an updateTaskAtomic seam missing from fake stores (~9), and FN-074's splitting removal leaving 4 reviewer-prompt tests asserting a deleted contract. Every one passed its own targeted verification. - AGENTS.md: new standing rule with the four search triggers (guard added, feature removed, order/default/constant/prompt changed, public method added), a fix-at-the-shared-factory preference, and an explicit ban on weakening a stale test or restoring removed behavior to satisfy one. - Executor prompt: the same searches, stated as a finish condition. - Full triage prompt: specs for behavior-changing tasks must include a step that NAMES the search, so it is planned rather than left to chance. The fast triage prompt is deliberately excluded: it carries a hard size budget (agent-prompts.test.ts caps it at 7500 chars) and adding this pushed it over — an instance of the very rule being documented, now cited in it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
339d849938 |
fix: classify legacy adoption review-lane literals
Mark isAtOrPastReviewLane as DELIBERATE-LITERAL so the lifecycle-column census ratchet stops treating FN-158's physical pre-cutover lane IDs as new unexamined guards. Refresh the pinned baseline to match. |
||
|
|
ea48af7ab5 |
fix: require a durable merge record for the step-finalization exemption
Full-suite set-diff against
|
||
|
|
a879ead0fc |
fix: let a proven merge finalize even with unfinished steps
FN-9193's branch landed on main as
|
||
|
|
038f802ba4 |
fix: make the workflow graph the only merge authority
ProjectEngine's in-review auto-merge sweep was a second merge authority. It judged eligibility from column, status, steps and retry budget alone, with no idea where the card sat in its workflow graph, so it merged work the graph had never authorized: FN-9191 merged ~2s after fn_task_done, before Code Review had ever started, and FN-9193 merged while Code Review was re-running — the gate then requested revision and reset the steps, but the in-flight merge landed the pre-remediation branch anyway and left the card mergeConfirmed WITH incomplete steps, unfinalizable for five hours. - classifyMergeSweepAdmission (core) admits only merge-confirmed finalization, a card parked at a merge-region node, an interrupted attempt, or a fenced quiescent stall. Every initiation is fenced on satisfied pre-merge gates. - All four doors prove authority: the sweep, the 300ms column-entry handoff (which matches FN-9191's timing better than any sweep tick), the unpause re-enqueue, and a position-only pre-dispatch re-check for cards the graph moved out of the merge lane while they were queued. - workflow-merge-region.ts holds the canonical merge-region predicate; INTERPRETER_ENTRY_NODE_KINDS now aliases it so the two cannot drift. - Multi-repo: branch-group integration/promotion are merge-region nodes, an in-flight sub-repo land reads as foreign liveness, and a cross-node merge-dispatch lease defers. - Sweep reads are batched, so admission costs O(1) queries per poll. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
db254241f1 |
FN-180: enforce merge execution and current review gates
Prevent merge progression while execution is active and require current, content-matched review approval before finalization. - Add shared pre-merge approval and content descriptor gates. - Exclude actively executing tasks from merge and reconcile confirmed merges safely. - Centralize step reopening and strengthen merge lifecycle, audit, and regression coverage. Files changed: ...80-merge-execution-exclusion-and-review-gate.md | 7 + docs/architecture.md | 1 + docs/run-audit.md | 2 + docs/testing.md | 5 + docs/workflow-steps.md | 2 + .../confirmed-merge-reconciliation.test.ts | 17 ++ .../src/__tests__/pre-merge-approval-gate.test.ts | 33 ++++ .../__tests__/pre-merge-approval-workspace.test.ts | 30 +++ .../src/__tests__/required-pre-merge-steps.test.ts | 47 ++++- packages/core/src/__tests__/task-merge.test.ts | 9 +- packages/core/src/db/legacy-adoption.ts | 7 + packages/core/src/index.gate.ts | 11 +- packages/core/src/index.ts | 11 +- .../src/merge/confirmed-merge-reconciliation.ts | 34 ++++ .../core/src/merge/merge-content-descriptor.ts | 10 + packages/core/src/merge/pre-merge-approval.ts | 71 +++++++ .../core/src/merge/required-pre-merge-steps.ts | 69 +++++++ packages/core/src/merge/task-merge.ts | 35 ++-- packages/core/src/task-store/merge-queue-ops.ts | 50 ++--- .../src/workflows/workflow-step-reopen-policy.ts | 18 ++ .../__tests__/ChatView.core-contracts.test.tsx | 5 +- .../__tests__/ChatView.core-interactions.test.tsx | 5 +- .../components/__tests__/ChatView.core.test.tsx | 5 +- .../components/__tests__/ChatView.draft.test.tsx | 5 +- .../__tests__/ChatView.message-edit.test.tsx | 5 +- .../__tests__/ChatView.mobile-render.test.tsx | 5 +- .../components/__tests__/ChatView.mobile.test.tsx | 5 +- .../__tests__/ChatView.scroll-to-top.test.tsx | 5 +- .../__tests__/ChatView.sessions-rooms.test.tsx | 5 +- .../__tests__/ChatView.thinking-level.test.tsx | 5 +- .../confirmed-merge-must-finalize.test.ts | 32 ++++ .../src/__tests__/executor-step-session.test.ts | 29 ++- .../src/__tests__/manual-merge-bypass.test.ts | 1 + .../merge-abort-clears-transient-status.test.ts | 66 ++++--- .../merge-content-descriptor-doors.test.ts | 28 +++ .../__tests__/merge-execution-exclusion.test.ts | 65 +++++++ .../__tests__/merge-gate-single-authority.test.ts | 28 +++ .../src/__tests__/merge-inflight-revoke.test.ts | 26 +++ .../merge-worktree-removal-live-session.test.ts | 29 +++ .../engine/src/__tests__/merger-ai-cleanup.test.ts | 8 +- .../src/__tests__/merger-merge-lifecycle.test.ts | 11 +- .../__tests__/step-reopen-single-authority.test.ts | 116 ++++++++++++ .../workflow-graph-optional-step-fix.test.ts | 10 + .../engine/src/__tests__/workspace-merger.test.ts | 13 +- .../engine/src/executor/cleanup-merge-state.ts | 45 +---- .../src/executor/finalize-already-reviewed-task.ts | 20 +- .../src/executor/recover-failed-pre-merge-step.ts | 7 +- .../src/executor/reopen-last-step-for-revision.ts | 41 +---- .../request-pre-merge-optional-step-fix.ts | 13 +- packages/engine/src/executor/reset-merge-state.ts | 7 +- .../src/executor/review-convergence-ladder.ts | 6 + packages/engine/src/executor/run-implementation.ts | 33 +++- .../engine/src/merge/auto-merge-finalization.ts | 49 +++-- packages/engine/src/merge/merge-content-capture.ts | 49 +++++ .../engine/src/merge/merge-execution-exclusion.ts | 47 +++++ packages/engine/src/merge/merger-ai.ts | 204 ++++++++++++++++----- packages/engine/src/merge/merger-errors.ts | 13 ++ packages/engine/src/merger.ts | 29 ++- packages/engine/src/project-engine.ts | 153 ++++++++++++---- .../engine/src/run-audit/run-audit-catalogue.ts | 12 ++ packages/engine/src/self-healing.ts | 36 ++-- packages/engine/src/util/run-audit.ts | 4 + .../engine/src/worktree/review-diff-fingerprint.ts | 36 +++- .../src/worktree/workspace-review-evidence.ts | 2 +- 64 files changed, 1420 insertions(+), 367 deletions(-) Fusion-Task-Id: FN-180 Fusion-Task-Lineage: 4c2cdae0-be25-49c9-a918-60768ddc7686 Co-authored-by: Fusion <noreply@runfusion.ai> |
||
|
|
95ea06b48a |
FN-179: add workspace contention wait-state recovery
Persist workspace acquisition contention as an operator-visible wait state and make recovery, lease authority, and localized dashboard status handling consistent. - Add the contention wait-state schema, persistence, reset, serialization, and audit plumbing. - Coordinate workspace acquisition claims, leases, retries, and self-healing recovery across engine and core. - Surface contention status in task cards and detail views with translated labels and regression coverage. - Document the workspace behavior and add the required changeset. Files changed: .changeset/fn-179-workspace-acquire-contention.md | 7 + AGENTS.md | 1 + docs/architecture.md | 4 +- docs/dashboard-guide.md | 1 + docs/workspaces.md | 4 +- .../src/__tests__/postgres/schema-applier.test.ts | 34 ++++- ...workspace-worktrees-concurrent-merge.pg.test.ts | 35 +++++ .../0066_fn_179_session_contention_wait_state.sql | 3 + packages/core/src/postgres/schema-applier.ts | 12 +- packages/core/src/postgres/schema/project.ts | 2 + packages/core/src/store.ts | 2 +- .../core/src/task-store/branch-and-pr-entities.ts | 2 +- packages/core/src/task-store/persistence.ts | 4 + packages/core/src/task-store/reset-lifecycle.ts | 2 + packages/core/src/task-store/serialization.ts | 2 + packages/core/src/task-store/task-artifacts-ops.ts | 4 + packages/core/src/task-store/task-mutation-ops.ts | 41 +++--- packages/core/src/task-store/task-row-mappers.ts | 2 +- packages/core/src/task-store/task-update.ts | 10 ++ packages/core/src/tasks/manual-retry-reset.ts | 2 + packages/core/src/types/task/task-core.ts | 4 + packages/dashboard/app/components/ListView.tsx | 4 +- packages/dashboard/app/components/TaskCard.tsx | 2 +- .../dashboard/app/components/TaskDetailModal.tsx | 1 + .../taskStatusBadgeLabel.host-inventory.test.ts | 19 +++ .../utils/__tests__/taskStatusBadgeLabel.test.ts | 7 + .../dashboard/app/utils/taskStatusBadgeLabel.ts | 8 ++ .../executor-planning-lock-transport-retry.test.ts | 132 ++++++++++++++++++ ...roject-engine-spec-drift-startup-replay.test.ts | 84 ++++++++++++ .../src/__tests__/self-healing-workspace.test.ts | 58 ++++++++ .../workspace-acquire-claim-release.test.ts | 69 ++++++++++ .../workspace-acquire-contention-hold.test.ts | 75 +++++++++++ .../workspace-acquire-lease-authority.test.ts | 122 +++++++++++++++++ .../worktree-acquisition-workspace.test.ts | 32 +++++ packages/engine/src/agent-tools.ts | 26 +++- .../engine/src/agents/active-session-registry.ts | 9 ++ .../create-authoritative-workflow-seams.ts | 14 +- packages/engine/src/executor/deps-bags.ts | 3 - .../engine/src/executor/execute-workflow-graph.ts | 4 +- packages/engine/src/executor/run-implementation.ts | 34 ++++- .../engine/src/executor/session-contention-hold.ts | 47 +++---- .../engine/src/executor/wire-executor-lifecycle.ts | 32 ++++- packages/engine/src/planning-handoff-recovery.ts | 11 ++ packages/engine/src/project-engine.ts | 8 +- packages/engine/src/self-healing.ts | 63 ++++++++- packages/engine/src/util/run-audit.ts | 4 + .../engine/src/worktree/worktree-acquisition.ts | 147 ++++++++++++++++----- packages/i18n/locales/en/app.json | 2 + packages/i18n/locales/es/app.json | 4 +- packages/i18n/locales/fr/app.json | 4 +- packages/i18n/locales/ko/app.json | 4 +- packages/i18n/locales/pt-BR/app.json | 4 +- packages/i18n/locales/zh-CN/app.json | 4 +- packages/i18n/locales/zh-TW/app.json | 4 +- packages/i18n/src/resources.d.ts | 2 + 55 files changed, 1103 insertions(+), 118 deletions(-) Fusion-Task-Id: FN-179 Fusion-Task-Lineage: 30f1b365-2847-4ec1-85b3-23a98c92de40 Co-authored-by: Fusion <noreply@runfusion.ai> |
||
|
|
e25f8907d9 |
FN-175: add review-gated verification workflow
Add review-owned verification, remediation, and documentation gates across workflow execution and task progress. - Add built-in review-gated coding workflow and verification/documentation nodes. - Preserve remediation steps and enforce finalize/merge guards after review findings. - Surface review-gate progress in the dashboard and document the workflow and audit behavior. - Add focused core, engine, and dashboard regression coverage. Files changed: .changeset/fn-175-review-gated-workflow.md | 7 ++ docs/architecture.md | 4 + docs/dashboard-guide.md | 4 + docs/run-audit.md | 5 ++ docs/workflow-steps.md | 6 ++ .../builtin-review-gated-coding-workflow.test.ts | 48 +++++++++++ .../__tests__/no-commits-finalize-guard.test.ts | 15 ++++ .../core/src/__tests__/remediation-steps.test.ts | 64 ++++++++++++++ packages/core/src/index.gate.ts | 9 ++ packages/core/src/index.ts | 10 +++ .../core/src/merge/no-commits-finalize-guard.ts | 12 ++- packages/core/src/store.ts | 6 +- .../core/src/task-store/remediation-step-ops.ts | 45 ++++++++++ packages/core/src/tasks/remediation-steps.ts | 48 +++++++++++ packages/core/src/types/task/task-log.ts | 15 ++++ .../builtin-documentation-delivery-group.ts | 32 +++++++ .../src/workflows/builtin-plan-review-group.ts | 11 ++- .../builtin-review-gated-coding-workflow-ir.ts | 60 +++++++++++++ .../workflows/builtin-verification-gate-group.ts | 26 ++++++ .../core/src/workflows/builtin-workflow-prompts.ts | 2 + .../builtin-workflow-remediation-nodes.ts | 20 +++++ packages/core/src/workflows/builtin-workflows.ts | 14 ++++ packages/core/src/workflows/index.ts | 3 + packages/dashboard/app/components/TaskCard.css | 5 ++ packages/dashboard/app/components/TaskCard.tsx | 12 ++- .../__tests__/taskProgress.review-gates.test.ts | 19 +++++ packages/dashboard/app/utils/taskProgress.ts | 2 + .../review-gated-remediation-steps.test.ts | 43 ++++++++++ .../review-gated-step-preservation.test.ts | 32 +++++++ .../review-gated-verification-gate.test.ts | 50 +++++++++++ .../executor/append-review-remediation-steps.ts | 97 ++++++++++++++++++++++ .../engine/src/executor/build-parse-steps-deps.ts | 1 + .../engine/src/executor/cleanup-merge-state.ts | 9 +- packages/engine/src/executor/deps-bags.ts | 9 +- .../src/executor/derive-remediation-steps.ts | 76 +++++++++++++++++ packages/engine/src/executor/free-reexports.ts | 1 + packages/engine/src/executor/impl-bindings.ts | 1 + .../request-pre-merge-optional-step-fix.ts | 17 ++++ packages/engine/src/executor/reset-merge-state.ts | 5 +- .../engine/src/executor/run-graph-custom-node.ts | 7 +- packages/engine/src/executor/run-implementation.ts | 3 + .../engine/src/executor/send-task-back-for-fix.ts | 5 +- .../src/executor/task-executor-session-facades.ts | 1 + packages/engine/src/merge/merger-ai.ts | 19 ++++- packages/engine/src/merger.ts | 27 +++++- packages/engine/src/self-healing.ts | 24 +++++- .../workflow-node-runners/parse-steps-runner.ts | 26 +++++- .../src/workflow-node-runners/verification-gate.ts | 77 +++++++++++++++++ .../src/workflows/workflow-graph-executor.ts | 4 +- 49 files changed, 1014 insertions(+), 24 deletions(-) Fusion-Task-Id: FN-175 Fusion-Task-Lineage: 3c555a09-4cea-4b03-a315-b6a354a2eac3 Co-authored-by: Fusion <noreply@runfusion.ai> |
||
|
|
2cb071fff5 |
FN-171: remove dashboard auto-reload setting
Retire the configurable version-change auto-reload option and make dashboard reload behavior mandatory.\n\n- Remove the auto-reload setting from schemas, UI, translations, persistence, and documentation.\n- Simplify version checking and update affected tests and settings guards.\n- Add a breaking-release changeset documenting the migration.\n\nFiles changed:\n .changeset/fn-171-removal.md | 7 +\n docs/dashboard-guide.md | 2 +\n docs/settings-reference.md | 3 +\n .../core/src/__tests__/settings-defaults.test.ts | 9 +\n packages/core/src/config/settings-schema.ts | 5 +\n packages/core/src/types/settings/settings-scope.ts | 5 -\n .../dashboard/app/__tests__/versionCheck.test.ts | 141 ++++++++-------------\n packages/dashboard/app/components/SettingsModal.css | 1 -\n .../__tests__/EngineControlMenu.test.tsx | 4 -\n .../app/components/settings/save-split.ts | 1 -\n .../sections/GlobalGeneralSection.search.ts | 10 --\n .../settings/sections/GlobalGeneralSection.tsx | 14 +-\n ...lobalGeneralSection.auto-reload-removed.test.tsx | 48 +++++++\n .../settings-default-descriptions.test.tsx | 1 -\n packages/dashboard/app/hooks/useAppSettings.ts | 25 +---\n packages/dashboard/app/versionCheck.ts | 58 +--------\n packages/i18n/locales/en/app.json | 2 -\n packages/i18n/locales/es/app.json | 2 -\n packages/i18n/locales/fr/app.json | 2 -\n packages/i18n/locales/ko/app.json | 2 -\n packages/i18n/locales/pt-BR/app.json | 2 -\n packages/i18n/locales/zh-CN/app.json | 2 -\n packages/i18n/locales/zh-TW/app.json | 2 -\n packages/i18n/src/resources.d.ts | 2 -\n 24 files changed, 129 insertions(+), 221 deletions(-) Fusion-Task-Id: FN-171 Fusion-Task-Lineage: b76ed733-0036-419d-ae5a-e0563433e957 Co-authored-by: Fusion <noreply@runfusion.ai> |
||
|
|
3af54418cf |
FN-9191: add the Iceberg dashboard theme
Add a persisted Iceberg palette across dashboard and desktop theme surfaces. - Define coordinated dark and light Iceberg color tokens and selector swatches. - Register Iceberg in shared persistence, theme selectors, and first-paint validation. - Add registry coverage, documentation, visual references, and a release changeset. Files changed: .changeset/fn-9191-iceberg-theme.md | 6 ++ docs/dashboard-guide.md | 5 +- docs/settings-reference.md | 4 +- packages/core/src/types/ui/execution-and-ui.ts | 2 + .../dashboard/app/__tests__/iceberg-theme.test.ts | 102 +++++++++++++++++++++ .../dashboard/app/components/ThemeSelector.css | 15 +++ .../components/__tests__/ThemeDropdown.test.tsx | 3 +- .../components/__tests__/ThemeSelector.test.tsx | 3 +- .../__tests__/CommandCenterControls.test.tsx | 3 +- packages/dashboard/app/components/themeOptions.ts | 2 + packages/dashboard/app/index.html | 3 +- packages/dashboard/app/public/theme-data.css | 85 +++++++++++++++++ packages/desktop/src/renderer/index.html | 2 + screenshots/fn-9191-iceberg-theme-dark.png | 3 + screenshots/fn-9191-iceberg-theme-light.png | 3 + 15 files changed, 234 insertions(+), 7 deletions(-) Fusion-Task-Id: FN-9191 Fusion-Task-Lineage: a8b441c6-763a-4c38-a682-bffab1fdd293 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
b47fb70b81 |
fix: defer merge on unrun pre-merge gates instead of failing the task
An enabled pre-merge gate that has not reported yet is a not-yet condition, not a failure. FN-9191 proved the difference is load-bearing: the in-review auto-merge sweep enqueued the card ~2s after fn_task_done and ~18s before the graph started its own Code Review node, the merge door correctly refused, and the auto-merge error path parked it status="failed". Code Review APPROVED two minutes later, but every subsequent merge — including the graph's own merge node — then died on "task is marked 'failed'". - Merge doors throw the typed PreMergeStepsNotRunError for that blocker. - The auto-merge error path treats it as a deferral: no status write, no mergeRetries burn, no operator handoff. - enqueueEligibleInReviewTasks holds a card out of the merge queue until every enabled pre-merge group has a result, so the race stops at admission. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
d71aa0d189 |
test: update schema-applier PG test for migrations 0061-0064
Migrations 0061 (activity-log task-id index), 0062 (remove task/subtask splitting), 0063 (AI merge review reconciliation), and 0064 (task repository scope) advanced SCHEMA_BASELINE_VERSION to 0064 without updating this non-gate PG integration test, leaving it red on the non-blocking suite: - Bump the immutable-identity assertion to 0064 and pin 0062-0064 identities. - Append the four new versions to all five getAppliedMigrations() lists. - Add central.central_activity_log to the hand-built 0000 upgrade fixture so the 0061 index migration finds the relation real 0000 DBs have from 0000_initial.sql (fixture gap, not a product regression). |
||
|
|
bfaa0f42da |
FN-158: enforce workspace multi-repo merge boundaries
Support workspace tasks across a shared root with scope-driven repositories and verifiable merge gates. - Route task work through one workspace directory with per-repository acquisition and isolation. - Add sandbox session policies and per-repository verification command handling. - Enforce required pre-merge checks and honest merge blocking for workspace changes. - Update workspace, workflow, and sandbox documentation and release metadata. Files changed: .changeset/fn-158-workspace-single-root.md | 7 + docs/sandbox.md | 6 +- docs/workflow-steps.md | 6 +- docs/workspaces.md | 12 +- .../core/src/__tests__/legacy-adoption.test.ts | 15 +- .../src/__tests__/required-pre-merge-steps.test.ts | 25 ++++ .../core/src/__tests__/store-bypass-review.test.ts | 24 ++- packages/core/src/__tests__/task-merge.test.ts | 24 +++ .../core/src/__tests__/worktree-layout.test.ts | 29 ++++ packages/core/src/db/legacy-adoption.ts | 20 ++- packages/core/src/index.gate.ts | 4 + packages/core/src/index.ts | 4 + .../core/src/merge/required-pre-merge-steps.ts | 26 ++++ packages/core/src/merge/task-merge.ts | 35 ++++- packages/core/src/store.ts | 59 ++++++-- packages/core/src/task-store/lifecycle-ops.ts | 1 + packages/core/src/task-store/merge-queue-ops.ts | 5 +- packages/core/src/task-store/moves.ts | 13 +- packages/core/src/task-store/task-artifacts-ops.ts | 11 +- packages/core/src/tasks/worktree-layout.ts | 43 +++++- packages/core/src/types/workflow/workflow-steps.ts | 3 +- .../executor-workspace-session-cwd.test.ts | 42 ++++-- .../src/__tests__/node-worktree-isolation.test.ts | 13 +- .../src/__tests__/pi-create-fn-agent.test.ts | 16 ++ .../engine/src/__tests__/project-engine.test.ts | 20 ++- .../src/__tests__/reviewer-workspace.test.ts | 30 +++- .../src/__tests__/run-verification-command.test.ts | 90 +++++++++++- .../__tests__/sandbox/sandbox-exec-policy.test.ts | 16 +- .../src/__tests__/sandbox/session-policy.test.ts | 45 ++++++ .../__tests__/workspace-add-repo-midflight.test.ts | 9 ++ .../engine/src/__tests__/workspace-e2e.test.ts | 13 +- .../workspace-root-worktree-routing.test.ts | 18 +-- packages/engine/src/agent-tools.ts | 15 +- packages/engine/src/agents/agent-runtime.ts | 19 +++ .../engine/src/agents/agent-session-helpers.ts | 15 ++ packages/engine/src/execution/hold-release.ts | 29 ++++ .../engine/src/execution/run-verification-tool.ts | 114 ++++++++++++++- .../create-authoritative-workflow-seams.ts | 20 +-- packages/engine/src/executor/deps-bags.ts | 5 +- .../executor/ensure-graph-custom-node-worktree.ts | 24 ++- .../executor/ensure-task-worktree-for-planning.ts | 36 ++--- .../engine/src/executor/execute-workflow-step.ts | 4 +- .../src/executor/finalize-already-reviewed-task.ts | 6 +- .../src/executor/prepare-graph-node-execution.ts | 14 +- .../engine/src/executor/run-graph-custom-node.ts | 161 +++++++++++++-------- packages/engine/src/executor/run-implementation.ts | 117 ++++++++++++--- packages/engine/src/merge/merger-ai.ts | 16 +- packages/engine/src/merger.ts | 20 ++- packages/engine/src/pi.ts | 150 ++++++++++++++++--- packages/engine/src/project-engine.ts | 10 +- packages/engine/src/runtimes/in-process-runtime.ts | 4 +- packages/engine/src/sandbox/bubblewrap-backend.ts | 55 ++++++- packages/engine/src/sandbox/bubblewrap-policy.ts | 10 +- packages/engine/src/sandbox/index.ts | 1 + .../engine/src/sandbox/sandbox-exec-backend.ts | 45 +++++- packages/engine/src/sandbox/sandbox-exec-policy.ts | 18 ++- packages/engine/src/sandbox/session-policy.ts | 41 ++++++ packages/engine/src/sandbox/types.ts | 11 ++ packages/engine/src/self-healing.ts | 1 + packages/engine/src/triage.ts | 10 ++ .../engine/src/worktree/worktree-acquisition.ts | 53 ++++--- 61 files changed, 1393 insertions(+), 315 deletions(-) Fusion-Task-Id: FN-158 Fusion-Task-Lineage: ba57f5a2-fa69-4210-8ea7-3d124be3deb2 Co-authored-by: Fusion <noreply@runfusion.ai> |
||
|
|
7d54e86e80 |
FN-159: filter AI merge protocol markers from blocking findings
Prevent the AI merge reviewer from persisting its own protocol syntax as blocking review findings. - Register and filter all review protocol markers and disposition lines. - Aggregate reviewer prose into bounded findings and preserve reconciliation safety. - Release prior findings that are not re-confirmed on approved candidates. - Add reconciliation state, tests, documentation, and a patch changeset. Files changed: .../fn-159-ai-merge-protocol-marker-findings.md | 7 ++ docs/architecture.md | 2 +- packages/core/src/types/task/task-core.ts | 6 ++ .../engine/src/__tests__/merger-ai-prompts.test.ts | 39 ++++++++++ .../src/__tests__/merger-ai-squash-gates.test.ts | 6 ++ .../engine/src/__tests__/merger-ai.test.ts | 58 +++++++++++++++ .../engine/src/__tests__/workspace-merger.test.ts | 3 +- packages/engine/src/merge/merger-ai-prompts.ts | 53 +++++++++++--- packages/engine/src/merge/merger-ai.ts | 84 ++++++++++++++++++---- 9 files changed, 231 insertions(+), 27 deletions(-) Fusion-Task-Id: FN-159 Fusion-Task-Lineage: 6eea1dec-1252-4b8d-b227-c84c24ab60af Co-authored-by: Fusion <noreply@runfusion.ai> |
||
|
|
794dae3196 |
fix(FN-149): advance schema ceiling to 0065 so Fusion stops rejecting its own database
FN-149 shipped migration 0065_fn_149_review_convergence_stage.sql and registered REVIEW_CONVERGENCE_STAGE_VERSION but left SCHEMA_BASELINE_VERSION at "0064". The first store open applied and recorded 0065; the next open (project store, same boot) hit assertBinaryNotOlderThanDatabase, saw 0065 > 0064 and threw StaleBinarySchemaError, so every startup died with "this binary only knows up to 0064" on fresh and upgraded databases alike. - Bump SCHEMA_BASELINE_VERSION to "0065" (marker only: applies no SQL, touches no data). - Move the DB-free migration-wiring assertions out of the PostgreSQL integration file into src/__tests__/migration-wiring-integrity.test.ts and wire it into test:unit-gate, so the ceiling/migration drift now fails the merge gate instead of main's boot. - Refresh the stale migration-identity expectations (0062-0065). Symptom verification: `node scripts/dev-with-memory.mjs --isolated=<tmp> --prebuild none` exited 1 with the guard error before; it now boots and serves the dashboard. |
||
|
|
c1818ea819 |
FN-151: make task reset always complete
Make reset a reliable description-only fresh start by fencing active planning work and cleaning discarded execution state. - Add reset lifecycle disposal for planning sessions, locks, artifacts, and reset worktrees. - Preserve operator-provided descriptions while clearing stale execution and planning projections. - Expose reset routes and add core, dashboard, and engine regression coverage. Files changed: .changeset/fn-151-task-reset-always-completes.md | 7 + docs/architecture.md | 3 + docs/dashboard-guide.md | 6 +- .../postgres/task-reset-publication.pg.test.ts | 71 +++++++++- .../core/src/__tests__/task-move-disposer.test.ts | 38 ++++++ packages/core/src/index.gate.ts | 2 + packages/core/src/index.ts | 2 + packages/core/src/task-store/reset-lifecycle.ts | 38 +++++- packages/core/src/tasks/task-move-disposer.ts | 36 +++++- .../src/__tests__/task-reset-lifecycle.test.ts | 110 +++++++++++++++- .../src/routes/register-task-workflow-routes.ts | 29 +++-- .../src/__tests__/agent-document-tools.test.ts | 49 +++++++ .../src/__tests__/reset-worktree-removal.test.ts | 77 +++++++++++ .../__tests__/triage-reset-planning-fence.test.ts | 118 +++++++++++++++++ packages/engine/src/agent-tools.ts | 60 +++++++-- packages/engine/src/agents/planning-liveness.ts | 19 +++ packages/engine/src/index.ts | 4 + packages/engine/src/plan-artifact-writeback.ts | 27 +++- packages/engine/src/planning-reset-fence.ts | 26 +++ packages/engine/src/triage.ts | 143 +++++++++++++++++++-- packages/engine/src/worktree/remove-reset-worktree.ts | 65 ++++++++++ 21 files changed, 882 insertions(+), 48 deletions(-) Fusion-Task-Id: FN-151 Fusion-Task-Lineage: 1c25d58e-2d23-4340-a489-51f3e2d8a7f4 Co-authored-by: Fusion <noreply@runfusion.ai> |