4ce3ff75b6dd458b9f38608423bba028cfc91921
557 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
4ce3ff75b6 |
fix(ce): the sync queue recorded "done" for a card that finished somewhere else (#2859)
A lane literal the census cannot see — it is a **call argument**, not a
comparison — and the two sibling hooks disagree about how to record the
same kind of fact:
```ts
onTaskMoved: async (task, fromColumn, toColumn, ctx) => {
await store.enqueueSyncAsync({ …, toColumn }); // the real column
},
onTaskCompleted: async (task, ctx) => {
await store.enqueueSyncAsync({ …, toColumn: "done" }); // ← a guess
},
```
On a board whose complete lane is named anything else, the sync-queue
row names a column that board does not have.
## Why fix a field nothing reads
`toColumn` is written to `ce_pipeline_sync_queue` and **never consumed
by any logic** — I checked every reference; it appears only in the
schema, the store's insert, and the row type. It is audit metadata.
That is both why it went unnoticed and why it is worth one token: the
single thing a wrong audit row costs you is the ability to reconstruct
what happened after the fact. A queue that says a card went to `done` on
a board with no `done` is worse than a queue with no column at all,
because it reads as authoritative.
## Structural ratchet, and I would rather say so than imply otherwise
`getCePipelineStore` requires a live PostgreSQL `AsyncDataLayer` and
throws without one, so driving the hook means standing up PG to
re-assert a one-token substitution — against the standing rule on slow
tests. The repo already takes this trade in the same shape
(`packages/core/src/__tests__/analytics-timing-roles-resolved.test.ts`,
whose analytics aggregators have the identical problem).
The test comment states plainly what it does and does not prove: it pins
that the hook reads the card's own column and holds no completion
literal; it does not exercise the write.
Comments are stripped before the negative assertion — the test's own
explanation names the old literal, and a ratchet that matches its own
prose passes forever without checking anything. (That mistake is already
in this program's history, which is why it is guarded here.)
## Revert proof (measured)
Restore `toColumn: "done"` — **both** assertions fail (the positive one
on the missing `task.column`, the negative one on the literal).
## Verification
- `pnpm test:gate` — 161 / 487 / 13 / 71 passed
- `pnpm lint` — clean
- `tsc --noEmit` (`@fusion-plugin-examples/compound-engineering`) —
clean
- full plugin suite — 319 passed across 32 files
🤖 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**
* Sync audit records now capture the task’s actual completion lane
instead of assuming it is named “done.”
* Improved audit accuracy for boards with custom completion lane names.
* **Tests**
* Added coverage to verify completion records use the task’s real
destination lane.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
92d82b7a17 |
fix(guard): the unwired-lane check reported 0 because its question was too weak (#2852)
A guard nobody has proven can fail is a number, not a check. This one
was returning a clean `[]` while **18** real unwired lane declarations
sat on `main` — including one it was specifically built to catch.
## The escape that found it
`diffSnapshots` in the glasses plugin:
```ts
opts: { notifyOnColumns: ReadonlySet<ColumnId>; completeColumnsByTaskId?: ReadonlyMap<...> }
...
const completeColumns = opts.completeColumnsByTaskId?.get(task.id);
const isComplete = completeColumns ? completeColumns.has(task.column) : task.column === "done";
```
**No file anywhere builds that map.** The conversion was decorative —
the literal decided every real poll, so on a renamed board the wearer is
notified of every column transition *except the card finishing*, the one
they care about. The name was already in the guard's vocabulary list,
the declaration was exported and optional; it satisfied every condition
the guard checks, and the guard said nothing.
## Three independent blind spots
| # | blind spot | why it mattered |
|---|---|---|
| 1 | `SCANNED_PACKAGES` omitted `plugins/` | plugins hold lane logic
like anything else — this one resolves workflow IRs and decides what
"finished" means |
| 2 | inline options-object types were not walked | only bare parameters
and *named* interfaces were. Whether a lane answer arrives as a
parameter, an interface property, or an inline field is a style choice —
**a check evadable by a style choice is decorative** |
| 3 | the mention rule was `source.includes(parameter)` **anywhere** |
satisfied by coincidence for any ordinarily-named parameter |
Fixing 1 or 2 alone would still have missed it: **measured on `main`,
the guard found 0 unwired across 1753 files, and 0 again across 2114
once `plugins` was added**, because the shape was invisible too.
### On (3), I proved it on myself
Renaming the unwired parameter from `completeColumnsByTaskId` to
`completeColumns` — a better name, chosen for good reasons — **silenced
the guard instantly**, because 15 unrelated production files declare a
local called `completeColumns`. The check had not been satisfied; it had
been switched off by a rename. That is exactly the failure the code
comment two lines up condemns, committed one edit later.
The fix is the cause, not a name blocklist: a file that never references
`diffSnapshots` cannot be the thing that wires `diffSnapshots`'s
options. Still deliberately loose — a co-occurrence test, not call-graph
analysis — which keeps the low false-positive rate that makes the guard
bearable while removing a false **negative** that scaled with how
ordinary a parameter's name was.
## The 17 this uncovered
Tightening (3) surfaced 17 further unwired declarations across core,
engine and dashboard. **Spot-checked, not assumed**:
`buildUnblockWeightMap` in `task-priority.ts` declares `terminalColumns`
and `reviewColumns`, and the only files that pass either are its own
tests — the production caller silently uses the built-in `{done,
archived}` default. That is the inert-conversion shape this module
exists to name.
They span three other batches, so they are recorded as a **ratcheted
baseline** in the shape `scripts/lifecycle-column-census.mjs` already
uses here — keyed on `file + parameter` so an unrelated edit above them
cannot manufacture a failure. A new one fails immediately; these can
only leave the list. Listing them beats pretending for another week that
they do not exist.
## The glasses fix
`completeColumnsByTaskId` -> a flat `completeColumns` set, matching its
sibling `notifyOnColumns` in the same options object, resolved **once
per poll** by `notifier.ts` via `resolveProjectColumnsForRoles`.
Project-scoped and not per task because this runs on a polling timer
over the whole board — a per-card workflow read would scale with the
board on every tick. Best-effort: a failed resolve leaves the diff on
its documented legacy default rather than dropping a poll.
Still gated by `alsoNotifyOnDone`, which the production caller passes as
`false`, so it remains unobservable at runtime. Wired anyway: the day
someone enables the flag the resolution must already be right — and now
the guard will say so if the wiring is removed.
## Revert proofs (measured, one per fix)
| revert | failure |
|---|---|
| unwire `notifier.ts` | baseline gains `plugins/…/diff.ts
completeColumns` |
| drop the inline-options walk | "covers an INLINE options-object type"
fails `expected [] to deeply equal [ 'completeColumns' ]`, and the repo
scan loses the glasses entry |
| drop the owner scoping | the repo scan loses **all 17** pre-existing
entries |
| restore `task.column === "done"` | both new `diff.test.ts` cases fail
|
The new diff cases assert **both** directions — a card in the resolved
lane fires, and a card in the legacy `done` does *not* once the caller
resolved other lanes. The second is what proves the resolved set
replaces the default rather than being unioned with it.
## Verification
- `pnpm test:gate` — 161 / 487 / 13 / 71 passed
- `pnpm lint` — clean
- `tsc --noEmit` — clean
- guard suite — 9/9; full glasses plugin — 188 passed across 19 files
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
21e688e1f9 |
fix(glasses): ?columns= silently returned the WHOLE board on a renamed board (#2849)
A lane-literal defect the census cannot see — the literals are
**Set/Array members**, not comparisons — in a live plugin, with **no
test coverage on the filter at all**. That absence is how the inversion
survived.
## The bug
```ts
const ALLOWED_COLUMNS = ["triage", "todo", "in-progress", "in-review", "done", "archived"];
function parseColumns(raw) {
const parsed = raw.split(",").filter(v => ALLOWED_COLUMNS.includes(v));
return parsed.length ? new Set(parsed) : null; // ← `null` ALSO means "no filter requested"
}
```
On a board whose lanes are named anything else, every requested id is
discarded, `parsed.length` is `0`, and the function returns `null` —
**the same value it returns when no filter was requested**. The caller
then does `columns ? all.filter(...) : all`, so the route answers `200`
with the **entire board**.
Asking for one column returns all of them. Nothing in the response says
the filter was dropped. The list also still named `triage`, a column U11
deleted, so it described a board that no longer exists in either
direction.
## The fix
No allow-list can be correct here and none is needed. Valid ids are
whatever the project's workflows declare, and `Task["column"]` is
already `ColumnId = Column | (string & {})` — open by construction.
Filtering directly on the requested ids needs **no resolution source at
all**, which is why this literal, unlike the display ordering in
`cards.ts` (documented DELIBERATE-LITERAL: this package depends on
`@fusion/plugin-sdk` only, so there is no IR or store to resolve from),
is a defect rather than a deferral.
**Deliberate behaviour change:** `?columns=nonsense` now returns an
**empty deck** instead of the whole board. "Show me column X" answered
with every column is not a lenient default — it is the bug wearing a
200.
## Revert proof (measured)
Restore the allow-list and **both** new cases fail:
```
FAIL > filters on a RENAMED lane instead of silently returning the whole board
expected [ { id: 'summary', …(5) }, …(2) ] to have a length of 2 but got 3
FAIL > answers an unknown column with an EMPTY deck, not with everything
expected [ { id: 'summary', …(5) }, …(2) ] to have a length of 1 but got 3
```
Both directions are asserted on purpose: a filter that matched *nothing*
would satisfy the renamed-lane case alone while being equally broken.
## Not changed, and why
`plugins/fusion-plugin-even-cards` carries the **identical** bug — I
wrote the fix there first. It was removed from the pnpm workspace
(`858bab2`, "remove `fusion-plugin-even-cards` from the active workspace
package list to avoid duplicate user-facing integrations") and its
README names this plugin as its replacement, so it is not built, tested,
or shipped by anything. Fixing it would only imply it still runs.
Reverted and left alone.
## Verification
- `pnpm test:gate` — 161 / 487 / 13 / 71 passed
- `pnpm lint` — clean
- `tsc --noEmit` (`@fusion-plugin-examples/even-realities-glasses`) —
clean
- full plugin suite — 188 passed across 19 files
- census `--strict` — exit 0 (unchanged: these literals are Set members,
invisible to it)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
||
|
|
d252c4e0cf |
fix(glasses): finished cards were crowding live work off the deck on a renamed board (#2854)
Not a labelling bug. `boardToDeck` filters finished cards out of a deck that is **capped at `maxCards`**, so on a board whose complete lane is named anything but `done`/`archived`, every finished card **consumes a slot and displaces live work**. The wearer sees fewer live tasks the more the team finishes — which reads as "nothing is happening", not as a defect. ```ts const active = tasks.filter((task) => task.column !== "archived" && task.column !== "done") .sort(...) .slice(0, Math.max(0, maxCards - 1)); // ← the cap is what makes this bite ``` ## Correcting an earlier DELIBERATE-LITERAL call This site was marked **DELIBERATE-LITERAL — no resolution source in this package**. That reasoning was inherited from the **deprecated** `fusion-plugin-even-cards`, which depends on `@fusion/plugin-sdk` alone. **This** package lists `@fusion/core` as a runtime dependency and already calls `resolveWorkflowIrById` / `resolveLifecycleColumns` in `quick-capture.ts` and `agent-actions.ts`. The half that *was* right: `cards.ts` genuinely cannot resolve anything — it takes plain `Task` rows. So the lane answer becomes a parameter and the **route** supplies it: one `listWorkflowDefinitions()` read per request regardless of board size, matching how `?columns=` already treats the board as a single pool. Best-effort, so a failed resolve leaves the deck on its documented default rather than failing the request — a slightly-wrong deck beats no deck on a pair of glasses. `terminalColumns` is in the `unwired-lane-parameter` vocabulary, so an unwired version of this parameter fails the build instead of sitting here looking converted. (That guard only learned to see this class in #2852.) ## Revert proof (measured) ``` FAIL > does not let a card in a RENAMED complete lane displace live work expected [ 'summary', 'FN-SHIPPED' ] to deeply equal [ 'summary', 'FN-LIVE' ] ``` `maxCards: 2` in the fixture is load-bearing — one summary card plus exactly one task slot, so an unfiltered finished card **displaces** the live one rather than merely joining it. A larger cap would let both through and the case would pass either way. The second case pins the degraded default (legacy `done`/`archived` still filtered when the caller resolved nothing), since most boards never rename anything. ## Not changed `cards.ts:187` — `task.column === "in-review" ? "In review" : "Moved in"` in the notification title. Genuinely cosmetic: a review card on a renamed board reads "Moved in" instead of "In review". No slot is lost and no decision is made from it, and `notificationCard` has no options object to thread a lane answer through, so converting it means widening a signature for a label. Left with the finding stated rather than silently swept in. ## Verification - `pnpm test:gate` — 161 / 487 / 13 / 71 passed - `pnpm lint` — clean - `tsc --noEmit` (`@fusion-plugin-examples/even-realities-glasses`) — clean - full plugin suite — 188 passed across 19 files - unwired-lane guard — 6/6, no new entries - census `--strict` — exit 0 Touches `board-routes.ts`, which #2849 also edits (different hunk — `parseColumns` vs the handlers), so the two merge cleanly in either order. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
ed6d54485b |
glasses plugin: the review actions could never resolve a review lane (4 guards + 3 invisible destinations) (#2816)
Four agent actions still keyed on literals, with three census-invisible `moveTask` destinations between them. `agent-actions.ts` already had `laneContext`/`destination` from an earlier partial conversion — these were simply never migrated. ## Census | file | main | here | | --- | ---: | ---: | | `plugins/fusion-plugin-even-realities-glasses/src/agent-actions.ts` | 4 | **0** | Plus 3 hardcoded `moveTask` destinations the census cannot see (`requestReview` → `in-review`, `returnToAgent` → `todo`, `retryTask` → `todo`). ## The real finding: this plugin could never resolve a review lane `resolveLifecycleColumns` keys its `review` role on the **`mergeOrchestration` trait alone**. A board whose review column carries only `merge-blocker` and/or `human-review` — the common custom shape, since `merge` is opt-in — resolves **no review lane at all**. So every review-gated action here (`requestReview`, `acceptReview`, `returnToAgent`, `retryTask`) compared against `undefined` and **refused every card**, and `requestReview` had nowhere to move one. This is not a regression from converting them; it is why they *could not* be converted with `lanes.review` as-is. Converting the four guards without noticing would have shipped four actions that fail closed on exactly the boards this program exists to support — a conversion that looks complete, passes its suite, and makes the plugin useless on a custom board. **Widened in `laneContext`, not in the shared resolver.** `resolveLifecycleColumns` is consumed well beyond this plugin, and its `review` role deliberately means "the merge-orchestration column" for the merge queue. The gap is already recorded in `notification-renamed-lifecycle-columns.test.ts` and in #2807 — reconciling the two definitions is a core-level decision, not one to take from a plugin. `mergeBlocker` is preferred over `humanReview` because a card cannot leave a merge-blocking column until the gate clears, which is the closer analogue of the legacy `in-review`. ## The suite caught an over-reach of mine My first version put a blanket `if (degraded) conflict(...)` at the top of `retryTask`, which broke a pinned invariant the test names outright: **"a degraded workflow does not block retries that move nothing."** The status-only retry just clears fields; refusing it because the workflow could not be read breaks a recovery that needs no lane at all. Degraded now blocks only the branches that actually **move**. Same reasoning applied to `acceptReview`, which also moves nothing. The existing `startWork` convention — conflict on degraded — is right precisely *because* it moves. ## Ordering `returnToAgent` and `retryTask` now resolve their destination **before** the field clear. Both cleared first, so a rejected move left the assignee and status — or the worktree, branch and base refs — nulled with the card exactly where it was. That is the fifth instance of this half-applied shape in the audit, and it is rule 3 in the class doc. ## Revert results (measured, each independently) | conversion | reverted → | | --- | --- | | `requestReview` destination | 1 failed — moves to the literal `in-review`, which this workflow does not declare | | `returnToAgent` destination | 1 failed — moves to the literal `todo`, same | Plus a non-vacuous companion: a renamed card *not* in the wip lane must still be refused by `requestReview`, so a gate admitting everything would not pass. ## Verification - Plugin suite — **186/186** - `pnpm test:gate` — 161 + 487 + 13 + 71, green - `tsc` on the plugin — clean - `pnpm lint`, `check:changesets`, census `--strict` — all clean (run explicitly) |
||
|
|
4184fde08d |
batch-cli-plugins: 7 guards — 3 were a foreign enum, and fn pr create refused every card on a renamed board (#2775)
`batch-cli-plugins` — the u7 worker's mega-batch: `packages/cli` + `plugins` + anything left. ## The batch is 7 guards, and 3 of them are not guards at all The census's per-file list gives this batch seven sites. Reading them, **three are a foreign vocabulary the census matches on the string alone**: | file | site | verdict | |---|---|---| | `plugins/fusion-plugin-reports/store/report-store.ts` | `next === "archived"` ×2 | **not a column** — `next` is a `ReportStatus` | | `plugins/fusion-plugin-reports/store/report-types.ts` | `to === "failed" \|\| to === "archived"` | **not a column** — same enum, its own terminal states | The reports plugin has its own status lineage (`draft → generating → review_* → approved → published`, plus `failed`/`archived`) that shares two spellings with the lifecycle vocabulary. A report is not on a board and has no workflow, so resolving an IR there would answer a question nobody asked. All three are marked `DELIBERATE-LITERAL` with the reason at the site. **This cuts the other way from #2763.** That PR establishes the census total as a *floor* (25 membership predicates it structurally cannot see). This is the opposite error in the same number: a foreign enum inflating it. The total is neither a ceiling nor a floor — it is an estimate with error in both directions, and the per-file list is worth reading before trusting a file's count. ## Converted (census before → after, per file) | file | before | after | |---|---|---| | `packages/cli/src/commands/pr.ts` | 1 | **0** | | `plugins/…/even-realities-glasses/notifications/diff.ts` | 1 | **0** | | `plugins/…/reports/store/report-store.ts` | 2 | **0** (deliberate) | | `plugins/…/reports/store/report-types.ts` | 1 | **0** (deliberate) | ### `fn pr create` refused every card on a renamed board The live defect in this batch. The gate was `task.column !== "in-review"`, and its error told the operator to move the task to a column their board does not have: ``` Error: Task must be in 'in-review' column to create a PR (current: signoff) ``` There is no way to satisfy that short of renaming the workflow back. Now resolved through core's `resolveReviewColumns`, and the message names the lanes that actually exist. **The SET, not `lifecycle.review`.** A board may declare more than one review lane, and a card parked in a `humanReview`-only lane is still a card you can open a PR from. A single-id answer keeps refusing those — the same narrowing #2728's review caught in the CLI retry gate, which is why the test pins both lanes. ## Skipped, with the reason **`plugins/fusion-plugin-even-cards` (2 guards) — blocked on packaging, not on analysis.** The defect is real: `boardToDeck` filters with `column !== "archived" && column !== "done"`, so on a renamed board every finished card stays in the deck, fills `maxCards`, and pushes the active cards off the display. The wearer sees a board that never finishes anything. I implemented the fix and **reverted it**: this plugin is not in `pnpm-workspace.yaml` and depends only on `@fusion/plugin-sdk` — it has no `@fusion/core` dependency, so the route cannot reach `resolveTaskLifecycleColumns`. Adding one is a packaging change, which this program's rules put out of scope. Shipping only the injected parameter without a caller was the alternative, and that is precisely the decorative conversion #2759 documents: the census would drop by 2 and the deck would keep the bug. Flagged for whoever owns the plugin's dependency surface. The glasses plugin next door *does* depend on `@fusion/core`, so this is a one-plugin problem, not a plugin-wide one. ## Honest note on the glasses conversion `diff.ts`'s completion branch is **currently unreachable** — the only production caller (`notifier.ts`) passes `alsoNotifyOnDone: false`. So that conversion changes nothing at runtime today. It is converted rather than marked deliberate because the literal is not deliberate: it is wrong, and would ship the bug the day someone turns the flag on. Stated here rather than left for a reviewer to discover. ## Verification - new CLI suite **4 passed**; `pr-command` + `pr-automerge-cleanup` + `bin-pr-router` **35 passed** - glasses plugin **181 passed (19 files)** · reports plugin **110 passed (23 files)** - `pnpm test:gate` — **158 / 10 / 487 / 71** · `pnpm lint` clean · `--strict` exits 0 **Revert proof, measured.** Restoring `if (task.column !== "in-review")` fails 3 of the 4 new cases (`process.exit:1` on both renamed lanes, and the refusal message reverts to naming `in-review`). The unresolvable-workflow case keeps passing — it is the legacy path — so the negative cases alone do not pin the fix and all four are required. ## Handoff to `batch-engine` `packages/engine/src/project-engine.ts` **5 → 0** is finished, green, and pushed as `handoff/project-engine-lanes-for-batch-engine` (`34dbb35209`) for the capacity worker to cherry-pick — it is engine-owned, not mine to land. It fixes two live defects: a card that **had merged** reported as a failed merge to `fn task merge` and the dashboard button (`merged: finalTask?.column === "done"`), and the three post-finalize `column === "done" && mergeConfirmed` fast-path checks, which on a renamed board sent an already-landed card down the bounce path — re-queued, retry-counted, and in the capped branch parked `failed` with its merge sitting on main. Plus `hasAutoHealableVerificationBufferFailure`, which returned false for every card on a renamed board, so a buffer-overflow verification failure was never auto-healed. 8 new tests, revert-proven (restoring the literal fails 4 of 8), gate green. --- ## Completion pass (u7) — the batch is now closed Two workers converged on this branch. I rebased onto the first-landed commit rather than force-pushing over it, took its wording wherever the conclusion was identical, and added what was missing. ### What this pass added 1. **`even-cards` (2 sites)** — the only in-scope file the first pass left open. Marked DELIBERATE-LITERAL: the package depends on `@fusion/plugin-sdk` only, and the SDK does not re-export the lifecycle role helpers, so there is no IR, no store, and no trait flags to resolve *from*. Fixing it properly means the SDK exposing role flags on the task shape it hands plugins — a structural change, out of scope, and recorded at the site as the correct home. Live consequence is cosmetic: a finished card on a renamed board shows as active in the glasses deck. 2. **A red test in the `fn pr create` conversion.** The incoming version rendered `Task must be in 'in-review' to create a PR`, dropping the word `column`. `task.test.ts:3422` pins `must be in 'in-review' column`, so that hunk failed `runTaskPrCreate > exits with error when task not in in-review column`. Restoring the word makes the single-lane message **byte-identical** to the pre-conversion one, which is what a vocabulary conversion should be — the guard's own test now passes unmodified. Marked at the site so it is not "simplified" back. 3. **Duplicate imports** — the two independent conversions each added `resolveWorkflowIrForTask`/`resolveReviewColumns`, which does not compile. Deduped in its own commit. ### Census Measured with `--json` on `origin/main` and on this branch. | file | before | after | action | |---|---|---|---| | `packages/cli/src/commands/pr.ts` | 1 | 0 | converted | | `plugins/fusion-plugin-reports/src/store/report-types.ts` | 1 | 0 | marked | | `plugins/fusion-plugin-reports/src/store/report-store.ts` | 2 | 0 | marked | | `plugins/fusion-plugin-even-cards/src/cards/board-cards.ts` | 2 | 0 | marked | | `plugins/fusion-plugin-even-realities-glasses/.../diff.ts` | 1 | 0 | marked | Backlog **415 → 408** (−7, exactly the in-scope count). Deliberate **40 → 46** (+6 marked); 6 + 1 converted = 7. `--strict` exits 0. **Nothing remains in `cli` + `plugins` + everything-else — there is no follow-up batch behind this one.** ### One note on the `even-realities-glasses` site Worth recording beyond "cannot resolve": its only production caller (`notifier.ts:80`) passes `alsoNotifyOnDone: false`, so that arm is **unreachable today**. Converting it could not have changed observed behaviour either way. ### Verification (measured, on the merged branch) - `pnpm --filter @runfusion/fusion exec tsc --noEmit` → exit 0 - `pnpm lint` → 0 errors - CLI `task.test.ts` → 144 passed, including the `runTaskPrCreate` guard test - `@fusion-plugin-examples/reports` → 110 passed; `even-realities-glasses` → 181 passed **Pre-existing failures, not from this change:** the 5 `runTaskImportFromGitHub` / `runTaskImportGitHubInteractive` tests fail identically on `origin/main` — verified by stashing this diff and re-running (5 failed / 144 passed both ways). --- ## Census audit (unowned follow-on) After closing the batch scope I audited whether the **392** column-backlog number is inflated by foreign vocabularies — the class this batch found in the reports plugin, where `"archived"` is a `ReportStatus` rather than a board lane. If that class were widespread, every remaining batch would be chasing sites that must not be converted. **It is not. The number is real.** A receiver-level pass over all 392 column-category sites found exactly **3** false positives, all in `plugins/fusion-plugin-reports` (`next`, a `ReportStatus`), all now marked in this PR. What was checked and cleared: - **Property-reached foreign enums** (`step.status`, `feature.status`, `mission.status`) — already correctly bucketed into the separate `status` category (185), not the column backlog. Verified against `merge-queue-ops.ts`: 11 lifecycle-spelled literals in the file, census counts **1**, and that 1 is the genuine `.column` guard. - **Bare step-status variables** (`status`, `currentStatus`, `liveStatus` compared to `"done"`/`"skipped"`) — likewise excluded. - **Every other receiver in the backlog** — `to`, `from`, `column`, `fromColumn`, `toColumn`, `latestColumn`, `state`, `preArchiveColumn`. All resolve to genuine task columns. `executor.ts`'s 15 sites were spot-checked line by line: all 15 are real. The gap the classifier genuinely cannot close is a foreign enum held in a **bare variable** — the receiver name carries no type information, so `next === "archived"` is indistinguishable from a lifecycle guard by AST alone. That is why the reports sites need a marker rather than a classifier fix, and it is now documented in `lifecycle-column-census-ast.mjs`'s header alongside the measured scope, so the remaining batches do not re-run this hunt. Census tests: **43 passed**. The change is comment-only. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
3e80dcb8ef |
fix(test): a Vite prefix-match alias silently unresolved a core subpath (greens full-suite shard 1) (#2686)
## What `full-suite.yml` shard 1 on main fails with **zero test failures** — it dies on a resolution error: ``` Failed to resolve import "@fusion/core/task-delete-attribution" from "packages/dashboard/app/api/client.ts" ``` **Root cause.** Vite string aliases match by **PREFIX**. So `find: "@fusion/core"` → `core/src/index.ts` rewrites `@fusion/core/task-delete-attribution` into `core/src/index.ts/task-delete-attribution`, which cannot resolve. The narrower subpath alias has to come *first*. The module exists and *is* correctly declared in `packages/core/package.json` exports — this is purely a test-config trap, and `packages/dashboard/vitest.config.ts` already documents it in a comment. Six configs alias `@fusion/dashboard` (whose `app/api/client.ts` imports that browser-safe leaf) while lacking the narrower alias, so they inherited the trap. This carries the same one-line pattern to all six. ## Measured `dependency-graph` — the project actually red on main: | | Test files | Tests collected | |---|---|---| | before | 3 failed \| 17 passed | 147 | | after | **20 passed** | **180** | **33 tests were never collected** — neither passing nor reported as failing. That is the part worth flagging: an unresolved import removes tests from the run silently, and the shard's own summary printed no `Tests N failed` line at all, which is why this red looked like infrastructure noise rather than a real defect. No regressions: `reports` 110, `cli-printing-press` 41, `compound-engineering` 317, **gate 726** — all green. `pnpm lint` clean. `@fusion/desktop` is `1 failed | 264 passed` **both before and after**; verified pre-existing on clean `origin/main` by reverting just that one config and re-running. Cause is `@fusion-plugin-examples/roadmap` entry resolution, unrelated — **flagged, not fixed.** ## Deliberately not changed Engine's *second* `@fusion/core` alias (the `.gate-bundle/core.mjs` entry) is untouched: that lane bundles core on purpose, and pointing it at source would defeat the isolation the gate bundle exists to provide. ## Full-suite triage this came out of (for whoever owns the rest) Reading the four red shards of the last completed run on main (`30523568756`): | Shard | Real cause | Owner | |---|---|---| | 1/4 | **this PR** — resolution error, 0 test failures | — | | 2/4 | 23 failed: `store-wedge-resolution.pg`, `central-archive-secrets`, `task-delete-caller-attribution`, `task-delete-nonblocking-cleanup` | #2669 / #2675 cover the first two | | 3/4 | **watchdog SIGKILL** mid-`@fusion/engine [1/2]` — no test failures, no summary | unowned | | 4/4 | 17 failed, all in `@runfusion/fusion` CLI (`project.test.ts` 8, `task.test.ts` 5, `extension.test.ts` 2, +2) | unowned | Two of the four shard reds contain **no failing test at all**, so "main's full-suite failure count" cannot be read off the shard conclusions — it has to be read off `Tests N failed` summary lines, and shards 1 and 3 emit none. |
||
|
|
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> |
||
|
|
4819c26349 |
chore(deps-dev): bump jsdom from 27.4.0 to 29.1.1 (#2450)
Bumps [jsdom](https://github.com/jsdom/jsdom) from 27.4.0 to 29.1.1. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/jsdom/jsdom/releases">jsdom's releases</a>.</em></p> <blockquote> <h2>v29.1.1</h2> <ul> <li>Fixed <code>'border-radius'</code> computed style serialization. (<a href="https://github.com/asamuzaK"><code>@asamuzaK</code></a>)</li> <li>Fixed computed style computation when using <code>'background-origin'</code> and <code>'background-clip'</code> CSS properties. (<a href="https://github.com/asamuzaK"><code>@asamuzaK</code></a>)</li> <li>Significantly optimized initial calls to <code>getComputedStyle()</code>, before the cache warms up. (<a href="https://github.com/asamuzaK"><code>@asamuzaK</code></a>)</li> </ul> <h2>v29.1.0</h2> <ul> <li>Added basic support for the ratio CSS type. (<a href="https://github.com/asamuzaK"><code>@asamuzaK</code></a>)</li> <li>Fixed <code>getComputedStyle()</code> sometimes returning outdated results after CSS was modified. (<a href="https://github.com/asamuzaK"><code>@asamuzaK</code></a>)</li> </ul> <h2>v29.0.2</h2> <ul> <li>Significantly improved and sped up <code>getComputedStyle()</code>. Computed value rules are now applied across a broader set of properties, and include fixes related to inheritance, defaulting keywords, custom properties, and color-related values such as <code>currentcolor</code> and system colors. (<a href="https://github.com/asamuzaK"><code>@asamuzaK</code></a>)</li> <li>Fixed CSS <code>'background</code>' and <code>'border'</code> shorthand parsing. (<a href="https://github.com/asamuzaK"><code>@asamuzaK</code></a>)</li> </ul> <h2>v29.0.1</h2> <ul> <li>Fixed CSS parsing of <code>'border'</code>, <code>'background'</code>, and their sub-shorthands containing keywords or <code>var()</code>. (<a href="https://github.com/asamuzaK"><code>@asamuzaK</code></a>)</li> <li>Fixed <code>getComputedStyle()</code> to return a more functional <code>CSSStyleDeclaration</code> object, including indexed access support, which regressed in v29.0.0.</li> </ul> <h2>v29.0.0</h2> <p>Breaking changes:</p> <ul> <li>Node.js v22.13.0+ is now the minimum supported v22 version (was v22.12.0+).</li> </ul> <p>Other changes:</p> <ul> <li>Overhauled the CSSOM implementation, replacing the <a href="https://www.npmjs.com/package/@acemir/cssom"><code>@acemir/cssom</code></a> and <a href="https://github.com/jsdom/cssstyle"><code>cssstyle</code></a> dependencies with fresh internal implementations built on webidl2js wrappers and the <a href="https://www.npmjs.com/package/css-tree"><code>css-tree</code></a> parser. Serialization, parsing, and API behavior is improved in various ways, especially around edge cases.</li> <li>Added <code>CSSCounterStyleRule</code> and <code>CSSNamespaceRule</code> to jsdom <code>Window</code>s.</li> <li>Added <code>cssMediaRule.matches</code> and <code>cssSupportsRule.matches</code> getters.</li> <li>Added proper media query parsing in <code>MediaList</code>, using <code>css-tree</code> instead of naive comma-splitting. Invalid queries become <code>"not all"</code> per spec.</li> <li>Added <code>cssKeyframeRule.keyText</code> getter/setter validation.</li> <li>Added <code>cssStyleRule.selectorText</code> setter validation: invalid selectors are now rejected.</li> <li>Added <code>styleSheet.ownerNode</code>, <code>styleSheet.href</code>, and <code>styleSheet.title</code>.</li> <li>Added bad port blocking per the <a href="https://fetch.spec.whatwg.org/#bad-port">fetch specification</a>, preventing fetches to commonly-abused ports.</li> <li>Improved <code>Document</code> initialization performance by lazily initializing the CSS selector engine, avoiding ~0.5 ms of overhead per <code>Document</code>. (<a href="https://github.com/thypon"><code>@thypon</code></a>)</li> <li>Fixed a memory leak when stylesheets were removed from the document.</li> <li>Fixed <code>CSSStyleDeclaration</code> modifications to properly trigger custom element reactions.</li> <li>Fixed nested <code>@media</code> rule parsing.</li> <li>Fixed <code>CSSStyleSheet</code>'s "disallow modification" flag not being checked in all mutation methods.</li> <li>Fixed <code>XMLHttpRequest</code>'s <code>response</code> getter returning parsed JSON during the <code>LOADING</code> state instead of <code>null</code>.</li> <li>Fixed <code>getComputedStyle()</code> crashing in XHTML documents when stylesheets contained at-rules such as <code>@page</code> or <code>@font-face</code>.</li> <li>Fixed a potential hang in synchronous <code>XMLHttpRequest</code> caused by a race condition with the worker thread's idle timeout.</li> </ul> <h2>v28.1.0</h2> <ul> <li>Added <code>blob.text()</code>, <code>blob.arrayBuffer()</code>, and <code>blob.bytes()</code> methods.</li> <li>Improved <code>getComputedStyle()</code> to account for CSS specificity when multiple rules apply. (<a href="https://github.com/asamuzaK"><code>@asamuzaK</code></a>)</li> <li>Improved synchronous <code>XMLHttpRequest</code> performance by using a persistent worker thread, avoiding ~400ms of setup overhead on every synchronous request after the first one.</li> <li>Improved performance of <code>node.getRootNode()</code>, <code>node.isConnected</code>, and <code>event.dispatchEvent()</code> by caching the root node of document-connected trees.</li> <li>Fixed <code>getComputedStyle()</code> to correctly handle <code>!important</code> priority. (<a href="https://github.com/asamuzaK"><code>@asamuzaK</code></a>)</li> <li>Fixed <code>document.getElementById()</code> to return the first element in tree order when multiple elements share the same ID.</li> <li>Fixed <code><svg></code> elements to no longer incorrectly proxy event handlers to the <code>Window</code>.</li> <li>Fixed <code>FileReader</code> event timing and <code>fileReader.result</code> state to more closely follow the spec.</li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
af3d78d2cd |
chore(deps-dev): bump vitest from 4.1.8 to 4.1.10 (#2446)
Bumps [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) from 4.1.8 to 4.1.10. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/vitest-dev/vitest/releases">vitest's releases</a>.</em></p> <blockquote> <h2>v4.1.10</h2> <h3> 🐞 Bug Fixes</h3> <ul> <li><strong>browser</strong>: Check fs access in builtin commands [backport to v4] - by <a href="https://github.com/hi-ogawa"><code>@hi-ogawa</code></a>, <strong>Hiroshi Ogawa</strong> and <strong>OpenCode (claude-opus-4-8)</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10680">vitest-dev/vitest#10680</a> <a href="https://github.com/vitest-dev/vitest/commit/5c18dd267"><!-- raw HTML omitted -->(5c18d)<!-- raw HTML omitted --></a></li> <li><strong>vm</strong>: Fix external module resolve error with deps optimizer query for encoded URI [backport to v4] - by <a href="https://github.com/SveLil"><code>@SveLil</code></a> and <a href="https://github.com/hi-ogawa"><code>@hi-ogawa</code></a> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10661">vitest-dev/vitest#10661</a> <a href="https://github.com/vitest-dev/vitest/commit/bae52b511"><!-- raw HTML omitted -->(bae52)<!-- raw HTML omitted --></a></li> </ul> <h5> <a href="https://github.com/vitest-dev/vitest/compare/v4.1.9...v4.1.10">View changes on GitHub</a></h5> <h2>v4.1.9</h2> <h3>🐞 Bug Fixes</h3> <ul> <li>Fix <code>importOriginal</code> with optimizer and query import [backport to v4] - by <strong>Hiroshi Ogawa</strong>, <strong>David Harris</strong>, <strong>Codex</strong>and <strong>Vladimir</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10546">vitest-dev/vitest#10546</a> <a href="https://github.com/vitest-dev/vitest/commit/a5180190c"><!-- raw HTML omitted -->(a5180)<!-- raw HTML omitted --></a></li> <li><strong>browser</strong>: <ul> <li>Wait for orchestrator readiness before resolving browser sessions [backport to v4] - by <strong>Vladimir</strong> and <strong>Séamus O'Connor</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10555">vitest-dev/vitest#10555</a> <a href="https://github.com/vitest-dev/vitest/commit/7fb29651a"><!-- raw HTML omitted -->(7fb29)<!-- raw HTML omitted --></a></li> <li>Wait for iframe tester readiness before preparing [backport to v4] - by <strong>Vladimir</strong> and <strong>Séamus O'Connor</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10497">vitest-dev/vitest#10497</a> and <a href="https://redirect.github.com/vitest-dev/vitest/issues/10556">vitest-dev/vitest#10556</a> <a href="https://github.com/vitest-dev/vitest/commit/fbc626c40"><!-- raw HTML omitted -->(fbc62)<!-- raw HTML omitted --></a></li> </ul> </li> <li><strong>mocker</strong>: <ul> <li>Hoist vi.mock() for vite-plus/test imports [backport to v4] - by <strong>Hiroshi Ogawa</strong>, <strong>LongYinan</strong>, <strong>Claude Opus 4.8</strong> and <strong>Vladimir</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10548">vitest-dev/vitest#10548</a> <a href="https://github.com/vitest-dev/vitest/commit/2c9559c02"><!-- raw HTML omitted -->(2c955)<!-- raw HTML omitted --></a></li> </ul> </li> <li><strong>pool</strong>: <ul> <li>Prevent test run hang on worker crash [backport to v4] - by <strong>Ari Perkkiö</strong> and <strong>Jattioui Ismail</strong> in <a href="https://redirect.github.com/vitest-dev/vitest/issues/10543">vitest-dev/vitest#10543</a> and <a href="https://redirect.github.com/vitest-dev/vitest/issues/10564">vitest-dev/vitest#10564</a> <a href="https://github.com/vitest-dev/vitest/commit/934b0f587"><!-- raw HTML omitted -->(934b0)<!-- raw HTML omitted --></a></li> </ul> </li> </ul> <h5><a href="https://github.com/vitest-dev/vitest/compare/v4.1.8...v4.1.9">View changes on GitHub</a></h5> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
5ae6332563 |
refactor: collapse dead SQLite dual-path code; keep migration-only readers (#2454)
# Remove dead SQLite dual-path code; keep migration-only readers ## Summary PostgreSQL cutover left hundreds of production dual-path branches (`backendMode ? PG : SQLite/store.db`) whose SQLite arms only hit throwing `Database`/`ArchiveDatabase`/`CentralDatabase` stubs. This change mechanically collapses those unreachable arms so production authority is AsyncDataLayer/PostgreSQL only, while preserving the six authorized read-only migration/recovery `DatabaseSync` seams. ## Dual-path mass removed | Metric | Before | After | |---|---|---| | `if (…backendMode)` (non-test) | ~328 | ~70 | | `store.db` / `this.db` refs in core (non-test) | ~570+ | ~375 (mostly pure legacy MissionStore/eval/insight SQLite classes + thin getters) | | Net diff | — | **~6.7k lines removed** across 41 files | Remaining `backendMode` checks are intentional (incomplete-PG sync safe-defaults, settings-sync disabled-on-PG, symbol-lock PG-only gates, “requires PostgreSQL” config versioning throws), not live SQLite authority. ## Subsystems cleaned - **Core TaskStore / task-store/***: collapsed if/else and early-return dual-path across reads, moves, lifecycle, mutations, workflow, archive, branch/PR, artifacts, comments, audit, project ops, etc. `initImpl` is PostgreSQL-only (SQLite startup tail deleted). - **Satellite stores**: automation, agent, routine, plugin, secrets, approval-request, central-core dual-path arms collapsed. - **Plugins**: reports async methods, compound-engineering pipeline + session stores, CLI Printing Press store — SQLite fallbacks removed; PG required. - **Engine**: no functional dual-path change beyond whitespace (settings-sync / peer-exchange PG-disabled behavior kept). ## Six migration-only readers retained (allowlist unchanged) 1. `packages/core/src/postgres/sqlite-migrator.ts` 2. `packages/core/src/project-identity.ts` 3. `packages/core/src/sqlite-validation.ts` 4. `packages/core/src/postgres/startup-factory.ts` 5. `packages/cli/src/commands/db.ts` 6. `scripts/lib/start-local-project.mjs` Plus low-level `sqlite-adapter` and migrator/startup-import tests. Inventory ratchet still requires exactly these six `new DatabaseSync(` production sites, all `readOnly: true`. ## Not treated as SQLite - `.fusion/project.json`, `task.json`, `agent-log.jsonl` file storage - AsyncDataLayer / Drizzle PG paths - Incomplete-PG sync safe-default stubs (still return empty/false/null under backend without consulting SQLite) ## Verification - `sqlite-production-reader-inventory.test.ts` — 15/15 pass - `incomplete-pg-ports.pg.test.ts` — 6/6 pass - Targeted PG tests (create-task, move, handoff, runtime-persistence, agent, mission, insight, central-core) — green - `tsc --noEmit` for `@fusion/core`, `@fusion/engine`, `@fusion/dashboard` — green - `scripts/check-no-getdatabase.mjs` — clean <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Improvements** * Improved end-to-end consistency by making PostgreSQL/async persistence the standard across core task/workflow, automation, agents, plugins, routines, secrets, approvals, central operations, and session storage. * Unified scheduling, settings, configuration revision writes, run/workflow selection, queues/leases/transitions, and audit/lifecycle updates around consistent async transaction behavior. * **Bug Fixes** * Fixed edge cases for archived/deleted reads, unarchive/recovery flows, not-found handling, and task/artifact/document/log/comment operations, including more reliable emissions and hydration across search/list and lifecycle operations. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
256c64a7bd |
chore(release): v0.74.0-beta.5
Version bump via changesets. |
||
|
|
0022621d22 |
chore(release): v0.74.0-beta.4
Version bump via changesets. |
||
|
|
bf317f6340 |
chore(release): v0.74.0-beta.3
Version bump via changesets. |
||
|
|
2560944663 |
chore(release): v0.74.0-beta.2
Version bump via changesets. |
||
|
|
a0496c175c |
chore(release): v0.74.0-beta.1
Version bump via changesets. |
||
|
|
58d55d6439 |
chore(release): v0.74.0-beta.0
Version bump via changesets. |
||
|
|
1847d2bc2a |
chore(release): back-merge v0.73.0 from release
Keeps .changeset/project-switch-modal-reset.md: it was re-edited on main after
the v0.73.0 cut (
|
||
|
|
e3dba364d1 |
FN-8564: update bundled Pi runtime to 0.82.0
Update Fusion's matched Pi dependencies and compatibility coverage for version 0.82.0. - Pin Pi AI and coding-agent packages to the exact 0.82.0 release pair. - Refresh provider catalog, supplemental model, auth storage, and Droid thinking coverage. - Add the published CLI patch changeset. Files changed: .changeset/fn-8564-pi-082.md | 7 + packages/cli/package.json | 4 +- packages/cli/src/__tests__/package-config.test.ts | 2 +- packages/core/package.json | 2 +- packages/dashboard/package.json | 2 +- ...ister-model-routes-kimi-k3-supplemental.test.ts | 6 +- packages/engine/package.json | 4 +- .../src/__tests__/provider-registration.test.ts | 4 +- packages/engine/src/auth-storage.ts | 11 +- packages/engine/src/pi.ts | 6 + packages/pi-claude-cli/package.json | 8 +- .../src/thinking-config.ts | 10 +- pnpm-lock.yaml | 176 +++++++++++---------- pnpm-workspace.yaml | 6 +- .../__tests__/check-pi-versions-pinned.test.mjs | 8 +- 15 files changed, 142 insertions(+), 114 deletions(-) Fusion-Task-Id: FN-8564 Fusion-Task-Lineage: 543c5e17-4cb2-446f-9a1c-ec7ec8b8117a Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
127b640b3f |
chore(release): v0.73.0
Version bump via changesets. |
||
|
|
593f38249c |
chore(release): v0.73.0-beta.6
Version bump via changesets. |
||
|
|
1d4cd27c73 |
fix(tests): give PG-harness plugin suites the 15s timeout the golden-template harness budgets for
The shared pg-test-harness pays the golden schema-template cold start inside the first PG test of each vitest invocation and is budgeted against core's 15s testTimeout, but the six PG-consuming plugin packages ran at vitest's 5s default — on saturated CI runners the first PG test (e.g. whatsapp-chat persistence.pg) timed out before its assertions ran. Propagate the 15s budget to all six plugin configs. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
26628b356b |
chore(release): v0.73.0-beta.5
Version bump via changesets. |
||
|
|
2499803c73 |
fix: guard CE sessions against concurrent-turn displacement and harden JSON-protocol parsing
Port the planning turn-admission invariant (FNXC:PlanningTurnAdmission, 2026-07-22) into the Compound Engineering orchestrator: at most one turn (opening/answer/resume-rehydration) is admitted per CE session, reserved synchronously and held until the turn settles — a re-entered mobile view re-submitting a turn now gets CeTurnInProgressError (HTTP 409) instead of displacing the in-flight turn's live agent, which surfaced as "Failed to parse agent response: AI returned no valid JSON". cancel()/discard() force-clear the reservation; releases are token-scoped so a stale release can't drop a newer turn's slot. In the engine interactive-ai-session seam: bump the reformat retry from one to two attempts (non-Anthropic default models comply less reliably with the JSON-only protocol), and log every failed parse with a bounded raw-response snippet plus resolved provider/model — including a distinct empty-assistant-message marker — so support can diagnose these reports without a repro. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
a45d82d09b |
chore(release): v0.73.0-beta.4
Version bump via changesets. |
||
|
|
2cbb80c501 |
chore(release): v0.73.0-beta.3
Version bump via changesets. |
||
|
|
241a5c94ea |
chore: bump @earendil-works/pi to 0.81.1 (#2399)
## Summary - Bump `@earendil-works/pi-ai` and `@earendil-works/pi-coding-agent` from **0.80.10 → 0.81.1** (exact matched pins). - Update `pnpm-workspace.yaml` overrides so floating `*` consumers (`droid-cli`, `pi-llama-cpp`, runtime plugins) stay on the same ModelRuntime surface. - Refresh pin-guard tests, package-config assertions, and FNXC notes for the new pin. ## What's new in pi 0.81.x - Qwen Token Plan providers - Expanded usage accounting (tools/compaction/branch summaries) - Resilient compaction retries + retry lifecycle events - Full provider-extension registration API - Built-in llama.cpp router management - Provider/catalog fixes (Bedrock env credentials, OpenAI Responses early-stream retry, Codex 272K defaults, extension stream-fallback restore) ## Test plan - [x] `scripts/check-pi-versions-pinned` (4/4) - [x] Typecheck: core, engine, dashboard, cli, pi-claude-cli - [x] `package-config.test.ts` (35) - [x] `provider-registration.test.ts` (14) - [x] `auth-storage-concurrency` + `model-registry-refresh` (15) - [x] `register-model-routes-kimi-k3-supplemental` (1) - [ ] CI gate green - [ ] Spot-check Anthropic OAuth + API key session - [ ] Spot-check openai-codex model picker / supplemental models <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Updates** * Updated the bundled Pi runtime to version 0.81.1. * Added support for newer models and providers, including Qwen Token Plan. * Improved usage accounting and session reliability. * Strengthened compaction retry handling and provider catalog accuracy. * Added support for the expanded maximum thinking level. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
88e343e331 |
chore(release): v0.73.0-beta.2
Version bump via changesets. |
||
|
|
dcc249c674 |
chore(release): v0.73.0-beta.1
Version bump via changesets. |
||
|
|
11c4def87f |
chore(release): v0.73.0-beta.0
Version bump via changesets. |
||
|
|
5af53bc94a |
FN-8422: fix Fusion MCP bridge packaging and model markers
Ensure Grok and Claude ACP sessions report usable custom-tool bridge outcomes and model labels. - Copy the MCP schema server into runtime build output and fail custom-tool setup with stable diagnostics. - Record bridge failure metadata safely and normalize ACP string model markers. - Add bridge smoke coverage, adapter regressions, documentation, and a patch changeset. Files changed: .changeset/fn-8422-mcp-bridge.md | 7 ++++ docs/grok-cli-contract.md | 8 +++++ .../src/__tests__/agent-session-helpers.test.ts | 37 ++++++++++++++++++++++ packages/engine/src/__tests__/pi.test.ts | 16 ++++++++++ packages/engine/src/agent-session-helpers.ts | 20 ++++++++++++ packages/engine/src/pi.ts | 27 ++++++++++++++-- plugins/fusion-plugin-claude-runtime/README.md | 6 ++++ plugins/fusion-plugin-claude-runtime/package.json | 2 +- .../src/__tests__/runtime-adapter.test.ts | 30 ++++++++++++++++++ .../src/__tests__/tool-bridge.test.ts | 33 ++++++++++++++++++- .../src/runtime-adapter.ts | 30 ++++++++++++++++-- .../src/tool-bridge.ts | 24 +++++++++++--- plugins/fusion-plugin-claude-runtime/src/types.ts | 2 ++ plugins/fusion-plugin-grok-runtime/package.json | 2 +- .../src/__tests__/runtime-adapter.test.ts | 24 ++++++++++++++ .../src/__tests__/tool-bridge.test.ts | 33 ++++++++++++++++++- .../src/runtime-adapter.ts | 30 ++++++++++++++++-- .../fusion-plugin-grok-runtime/src/tool-bridge.ts | 24 +++++++++++--- plugins/fusion-plugin-grok-runtime/src/types.ts | 2 ++ 19 files changed, 338 insertions(+), 19 deletions(-) Fusion-Task-Id: FN-8422 Fusion-Task-Lineage: 6738f1bd-23f7-4fd3-8490-178d956b362d Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
2c1567c6b8 |
FN-8418: add WhatsApp QR pairing settings
Add WhatsApp connection pairing guidance directly in plugin settings. - Display a QR code and phone pairing instructions for WhatsApp Chat connections. - Expose connection details through the plugin and document the setup flow. - Add dashboard and plugin regression coverage plus a release changeset. Files changed: .changeset/fn-8418-whatsapp-settings-pairing.md | 7 + docs/plugin-management.md | 2 +- .../dashboard/app/components/PluginManager.tsx | 4 + .../app/components/WhatsAppChatPairingPanel.css | 115 ++++++++++++++ .../app/components/WhatsAppChatPairingPanel.tsx | 165 +++++++++++++++++++++ .../components/__tests__/PluginManager.test.tsx | 21 +++ .../__tests__/WhatsAppChatPairingPanel.test.tsx | 78 ++++++++++ plugins/fusion-plugin-whatsapp-chat/README.md | 19 +-- .../src/__tests__/connection.test.ts | 16 +- .../src/__tests__/index.test.ts | 33 +++++ .../fusion-plugin-whatsapp-chat/src/connection.ts | 21 ++- plugins/fusion-plugin-whatsapp-chat/src/index.ts | 15 +- 12 files changed, 479 insertions(+), 17 deletions(-) Fusion-Task-Id: FN-8418 Fusion-Task-Lineage: a16b7d25-422d-4612-83d4-d5ac9c049aec Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.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> |
||
|
|
d940bf3d5c |
FN-8358: add roadmap-item structure previews
Enable native previews and hosted navigation for roadmap items. - Extend native structure references and API resolution through the roadmap adapter. - Register the bundled Roadmaps view across desktop and mobile navigation. - Cover roadmap preview availability, navigation, and route behavior. Files changed: ...n-8358-roadmap-item-native-structure-preview.md | 7 ++++ docs/dashboard-guide.md | 6 ++-- packages/core/src/types.ts | 24 ++++++++----- packages/dashboard/app/App.tsx | 24 ++++++++----- .../dashboard/app/components/LeftSidebarNav.tsx | 12 +++---- .../app/components/NativeStructurePreview.tsx | 10 ++++-- .../app/components/__tests__/App.test.tsx | 13 ++++--- .../app/components/__tests__/Header.test.tsx | 5 ++- .../components/__tests__/LeftSidebarNav.test.tsx | 5 ++- .../app/components/__tests__/MobileNavBar.test.tsx | 4 +-- .../__tests__/NativeStructurePreview.test.tsx | 40 ++++++++++++++++------ .../__tests__/registerBundledPluginViews.test.tsx | 24 ++++++++++--- .../app/plugins/registerBundledPluginViews.ts | 23 +++++++++++++ packages/dashboard/src/native-structure-preview.ts | 25 +++++++++++++- .../native-structure-preview-routes.test.ts | 31 +++++++++++++++-- .../src/routes/register-task-workflow-routes.ts | 4 +-- packages/dashboard/vite.config.ts | 4 +++ packages/dashboard/vitest.config.ts | 4 +++ plugins/fusion-plugin-roadmap/package.json | 5 +++ .../fusion-plugin-roadmap/src/dashboard-view.tsx | 5 +++ plugins/fusion-plugin-roadmap/src/index.ts | 14 ++++++-- 21 files changed, 223 insertions(+), 66 deletions(-) Fusion-Task-Id: FN-8358 Fusion-Task-Lineage: c369ce87-eef0-4d06-bf23-bced9c4363f9 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
aa401123ea |
fix: make Windows updates and CE personas reliable (#2340)
## Summary Windows installs with slow native dependencies now get five minutes to finish, and a real timeout is reported as an actionable terminal retry instead of a wall of preceding npm deprecation warnings. Registry `ETIMEDOUT` errors keep their network diagnosis, including after the legacy-bin `--force` retry. Compound Engineering personas are now included in the published CLI bundle, with complete source-to-staged coverage for all persona definitions and a clear startup error if the bundled assets are missing or empty. The PostgreSQL statement visible in the report was validated by the existing real-Postgres schema reapply test. Its actual `caused by` detail was truncated, so this PR deliberately makes no speculative database change. ## Validation - Dashboard updater tests: 22 passed - CLI updater tests: 16 passed - CE persona installer tests: 7 passed - Published bundle persona assertion: passed against every source persona - CLI and CE plugin typechecks: passed - Changed production/config lint and strict changeset validation: passed - Real PostgreSQL schema reapply integration test: passed --- [](https://github.com/EveryInc/compound-engineering-plugin) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Windows CLI and dashboard updates now allow up to five minutes for installation and restore Compound Engineering agent personas during npm installs. * Update failures now surface clearer, terminal timeout guidance (while preserving specific network connection diagnostics) and avoid misleading “deprecated”/generic timeout text. * Persona assets are reliably included in plugin builds and bunded persona installation now errors clearly when definitions are missing or empty. * **Tests** * Expanded update and bundling coverage for the new 5-minute timeout and error-handling scenarios. <!-- end of auto-generated comment: release notes by coderabbit.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 --> |
||
|
|
c8b4e23ca4 |
FN-8357: show verification videos in the Quality hub
Surface executor-produced task verification videos in the top-level Quality hub. - Fetch review-artifact settings and video artifacts per selected project. - Render tokenized inline videos with source-task navigation and responsive states. - Add host interop aliases, coverage, documentation, and a minor changeset. Files changed: .changeset/FN-8357-quality-verification-videos.md | 7 + docs/settings-reference.md | 2 +- docs/workflow-steps.md | 2 +- packages/dashboard/tsconfig.app.json | 1 + packages/dashboard/vite.config.ts | 2 + packages/dashboard/vitest.config.ts | 2 + plugins/fusion-plugin-quality/package.json | 1 + .../dashboard-view-verification-videos.test.tsx | 131 ++++++++++++++++++ .../src/dashboard-interop.d.ts | 20 +++ .../fusion-plugin-quality/src/dashboard-view.css | 87 ++++++++++++ .../fusion-plugin-quality/src/dashboard-view.tsx | 151 +++++++++++++++++++-- plugins/fusion-plugin-quality/tsconfig.json | 1 + plugins/fusion-plugin-quality/vitest.config.ts | 8 ++ pnpm-lock.yaml | 135 +++++++++++++++++- 14 files changed, 532 insertions(+), 18 deletions(-) Fusion-Task-Id: FN-8357 Fusion-Task-Lineage: 728a5417-87ed-4203-850d-8ee108206766 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
b8cd3d21fb |
fix: surface OMP ACP Internal error details and harden tool MCP spawn
OMP session/new was dying with opaque "Internal error" when fusion-custom-tools MCP pointed at a missing schema server, or when bare models hit unauthenticated providers. Prefer data.details in diagnostics, resolve mcp-schema-server.cjs from multiple package layouts, skip the tool bridge when the asset is missing, drop stdio MCP entries whose command path does not exist, and forward common provider env keys (ZAI/MiniMax/Kimi) into the ACP subprocess. |
||
|
|
55101e03cf |
fix: make OMP chat resolve provider-qualified model selectors
Bare picker ids like MiniMax-M2.5 were ambiguous across omp providers and landed on unauthenticated plan aliases, which broke ACP with Internal error. Prefer `omp models --json` selectors, resolve bare ids before spawn, and copy mcp-schema-server.cjs into dist so the Fusion tool bridge can start. |
||
|
|
1215c76d9a |
FN-8326: add roadmap report deduplication
Add an optional public-roadmap source for report deduplication. - Add project settings and localized controls for roadmap matching. - Resolve roadmap entries through the plugin API and stop strong duplicate reports before filing. - Cover report pipeline, route, UI, and roadmap store behavior with tests. Files changed: .changeset/fn-8326-roadmap-report-dedup.md | 7 +++ docs/dashboard-guide.md | 2 + docs/settings-reference.md | 1 + .../core/src/__tests__/settings-parity.test.ts | 3 + packages/core/src/settings-schema.ts | 1 + packages/core/src/types.ts | 6 ++ packages/dashboard/app/components/ReportModal.tsx | 11 +++- .../app/components/__tests__/ReportModal.test.tsx | 14 +++++ .../__tests__/SettingsModal.general.test.tsx | 2 + .../settings/sections/GeneralSection.tsx | 10 ++++ .../settings-default-descriptions.test.tsx | 1 + .../src/__tests__/report-pipeline.test.ts | 31 +++++++++++ .../src/__tests__/report-roadmap-source.test.ts | 32 +++++++++++ .../dashboard/src/__tests__/report-routes.test.ts | 27 +++++++-- packages/dashboard/src/index.ts | 1 + packages/dashboard/src/report-pipeline.ts | 36 +++++++++++- packages/dashboard/src/report-roadmap-source.ts | 64 ++++++++++++++++++++++ .../dashboard/src/routes/register-report-routes.ts | 3 + packages/i18n/locales/en/app.json | 10 +++- packages/i18n/locales/es/app.json | 10 +++- packages/i18n/locales/fr/app.json | 10 +++- packages/i18n/locales/ko/app.json | 10 +++- packages/i18n/locales/zh-CN/app.json | 10 +++- packages/i18n/locales/zh-TW/app.json | 10 +++- .../src/__tests__/roadmap-store-factory.test.ts | 25 +++++++++ .../src/routes/roadmap-routes.ts | 24 +------- plugins/fusion-plugin-roadmap/src/server/index.ts | 34 ++++++++++++ 27 files changed, 360 insertions(+), 35 deletions(-) Fusion-Task-Id: FN-8326 Fusion-Task-Lineage: e9731c3f-dd92-44ac-910b-0e0efbaaf288 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
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 --> |
||
|
|
6308887b45 |
FN-8274: fix compound-engineering PostgreSQL test URL derivation
Use the shared PostgreSQL test base URL across Compound Engineering's test harnesses. - Import the core PostgreSQL URL configuration for admin and integration test connections. - Add a credential-safe source guard for base URL derivation. - Declare the shared URL export for Compound Engineering tests. Files changed: .../src/__tests__/_harness.ts | 15 ++++---- .../src/__tests__/base-url-derivation.test.ts | 42 ++++++++++++++++++++++ .../src/__tests__/pg-test-harness.d.ts | 1 + .../src/__tests__/pipeline-store.pg.test.ts | 12 +++---- 4 files changed, 57 insertions(+), 13 deletions(-) Fusion-Task-Id: FN-8274 Fusion-Task-Lineage: 84921b47-4275-4357-9e3a-be025863dbb3 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
90e8a10608 |
fix: resolve claude-runtime probe source for CLI full-suite (#2292)
## Summary Full Suite after #2291: shards 1–3 green; shard 4 failed CLI suites with: `Failed to resolve entry for package "@fusion-plugin-examples/claude-runtime"` from `dashboard/src/runtime-provider-probes.ts` under the CLI vitest package lane. - Add `plugins/fusion-plugin-claude-runtime/src/probes-entry.ts` (probe + model discovery only) - Alias `@fusion-plugin-examples/claude-runtime` to that entry in CLI vitest config (same class as Cursor/Grok/OMP source aliases, but avoids ACP index load) ## Test plan - [x] Local: vitest-workspace-resolution, task-steer, extension-task-tools - [ ] PR gate - [ ] Post-merge Full Suite green <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved CLI resolution for Claude runtime diagnostics and provider model discovery. * Prevented unnecessary runtime dependencies from affecting CLI test execution. * **Refactor** * Added a lightweight entry point for accessing Claude binary checks and provider model discovery. <!-- end of auto-generated comment: release notes by coderabbit.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 --> |
||
|
|
e4ddfe0218 |
fix: make Grok process lifecycle tests full-suite safe (#2289)
## Summary Full Suite after #2288 still red on shard 4: `process-lifecycle.test.ts` times out at 5s under shard transform load even after reducing reimports. - Move Symbol.for `process.exit` reaper onto `process-manager` (lifecycle owner) - Stress test reimports that module (not the full plugin graph) - Explicit 15s timeout for the cold-transform bound stress test ## Test plan - [x] Local process-lifecycle green (~2s) - [ ] PR merge gate - [ ] Post-merge Full Suite green <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Improved Grok runtime process cleanup during application shutdown. - Prevented duplicate cleanup handlers from accumulating during repeated module loading. - Ensured managed processes are reliably terminated when the process exits. - **Tests** - Expanded lifecycle coverage to validate repeated loading scenarios. - Increased test timeouts for more reliable stress-test execution. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
5c7ed8b26f |
chore(release): v0.72.0
Version bump via changesets. |
||
|
|
8da52767b6 |
fix: clear remaining full-suite floaters after #2287 (#2288)
## Summary #2287 cleared most of Full Suite run 29633869887 / post-merge 29634793317. Shards 1 and 2 went green; remaining floaters: - **TaskDetailModal.css FN-8154** — assert FN-8166 zeroed mobile `.detail-activity` inset (`padding-inline-end: 0`), not the pre-8166 `var(--space-md)` residual - **QuickEntryBox** — wait for cleared input / priority button after create under shard load (not only `onCreate` mock call) - **grok process-lifecycle** — prove Symbol.for exit-hook bound with 2 reimports so transform cost stays under 5s on full-suite shards ## Test plan - [x] Local: FN-8154, QuickEntry clear/priority, process-lifecycle - [ ] PR merge gate green - [ ] Post-merge Full Suite on `main` green <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Improved Quick Entry tests to wait for textarea clearing and verify priority resets to normal after task creation. * Updated CSS contract assertions for mobile task-detail activity spacing to match the latest overlay/inset behavior. * Streamlined the Grok plugin process lifecycle test loop to run fewer module-evaluation iterations while keeping existing lifecycle and warning checks. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
38c6fdc60d |
fix: green full-suite after mock and stacking drift (#2287)
## Summary Restacks onto latest main after #2285 and clears the remaining Full Suite red classes from run [29633869887](https://github.com/Runfusion/Fusion/actions/runs/29633869887) (post-#2285): - **Shard 1:** `agent-skills-flow` vitest TDZ — hoist `mockFiles` via `vi.hoisted` (same class as skill-resolver in #2285) - **Shard 2/3:** incomplete mocks after product drift - `isFullScreenSheetViewport` / `isShortViewport` on viewport mocks (without overriding dynamic mobile helpers) - `fetchCodebaseMetrics` on Command Center `api/legacy` mocks - `fetchSettings` on `agent-modals-mobile` api mock - **Shard 3:** PlanningMode `ui-interactions` race — sync-settle `fetchGlobalSettings` (FN-8245 pattern from planning-flow) - **Shard 3:** settings search drift guard — inventory `SettingsFieldRow` `htmlFor` keys (`mobileNavPrimaryItems`) - **Shard 2:** FloatingWindow shared-stack product bug — only reclaim z-index on hidden→visible (not every mount effect), so last-mounted utility stays on top - **Shard 4:** grok process-lifecycle timeout under shard load — prove bound with 5 reimports instead of 15 ## Test plan - [x] `agent-skills-flow.test.ts` green - [x] `process-lifecycle.test.ts` green - [x] FileBrowserModal, FloatingWindowStack.cross-type, agent-modals-mobile, settings-search-index, SystemControlsArea, PlanningModeModal.ui-interactions + planning-flow (210 tests) green - [ ] PR merge gate (Lint/Typecheck/Build/Gate) - [ ] Post-merge Full Suite on `main` green <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved floating-window stacking so reopened or interacted windows appear in the correct order. * Restored consistent layering between floating windows and expanded dock modals. * **Tests** * Updated automated coverage for viewport behavior, codebase metrics, settings search indexing, and process lifecycle scenarios. * Improved test reliability and consistency across responsive layouts and modal interactions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
1afce9532a |
fix: green full-suite after product and CI PG drift (#2285)
## Summary Main Full Suite was red again after release/desktop workflow drift, engine mock gaps, mission landed-SHA gating, and compound-engineering PG admin auth on GHA (`USER=runner`). ## Fixes | Area | Failure | Fix | |------|---------|-----| | desktop `release-workflow` | expected old `find artifacts -type f` | assert pruned collect + `release-files/*` | | `step-session-executor` | missing `resolveExecutorFallbackThinkingLevel` | mock export | | tool-availability tests | empty tools (cascade from above) | fixed by mock | | `skill-resolver` | TDZ on `mockFiles` during import | `vi.hoisted` filesystem state | | `merge-error-recovery` | enqueue no-op when not started | set `started=true` | | mission behavioral posture | `blocked` (no landed SHA / git probe) | `mergeDetails.commitSha` + staleness stub | | GraphTaskNode | missing `useOptionalToast` | mock both toast exports | | CE `pipeline-store.pg` | psql as `runner` | admin via `FUSION_PG_TEST_URL_BASE` | ## Test plan - [x] step-session-executor, skill-resolver, merge-error-recovery, mission-validator-behavioral-posture (203) - [x] release-workflow (10) - [x] `pnpm --filter @fusion/engine test:core` (294) - [ ] Full Suite (non-blocking) after merge <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Bug Fixes** - Improved desktop release artifact collection by pruning nested `runtime` and `migrations` directories and consistently staging release uploads via a dedicated `release-files` mapping. - **Tests** - Enhanced engine merge error-recovery coverage and mission validator behavioral posture setup. - Improved test reliability by synchronizing mocked filesystem state, executor fallbacks, and toast hook variants. - Updated Postgres test harness/admin commands to use a configurable base URL; refined related Windows changeset description. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
7dda1aa3f5 |
chore(release): v0.71.0
Version bump via changesets. |