13bf7e001d78cc6df169883dfbb13a7183a4a8e3
184 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
a6138abeff |
U12: DELIBERATE-LITERAL counts key on file AND column — closing the P1 left on merged #2661 (#2666)
Closes the P1 that was still open when #2661 merged. ## The hole A per-file integer is offset **within a single file**: remove one reviewed `todo` exemption, add an `in-review` one beside it, and the number never moves. The fresh guard is invisible to the column counts too, because deliberate findings are excluded from them — so `--strict` goes green with a new lifecycle-column guard hiding inside an existing marker. Now keyed on **file AND column id**. **Proven with the exact scenario:** swapping a marked `triage` for `done` inside `TaskCard.tsx` leaves the per-file total unchanged and now fails with ``` packages/dashboard/app/components/TaskCard.tsx (DELIBERATE-LITERAL: done): 0 -> 1 ``` ## The pattern worth naming This is the **third** time this instrument has been defeated by an aggregate: | version | defeated by | |---|---| | repo-wide `totals.deliberate` | an addition in file A offset by a removal in file B | | per-file integer | an addition offset by a removal **in the same file** | | per-file per-column | — | Each step narrows what can offset silently, and I walked into the next one twice by fixing the *reported case* rather than the *shape*. Writing it down because the same reflex will produce a fourth if someone adds another aggregate here. **The residual is deliberate, not an oversight:** a same-file **same-column** swap still offsets. Two `todo` exemptions in one file are interchangeable by definition, so there is nothing a reviewer could act on. That is recorded at the site so the next person doesn't rediscover it as a bug. ## Migration, again The key **shape** changed (`file` → `file\0columnId`), which is the same hazard as a missing field: comparing new keys against old reports every existing marker as a fresh rise and pushes people to convert already-reviewed literals. I hit it on the first run here — `TaskCard (DELIBERATE-LITERAL: triage): 0 -> 2` — exactly as I did one shape earlier in #2661. Detected by the delimiter rather than a version field, since old keys have none, and re-seeded on the next `--update-baseline`. 15 file+column entries recorded. ## Verification `pnpm lint` clean. `pnpm test:gate` green (10 / 158 / 487 / 71). `pnpm check:lifecycle-columns` exits 0. Independent of #2655; either order merges. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
dca20496f4 |
consolidate/u7: plugins to zero + 8 executor rebound guards + resume lanes (supersedes #2607, #2635, #2640) (#2644)
Consolidation branch for U7, per the new one-branch working mode. **Supersedes #2607, #2635, #2640** — the three of my PRs that were stuck on review threads. My other seven (#2602, #2605, #2606, #2611, #2621, #2628, #2633) are green with **zero unresolved threads** and are deliberately left alone for the merge sweep. ## What is in here, file by file | file | change | guards before → after | |---|---|---| | `plugins/…/glasses/src/agent-actions.ts` | gates, destinations and degraded-resolution refusal all resolve from the task's own workflow | 2 → 0 | | `plugins/…/glasses/src/quick-capture.ts` | accepted capture columns come from the board; default no longer names the deleted column | 1 → 0 | | `plugins/…/glasses/src/settings.ts` | quick-capture default was `triage`, the column #2515 removed | (assignment, uncounted) | | `plugins/…/dependency-graph/src/GraphTaskNode.tsx` | redundant column condition deleted | 1 → 0 | | `packages/engine/src/executor.ts` | 8 rebound guards compare the resolved column; 4 resume-eligibility literals share one resolver | 151 → 143 (+4 off-bar) | | `packages/engine/src/__tests__/` | 4 new suites, 26 cases | — | `plugins/` reaches **zero** column guards with this branch. ## The three threads it closes **#2607 — five findings, all mine, all the same rule.** I kept *qualifying* a legacy-id fallback instead of removing it: | attempt | rule | hole review found | |---|---|---| | 1 | fall back to `todo` when the role is missing | moved cards to phantom columns | | 2 | …only if the workflow **declares** `todo` | aliased **review** lane named `todo` | | 3 | …and only if no other role is assigned to it | **traitless** parking column named `todo` | The qualifications were the mistake. Once `resolveLanes` returns a lane set the workflow *has* a column vocabulary, so "no column carries the hold trait" is a complete answer — refuse. `destination()` is two lines now, with no aliasing surface left to qualify. Plus a sixth, which is a genuinely different state: **degraded resolution is indistinguishable from the default board.** `resolveWorkflowIrForTask` is total by design — a missing definition silently returns the *default* coding IR — so a card on a custom board whose definition could not be read resolved to `todo`/`in-progress`. `undefined` lanes cannot express that (it means "no workflow at all", where the legacy ids *are* the answer). The actions now refuse with 409. #2618 would replace this check with resolver provenance; it is not merged, so this does not depend on it. **#2635 — "seven rebound sites remain untested."** Fair; my "same shape" note was an assertion, not coverage. Seven of the eight need a live graph run to reach, so the *shape* is pinned instead: a static check that no guard in front of a rebound move compares against a column literal, with a vacuity case (the same detection run against the original shape) and a match-count floor (≥8), because a guard reporting success on zero matches is worse than no guard. **#2640 — duplicate workflow resolution.** Framed as I/O; it is also a correctness bug. Eligibility and re-entry are two halves of one decision and resolved the workflow separately, so a workflow edit landing between them has the halves reading *different boards*. Now one caller-owned memo per decision — caller-owned because a process-lifetime cache would have to guess when a mid-flight workflow edit invalidates it. ## Behavioural findings, not tidying - **The last-resort recovery for completed-but-stranded work did not exist off the default lineage.** `promotedFromPlannerColumn` was false on a renamed board, so finished work resting in planning was never promoted; the code fell through to a review handoff that role adjacency rejects, and the card stayed stuck with its work complete. - **Rebound guards could not see the column their own move targeted.** U5b converted the move target; the eight `column !== "todo"` checks in front of it were left literal, so on a renamed board the engine moved a card into the column it was already in — and `moveTaskInternal` runs reset-on-entry on every real move, so at the `preserveProgress: false` site it reset step progress a second time. - **The FN-1404 `task:move` audit row was lying**, recording `to: "todo"` while the move target was resolved. A run-audit trail that disagrees with the move it describes is worse than none. Not a comparison, so no census counts it. - **A task interrupted by an engine pause never resumed on a renamed board** (off-bar, `in-review`/`in-progress` literals): four comparisons decided one question and had to agree; two of them disagreed on a renamed board, so re-entry silently never fired. ## Revert proofs, isolated per site | reverted | result | |---|---| | `destination()` back to attempt 3 | 3 of 38 fail | | degraded-resolution refusals removed | 2 of 42 fail | | capture set back to the legacy five | 2 of 3 fail (renamed-board suite) | | forward exclusions → literals | 1 of 14 fails | | missing-wip refusal removed | 2 of 14 fail | | `promotedFromPlannerColumn` → literals | 3 of 7 fail | | promotion target → `"in-progress"` | 3 of 7 fail | | one rebound guard → `!== "todo"` | 1 of 3 fails (static shape) | | resume lanes → legacy trio | 1 of 5 fails | Every conversion is paired with a negative — a forward move, a not-a-planner-lane card, a default-lineage card, an unresolvable workflow — so neither "always fire" nor "never fire" can pass for "resolve the role". ## Commit discipline Twelve commits, each one thing: the code move (`resolvePlannerLanes` out of `triage.ts`) is separate from every behavior change, and each review fix is its own commit with its own revert proof. ## Verification - `pnpm test:gate` **71/71** - 162/162 across the glasses plugin's 19 files; 26/26 across the four new engine suites - engine + glasses typecheck clean; `pnpm lint` clean 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Engine recovery and retries now work correctly with renamed or customized workflow columns. * Tasks in manual-intake columns are no longer automatically planned. * Agent actions and quick capture now respect each board’s declared columns and lifecycle stages. * Awaiting-approval tasks are recognized regardless of their current column. * Command Center SDLC funnel stages now accurately reflect customized workflows. * **Documentation** * Added guidance for safely changing workflow-column logic and interpreting lifecycle-column checks. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
cef1b08af3 |
U12: the census baseline follows the count down — and goes in the merge gate (#2661)
Coordinator item 2. The census had the right mechanism and no teeth. ## The gap `--strict` already fails on a rise **and** on an unrecorded drop — that logic was correct. But nothing blocking ran it, so the baseline drifted to **854 while the tree held 787**. That is **67 guards of regression that would have merged silently**: a high-water mark wearing a ratchet's name. This is the same shape as the ceilings I tightened in #2647, one level up. Worth saying plainly: I fixed the vitest ratchet's slack by hand and did not check whether the *authoritative* instrument had the same problem. It did, and by a much larger margin. ## Three changes 1. **`--strict` runs in `test:gate`.** The baseline cannot go stale again without a red gate. 2. **Baseline re-recorded: 854 → 785** across 14 files (`triage` 38 → 9). 3. The single RISE is resolved honestly rather than absorbed. ## The +3 investigation One file rose: `register-task-workflow-routes.ts` **22 → 23**. #2621 replaced one `task.column === "todo"` with `task.column === "triage" || task.column === "todo"` — a net **+1** that also reintroduced a `triage` literal, while the PR title reported *"count 0 → 0"*. Not an accusation. There was no gate for the author to check against, and a hand-counted claim in a PR title is exactly the thing that goes wrong without one. Change 1 is the fix. **The literal is justified and stays**, marked `DELIBERATE-LITERAL` rather than converted. It is the **v1-IR arm**: a v1 workflow yields no role assignments, so `resolveLifecycleColumns` returns nothing and the legacy pre-implementation ids are the only pre-WIP signal available. The `else` branch directly below already resolves intake/hold for every v2 workflow. Converting this arm would not finish anything — it would delete the only answer v1 boards have and admit `in-progress`/`in-review` cards into a rebound that clears worktree, branch and retry counters, which is the regression #2621 was fixing. ## Both directions proven | direction | probe | result | |---|---|---| | rise | add `t.column === 'in-review'` | `live-agent-count.ts: 6 -> 7`, exit 1 | | drop | convert one guard | `self-healing.ts: allows 111, tree has 110`, exit 1 | **The drop probe took three attempts to test honestly, and the first two "passed" while proving nothing:** 1. I renamed a receiver (`task.column` → `Probe`) — the classifier is **fail-closed**, so an unknown receiver is still counted and the number never moved. 2. I targeted a site in `hold-release.ts` that carries a `DELIBERATE-LITERAL` marker — not counted as a column guard at all, so removing it changed nothing. Only removing a counted comparison outright moved the number. Both false negatives came from me assuming the probe worked because the command exited the way I expected. ## On auto-rewrite vs fail-and-instruct You offered either. The script already does **fail-and-instruct**, with `--update-baseline` as the explicit re-record, and I kept it that way rather than making the test rewrite the baseline during a run. Reason: a silent downward rewrite means a conversion PR's own diff never shows the number moving, so "census before/after in the PR body" becomes unverifiable — the reviewer would have to re-derive it. Failing with the new number in the message puts it in the diff where a human sees it, and it costs one command. ## Verification `pnpm lint` clean. `pnpm test:gate` green with the census in it — `every file matches its baseline exactly` (10 / 132 / 487 / 71). Note for the fleet launch: with `--strict` gating, **every** conversion PR must now re-record the baseline in the same PR. That is the intended cost, and it makes the fleet's "baseline must shrink by exactly the converted count" rule mechanically enforced instead of a review instruction. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
efbbc45eb0 |
U12: the LAST triage guard — Plan was offered on executing cards named triage (#2664)
The final `column === "triage"` in production source, and it was a live
defect rather than dead vocabulary.
## The defect
`isPreExecutionHoldColumn` ORed the legacy id with the traits
**unconditionally**:
```ts
return column === "triage" || flags?.intake === true || flags?.hold === true;
```
That is not a fallback. A resolved column merely *named* `triage`
answered true even when its own traits said work was underway — so the
context menu offered **Plan**, which re-plans, on a card that is already
executing.
Now flags-first, with the id as the documented no-metadata answer.
## Why the file's earlier conversion missed it
Every existing case in `TaskContextMenu.test.tsx` passes a column with
**no flags**, or with `hold`/`intake` set. All of them agree under both
forms, so the suite could not distinguish them. Nothing exercised a
column whose **name and traits disagree**, which is the only shape that
separates an OR from a fallback.
Three new cases cover it. Revert check: restoring the OR form fails the
first one — Plan reappears on a mid-flight card.
## The asymmetry is preserved, and now tested
The degraded set stays `{triage}` **alone**, deliberately not the
`{todo, triage}` used by `isPreImplementationColumnRole`. That helper
drives the preserve-progress prompt, where a flagless `todo` *should*
prompt because losing steps is unrecoverable. This drives Plan, where a
flagless `todo` must **not** offer to re-plan a card that may already be
planned. The file documented that difference; nothing asserted it. Now a
test does.
## On reaching zero honestly
The surviving literal is marked `DELIBERATE-LITERAL`. It is the degraded
answer, not an unconverted guard — there is no trait to read when
`flags` is `undefined`, which happens during first paint and for a card
in a column its workflow no longer declares. Deleting it would silently
withdraw Plan from exactly the stranded cards that most need
re-planning.
So **`triage → 0` means "no unconverted guards remain", not "the string
is gone"**, and I would rather say that than move a number by deleting a
fallback.
| branch | triage |
|---|---:|
| `origin/main` | 5 |
| this PR | **4** |
| #2655 (flag resolution, removes 4 in `moves.ts`) | 1 → **0** combined
|
I found it with the census's own AST classifier rather than grep — my
grep of the same tree returned only comment prose and would have had me
report the bar as met while a real defect sat in
`TaskContextMenu.tsx:179`.
## Verification
`pnpm lint` clean. `pnpm test:gate` green (10 / 158 / 487 / 71). `pnpm
check:lifecycle-columns` exits 0 with the baseline re-recorded in this
PR (column 769 → 768, deliberate 12 → 13). `tsc -p tsconfig.app.json`
clean. `TaskContextMenu.test.tsx` 18/18.
Depends on nothing; stacks cleanly with #2655 and #2661.
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
20878e9d5f |
census: count column: "<legacy>" query filters as a separate, separately-pinned instrument (backlog unchanged at 784) (#2650)
Pre-launch input for the 779-guard fleet. **The backlog number does not
move: 784 before, 784 after.** This adds a second number beside it.
## The problem it measures
A guard is not the only way a legacy column id decides behaviour:
```ts
const todo = await this.store.listTasks({ column: "todo", slim: true });
```
That is a **source query** — it selects the rows a sweep considers *at
all*. On a renamed or merged board it returns nothing, so a sweep whose
per-task predicate was correctly converted still does nothing, while
looking converted. `self-healing.ts:2849` names the pairing in prose,
and #2560 had to repair exactly that combination after a converted
predicate was left with a literal query.
The census walks comparison `BinaryExpression`s. A `PropertyAssignment`
is not one, so this class was invisible to the instrument **and to its
ratchet** — it could grow silently.
Measured: **83 query filters, 43 IR node definitions.**
I proved one live consequence earlier on #2648:
`recoverStuckMergeDeadlocks` cannot see a renamed board at all — the
renamed rows exist and none appear in its three-literal union
(`renamedInsideUnion=0`, on a live PG store).
## Why this matters *before* the fleet is briefed
The fleet rule is *"the baseline ratchet must shrink by exactly the
converted count."* In `self-healing.ts` — the largest batch at 111 —
both classes sit in the same functions, so today a worker either:
- converts only the comparisons → arithmetic is clean, and sweeps whose
source query still filters a dead literal stay blind; or
- converts the query too → the count does **not** move by the converted
amount, and a more-correct PR looks like a miscount.
The second punishes the better worker. With a second pinned number,
converting a query becomes visible work instead of an apparent error.
## Counted separately, deliberately
`totals.column` is a published shape — the baseline, the reporter, and
other workers' in-flight PRs read it, and the completion bar is defined
against it. Growing it would move a number the program is actively
driving to zero.
So the new counts live in `summary.properties` / `queryByFile`, under
their own baseline keys, with their own both-directions ratchet (same
rule as #2633's, including the stale-allowance half). `totals` keeps its
**exact** shape — two existing tests assert it with `toEqual`, and
breaking a contract others depend on mid-flight to add a number is not
worth it.
## Definitions are not queries
Workflow IR graph nodes carry `column:` to declare where a node lives —
`{ id: "review", kind: "...", column: "in-review" }`. That is the
lineage describing itself: not a lookup, not convertible, and ~43 of the
raw matches. They are told apart **structurally** (an `id`/`kind`
sibling in the same object literal), not by filename, so a definition
written anywhere classifies the same way.
## Baseline seeding, stated plainly
`--update-baseline` could not pin a **new** category: the regression
check runs before the write, and with no prior key every file reads as a
rise. I seeded the three new keys once, directly, leaving every guard
field byte-identical. The diff is purely additive — no removals.
## Finding, not caused by this change
**`--strict` is already red on clean main**:
`register-task-workflow-routes.ts` is **23** against a baseline of
**22**. Verified by stashing this branch and re-running on an unmodified
tree. Until that is reconciled the guard ratchet is passing nothing —
worth fixing before the fleet starts relying on it as the work order.
## Verification
- census suites **44 green**, 6 new cases: counted; kept out of the
backlog; definition-not-query; both instruments independent (a bug
routing comparisons into the query bucket would otherwise look clean on
both); `DELIBERATE-LITERAL` honoured; non-legacy id ignored
- `node scripts/lifecycle-column-census.mjs` → backlog still 784
- `pnpm lint` exit 0, `pnpm test:gate` exit 0 (695)
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
2771408bba |
ci: enforce the lifecycle-column ratchet — it has never actually run (#2654)
**The ratchet was advisory.** `scripts/lifecycle-column-census.mjs` existed only as `pnpm census:lifecycle-columns` — without `--strict` — and **no workflow invoked it**. Nothing has ever compared the tree to the baseline. Every "the baseline ratchet holds them" assumption in this program rested on a check that does not run. That explains both classes of hole: **1. Three PRs lowered counts without re-recording,** leaving allowances the deleted guards could return through while every check stayed green. I've tightened them across #2593 and earlier PRs, but nothing stops the next one. **2. #2621 GREW the count while its own title claimed "count 0 → 0".** It added `column === "triage"` and `column === "todo"` at `register-task-workflow-routes.ts:2681`, taking that file to **23 against an allowance of 22**. It landed unchallenged. This is the failure mode the ratchet exists to prevent, and it happened *inside this program*, in a PR that asserted the opposite. ## The change Adds `check:lifecycle-columns` (the census with `--strict`) to the `pr-checks.yml` lint job, next to `check:changesets` and `check:routes-modular` — the established pattern. **~1.8s over ~1950 files**, so this is not a slow-test addition. ## Proven to fail, in both directions A guard that reports success without checking anything is worse than no guard, so: | injected defect | result | |---|---| | `const __probe = (c: string) => c === "triage"` added to `moves.ts` | `count ROSE — moves.ts: 39 -> 40`, exit 1 | | run against main's current baseline | exit 1 on `mission-feature-sync.ts: allows 5, tree has 0` | Both reverted; exit 0 restored. Note the second row: **this check is RED on main right now**, which is the point. ## Merge order **Stacked on #2593**, which carries the `DELIBERATE-LITERAL` marker for the #2621 site (a v1 IR declares no roles, so no trait can answer that question) plus the baseline re-record. Standalone on main this PR is red — correctly. **Merge #2593 first**, then this. I stacked rather than duplicating those two edits because I already caused one conflict today by appending related content from two branches, and #2651 merged a correction ahead of the section it corrected. Same-content edits in two PRs is the same mistake. ## Census Unchanged by this PR: **776 total, triage 5, reviewed 16** — it adds no guards and converts none. It only makes the numbers enforceable. ## For the fleet This should land before the 776-guard fleet launches. The brief says "the baseline ratchet must shrink by exactly the converted count" — until now nothing verified that claim, so a batch worker could report a shrink that did not happen, or grow the count while converting, and CI would agree. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
8e211d1870 |
TAKING scripts/: parse instead of grep — an AST classifier for the lifecycle-column bar, cross-checked by a second implementation (#2633)
The program's completion bar is "`column === "triage"` reaches zero".
This measures what that bar actually covers, and checks the measurement
in so it cannot drift.
## The number, measured by the checked-in tool
```
lifecycle-column-census: scanned 1956 source files
COLUMN guards (the backlog): 1031
ROLE comparisons (not guards): 10
DELIBERATE-LITERAL (reviewed): 4
by column id:
313 done
217 in-review
201 in-progress
177 archived
83 todo
40 triage
top files:
151 packages/engine/src/executor.ts
136 packages/engine/src/self-healing.ts
50 packages/dashboard/app/components/TaskCard.tsx
44 packages/core/src/task-store/moves.ts
34 packages/dashboard/app/components/TaskDetailModal.tsx
```
**`triage` is under 4% of the class.** Every one of those 1031 sites is
the same defect: a lifecycle decision made by column NAME, which stops
matching the moment a board renames a column. The bar can be met in full
while 991 identical guards remain — and two files hold a quarter of
them.
## The tracked count is wrong in three directions at once
Each of these cost real work this week, which is why this is a PR and
not a comment.
1. **Vocabulary.** It measures one of six legacy ids.
2. **Receiver.** It is anchored on locals named
`column`/`toColumn`/`fromColumn`, so it never saw the three real guards
in `executor.ts` written against `from` and `originColumn`. One of those
meant completed-but-stranded work was never recovered on a renamed
board, with nothing else owning that state (converted in #2628).
3. **Collision.** `role === "triage"`, `agentType === "triage"`,
`entry.agent === "triage"` compare an **AGENT ROLE**. The planner *lane*
is named `triage` and keeps that name — U11 removed the *column*. Ten
such sites were counted as backlog, and the "obvious" fix (renaming the
role) silently empties the planner's prompt template and mis-binds its
model markers.
A count that is too high and too low simultaneously sends work to the
wrong files while hiding the files that need it. So the census reports
**three separate numbers** and never nets them.
## Proven to fail on the original defect
Not asserted — exercised:
```
$ # reintroduce `task.column === "triage" || task.column === "todo"` into live-agent-count.ts
$ node scripts/lifecycle-column-census.mjs --strict; echo "exit=$?"
packages/core/src/live-agent-count.ts: 10 -> 12
exit=1
$ # restore the file
$ node scripts/lifecycle-column-census.mjs --strict >/dev/null; echo "exit=$?"
exit=0
```
The CLI also exits 1 when its own file list comes back empty — a guard
that reports success without checking anything is worse than no guard.
## 12 regression cases, split by what they defend
Must catch: all six ids; a guard on a local named `from`/`originColumn`
(verbatim the executor.ts shape); single quotes; negation; several
comparisons on one line.
Must **not** catch: role comparisons; comment prose (two tracked
"guards" in `replan-target.ts` were prose about a filter that lives in
another file); a trailing `// … === "triage"` on a code line; sites
carrying a `DELIBERATE-LITERAL` marker.
Plus: **one marker cannot launder a distant guard in the same file** —
that is how allowlists rot.
## Report-only, deliberately
`--strict` compares per-file counts against
`scripts/lib/lifecycle-column-census-baseline.json` and fails when any
file's count **rises**. It is **not** wired into the merge gate: a
thousand-site backlog cannot be a blocking check the day it is first
measured, and a guard nobody can pass is a guard everyone disables.
Owners tightening their own area re-record the baseline in the PR that
lowers it. This is the ratchet shape the `DELIBERATE-LITERAL` markers
scattered through the program already anticipate.
## Stated limitation
Classification is by receiver **name**, so a future field named `agent`
that holds a column would be misclassified as a role comparison.
Recorded at the site, and it is precisely why the two classes are
reported separately instead of netted into one figure.
## Verification
- 12/12 new cases
(`packages/engine/src/__tests__/lifecycle-column-census.test.ts`)
- `pnpm test:gate` **71/71**; `pnpm lint` clean
- `pnpm census:lifecycle-columns`, `--json`, and `--strict` all
exercised end to end
- documented in `docs/testing.md`; no production code touched
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
7871b28766 |
fix(core): bind the in-transaction capacity gate — one shared pool-id convention (NOT user-visible yet — see R2) (#2488)
## The bug `moves.ts` asked `countActiveInCapacitySlotAsync` for occupants of pool `"builtin:coding"`, while the counter buckets selection-less rows under `DEFAULT_WORKFLOW_POOL_ID` (`"__default-workflow__"`). Nothing ever landed in the pool being asked about, so the count came back **0** and a finite limit could never bind. ## Root fix, not a literal swap A shared *constant* would not have prevented this: **`DEFAULT_WORKFLOW_ID` was already imported in `moves.ts` and the code still wrote a literal.** So both sides now call a shared **function**, `resolveCapacityPoolId` — "which pool does a selection-less task belong to" has exactly one answer and no call site is in a position to disagree with it. The one variable serving two masters is split: a capacity **pool key** (a bucketing sentinel that must not collide with a workflow id) and a **workflow id** (telemetry, must stay a real id). The emitted `TaskTransitioned` payload is byte-identical. ## Checked, not assumed: no second copy `scheduler.ts:2514` and `:2536` do carry `?? "builtin:coding"` — but as an **IR resolution key** (`resolveWorkflowIrById`), where a real workflow id is required and the pool sentinel would not resolve at all. Same literal, different concept, correctly used. A blanket replace would have broken it. ## Something did depend on the gate being dead — exactly one thing `move-path-equivalence.pg.test.ts` → *"UNPROVEN: in-transaction column capacity did NOT reject on EITHER path in this fixture"*. It left the cause open — > something further in (`resolveColumnCapacity`'s limit resolution, or what `countActiveInCapacitySlotAsync` counts as an occupant — a task with no session/agent may not count) keeps the check from firing … This suite does not establish which. — and predicted its own obsolescence (*"if a future change makes this reject, that is the capacity gate coming alive"*). **Neither guess was right; it was the pool id.** Updated to assert the divergence with the answer recorded — **not weakened**. Its fixture also had to start each phase from an empty wip column: once the gate binds, the inline phase's leftovers trip the cap on the *holder* move before the contended move under test runs. `schema-applier.test.ts` failed only in the full-suite run and passes in isolation both with and without the fix — cross-file contamination, not mine. ## Before / after — measured, both directions `maxConcurrent: 1`, real PG store, real `moveTask`: | | flagOFF / no selection | flagOFF / selection | flagON / no selection | flagON / selection | |---|---|---|---|---| | **before** | ADMITTED | ADMITTED | **ADMITTED** ← the bug | REJECTED | | **after** | ADMITTED | ADMITTED | **REJECTED** | REJECTED | The E2E acceptance row asserts **held at cap 1 and admitted at cap 2 on the same fixture**, so it cannot pass by simply never admitting anything. **With the fix reverted that row fails**; the `admitted` case still passes, as it should. The Phase A3 ratchet's two flipped assertions also fail with the fix reverted. Ratchet flipped exactly as its author specified: `DEFECT (R1)` becomes a rejection, and `it.fails` on the invariant becomes a plain `it`. ## ⚠️ This is NOT user-visible yet — please read before merging The premise this was approved on ("once it binds, cards that currently slip through will start being held") **does not hold for this change alone.** The whole capacity block sits inside `if (useWorkflow && workflowIr && fromColumn !== toColumn)`, and `useWorkflow` is `experimentalFeatures.workflowColumns === true` — absent from `DEFAULT_GLOBAL_SETTINGS`, with **no writer anywhere outside tests**. That is Phase A3's R2, still live and now retitled `DEFECT (R2, STILL LIVE)` with the measured matrix recorded in it. So on merge: nothing changes for any real project. Making it actually bind means **also** removing the `useWorkflow` condition — a materially larger, genuinely user-visible change that I have not made unilaterally. Escalated for a decision; if that lands, the changeset here should be re-categorised. ## Review follow-up (48e79ffd9): the convention was still duplicated — swept and ratcheted The first pass added the resolver and routed the transactional gate + counters, but **hold-release still derived the pool independently**. Swept the repo: six sites name the sentinel, **five derive the convention** and now call `resolveCapacityPoolId` (`hold-release.ts:116/118/442/576`, `task-store-helpers.ts:290`). The sixth, `scheduler.ts:1558`, names the default pool as a literal in a capacity *diagnostic* — no selection input, nothing to disagree with — so it keeps the constant. **Does this change hold-release behavior? No, and it was never releasing against the wrong pool.** hold-release computed `x ?? DEFAULT_WORKFLOW_POOL_ID`, which is exactly what the counter buckets under; `moves.ts` (`?? "builtin:coding"`) was the sole disagreeing site, and the first commit moved *it* into agreement with hold-release, not the reverse. `resolveCapacityPoolId(x)` **is** `x ?? DEFAULT_WORKFLOW_POOL_ID`, so every routed site computes an identical value for every input. **No second user-visible change rides along with this PR** — the only behavior delta remains the gate binding on the flag-ON path, which per R2 is still not the path production takes. Evidence: hold-release + capacity suites **43/43 identical before and after**. **The resolver is now the only way to compute a pool id, not merely the newest way.** `scripts/check-capacity-pool-id.mjs` fails on any inline `?? DEFAULT_WORKFLOW_POOL_ID` outside `workflow-capacity.ts`, wired into **both `pretest` and the blocking `test:gate`**. A review note would not have sufficed: the original defect landed in a file that *already imported* the canonical constant. Verified both ways — clean run scans 1124 files and passes; reintroducing the old hold-release expression exits 1 and names the line. ## Review follow-up (a5b675503): the ratchet was rebuilt because it would not have caught the bug The first ratchet matched one spelling (`?? DEFAULT_WORKFLOW_POOL_ID`) and the real defect used another (`?? "builtin:coding"`). **Verified: reintroducing the original defect and running the old checker exits 0.** A guard that reports success without checking is worse than no guard — it stops anyone looking. Rebuilt on the TypeScript AST with two rules. **Rule 1 (sink):** a value reaching a capacity counter's `workflowId` must come from `resolveCapacityPoolId`, or a local initialized from it — so it fires on the original defect regardless of which literal was used, on one line or twenty. **Rule 2 (sentinel):** no `??` onto the sentinel at any qualification depth or as its raw value; multiline is one AST node and caught by construction. `?? "builtin:coding"` is deliberately *not* banned outright — it is the legitimate default for a *workflow* id in ~8 places, and is only a bug when it reaches a capacity pool. **Fails closed three ways** that previously reported success without inspecting: unreadable file, unparseable file, and an empty file listing (the old script would have printed a green tick off a broken glob). **Acceptance was not "passes on main".** Each form was reintroduced into the real source and confirmed to fail: the original defect in `moves.ts`, a multiline fallback, and a deeply qualified sentinel. All are pinned in `capacity-pool-id-check.test.ts` (12 cases: 7 must-catch starting with the reduced actual pre-fix `moves.ts`, 4 must-not-flag, 1 fail-closed) so the guard cannot silently narrow again. Also added to `pretest:full`, which had omitted it. ### Follow-up (0be8df6ea): a dead rule found by fixing a test title Splitting the mislabelled fail-closed test surfaced more than a mislabel: **`ts.createSourceFile` is error-tolerant and does not throw on malformed syntax**, so the `try/catch` behind the `unparseable` rule was unreachable and that rule could never fire. The earlier "fails closed three ways" claim was overstated — the guard advertised a capability it did not have. Detection now reads `sf.parseDiagnostics`; a partial AST can silently lack the `??` nodes and sink calls the rules look for, so "did not parse" must not read as "inspected and clean". Mutation-verified: reverting the detection fails that case and only that case. Test-file exclusion also moved to the repo's `{test,spec}.{ts,tsx}` guideline shape — a `.spec.ts` under `packages/<pkg>/src/` was being scanned as production source. Verified both ways: the `.spec.ts` is skipped, and the identical content in a non-test file is still caught, so the exclusion is scoped rather than a hole. ## Verification - engine + core `tsc --noEmit` clean - `pnpm test:gate` green (299 + 10 + 71) - E2E 20/20; capacity + move-path suites 14/14 - full core PG: **1037 passed / 3 failed** — all three reproduce with the fix stashed (pre-existing) - engine-default: **279 failed** vs **280 at baseline** with the fix stashed — pre-existing red lane, no regression - hold-release + capacity suites: **43/43 identical before and after** the resolver routing - `check-capacity-pool-id` ratchet: 14/14 regression cases; clean over 1124 files; exits 1 on the original defect, a multiline fallback, and a deeply qualified sentinel reintroduced into real source 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Fixed capacity-limit accounting when workflow selection is missing by consistently deriving the correct capacity pool id. * Made capacity enforcement align across move and hold/release paths, rejecting over-limit moves with `capacity-exhausted`. * **Tests** * Updated PostgreSQL and added an E2E scenario to verify the corrected in-transaction gating behavior at `maxConcurrent` limits of 1 and 2. * **Chores** * Added an automated guard to detect inconsistent capacity pool id fallback patterns in code. * **Public API** * Exposed `resolveCapacityPoolId` for consistent capacity pool id derivation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
034827f251 |
FN-8623: restore CDP touch geometry test lane
Restore a dedicated Chromium CDP lane for dashboard touch-geometry coverage. - Add an opt-in touch-geometry test command and isolated Vitest project. - Keep the browser-dependent spec out of deep and quality backfill collection. - Document browser discovery, port, and single-collection requirements. Files changed: docs/testing.md | 10 ++- packages/dashboard/package.json | 1 + .../__tests__/dashboard-test-config-guard.test.ts | 71 +++++++++++++++++++++- .../task-modal-touch-resize-browser.test.ts | 5 ++ packages/dashboard/vitest.config.ts | 28 ++++++++- scripts/lib/test-inventory-spec.json | 3 +- 6 files changed, 114 insertions(+), 4 deletions(-) Fusion-Task-Id: FN-8623 Fusion-Task-Lineage: eafd7497-9302-49a4-8e9e-aa93c9f56a6f Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
93a403af67 |
fix(dashboard): import delete-attribution constants via browser-safe subpath
The client bundle aliases `@fusion/core` to the leaf `core/src/types.ts` to keep Node-only dependencies out of the browser, so a package-root import of `FUSION_CLIENT_HEADER`/`FUSION_DASHBOARD_UI_CLIENT` typechecked but failed `vite build`: "FUSION_CLIENT_HEADER" is not exported by "../core/src/types.ts" Follow the documented pattern instead of widening the root alias: declare a `./task-delete-attribution` subpath export, add the matching Vite alias ahead of the broader `@fusion/core` key (Vite matches in order), register the module in the browser-safe-core allowlist, and import the subpath from the client. `task-delete-attribution.ts` has no imports at all, so it is a safe leaf. `app/utils/detectContentLanguage.ts` already warned about exactly this trap; the miss was mine for verifying with typecheck, lint and test:gate but not `pnpm build`, which is one of the four checks CI blocks on. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
c7fa02f370 |
FN-8597: restore executor task-done invariant coverage
Restore the quarantined executor graph-completion invariant suite with real foreach projections. - Exercise complete and partial expanded workflow-step projections at the merge boundary. - Remove the rescued invariant suite from Vitest quarantine and clear its ledger entry. - Extend the shared executor logger mock with the debug method required by the integration tip. Files changed: .../__tests__/executor-task-done-invariant.test.ts | 267 +++++++++++++++++++-- .../engine/src/__tests__/executor-test-helpers.ts | 7 + packages/engine/vitest.config.ts | 7 - scripts/lib/test-quarantine.json | 8 +- 4 files changed, 254 insertions(+), 35 deletions(-) Fusion-Task-Id: FN-8597 Fusion-Task-Lineage: 05a08e31-7da0-4c93-86a0-9baf8db7ce52 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
084dd76d64 |
feat(release): write release copy with opus and draft tweets for betas too
- distillation runs on opus (env-overridable) with a 4-minute budget - highlights must name the surface and outcome; vague filler is banned - tweets target 200-280 chars with concrete changes and varied structure - betas get their own tester-facing draft carrying `fn update --channel beta` - prerelease openers read as "Fusion 0.74 beta:" instead of "Fusion 0.74-beta.0" |
||
|
|
330e4970f0 |
refactor(release): move the version-anchor package.json rewrite into the shared lib
Makes the re-anchor file mutation unit-testable alongside the anchor decision. |
||
|
|
dba9746287 |
fix(release): base the next beta on the shipped stable version
After a stable release, main stayed inside the old pre-mode cycle, so the next beta numbered below the published stable (v0.73.0-beta.7 after v0.73.0) and the dev checkout kept reporting the last beta. - beta releases re-anchor a stale pre-mode cycle on the newest stable tag - both channels refuse a version at or below the newest published stable - stable promotion now back-merges release into main automatically (fail-soft on conflict) so the local dev version is the stable version |
||
|
|
c5e9a7956a |
fix(ci): stop watchdog false-kills of the grown core slice; actually upload timing artifacts
- Shard watchdog floor 25min (was 15): the July PG-cutover test growth pushed @fusion/core past 900s on contended CI runners; run 30075604930 killed a healthy core run at exactly the floor because the 27-day-old (still "fresh") undercounting timings snapshot tightened the budget to it — the same false-kill class as the 5->15min raise. Floor pin + in-band example updated. - full-suite.yml timing upload: include-hidden-files — the .timings/ dot-dirs were silently excluded by upload-artifact@v4, so the step has uploaded nothing since it was added and the snapshot could never be refreshed from CI. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
ff165ecb5a |
fix: scope beta release notes to that beta's changesets; stable keeps full-cycle rollup
Pre-mode preserves consumed changeset .md files, so every beta's distilled notes and GitHub prerelease body aggregated the entire cycle since the last stable (v0.73.0-beta.4 shipped the full 0.72.0→0.73.0 aggregate). Betas now distill only changesets not yet recorded in pre.json's consumed ledger, and fail loudly when a beta would ship nothing new. Stable promotion still feeds the full preserved set, keeping its notes an explicit rollup of every beta in the cycle. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
42fe154abe |
FN-8533: add mobile planning comment actions
Make contextual plan comments reachable from the mobile action rail and restore focus after editing. - Add responsive desktop and mobile comment triggers with contextual styling and documentation. - Preserve the selected quote and restore the remounted trigger after canceling or adding a comment. - Cover action placement, focus restoration, and browser interaction behavior. Files changed: .changeset/fn-8533-mobile-planning-comments.md | 7 ++ docs/dashboard-guide.md | 2 +- .../dashboard/app/components/PlanningModeModal.css | 20 ++++ .../dashboard/app/components/PlanningModeModal.tsx | 44 ++++++- .../__tests__/PlanningModeModal.css.test.ts | 10 ++ .../PlanningModeModal.planning-flow.test.tsx | 40 +++++-- .../PlanningModeModal.ui-interactions.test.tsx | 5 + .../dashboard/app/planning-browser-e2e-fixture.tsx | 3 +- .../src/__tests__/planning-browser-e2e.test.ts | 133 +++++++++++++++++++-- packages/dashboard/vitest.config.ts | 11 +- scripts/lib/test-quarantine.json | 5 - 11 files changed, 242 insertions(+), 38 deletions(-) Fusion-Task-Id: FN-8533 Fusion-Task-Lineage: e0d561be-ecc8-456e-807e-a1dc677b5d9c Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
1e05793876 |
fix(ci): green full-suite bookkeeping after origin/main cutover (#2392)
## Summary Restores green merge-gate and package-default suites after repeated `origin/main` merges brought workflow-graph ownership cutover drift into CI. - Align engine/dashboard/core tests with post-cutover contracts (`moveTaskIf`/`deleteTaskIf`, graph handoff, worktree-pool reclaim via `removeWorktree` + `RemovalReason`, multi-step RESUMING parse, soft-pause merge requester, graph-terminal failure surfaces). - Small product fixes needed for real regressions uncovered by the suite: soft-delete refuse before graph routing, skip DUPLICATE step-heading withhold when an explicit marker is present, PG schema applier guards, and related bookkeeping (research promote tool inventory / migration seed, stop shell `psql` in PG admin DDL). - Quarantine/ledger hygiene only where required by standing rules; no timeout/worker appeasement. ## Verification - `pnpm test:gate` ×2 green - `@fusion/engine` full package suite green (~9083 tests) - Targeted core/dashboard clusters green (schema applier, agent-runs UI, settings descriptions, mobile close) ## Test plan - [x] `pnpm test:gate` (twice) - [x] `pnpm --filter @fusion/engine test` - [ ] CI full suite / PR checks on this branch - [ ] Confirm no unrelated product behavior changes beyond the listed regression fixes <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added support for `roadmap-item` native structure kinds, including native structure embeds and metadata validation. * Added Stable and Beta release channel options in General settings. * Added per-action reporting target configuration with clearer “unset” guidance. * **Bug Fixes** * Improved heartbeat/prompt behavior when patrol is disabled. * Prevented deleted tasks from continuing through execution. * Made recovery for explicit duplicate redirects more permissive. * Hardened database migration and test database cleanup to reduce flaky failures. * **Documentation** * Updated settings text for release channels, reporting targets, and inheritance/unset behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
7911fdb9b1 |
fix(release): preserve distilled changelog summaries across releases
syncRootChangelog rewrote every prior release from raw package notes, so only the latest distilled Highlights view survived. Re-emit already-distilled bodies on sync, keep the archive pointer outside version sections, and restore wiped summaries from release history. |
||
|
|
eef5eb751e |
FN-8453: unify concurrency accounting and indicators
Unify live-agent capacity accounting across engine and dashboard. - Derive Running and Waiting from workflow traits and durable agent liveness. - Apply unified limits to planner, executor, and merge admission while updating dashboard indicators. - Remove duplicate concurrency controls and document the unified operator model. Files changed: .changeset/fn-8453-unified-concurrency.md | 7 + docs/agent-tool-surface-full-loop.md | 4 +- docs/architecture.md | 2 +- docs/dashboard-guide.md | 4 +- docs/settings-reference.md | 4 +- .../skill/fusion/references/fusion-capabilities.md | 4 +- .../core/src/__tests__/live-agent-count.test.ts | 91 ++++---- packages/core/src/index.gate.ts | 6 + packages/core/src/index.ts | 6 + packages/core/src/live-agent-count.ts | 107 ++++++--- packages/dashboard/app/App.tsx | 28 ++- packages/dashboard/app/api/board-workflows.ts | 2 + packages/dashboard/app/components/Column.tsx | 6 +- .../dashboard/app/components/EngineControlMenu.tsx | 26 --- .../dashboard/app/components/ExecutorStatusBar.tsx | 38 ++- .../dashboard/app/components/SettingsModal.tsx | 1 - .../app/components/__tests__/Column.test.tsx | 6 +- .../__tests__/EngineControlMenu.test.tsx | 10 +- .../__tests__/ExecutorStatusBar.test.tsx | 32 ++- .../command-center/CommandCenterControls.tsx | 26 --- .../settings/sections/SchedulingSection.search.ts | 9 - .../settings/sections/SchedulingSection.tsx | 13 -- .../app/hooks/__tests__/useExecutorStats.test.ts | 12 +- packages/dashboard/app/hooks/useExecutorStats.ts | 50 ++-- .../src/__tests__/project-store-resolver.test.ts | 11 +- packages/dashboard/src/project-store-resolver.ts | 14 +- .../register-config-mcp-pi-settings-routes.ts | 3 +- packages/engine/src/__tests__/concurrency.test.ts | 123 +++++++++- .../engine/src/__tests__/project-engine.test.ts | 34 +++ packages/engine/src/__tests__/triage.test.ts | 7 +- packages/engine/src/concurrency.ts | 207 ++++++++++++++++- packages/engine/src/project-engine.ts | 151 ++++++++++-- packages/engine/src/scheduler.ts | 82 ++++++- packages/engine/src/triage.ts | 254 +++++++++++++-------- .../lib/dashboard-browser-safe-core-modules.json | 5 + 35 files changed, 991 insertions(+), 394 deletions(-) Fusion-Task-Id: FN-8453 Fusion-Task-Lineage: 12cfa5df-675d-4fce-b17e-932376544239 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
634295c72f |
fix(planning): keep questions out of mailbox
Keep planning questions in their dedicated surface while preserving ntfy alerts, and tighten the desktop planning panes without changing compact or shared layouts. |
||
|
|
860533eff2 |
FN-8402: extract config, MCP, and Pi settings routes
Extract config, MCP, and Pi-settings handlers into a dedicated dashboard route registrar. - Move seven configuration and MCP endpoint handlers out of the API-route orchestrator. - Preserve registrar mount precedence and document the expanded route map. - Add registrar coverage and update the inline-route modularity baseline. Files changed: .../src/__tests__/mcp-documentation.test.ts | 2 +- packages/dashboard/src/routes.ts | 303 +-------------------- packages/dashboard/src/routes/README.md | 84 +++--- .../register-config-mcp-pi-settings-routes.test.ts | 61 +++++ .../src/routes/create-api-routes-mount-sequence.ts | 2 +- .../register-config-mcp-pi-settings-routes.ts | 275 +++++++++++++++++++ scripts/lib/routes-modular-baseline.json | 2 +- 7 files changed, 385 insertions(+), 344 deletions(-) Fusion-Task-Id: FN-8402 Fusion-Task-Lineage: f5f71f64-03cf-41cf-9fb2-33046b0c04bf Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
e1dddcbfae |
FN-8404: extract dashboard domain route registrars
Move maintenance, AI text assistant, and setup/activity endpoints into focused dashboard route registrars. - Register the extracted domains in the API mount sequence. - Preserve route precedence and document registrar responsibilities. - Add registrar coverage and refresh the modular-route baseline. Files changed: packages/dashboard/src/routes.ts | 948 +-------------------- packages/dashboard/src/routes/README.md | 82 +- .../register-ai-text-assistant-routes.test.ts | 49 ++ .../register-setup-activity-routes.test.ts | 54 ++ .../register-system-maintenance-routes.test.ts | 48 ++ .../src/routes/create-api-routes-mount-sequence.ts | 8 +- .../routes/register-ai-text-assistant-routes.ts | 327 +++++++ .../src/routes/register-setup-activity-routes.ts | 320 +++++++ .../routes/register-system-maintenance-routes.ts | 320 +++++++ scripts/lib/routes-modular-baseline.json | 2 +- 10 files changed, 1176 insertions(+), 982 deletions(-) Fusion-Task-Id: FN-8404 Fusion-Task-Lineage: d6b5be1f-e011-47fc-a7f8-5df89893766f Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
fe9269b57b |
fix(i18n): restore Chinese roadmap duplicate labels (#2358)
## Summary - restores the missing Simplified Chinese duplicate-roadmap report label - restores the missing Traditional Chinese duplicate-roadmap report label - adds a patch changeset for the catalog correction ## Test plan - `pnpm --filter @fusion/i18n test` (5 files, 29 tests) - `pnpm build` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Restored Simplified and Traditional Chinese translations for duplicate roadmap report titles. * Updated the roadmap reporting UI text to clarify when a report is already in the roadmap and ask whether to add the user’s data point. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
5c67b19cb2 |
FN-8394: rescue deterministic quarantined tests
Restore reliable test coverage and delete quarantined tests that could not be rescued. - Replace process- and database-dependent tests with bounded dependency seams - Restore stabilized CLI, dashboard, and plugin test coverage - Remove unrescuable bundle and merge-worktree test suites and clear the quarantine ledger Files changed: packages/cli/src/__tests__/bundle-output.test.ts | 519 ------------ .../src/commands/__tests__/task-lock-retry.test.ts | 10 + packages/cli/vitest.config.ts | 8 - .../TaskDetailModal.tab-persistence.test.tsx | 2 +- .../__tests__/TaskDetailModal.test-helpers.ts | 7 + .../src/__tests__/dev-server-process.test.ts | 391 ++++----- packages/dashboard/src/dev-server-process.ts | 22 +- packages/dashboard/vitest.config.ts | 21 +- .../merge-reuse-task-worktree.slow.test.ts | 876 --------------------- packages/engine/vitest.config.ts | 7 - .../src/__tests__/process-lifecycle.test.ts | 21 +- .../fusion-plugin-grok-runtime/vitest.config.ts | 2 - .../src/__tests__/async-quality-store.pg.test.ts | 148 +++- plugins/fusion-plugin-quality/vitest.config.ts | 3 +- scripts/lib/test-quarantine.json | 43 +- 15 files changed, 323 insertions(+), 1757 deletions(-) Fusion-Task-Id: FN-8394 Fusion-Task-Lineage: e949b33e-b8d5-4f73-a002-e550b97ee125 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
b07f207b00 |
FN-8403: extract automation and plugin route registrars
Move automation and plugin HTTP handlers out of the routes aggregator into focused domain modules. - Extract live automation streaming and step-execution helpers - Register automation, routine, webhook, and plugin handlers through the domain registrar - Document plugin route ordering and update modular-route baselines Files changed: packages/dashboard/src/routes.ts | 2779 ++------------------ packages/dashboard/src/routes/README.md | 3 +- .../dashboard/src/routes/automation-live-run.ts | 322 +++ .../src/routes/automation-step-execution.ts | 445 ++++ .../src/routes/plugin-bundled-runtimes.ts | 88 + .../src/routes/register-plugins-automation.ts | 1540 ++++++++++- scripts/lib/routes-modular-baseline.json | 2 +- scripts/line-count-baseline.json | 2 +- 8 files changed, 2604 insertions(+), 2577 deletions(-) Fusion-Task-Id: FN-8403 Fusion-Task-Lineage: 2072d39b-6335-4163-a56a-7d418edc9095 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
e0e395a715 |
FN-8365: enforce dashboard route registrar mount order
Keep dashboard API registration modular while preserving Express route precedence. - Route all top-level dashboard registrars through a runtime-checked canonical mount sequence - Add mount-order and inline-route-ratchet coverage with CI enforcement - Document registrar ownership and mount-order conventions Files changed: .github/workflows/pr-checks.yml | 3 + AGENTS.md | 2 + package.json | 5 +- packages/dashboard/src/routes.ts | 136 +++++----- packages/dashboard/src/routes/README.md | 276 ++++++++++----------- packages/dashboard/src/routes/__tests__/create-api-routes-mount-order.test.ts | 66 +++++ packages/dashboard/src/routes/create-api-routes-mount-sequence.ts | 54 ++++ scripts/__tests__/check-routes-modular.test.mjs | 28 +++ scripts/check-routes-modular.mjs | 65 +++++ scripts/lib/routes-modular-baseline.json | 3 + 10 files changed, 433 insertions(+), 205 deletions(-) Fusion-Task-Id: FN-8365 Fusion-Task-Lineage: 9c36a263-ed5e-4524-8ea5-71ed3f3e34d9 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
b2c784b3f8 |
FN-8381: remove flaky dist-barrel test
Remove the repeatedly quarantined extension dist-barrel test while retaining source-level listing coverage. - Delete the CPU-bound dist-barrel regression test after its fourth quarantine cycle. - Remove its quarantine exclusion and ledger entry. - Document retained source-level formatting and truncation coverage. Files changed: .../src/__tests__/extension-dist-barrel.test.ts | 204 --------------------- packages/cli/src/__tests__/extension.test.ts | 4 +- packages/cli/vitest.config.ts | 6 +- scripts/lib/test-quarantine.json | 5 - 4 files changed, 6 insertions(+), 213 deletions(-) Fusion-Task-Id: FN-8381 Fusion-Task-Lineage: ba6e61e1-fba1-4308-9d9d-1d3f387aa5e9 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
965f15f5ca |
FN-8368: enforce browser-safe dashboard core imports
Prevent dashboard code from bypassing Vite's browser-safe core boundary. - Add an allowlist-backed scanner for dashboard core value imports, including dynamic template imports. - Run the scanner in test and merge-gate prechecks, with regression coverage and import guidance. - Document reviewed browser-safe core leaves and Vite alias requirements. Files changed: docs/dashboard-guide.md | 6 + package.json | 6 +- packages/dashboard/vite.config.ts | 5 + ...no-node-only-core-imports-in-dashboard.test.mjs | 80 ++++++++++ ...heck-no-node-only-core-imports-in-dashboard.mjs | 167 +++++++++++++++++++++ .../lib/dashboard-browser-safe-core-modules.json | 59 ++++++++ 6 files changed, 320 insertions(+), 3 deletions(-) Fusion-Task-Id: FN-8368 Fusion-Task-Lineage: 13e70672-d1da-430c-a360-0a714ad33d9f Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
845d82ec67 |
fix(ci): restore full-suite after verification request + lucide mock gaps (#2332)
## Summary Main Full Suite shards have been red after recent landings. Root causes: 1. **Executor tests** — `execute()` now polls `getTaskVerificationRequestAsync` (chat-enqueued verification). Shared `createMockStore()` (and soft-delete inline store) lacked the method, so nearly every execute-path suite failed with `is not a function`. 2. **TaskDetailModal suites** — `NativeStructurePreview` imports `Map` / `Lightbulb` / `BarChart3` / `Target` / `CircleAlert` from lucide; the shared TaskDetail lucide mock omitted them, so suites failed at import. 3. **Grok process-lifecycle** — 15s bound stress timed out under full-suite load without product-bug evidence → quarantined on sight per AGENTS.md. ## Test plan - [x] `executor-task-done-blocked`, `executor-fast-mode-workflows`, concurrent-execute race - [x] `executor-step-session`, plan-only scope leak, review-step indexing - [x] `TaskDetailModal.create-pr` + `TaskDetail.mobile-transition` - [ ] Full Suite CI on this PR <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Added `html2canvas` support in the dashboard to enable HTML-to-canvas rendering needed for visual structure previews. * **Tests** * Updated task execution test mocks to handle task verification-request flows reliably. * Improved task deletion safeguard coverage and related execution behavior checks. * Enhanced test stubs to support structure preview rendering elements during modal-related tests. * **Chores** * Quarantined a timing-sensitive process lifecycle test and refreshed quarantine tracking to improve full-suite stability. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
de2669fd17 |
fix(ci): mock createAgentTask for route tests; quarantine merge-reuse slow flake (#2327)
## Summary - Default `createAgentTask` in dashboard `@fusion/engine` mock so planning/subtask create routes return 201 (FN-8277). - Mock `findRecentTasksBySourceParentTaskId` on github/planning route stores. - Quarantine `merge-reuse-task-worktree.slow.test.ts` (engine-slow load flake, run 29663725381). ## Evidence - Prior full green: Full Suite run **29663526777** on #2325. - Tip red class: routes-github/planning 500 + engine-slow lease residual. ## Test plan - [x] routes subtask create-tasks / shared branch groups tests green locally - [ ] Full Suite all 4 shards + engine-slow green on main tip after merge <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved task and subtask creation test coverage to correctly handle parent-scoped duplicate checks. * Updated test behavior to return reliable task creation results. * **Tests** * Quarantined a flaky integration test from the slow test suite to improve test run reliability. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
569abcc258 |
fix(ci): quarantine CLI bundle-output and dist-barrel load flakes (#2325)
## Summary Quarantine `bundle-output.test.ts` and `extension-dist-barrel.test.ts` after tip Full Suite shard 4 (run 29662476909) hit package-lane-only desktop build ENOENT + 10s beforeAll timeout. Prior green Full Suite: run 29662309385 on #2323. ## Test plan - [ ] Full Suite all 4 shards green on main after merge |
||
|
|
6268433d37 |
fix(ci): parent-task uniqueness mocks, roadmap search index, flake quarantine (#2323)
## Summary - FN-8277 parent-scoped uniqueness: mock `findRecentTasksBySourceParentTaskId` in heartbeat/triage/split suites. - FN-8326: index `reportRoadmapDedup` in Settings search. - Quarantine re-flaked `dev-server-process` under full-suite API load (run 29661202279). ## Test plan - [x] Targeted createTask / search-index tests green locally - [ ] Full Suite all 4 shards green on main after merge |
||
|
|
89b42ed1d6 |
fix(ci): ideation heartbeat tools, review-artifact i18n, tab-persist quarantine (#2321)
## Summary - Heartbeat customTools inventory includes FN-8295 ideation tools (63 total). - Non-en i18n parity for FN-8286 `reviewArtifacts` Command Center + settings keys. - Quarantine `TaskDetailModal.tab-persistence.test.tsx` (CI load flake; green focused thrice). ## Test plan - [x] heartbeat expected-tools case green - [x] i18n-gate-coverage + parity green - [ ] Full Suite all 4 shards green on main after merge |
||
|
|
17ee1a8040 |
fix(ci): restore Full Suite bookkeeping after concurrent main landings (#2316)
## Summary - Align heartbeat `customTools` expectations with FN-8294 mission hierarchy tools (43→58). - Refresh `COORDINATION_EXEMPT_TOOLS` snapshot for `fn_mission_list` / `fn_mission_show`. - Backfill `commandCenter.portability.*` for non-en locales and map `reportMode` / `reportModeByAction` / `embeddedPostgresMaxConnections` into settings default-description inventory with i18n help text. - Realign FN-8064 skip-narration unit test with store-owned proactive chat (no tool-side `appendAgentLog`). - Quarantine load-sensitive `async-quality-store.pg.test.ts` (5s timeout + leftover psql under full-suite shard load; run 29657633544). ## Test plan - [x] `pnpm --filter @fusion/engine exec vitest run` gating-classifications + executor-prompt + heartbeat expected-tools case - [x] `pnpm --filter @fusion/i18n exec vitest run` i18n-gate-coverage + parity - [x] `pnpm --filter @fusion/dashboard exec vitest run` settings-default-descriptions - [ ] Full Suite all 4 shards green on main after merge <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Settings** * Added clearer, localized help text for report modes and per-action overrides, including inheritance behavior. * Added advanced embedded database connection-limit settings and validation guidance. * **Localization** * Expanded translations for report settings, database tuning, and organization configuration import/export workflows across supported languages. * **Tests & Maintenance** * Updated test coverage and expectations for expanded tools and reporting behavior. * Quarantined a flaky database-related test. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
6bf20ea249 |
fix(ci): quarantine CLI lock-retry flakes + settle planning tab-lock (#2305)
## Summary - Full Suite after FN-8271 restore turned red again ([29648952207](https://github.com/Runfusion/Fusion/actions/runs/29648952207)): - **shard 4**: `mcp-lock-retry` / `task-lock-retry` 5s timeouts under package-lane load - **shard 3**: planning “never acquires a tab lock…” — `respondToPlanning` never called after Small/Continue - Re-quarantine the two CLI lock-retry files in ledger + `packages/cli/vitest.config.ts` (no timeout appeasement). - Planning tab-lock test: select Small via radio role, wait for checked, longer `waitFor` on respond. ## Test plan - [x] lockstep-cli-quarantine - [x] planning tab-lock interaction test - [ ] Full Suite all 4 shards green on main <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved the reliability of the dashboard planning flow by using more precise controls and bounded waits during automated interactions. * **Tests** * Quarantined two intermittently timing-out CLI integration tests to reduce full-suite instability. * Documented the quarantine reasons and tracking details for the affected tests. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
afb2ed0650 |
FN-8271: restore quarantined CLI tests under shard load
Restore affected CLI and engine tests by removing load-amplifying fixture work and synchronizing fake-timer recovery. - Replace the dist-barrel PostgreSQL fixture with an injected in-memory task store. - Move mission and goal tool coverage to the shared PostgreSQL harness and complete plugin-store mocks. - Return rescued CLI and heartbeat tests to default lanes and clear their quarantine records. Files changed: .../src/__tests__/extension-dist-barrel.test.ts | 90 ++++++++-------------- .../__tests__/extension-mission-goal-tools.test.ts | 27 ++++--- packages/cli/src/commands/__tests__/plugin.test.ts | 11 +++ packages/cli/vitest.config.ts | 21 +---- .../src/__tests__/heartbeat-error-recovery.test.ts | 33 ++++---- packages/engine/vitest.config.ts | 7 +- scripts/lib/test-quarantine.json | 78 +------------------ 7 files changed, 84 insertions(+), 183 deletions(-) Fusion-Task-Id: FN-8271 Fusion-Task-Lineage: 212a3ec7-db6b-4e80-97c3-1c704822cf60 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
e436635abd |
FN-8270: restore PostgreSQL migration quarantine tests
Restore seven PostgreSQL-compatible engine suites to the active test runs. - Model asynchronous insight and goal-store collaborators in reporter and diagnostics tests. - Await PostgreSQL audit reads in merger reliability tests. - Remove the restored suites from Vitest exclusions and the quarantine ledger. Files changed: .../__tests__/backlog-pressure-reporter.test.ts | 19 +++++++---- .../dependency-blocked-todo-reporter.test.ts | 15 ++++++--- .../goal-injection-diagnostics-wiring.test.ts | 15 ++++++--- .../__tests__/merger-cwd-fallback-removed.test.ts | 13 +++++--- .../integration-worktree-state.test.ts | 13 +++++--- .../merge-runner-spawn-enoent-prevention.test.ts | 15 +++++--- .../meta-chain-auto-close.test.ts | 9 ++++-- packages/engine/vitest.config.ts | 20 ++---------- scripts/lib/test-quarantine.json | 37 +--------------------- 9 files changed, 73 insertions(+), 83 deletions(-) Fusion-Task-Id: FN-8270 Fusion-Task-Lineage: 65be82ef-f4d4-4a8a-b3cc-63486ee0823a Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
c0cce18cfb |
fix: QuickEntry agent outside-click + quarantine CLI full-suite cascade (#2291)
## Summary Latest Full Suite after #2290 was green on shards 1–2 and nearly green on 3–4: - **Shard 3:** QuickEntry agent picker outside click left the portal open (product) — capture-phase mousedown + open-token so late `fetchAgents` cannot re-open a dismissed picker - **Shard 4:** `@runfusion/fusion` package-lane cascade (87 failures from `extension-dist-barrel` hookTimeout + lock-retry timeouts under load) — quarantine the 14 observed files on sight (ledger + vitest exclude), no timeout appeasement Also hardens the agent-picker outside-click test. ## Test plan - [x] Local agent picker portal tests green - [ ] PR gate - [ ] Post-merge Full Suite green <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Fixed the Quick Add agent picker so it reliably closes when clicking outside. - Prevented delayed agent-loading results from reopening the picker after it has been dismissed. - Improved the picker’s loading behavior by displaying it immediately while agents are being retrieved. - **Tests** - Added coverage for dismissing the agent picker with an outside click. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
377cb9c90a |
FN-8258: complete PostgreSQL quarantine rescues
Complete PostgreSQL-backed rescue coverage while retaining archived shared-branch landing proof. - Preserve merge details when archiving and restoring tasks for branch-group promotion. - Migrate remaining quarantine tests and mocks to PostgreSQL-aware boundaries. - Remove rescued tests from the engine quarantine configuration and ledger. Files changed: .changeset/fn-8258-pg-quarantine.md | 7 +++ .../core/src/task-store/archive-lifecycle-2.ts | 1 + packages/core/src/task-store/remaining-ops-6.ts | 8 ++- packages/core/src/task-store/serialization.ts | 1 + .../__tests__/agent-tools-intake-column.test.ts | 26 ++++------ .../agent-workflow-tools-exposure.test.ts | 18 +++---- .../engine/src/__tests__/executor-task-done-invariant.test.ts | 33 ++++++------ .../engine/src/__tests__/executor-test-helpers.ts | 7 +++ .../src/__tests__/group-merge-coordinator.test.ts | 43 ++++++++++------ .../hybrid-executor-multi-node-routing.test.ts | 5 ++ .../mission-factory-parity.integration.test.ts | 2 +- .../engine/src/__tests__/routine-runner.test.ts | 56 +++++++++++++-------- .../self-healing-meta-archive-guards.test.ts | 28 +++++------ .../src/__tests__/triage-token-usage.test.ts | 58 +++++----------------- .../__tests__/workflow-graph-task-runner.test.ts | 16 +++--- packages/engine/src/hybrid-executor-gate.ts | 8 ++- packages/engine/vitest.config.ts | 12 +---- scripts/lib/test-quarantine.json | 52 +------------------ 18 files changed, 165 insertions(+), 216 deletions(-) Fusion-Task-Id: FN-8258 Fusion-Task-Lineage: 121c2b52-ad50-4475-b925-7a36ecfaf28b Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
2ab0413c07 |
fix: make OMP process lifecycle tests full-suite safe (#2290)
## Summary After #2289, Full Suite shard 4 still failed on the **OMP** twin of the Grok process-lifecycle stress test (`import("../index.js")` × 15 under shard transform load → 5s timeout). Apply the same fix class as grok-runtime: - Symbol.for exit reaper on `process-manager` - Stress test reimports that module - 15s timeout for cold transform ## Test plan - [x] Local OMP process-lifecycle green - [ ] PR gate - [ ] Post-merge Full Suite <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Improved cleanup of OMP ACP processes when the application exits. - Prevented duplicate exit handlers and excess listener growth during runtime reloads. - Preserved reliable process lifecycle behavior under repeated module loading. - **Tests** - Added lifecycle coverage for repeated process-manager reloads. - Optimized the stress test to complete more efficiently while retaining cleanup assertions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
e24f765495 |
FN-8252: rescue quarantined engine tests
Restore non-mechanical engine coverage with PostgreSQL-safe test fixtures and awaited overseer audit writes. - migrate eligible engine tests to shared PostgreSQL harnesses and restore their Vitest coverage - harden mission and advisory reporting paths for async persistence and observable failures - await the production planner-overseer audit callback and verify the start() wiring preserves persistence Files changed: .../__tests__/mission-autopilot-end-to-end.test.ts | 27 ++-- .../engine/src/__tests__/mission-autopilot.test.ts | 4 +- .../planner-overseer-intervention-wiring.test.ts | 39 +++--- .../engine/src/__tests__/project-engine.test.ts | 138 ++++++++++++++++----- .../unlinked-missions-advisory-reporter.pg.test.ts | 51 ++++++++ .../unlinked-missions-advisory-reporter.test.ts | 20 ++- packages/engine/src/mission-execution-loop.ts | 27 ++-- packages/engine/src/project-engine.ts | 41 +++--- .../src/unlinked-missions-advisory-reporter.ts | 23 ++-- packages/engine/vitest.config.ts | 6 +- scripts/lib/test-quarantine.json | 27 +--- 11 files changed, 260 insertions(+), 143 deletions(-) Fusion-Task-Id: FN-8252 Fusion-Task-Lineage: 4f86ce7e-11a2-4704-a5d1-00e0a8c1448e Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
c43fdbb520 |
FN-8245: stabilize dashboard focus and planning tests
Make dashboard test execution deterministic and restore quarantined coverage. - Defer oversight-menu autofocus until the opening frame and cover both breakpoints. - Replace timing-dependent planning stream mocks with deterministic microtasks. - Isolate QuickEntryBox focus state and re-admit restored dashboard tests. Files changed: .../dashboard/app/components/TaskDetailModal.tsx | 15 ++- .../PlanningModeModal.planning-flow.test.tsx | 132 ++++++++++++++------- .../components/__tests__/QuickEntryBox.test.tsx | 13 ++ .../TaskDetailModal.oversight-mobile.test.tsx | 19 +-- packages/dashboard/vitest.config.ts | 24 ++-- scripts/lib/dashboard-curated-skiplist.json | 4 + scripts/lib/test-quarantine.json | 20 ---- 7 files changed, 140 insertions(+), 87 deletions(-) Fusion-Task-Id: FN-8245 Fusion-Task-Lineage: cd9b0638-0a6b-4dcf-980a-e90ba72b5db9 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
59815fd563 |
FN-8240: restore dashboard API test coverage
Restore quarantined dashboard API coverage and harden PostgreSQL template setup. - Re-enable 18 dashboard API tests by clearing their quarantine ledger and Vitest exclusions. - Preserve remote tunnel providers in route test mocks. - Prevent PostgreSQL template cleanup races and terminate stale template sessions before copies. Files changed: .../core/src/__test-utils__/pg-test-harness.ts | 28 ++++--- .../src/__tests__/routes-remote-access.test.ts | 7 +- packages/dashboard/vitest.config.ts | 25 ++---- scripts/lib/test-quarantine.json | 90 ---------------------- 4 files changed, 30 insertions(+), 120 deletions(-) Fusion-Task-Id: FN-8240 Fusion-Task-Lineage: 19269246-4eb7-418f-ab0d-bf90ba5dfb49 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
7760d783bd |
fix: green full-suite after getAgentLogCount and inventory drift (#2266)
## Summary - Follow-up after #2229: full suite on main still failed on dashboard curated inventory (21 ungated files) and mass engine failures (`this.store.getAgentLogCount is not a function`). - Harden executor tool-failure cursor capture for minimal/test `TaskStore` adapters (same optional-API pattern as `project-engine`), keep mock fixtures in lockstep, and quarantine inventory-only dashboard files with ledger + vitest exclude. ## Changes - **Executor**: optional `getAgentLogCount` / `getAgentLogs` / `updateTask` at graph entry and trailing-failure detection. - **Mocks**: `createMockStore`, soft-delete guard, post-done continuation, cron `getGlobalSettingsDir`, executor-prompt `bulkCompletionRefusalAt` (FN-8141). - **i18n** (prior commit): es/fr/ko/zh-CN/zh-TW triage-duplicate keys. - **Inventory**: 21 dashboard files → `test-quarantine.json` + `vitest.config.ts` lockstep (VAL-REMOVAL SQLite / load flakes / build-only dist assert). ## Test plan - [x] `node scripts/check-test-inventory.mjs --dashboard-curated` - [x] `pnpm test:gate` - [x] engine: soft-delete, prompt, cron, post-done, tool-failure-retry, and related samples - [x] `@fusion/core` schema-applier + `@fusion/i18n` parity - [ ] Full Suite (non-blocking) on this PR / main after merge <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added localized text for triage duplicate-resolution settings and near-duplicate task actions in Spanish, French, Korean, Simplified Chinese, and Traditional Chinese. - Users can now see translated options and confirmations to keep or delete detected duplicate tasks. - **Bug Fixes** - Improved resilience during task execution and recovery when optional activity-log services are unavailable, preventing avoidable failures during error handling. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
29543a0aac |
FN-8157: add PostgreSQL workflow step-instance persistence
Persist workflow foreach step-instance state through async PostgreSQL store APIs. - Add async save, load, and stale-run pruning operations backed by Drizzle. - Route executor persistence, recovery, and integration projection through async APIs. - Cover PostgreSQL persistence and migrate foreach wiring coverage to the PG harness. - Quarantine unrelated flaky route and triage tests per the test ledger. Files changed: .../workflow-run-step-instances.pg.test.ts | 100 +++++++++++++++++++ packages/core/src/store.ts | 14 ++- packages/core/src/task-store/remaining-ops-6.ts | 109 ++++++++++++++++++++- .../dashboard/src/__tests__/routes-github.test.ts | 14 +-- .../src/routes/register-task-workflow-routes.ts | 18 ++-- packages/engine/src/__tests__/triage.test.ts | 6 +- .../src/__tests__/workflow-foreach-wiring.test.ts | 59 +++++------ packages/engine/src/executor.ts | 57 ++++++++--- packages/engine/src/triage.ts | 4 +- packages/engine/vitest.config.ts | 2 +- scripts/lib/test-quarantine.json | 7 +- 11 files changed, 315 insertions(+), 75 deletions(-) Fusion-Task-Id: FN-8157 Fusion-Task-Lineage: c359f0d3-9191-4d27-aaed-9912419c5c27 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
478f226a54 |
test: green full-suite CI after main drift (#2229)
## Summary Restores green **Full Suite (non-blocking)** runs on `main`. Recent main merges left i18n key parity, schema baseline bookkeeping (0011→0012), heartbeat tool inventory (FN-8058 `fn_task_logs_read`), and merger whitespace-classification mocks (execFile `git diff -p -w :2: :3:`) out of date, so all four test shards failed. ## Root causes observed on main - **Shard 4 / `@fusion/i18n`**: missing `skipConfirmationDialogs*` + `reviewBudgetExhausted` in non-en locales; orphan `awaitingApprovalPlanReviewReplanCap` - **Shard 3 / `@fusion/core`**: `SCHEMA_BASELINE_VERSION` advanced to `0012` while tests still equated it with `OWNER_PROJECT_ID_SPLIT_VERSION` (`0011`) and omitted `0012` from applied-migration lists - **Shards 1–2 / `@fusion/engine`**: tool count/snapshot drift for `fn_task_logs_read`; merger tests still mocked `git diff-tree` for trivial classification after the execFile `:2:`/`:3:` cutover; mock provider `updateTask` arity drift ## Changes - Locale catalogs: add missing keys, drop orphan key - Schema applier tests: immutable 0011 identity + baseline 0012 lists - Heartbeat + gating snapshots: include `fn_task_logs_read` - Merger unit mocks: recognize `git diff -p -w :2:path :3:path` - Mock provider: accept optional third `updateTask` arg ## Test plan - [x] `pnpm --filter @fusion/i18n exec vitest run` — 23/23 - [x] `pnpm --filter @fusion/core exec vitest run src/__tests__/postgres/schema-applier.test.ts` (immutable + automation upgrade) — pass - [x] `pnpm --filter @fusion/core exec vitest run` project-identity + satellite-fusiondir — pass - [x] Engine suites from failed CI shards (file-scoped, hermes/openclaw/paperclip/grok, reliability post-finalize/mission, heartbeat, gating, merger recovery/prompt, mock-provider, etc.) — pass - [ ] Full Suite workflow green on merge to main <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Improved project data isolation across backend operations. - Added safer optional toast handling when UI components render outside the full application shell. - Added support for reading task logs during agent heartbeat sessions. - **Bug Fixes** - Prevented runtime probes from hanging and avoided scanning large binary files. - Improved path handling for workspaces with missing descendants. - Corrected task retry state resets and GitHub import/issue-close behavior. - **Style** - Improved chat, terminal, and settings spacing. - Added clearer accessibility labeling for the auto-merge control. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
2142841f0c |
FN-8111: restore reliability test coverage
Restore PostgreSQL-compatible reliability coverage and prevent completed tasks from wedging on stale continuation recovery. - Update reliability fixtures and audit assertions for PostgreSQL-backed stores - Prioritize completed-task handling before stale assistant-continuation retries - Unquarantine the restored meta-archive and continuation reliability suites Files changed: .../explicit-duplicate-marker-sweep.test.ts | 4 ++++ .../meta-archive-guard-composition.test.ts | 26 +++++++++++++++++----- .../post-done-continuation-no-wedge.test.ts | 3 ++- packages/engine/src/executor.ts | 7 ++++++ packages/engine/vitest.config.ts | 4 ++-- scripts/lib/test-quarantine.json | 10 --------- 6 files changed, 36 insertions(+), 18 deletions(-) Fusion-Task-Id: FN-8111 Fusion-Task-Lineage: 8b30b5cb-c160-44e1-8e8c-dd58f4877edc Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
4a797d3804 |
FN-8117: restore explicit duplicate marker sweep coverage
Configure duplicate-marker PG fixtures with canonical FN task IDs so the sweep coverage exercises real deletion paths. - Set taskPrefix to FN for duplicate-marker reliability fixtures. - Remove the corrected test from the PG quarantine ledger and Vitest exclusions. - Document why valid marker IDs are required for this coverage. Files changed: .../explicit-duplicate-marker-sweep.test.ts | 20 +++++++++++++------- packages/engine/vitest.config.ts | 4 +++- scripts/lib/test-quarantine.json | 5 ----- 3 files changed, 16 insertions(+), 13 deletions(-) Fusion-Task-Id: FN-8117 Fusion-Task-Lineage: 3b09cbbe-924c-4e3c-849b-cf7643b0ac0e Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
0b488523c2 |
FN-8104: retire legacy SQLite database fallbacks
Retire legacy SQLite database calls from PostgreSQL-only startup and self-healing paths. - Route plugin schema initialization exclusively through the PostgreSQL executor. - Delegate soft-delete column repair to the PostgreSQL reconciliation seam. - Remove temporary getDatabase allowlist entries and add no-SQLite regression coverage. Files changed: .../postgres/store-safe-defaults.pg.test.ts | 14 +++++- packages/core/src/store.ts | 24 ++++------ .../engine/src/__tests__/plugin-runner.test.ts | 6 --- .../self-healing-fake-overlap-seam.test.ts | 44 +++++++++++++++++++ packages/engine/src/self-healing.ts | 51 +++++----------------- scripts/lib/getdatabase-allowlist.json | 17 +------- 6 files changed, 77 insertions(+), 79 deletions(-) Fusion-Task-Id: FN-8104 Fusion-Task-Lineage: 88dee027-51c3-4c68-94dc-88191fe20330 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |