d873ee816017240a7d5d594dea67166cd0c3d17c
12330 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
d873ee8160 |
docs: correct KTD-6 — the "flag-off" move path is live, the hooks path is dead (#2466)
Docs only. Corrects a factual error in the program plan merged in #2463, found during Phase A execution. ## What was wrong KTD-6 listed three deletions as "provably dead." Two are. The third — the flag-off inline move path in `task-store/moves.ts` — is the **live** path: - It is gated on `isWorkflowColumnsCompatibilityFlagEnabled` (`store.ts:38`), which reads the **raw** `experimentalFeatures.workflowColumns` key. - That is a *different* function from the always-true public `isWorkflowColumnsEnabled`, which is what the plan reasoned from. - No production code writes that key, so the flag reads false — the inline branch runs for essentially every project, and `default-workflow-hooks.ts` is the dead one. - `moves.ts:637` already said so: *"this 'flag-OFF' branch is the DEFAULT move path for nearly every project — the strict compat flag reads false because nothing sets it."* Deleting it would have swapped every project onto an untravelled code path and called it a cleanup. ## Changes - **KTD-6** carries the correction inline, with the two consequences that bind the rest of the program. - **U2** rescoped to the two proven-dead deletions; `moves.ts` is out of scope for it. - **New U2b** converges the two implementations with a per-behavior equivalence proof, and **blocks Phase B** — nothing downstream may assume the trait-hook path runs until it lands. - **U3's emit point must attach to the live inline path.** Wired into the dead hooks path, the event seam would never fire — and because subscribers are non-authoritative by design, *nothing would fail a test*. - Risk table gains: *a "dead" branch turns out to be live*. ## How it was caught The Phase A worker escalated instead of following the instruction, because U2 carried a delete-only Execution note: *any behavior change found while removing a branch means the branch was not dead — stop and treat it as a finding*. I verified the claim independently (flag function, absent writers, live `settings.json`, source comment) before accepting it. That note stays on every deletion unit. 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Clarified terminology in the workflow lifecycle migration plan, distinguishing the live inline move path from the compat-flag behavior. * Expanded the convergence phase with explicit behavior-equivalence requirements, pinned observable expectations, and removal of compat-flag branching. * Updated the migration diagram and phase ordering to reflect the new gating structure, revised scope boundaries, and refreshed risk mitigations. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
8b039a543e |
fix(desktop): advance Pi runtime pin to 0.82.1 for packaging PR lane (#2465)
## Summary - Advance the matched Pi runtime pin (`pi-ai`, `pi-coding-agent`, `pi-agent-core`, `pi-tui`) from **0.82.0 → 0.82.1** so electron-builder's production-dependency walk accepts `pi-agent-core`'s `pi-ai@^0.82.1` requirement. - Fixes the Desktop packaging PR-lane failure: `Production dependency @earendil-works/pi-ai not found for package @earendil-works/pi-agent-core` (required `^0.82.1`). - Keep the workspace override guard; update pin-policy fixtures and CLI package-config expectations. - Tighten the advisory packaging step-order test so it asserts against the real `electron-builder --dir` step (not a missing release-only step name that previously passed via `indexOf === -1`). - Run `pnpm dedupe` so the packaging lane's lockfile dedupe early-warning is clean. ## Context #2439 pinned the full Pi closure at 0.82.0 and made recent main-based packaging runs green. This advances to the current upstream patch so deploy + electron-builder stay aligned with `pi-agent-core@0.82.1`'s declared dependency range. ## Test plan - [x] `node scripts/check-pi-versions-pinned.mjs` - [x] `node --test scripts/__tests__/check-pi-versions-pinned.test.mjs` - [x] `pnpm --filter @runfusion/fusion exec vitest run src/__tests__/package-config.test.ts` - [x] `pnpm --filter @fusion/desktop exec vitest run src/__tests__/release-workflow.test.ts` - [x] `pnpm dedupe --check` - [ ] GitHub: Desktop packaging (should run full packaging walk — lockfile/package.json touched) - [ ] GitHub: PR Checks (Lint, Typecheck, Build, Gate) |
||
|
|
3c5d07ab01 |
docs: workflow-owned lifecycle program plan + column-placement contract (#2463)
Docs only — no code. Companion to #2462. ## `docs/solutions/architecture-patterns/workflow-node-column-placement-and-graph-entry-contract.md` Why a workflow node's `column` is a lifecycle contract rather than a display choice: it decides **who can drive the node**, **whether the card holds a WIP slot**, and **whether anything can move it onward**. Contents: - The graph **entry contract** (`resolveColumnResumeNode`, shipped in #2462) with the resume table. - The **plan-in-place chain** — triage → finalize → continuation seed → drain → resume → capacity suspend → release — annotated with the check each link performs. Notably `todo`, not `triage`: an intake column has no releaser, so a card parked there waits for a human. - Why the pre-release gate must be narrow (column match **and** enablement). - The measured failure table from three reverted placement attempts. - Why removing a column is a lifecycle-vocabulary refactor, not a workflow edit: **82 guards** that silently stop matching, **43 writes** to a column that no longer exists, **59 dashboard literals**. A guard that never fires doesn't fail a test — it disables a recovery path. ## `docs/plans/2026-07-26-001-refactor-workflow-owned-lifecycle-plan.md` The program that finishes the job, in four movements: 1. Resolve lifecycle columns from the workflow instead of ~207 string literals. 2. Move every lane — planning, execution, review, merge — behind graph nodes; lane services keep substrate only (storage, leases, timers, supervision, capacity, recovery, audit). 3. A **post-commit event seam**: transitions commit transactionally, *then* emit; subscribers react and may enqueue durable work items, but no subscriber performs a transition. Enforced by test — dropping every subscriber must change no lifecycle outcome. 4. Only then merge Todo into a single Planning column. Phased so each phase lands green independently, with the IR change deliberately **last** (KTD-7). Changing the workflow first makes the suite green over dead guards — that's how the earlier attempts hid their own breakage. The merge lane **adopts** the existing design in `docs/plans/2026-06-09-003-refactor-workflow-owned-merge-full-migration-slices-plan.md` (slices S02–S08, still `draft-stack-handoff`) rather than authoring a competing one, with a note to re-validate against current `main` since it was drafted seven weeks ago. Scale is stated honestly: ~48k lines across the four lane services, with the executor unit explicitly landing across several commits rather than one sweep. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
99c9f14ee0 |
feat: run Plan Review in the planning lane with a Plan Review badge (#2462)
## What Plan Review, planning, and the replan loop move from the implementation column into the **planning lane** (`todo`), so a task under specification never holds a WIP slot. The card crosses into `in-progress` exactly once, at `parse`, released by the scheduler. Operators also finally see a **Plan Review** badge while the gate runs — it was previously invisible on the default workflow. ## The part that made it possible Moving the node is ten lines. It was attempted three times and reverted each time, because a graph run with no durable continuation replayed from `start` and dragged an in-progress card *backward* out of the WIP column, firing `abort-on-exit` and stranding it in a pre-WIP column with no releaser. So this PR adds the graph **entry contract** — `resolveColumnResumeNode`: | Card is in | Resumes at | |---|---| | `triage` | `start` | | `todo` | `plan` | | `in-progress` | `parse` — never re-plans, never moves backward | | `in-review` | first review node — gates are not skipped | `ir.columns` is ordered and that order is the lifecycle order; rework and failure edges are excluded so the entry point is always the main path. The proof it's the right fix: **`executor-task-done-invariant` passes unmodified** after failing every previous attempt. ## Also in here - **Release gate narrowed twice.** `isUnplannedForExecution` applies its pre-release plan-review gate only when the node's column equals the card's column *and* the group is enabled for the task. The enablement check fixes a real deadlock — a task with Plan Review toggled off was held forever waiting for evidence nothing would ever write. - **Badge cleanup.** Gate badge reads "Plan Review" instead of the ambiguous "Reviewing" and no longer hides behind a lane restriction; the status badge stops duplicating it; `planning` renders as "Planning" instead of the raw engine token. - **Coding (Ideas)** renames its planner column to "Planning" (id `todo` unchanged) and loses its private planning-node re-home — the graph it clones is already plan-in-place. - **New sweep** `reconcileUndeclaredTaskColumns` re-homes a row whose column its workflow no longer declares. Written for a follow-up, kept because it makes any column edit survivable. ## Test changes Scheduler and release fixtures now model a card whose Plan Review passed — the state every real card is in when the capacity sweep sees it. A held unreviewed card is the gate working, and that path stays owned by `pre-release-plan-review.test.ts`. New `workflow-graph-entry-contract.test.ts` covers the invariant at every lifecycle position, plus the gap-column and remediation-node cases. ## Verification Gate 299 + 70 + 10, dashboard badge suites 672, engine workflow/entry/executor suites 147, core 122. Lint and typecheck clean. Full engine suite sits at the pre-existing baseline (notifier / plugin-runner / notification-service, untouched by this). ## Follow-up Removing the Todo column entirely is a separate ~207-site lifecycle-vocabulary refactor — planned in `docs/plans/2026-07-26-001-refactor-workflow-owned-lifecycle-plan.md` (companion docs PR). 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Plan Review now runs in the Planning lane before implementation begins. * Cards resume from their current workflow column without replaying earlier steps. * Added automatic recovery for cards stranded in outdated workflow columns. * **Improvements** * Renamed the Coding (Ideas) planner column to “Planning.” * Refined Plan Review gating to respect enabled settings and the card’s current column. * Updated planning and Plan Review badges for clearer, consistent labels across cards and lists. * **Bug Fixes** * Improved workflow transitions and release behavior around planning, review, and execution. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
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 --> |
||
|
|
52d64fa66e |
fix(engine): project CE steps after review handoff (#2464)
## Summary - reconcile successful graph-native workflow results with pending task checklist steps even when review handoff already moved the card into the merge column - preserve terminal, paused, and no-redundant-move behavior - cover the real Compound Engineering post-review-handoff state with a regression test ## Root cause Compound Engineering runs `review-handoff` before `merge`. Review handoff moves the task to `in-review`, which is also the merge column. `ensureWorkflowMergeBoundaryTask()` returned immediately for cards already in that column, before projecting successful `workflowStepResults` onto legacy `Task.steps[]`. The merger then saw `0/N` and rejected approved work with `task has incomplete steps`. ## Verification - RED: regression test failed before the fix because `store.updateTask` was never called - GREEN: `executor-graph-boundary.test.ts` — 6 passed - relevant non-PostgreSQL set — 31 passed, 5 PostgreSQL tests explicitly skipped - `@fusion/engine` typecheck passed - changeset format passed - `git diff --check` passed ## Baseline note `ce-workflow-step-executor.test.ts` currently has three failures on clean `origin/main` after FN-8601 foreach-proof hardening. The same failures reproduce without this patch and are not regressions from this change. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved reconciliation after review handoff by projecting completed step results onto the legacy checklist when reaching the merge column. * Prevented tasks from being marked approved with incomplete step counts (including “0/N” style states). * Reduced unnecessary merge failures and deadlock/pause scenarios when merge-column progress was already recorded. * **Tests** * Added coverage for execute-and-merge workflows, ensuring merge-boundary resolution updates pending steps without moving the task. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
d6c7e7dc74 |
chore(deps): bump actions/cache from 4 to 6 (#2441)
Bumps [actions/cache](https://github.com/actions/cache) from 4 to 6. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/cache/releases">actions/cache's releases</a>.</em></p> <blockquote> <h2>v6.0.0</h2> <h2>What's Changed</h2> <ul> <li>Update packages, migrate to ESM by <a href="https://github.com/Samirat"><code>@Samirat</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1760">actions/cache#1760</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/cache/compare/v5...v6.0.0">https://github.com/actions/cache/compare/v5...v6.0.0</a></p> <h2>v5.1.0</h2> <h2>What's Changed</h2> <ul> <li>Bump <code>@actions/cache</code> to v5.1.0 - handle read-only cache access by <a href="https://github.com/jasongin"><code>@jasongin</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1775">actions/cache#1775</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/cache/compare/v5...v5.1.0">https://github.com/actions/cache/compare/v5...v5.1.0</a></p> <h2>v5.0.5</h2> <h2>What's Changed</h2> <ul> <li>Update ts-http-runtime dependency by <a href="https://github.com/yacaovsnc"><code>@yacaovsnc</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1747">actions/cache#1747</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/cache/compare/v5...v5.0.5">https://github.com/actions/cache/compare/v5...v5.0.5</a></p> <h2>v5.0.4</h2> <h2>What's Changed</h2> <ul> <li>Add release instructions and update maintainer docs by <a href="https://github.com/Link"><code>@Link</code></a>- in <a href="https://redirect.github.com/actions/cache/pull/1696">actions/cache#1696</a></li> <li>Potential fix for code scanning alert no. 52: Workflow does not contain permissions by <a href="https://github.com/Link"><code>@Link</code></a>- in <a href="https://redirect.github.com/actions/cache/pull/1697">actions/cache#1697</a></li> <li>Fix workflow permissions and cleanup workflow names / formatting by <a href="https://github.com/Link"><code>@Link</code></a>- in <a href="https://redirect.github.com/actions/cache/pull/1699">actions/cache#1699</a></li> <li>docs: Update examples to use the latest version by <a href="https://github.com/XZTDean"><code>@XZTDean</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1690">actions/cache#1690</a></li> <li>Fix proxy integration tests by <a href="https://github.com/Link"><code>@Link</code></a>- in <a href="https://redirect.github.com/actions/cache/pull/1701">actions/cache#1701</a></li> <li>Fix cache key in examples.md for bun.lock by <a href="https://github.com/RyPeck"><code>@RyPeck</code></a> in <a href="https://redirect.github.com/actions/cache/pull/1722">actions/cache#1722</a></li> <li>Update dependencies & patch security vulnerabilities by <a href="https://github.com/Link"><code>@Link</code></a>- in <a href="https://redirect.github.com/actions/cache/pull/1738">actions/cache#1738</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/XZTDean"><code>@XZTDean</code></a> made their first contribution in <a href="https://redirect.github.com/actions/cache/pull/1690">actions/cache#1690</a></li> <li><a href="https://github.com/RyPeck"><code>@RyPeck</code></a> made their first contribution in <a href="https://redirect.github.com/actions/cache/pull/1722">actions/cache#1722</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/cache/compare/v5...v5.0.4">https://github.com/actions/cache/compare/v5...v5.0.4</a></p> <h2>v5.0.3</h2> <h2>What's Changed</h2> <ul> <li>Bump <code>@actions/cache</code> to v5.0.5 (Resolves: <a href="https://github.com/actions/cache/security/dependabot/33">https://github.com/actions/cache/security/dependabot/33</a>)</li> <li>Bump <code>@actions/core</code> to v2.0.3</li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/cache/compare/v5...v5.0.3">https://github.com/actions/cache/compare/v5...v5.0.3</a></p> <h2>v.5.0.2</h2> <h1>v5.0.2</h1> <h2>What's Changed</h2> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Changelog</summary> <p><em>Sourced from <a href="https://github.com/actions/cache/blob/main/RELEASES.md">actions/cache's changelog</a>.</em></p> <blockquote> <h1>Releases</h1> <h2>How to prepare a release</h2> <blockquote> <p>[!NOTE] Relevant for maintainers with write access only.</p> </blockquote> <ol> <li>Switch to a new branch from <code>main</code>.</li> <li>Run <code>npm test</code> to ensure all tests are passing.</li> <li>Update the version in <a href="https://github.com/actions/cache/blob/main/package.json"><code>https://github.com/actions/cache/blob/main/package.json</code></a>.</li> <li>Run <code>npm run build</code> to update the compiled files.</li> <li>Update this <a href="https://github.com/actions/cache/blob/main/RELEASES.md"><code>https://github.com/actions/cache/blob/main/RELEASES.md</code></a> with the new version and changes in the <code>## Changelog</code> section.</li> <li>Run <code>licensed cache</code> to update the license report.</li> <li>Run <code>licensed status</code> and resolve any warnings by updating the <a href="https://github.com/actions/cache/blob/main/.licensed.yml"><code>https://github.com/actions/cache/blob/main/.licensed.yml</code></a> file with the exceptions.</li> <li>Commit your changes and push your branch upstream.</li> <li>Open a pull request against <code>main</code> and get it reviewed and merged.</li> <li>Draft a new release <a href="https://github.com/actions/cache/releases">https://github.com/actions/cache/releases</a> use the same version number used in <code>package.json</code> <ol> <li>Create a new tag with the version number.</li> <li>Auto generate release notes and update them to match the changes you made in <code>RELEASES.md</code>.</li> <li>Toggle the set as the latest release option.</li> <li>Publish the release.</li> </ol> </li> <li>Navigate to <a href="https://github.com/actions/cache/actions/workflows/release-new-action-version.yml">https://github.com/actions/cache/actions/workflows/release-new-action-version.yml</a> <ol> <li>There should be a workflow run queued with the same version number.</li> <li>Approve the run to publish the new version and update the major tags for this action.</li> </ol> </li> </ol> <h2>Changelog</h2> <h3>6.1.0</h3> <ul> <li>Bump <code>@actions/cache</code> to v6.1.0 to pick up <a href="https://redirect.github.com/actions/toolkit/pull/2435">actions/toolkit#2435 Handle cache write error due to read-only token</a></li> <li>Switch redundant "Cache save failed" warning to debug log in save-only</li> </ul> <h3>6.0.0</h3> <ul> <li>Updated <code>@actions/cache</code> to ^6.0.1, <code>@actions/core</code> to ^3.0.1, <code>@actions/exec</code> to ^3.0.0, <code>@actions/io</code> to ^3.0.2</li> <li>Migrated to ESM module system</li> <li>Upgraded Jest to v30 and test infrastructure to be ESM compatible</li> </ul> <h3>5.0.4</h3> <ul> <li>Bump <code>minimatch</code> to v3.1.5 (fixes ReDoS via globstar patterns)</li> <li>Bump <code>undici</code> to v6.24.1 (WebSocket decompression bomb protection, header validation fixes)</li> <li>Bump <code>fast-xml-parser</code> to v5.5.6</li> </ul> <h3>5.0.3</h3> <ul> <li>Bump <code>@actions/cache</code> to v5.0.5 (Resolves: <a href="https://github.com/actions/cache/security/dependabot/33">https://github.com/actions/cache/security/dependabot/33</a>)</li> <li>Bump <code>@actions/core</code> to v2.0.3</li> </ul> <h3>5.0.2</h3> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
88cc152d12 |
chore(deps): bump actions/setup-node from 4 to 7 (#2440)
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 7. <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/actions/setup-node/releases">actions/setup-node's releases</a>.</em></p> <blockquote> <h2>v7.0.0</h2> <h2>What's Changed</h2> <h3>Enhancements:</h3> <ul> <li>Add cache-primary-key and cache-matched-key as outputs by <a href="https://github.com/gowridurgad"><code>@gowridurgad</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1577">actions/setup-node#1577</a></li> <li>Migrate to ESM and upgrade dependencies by <a href="https://github.com/gowridurgad"><code>@gowridurgad</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1574">actions/setup-node#1574</a></li> </ul> <h3>Bug fixes:</h3> <ul> <li>Remove dummy NODE_AUTH_TOKEN export by <a href="https://github.com/gowridurgad"><code>@gowridurgad</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1558">actions/setup-node#1558</a></li> <li>Only use <code>mirrorToken</code> in <code>getManifest</code> if it's provided by <a href="https://github.com/deiga"><code>@deiga</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1548">actions/setup-node#1548</a></li> </ul> <h3>Documentation updates:</h3> <ul> <li>Add documentation for publishing to npm with Trusted Publisher (OIDC) by <a href="https://github.com/chiranjib-swain"><code>@chiranjib-swain</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1536">actions/setup-node#1536</a></li> <li>docs: Update restore-only cache documentation by <a href="https://github.com/priya-kinthali"><code>@priya-kinthali</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1550">actions/setup-node#1550</a></li> <li>docs: Update caching recommendations to mitigate cache poisoning risks by <a href="https://github.com/chiranjib-swain"><code>@chiranjib-swain</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1567">actions/setup-node#1567</a></li> </ul> <h3>Dependency update:</h3> <ul> <li>Upgrade <code>@actions/cache</code> to 5.1.0, log cache write denied by <a href="https://github.com/jasongin"><code>@jasongin</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1569">actions/setup-node#1569</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/chiranjib-swain"><code>@chiranjib-swain</code></a> made their first contribution in <a href="https://redirect.github.com/actions/setup-node/pull/1536">actions/setup-node#1536</a></li> <li><a href="https://github.com/deiga"><code>@deiga</code></a> made their first contribution in <a href="https://redirect.github.com/actions/setup-node/pull/1548">actions/setup-node#1548</a></li> <li><a href="https://github.com/jasongin"><code>@jasongin</code></a> made their first contribution in <a href="https://redirect.github.com/actions/setup-node/pull/1569">actions/setup-node#1569</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/setup-node/compare/v6...v7.0.0">https://github.com/actions/setup-node/compare/v6...v7.0.0</a></p> <h2>v6.5.0</h2> <h2>What's Changed</h2> <ul> <li>Update <code>@actions/cache</code> to 5.1.0 and add security overrides for undici and fast-xml-parser by <a href="https://github.com/HarithaVattikuti"><code>@HarithaVattikuti</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1579">actions/setup-node#1579</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/setup-node/compare/v6.4.0...v6.5.0">https://github.com/actions/setup-node/compare/v6.4.0...v6.5.0</a></p> <h2>v6.4.0</h2> <h2>What's Changed</h2> <h3>Dependency updates:</h3> <ul> <li>Upgrade <a href="https://github.com/actions"><code>@actions</code></a> dependencies by <a href="https://github.com/Copilot"><code>@Copilot</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1525">actions/setup-node#1525</a></li> <li>Update Node.js versions in versions.yml and bump package to v6.4.0 by <a href="https://github.com/priya-kinthali"><code>@priya-kinthali</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1533">actions/setup-node#1533</a></li> </ul> <h2>New Contributors</h2> <ul> <li><a href="https://github.com/Copilot"><code>@Copilot</code></a> made their first contribution in <a href="https://redirect.github.com/actions/setup-node/pull/1525">actions/setup-node#1525</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/actions/setup-node/compare/v6...v6.4.0">https://github.com/actions/setup-node/compare/v6...v6.4.0</a></p> <h2>v6.3.0</h2> <h2>What's Changed</h2> <h3>Enhancements:</h3> <ul> <li>Support parsing <code>devEngines</code> field by <a href="https://github.com/susnux"><code>@susnux</code></a> in <a href="https://redirect.github.com/actions/setup-node/pull/1283">actions/setup-node#1283</a></li> </ul> <!-- raw HTML omitted --> </blockquote> <p>... (truncated)</p> </details> <details> <summary>Commits</summary> <ul> <li><a href=" |
||
|
|
0e3d2a2265 |
refactor: delete meta-task auto-archive and automated recovery follow-ups (#2461)
Deletes two pieces of automated "meta" machinery that filed and garbage-collected cards restating state already on the task that failed. Net **-1015 lines**. ## Why **Automated recovery follow-ups.** `createAutomatedFollowup` and its dedup engine (289 lines of signature matching, 1h recurrence rate-limiting, 24h supersedes windows) existed to file recovery cards for verification-cap and merge-conflict give-ups. In both cases the parent is *already* parked `failed` with a descriptive `error` and a log entry carrying the failing command, branch, and output — the card was a second copy of that. **Meta-task auto-archive.** The sweeps that garbage-collected those cards were worse than redundant: the regex classifier matched ordinary feature work, and its positional fallback bound cards to unrelated tasks, so **live work could be archived**. They are removed together, because the auto-archive sweeps only existed to clean up after the follow-up engine. ## What changed ### Deleted - `packages/engine/src/verification-followup-dedup.ts` in full — `createAutomatedFollowup`, `decideAutomatedFollowup`, `AutomatedFollowupKind`, `computeVerificationFailureSignature`, `extractFailingTestFiles`. - `findActiveRecoveryFollowUp` — dead code, defined and never called (`tsc` independently flagged it `6133 declared but its value is never read`). - The meta-task auto-archive sweeps `autoArchiveResolvedMetaTasks` / `autoArchiveStalledMetaTasks` and helpers `classifyMetaTask` / `resolveMetaTargetTaskId` / `computeMetaChainDepth` / `archiveMetaTask` / `evaluateMetaAutoArchiveGuards`, plus settings `metaTaskStallAutoCloseMs` and `metaTaskActiveExecutionGraceMs`. - Run-audit types `task:auto-archived-meta-resolved`, `task:auto-archived-meta-stalled`, `task:auto-archive-meta-resolved-skipped`, `task:auto-archive-meta-stalled-skipped`, `verification:followup-created`, `verification:followup-deduped`. The two signature helpers were **deleted rather than relocated** — once the three call sites went they were provably unreachable: `buildVerificationFailureSignature` had exactly one caller, and it was the only caller of `extractFailingTestFiles`. ### Call sites 1 and 2 — park kept, card dropped Verification-cap and merge-conflict give-ups keep their park, audit event, operator comment, and log entry. Site 1's `error` string was reworded off `"See follow-up task for investigation."` (no follow-up will exist) to carry the guidance itself. `autoResolveDisabled` was **kept** — it still drives the outer park guard and the `reason` string; only the inner branch that guarded card creation is gone. ### Call site 3 — autostash orphan, replaced not deleted This one is a genuine data-loss guard, so it keeps a durable trail. A `live`-classified orphan is a merger stash holding **real uncommitted work**, and unlike sites 1–2 there is no parked parent — the parent may already be `done` and merged, so nothing else on the board would ever mention the stash. The card is replaced by a `logEntry` **and** an `addTaskComment` on the parent, preserving every fact the old description carried: the sha, `record.label` (the handle `git stash` recovery needs), `record.detectedByTaskId`, and `sourcePhase`. New truthful run-audit event `task:autostash-orphan-live-detected` replaces the borrowed `verification:followup-*` name, with ids/outcomes-only metadata per AGENTS.md. ### Kept unchanged: the two real product features Eval follow-ups (`eval-followups.ts`) and PR-comment follow-ups (`pr-comment-handler.ts`) only borrowed the shared engine for its dedup pass. Both keep their exact behavior, column, priority, `sourceType`, and log lines, with dedup inlined as a `listTasks` scan on `suggestionId` / `prNumber` respectively. Both fail open (create) if the listing throws, matching the old engine. ## Test changes — read this one Two tests asserted the *deleted* engine's rate-limited `"[verification recurrence]"` logEntry. Those assertions were removed, **not loosened**: both tests still assert no duplicate card is created, and the eval test still asserts the existing id is reported back. No coverage of surviving behavior was weakened. The three `meta-*` test files were deleted along with the sweeps they covered. ## Verification ``` $ pnpm test:gate Test Files 2 passed (2) Tests 10 passed (10) # core Test Files 16 passed (16) Tests 299 passed (299) # engine-core Test Files 1 passed (1) Tests 70 passed (70) # ci-shape GATE_EXIT=0 $ pnpm --filter @fusion/engine --filter @fusion/core exec tsc --noEmit -p tsconfig.json TSC_EXIT=0 (no output) ``` Plus a file-scoped run over the touched surfaces (`eval-followups`, `pr-comment-handler`, `merger-autostash-orphan-surface`, `merger-autostash-cleanup`, `run-audit`, `run-audit-secret-taxonomy`, `project-engine`, `project-engine-manager`): **213/213 passed**. A repo-wide grep confirms no surviving references to any deleted symbol, module, or audit event. 🤖 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** * Failed tasks now retain recovery and verification details directly on the original task instead of generating separate follow-up cards. * Live autostash issues now preserve stash information in task comments and activity logs. * Existing evaluation and pull-request follow-ups continue to be reused when appropriate. * **Changes** * Removed automatic archival of meta-tasks. * Removed obsolete meta-task timing settings. * **Documentation** * Updated architecture and settings documentation to reflect these workflow changes. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
d19c82b33b |
test(dashboard): align modal and locale fixtures (#2460)
## Summary - query Task Detail modal assertions from the document after its FloatingWindow portal migration - sync secondary locale catalogs with the current English key structure ## Test plan - `pnpm --filter @fusion/dashboard exec vitest run app/components/__tests__/TaskDetailModal.attachments-and-tabs.test.tsx --silent=passed-only --reporter=dot` - `pnpm i18n:status` - `pnpm --filter @fusion/dashboard build` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added missing localization entries for workflow selection/help text, action-based report targeting, agent tool output limit hints, auto-update/restart messaging, and task refinement status labels across Spanish, French, Korean, Simplified Chinese, and Traditional Chinese. * **Tests** * Updated task detail modal tests to query the correct rendered document root so portal/modal content is asserted reliably. * Minor test formatting adjustments to keep assertions consistent without changing coverage. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
11887625f1 |
test(dashboard): align touch fixture with FloatingWindow (#2459)
## Summary - update the touch-resize browser fixture assertions for New Task's FloatingWindow migration - verify the shared nine touch targets, resize handle ID, and unified geometry persistence key ## Test plan - `corepack pnpm --filter @fusion/dashboard build` - `corepack pnpm --filter @fusion/dashboard exec vitest run --project dashboard-browser-touch --silent=passed-only --reporter=dot src/__tests__/task-modal-touch-resize-browser.test.ts` - `corepack pnpm check:changesets` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Updated tablet touch-resize coverage for task-detail to use the shared southeast resize handle and corrected expected hit-target counts. * Refreshed hit-target detection and drag target assertions after switching the test surface to the task-detail/floating window layout. * Updated persistence/geometry validations to compare the stored unified width/height against the resized panel dimensions. * Reworked desktop vs tablet assertions, including tighter overlay padding checks and standardized shared resize-handle sizing expectations. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
232e17d1cb |
test(engine): complete runtime logger mock (#2458)
## Summary - add the missing `debug` method to the runtime-resolution logger mock - prevent logger calls from short-circuiting runtime selection assertions ## Test plan - `pnpm --filter @fusion/engine exec vitest run src/__tests__/runtime-resolution.test.ts` - `pnpm --filter @fusion/engine typecheck` - `pnpm check:changesets` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Updated the runtime-resolution test suite’s mocked logger to also support debug-level messages, alongside existing log, warn, and error handling. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
159fbbe9f8 |
fix(i18n): restore auto-update locale parity (#2456)
## Summary - restore the two auto-update settings keys in all five secondary locale catalogs - keep generated locale structure aligned with the authored English catalog ## Test plan - `pnpm i18n:status` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Localization** * Added new settings text keys for “automatic updates and restart” (and its help text) in Spanish, French, Korean, Simplified Chinese, and Traditional Chinese. * The new values are placeholders (currently empty), so the UI may show missing/blank text until translations are completed. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
d6c917d726 |
feat(dashboard): add view and settings-section enumeration API (#2453)
## Summary Gives external integrations (command palettes, plugin launchers, alternate dashboard shells) a supported way to **discover the host UI** — instead of hardcoding the dashboard's view ids, labels and settings search terms and hand-syncing them on every release. This is the read-only metadata slice of the "constrained by a stable host context and API client" idea in `docs/proposals/2026-07-01-dashboard-theme-plugin-system.md`, and the follow-on to #2415 (theme tokens + overlay layering). Two additions, both inert unless called: | Endpoint | Returns | |---|---| | `GET /api/views` | Every registered built-in view id, in dashboard order — `id`, English `label`, plus optional i18n `labelKey`, legacy `aliases` and `internal` flag. | | `GET /api/settings/sections` | Selectable Settings sections — `id`, `label`, `labelKey`, `scope`, `group`, `keywords`, `searchableKeys`, `advanced`. | Both are read-only, return static project-independent metadata, take no project id, and are mounted inside `createApiRoutes` so they sit behind exactly the same `/api` authentication as every other dashboard route — no more, no less. ## What actually changed — one source of truth The endpoints are the small part. The core of the diff is **collapsing duplicated UI metadata into two shared registries that now drive both the dashboard UI and the API**: - `packages/dashboard/src/shared/dashboard-views.ts` — canonical view ids + English labels + i18n keys + legacy aliases. - `packages/dashboard/src/shared/settings-sections.ts` — canonical settings sections + scope/group/search metadata, with `group` and `advanced` derived from the list's own structure. `LeftSidebarNav`, `SettingsModal` and `useViewState` were rewritten to consume those registries instead of carrying their own copies (net **−230 lines** in `SettingsModal` alone). Edit the registry and the rendered UI and the API move together. ## Drift protection Being precise about what each test can and cannot catch, because "no-drift" claims are easy to overstate: - `left-sidebar-nav-registry-parity.test.tsx` — the one test that catches drift the registry does not already determine. It **renders** the sidebar with a recording `t()` spy and pins each entry's translation key and English fallback to the registry (the sidebar still hardcodes its keys). It also asserts the rendered destination count equals the enrolled id list, so a newly added sidebar view fails until it is enrolled. - `ui-metadata-sync.test.ts` — pins the Settings navigation list, advanced-visibility set, persisted view list, reset-key registry and both endpoint payloads to the registries. Since those consumers are now *derived* from the registries, these assertions mainly guard against a future consumer **re-hardcoding** its own copy. Two of them do stand on their own: each section's served `group` is pinned to the group header it actually renders under, and no published `labelKey` may resolve to a non-leaf i18n node. - `register-ui-metadata-routes.test.ts` — drives the real Express router and asserts each endpoint serves the registry payload verbatim, with no filtering or reshaping. - Exactly two **existing** tests are updated, both for the same reason: they asserted that `SettingsModal.tsx`'s *source text* contains a section literal that now lives in the registry. `VoiceInputSection.modal-visibility.test.tsx` now asserts Voice Input's Basic-mode contract against `SETTINGS_SECTION_METADATA`, and `mcp-documentation.test.ts` reads the registry for the two MCP section ids. No other existing test in the package changes. ## Design notes / decisions for review - **`GET /api/views` returns the full registry, not the live menu.** It includes flag-gated / experimental ids and `internal` (non-navigable) destinations; reachability depends on flags and plugins this endpoint does not evaluate. Documented as "known view ids", not "visible nav entries". - **`labelKey` is optional and best-effort; `label` is the guarantee.** A `labelKey` is published only where the dashboard itself renders that view's title through it. `graph` (labelled from a plugin manifest) and the internal `task-detail` carry none rather than advertise a key that resolves to nothing — and `task-detail` in particular must not point at `taskDetail.title`, which is an occupied i18n *namespace* whose lookup returns an object rather than falling through to a default. A guard test now enforces that. Separately, a few published keys (`nav.ideation`, `nav.importTasks`, `nav.automations`, `pr.view.title`) are the dashboard's real keys but aren't in the shipped catalogs yet because the host supplies their English inline; the docs say plainly that consumers must fall back to `label`. - **`keywords` / `searchableKeys` are explicitly non-contractual.** `searchableKeys` exposes the raw i18n translation-key strings backing a section's searchable copy; values, ordering and presence may change between releases. Documented as best-effort search hints, never stable identifiers. - **Migration is deliberately partial.** The desktop sidebar, Settings navigation and persisted view list now come from the registries; `Header.tsx` and the mobile More sheet still hardcode a few of the same labels. They can still drift from what `GET /api/views` reports; converting them is left to a follow-up so this diff stays reviewable. - **No project scoping, deliberately.** The proposal doc rightly pushes plugin traffic through a project-scoped client — these two endpoints are the exception that proves the rule: they return static registry metadata that is identical for every project, so threading a `projectId` would imply a scoping guarantee that does not exist here. They never touch `getScopedStore` / `TaskStore`. - **Two endpoints rather than one `/api/ui-metadata` envelope.** Views and Settings sections are independent registries with different consumers, and `/settings/sections` sits naturally beside the existing `/settings/*` routes. A consumer that only needs navigation doesn't pay for settings metadata. - **The registry extraction ships with the endpoints rather than as a separate PR.** The registries *are* the mechanism that keeps the API honest — split apart, the first half is a refactor with no observable effect and the second can't land without it. - **Placement:** `packages/dashboard/src/shared/` is a new directory, and these are the first *production* `app/ → src/` imports in the package (today the only one is in `ProviderIcon.test.tsx`). They sit under `src/` because `src/`'s tsconfig cannot import `app/`, so a module both sides consume has nowhere else to go; both registries are dependency-free data leaves, and `vite build` plus `check-no-node-only-core-imports-in-dashboard` confirm the client bundle is unaffected. The considered alternative was `packages/core/src` behind the `dashboard-browser-safe-core-modules.json` allowlist, where `mobile-nav-primary-items.ts` keeps a destination→labelKey table — these stayed out of `core` because they are dashboard-owned UI ids, and because the two tables describe different surfaces (core mirrors the mobile nav's `nav.skills`/`nav.settings`; this registry mirrors the desktop sidebar's `header.skillsView`/`header.settings`). - Ships a `@runfusion/fusion` **minor** changeset (`category: feature`). Happy to adjust any of the above — shape, placement, or dropping `searchableKeys` — if you'd rather it landed differently. ## Verification - Rebased onto `main@26dcccb7c`. Two conflicts, both resolved by absorbing upstream's work rather than reverting it: - `SettingsModal.tsx` — upstream's `voice-input` section (and the `FNXC:VoiceInput` decision comment explaining it stays out of the advanced-only set) moved into the registry. The registry's section list is byte-identical to `main`'s `SETTINGS_SECTIONS` (45/45 entries, all fields), and the registry-derived `ADVANCED_SETTINGS_SECTION_IDS` is identical to `main`'s hardcoded set (19/19, same order) — both verified mechanically, not by eye. Upstream's `RUNTIME_*` hide-uninstalled-runtimes sets are untouched. - `routes/README.md` — the `mount-sequence` list regenerated from `CREATE_API_ROUTES_REGISTRAR_MOUNT_SEQUENCE`, so `registerVoiceRoutes` and `registerUiMetadataRoutes` are both in place and the contract test passes. - `DASHBOARD_VIEWS` covers exactly `main`'s `BuiltInTaskView` union, aliases included, and `BUILT_IN_TASK_VIEWS` reproduces `main`'s 27-entry array in order (`devserver` still preceding `dev-server` for the migration path). - Every one of the 20 sidebar labels the refactor rewrote was checked to be byte-identical to `main`'s hardcoded fallback, and every `FNXC:` decision comment displaced by the move was accounted for — all 75 in `SettingsModal.tsx` and all 11 in `useViewState.ts` survive, relocated onto the registry entries they document. - The full `dashboard-app` + `dashboard-api` suites were run at this commit (**20,706 passing**) and again on unmodified `main@26dcccb7c`, and the failing-file sets compared: **every file that fails here also fails on `main`** — nothing regresses. The overlap is environment-driven (Postgres-backed `*.pg.test.ts`, tests needing built `dist` artifacts, and `SettingsModalNodeRouting.test.tsx`'s `No "fetchSystemInfo" export is defined on the "../../api" mock`), none of it touched by this change. - `tsc --noEmit` clean for both dashboard projects, `eslint` clean on every changed file, and `vite build` of the client bundle succeeds (the two pre-existing `@fusion-plugin-examples/claude-runtime` / `playwright-core` module-resolution errors reproduce on unmodified `main`). - Repo gate scripts pass: `check-changeset-format`, `check-routes-modular`, `check-no-node-only-core-imports-in-dashboard`, `check-no-cwd-relative-dashboard-test-reads`, `check-mock-completeness`. - The three new assertions were mutation-tested rather than assumed load-bearing: breaking the registry's `group` derivation, dropping an enrolled sidebar id, and re-pointing `task-detail` at the `taskDetail.title` namespace each make their test fail. - Local CodeRabbit review over two passes: 3 minor findings, all addressed (parity projection missing `group`; route tests asserting partial instead of exact payloads; the `labelKey` guard not covering the settings registry). <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added authenticated, read-only APIs for discovering dashboard views and selectable Settings sections. * Added dashboard view metadata, including labels, aliases, internal status, and translation keys. * Added Settings metadata with grouping, scope, advanced status, and search-related information. * Updated navigation and Settings UI labels to use shared metadata. * **Documentation** * Documented the new metadata endpoints and integration guidance. * **Bug Fixes** * Added safeguards and automated checks to keep UI navigation and API metadata synchronized. <!-- end of auto-generated comment: release notes by coderabbit.ai --> Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
00778cb10f |
test(engine): refresh shellout allowlist (#2451)
## Summary - refresh the engine synchronous-shellout allowlist after recent self-healing and executor source additions shifted audited call sites - keep the guard's path, primitive, and signature checks unchanged ## Test plan - `corepack pnpm --filter @fusion/engine exec vitest run src/__tests__/engine-no-blocking-shellout.test.ts --silent=passed-only --reporter=dot` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Updated static validation allowlists for audited synchronous shell command operations so matching stays accurate with the latest call-site locations. * Kept safeguards that prevent unapproved blocking shell commands from passing validation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: gsxdsm <gsxdsm@users.noreply.github.com> |
||
|
|
f1a2d9ae1f |
FN-8626: validate committed test timing snapshot
Add an automated guard that keeps CI test-sharding timings usable. - Validate snapshot structure, freshness, and recorded test-file paths. - Confirm planning loads the snapshot and shard dry-runs use it without stale warnings. Files changed: scripts/__tests__/ci-test-shard-timings.test.mjs | 50 +++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) Fusion-Task-Id: FN-8626 Fusion-Task-Lineage: ada6525f-8dcc-4494-8586-3aa2e41618f3 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
3f33cb000f |
feat: per-origin workflow selection + feedback-derived refinement titles
Two task origins had no workflow picker in front of the operator and always inherited the project default: `fn task create` (CLI + the `fn_task_create` agent tool) and refinement tasks. Add a Project General setting for each, where blank/unset means "Selected workflow" (the operator's current Board lane, falling back to the project default) and a concrete id pins that origin. Because the Board lane lives in browser localStorage, non-browser callers could not resolve "Selected workflow" at all. `boardSelectedWorkflowId` mirrors the lane into project settings so they can. Note this makes the mirrored lane project-scoped: two operators on one project share it, last switch wins. The Board never reads it back, so the only effect is which workflow a newly created task inherits. Resolution is `TaskStore.resolveOriginWorkflowOverrideId(origin)`: pinned setting -> mirrored lane -> `undefined` to inherit each caller's existing default-workflow path unchanged. A deleted or fragment id degrades to inherit rather than throwing, so a stale settings value can never break task creation. An explicit `workflow_id` argument to `fn_task_create` still wins. Separately, a refinement is now titled by the operator's own feedback via the shared `deriveFallbackTaskTitle`, not `Refinement: <parent title>`. Ten refinements of one task previously rendered ten identical titles, so the board could not tell them apart while the text saying what each one asked for sat in the description. Provenance moves to a `Refines <id>` card chip alongside the existing detail-view parent link and dependency edge. Verified: merge gate (299 tests), lint, full build, and typecheck for core, CLI, and dashboard all pass. New coverage: origin resolution across both origins and the full precedence ladder, the two settings pickers, the board-lane mirror, refinement titling (including sibling distinctness), and the card chip. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
e4cb957b57 |
FN-8619: migrate modal geometry to FloatingWindow
Unify migrated modal geometry and responsive behavior under FloatingWindow. - Cover Agent Detail and GitHub Import floating-window interaction and persistence contracts. - Preserve unique Agent Detail labels, mouse-only backdrop dismissal, and tablet touch layouts. - Update the dashboard modal migration inventory. Files changed: docs/dashboard-modal-inventory.md | 6 +- .../dashboard/app/components/AgentDetailView.css | 49 +++++----- .../dashboard/app/components/AgentDetailView.tsx | 6 +- .../dashboard/app/components/FloatingWindow.css | 10 +- .../dashboard/app/components/TaskDetailModal.css | 15 +++ .../AgentDetailView.floating-window.test.tsx | 102 +++++++++++++++++++++ .../__tests__/GitHubImportModal.test.tsx | 58 ++++++++++++ ...etailModal.responsive-and-dependencies.test.tsx | 24 +++++ 8 files changed, 241 insertions(+), 29 deletions(-) Fusion-Task-Id: FN-8619 Fusion-Task-Lineage: efa95e41-b12e-4e5d-aeb2-65b43c2dd8e0 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
43160a7aae |
FN-8621: migrate complex modals to FloatingWindow
Unify complex dashboard modal presentation under persisted FloatingWindow geometry. - Migrate Create Room, Task Detail, Agent Detail, and GitHub Import modal presentations. - Preserve documented embedded and docked exceptions, dismissal behavior, and nested scrolling. - Add presentation-contract coverage and publish dashboard guidance and changesets. Files changed: ...n-8619-resize-persist-modals-floating-window.md | 7 ++ .changeset/fn-8621-create-room-floating-window.md | 7 ++ docs/dashboard-guide.md | 16 +++- docs/dashboard-modal-inventory.md | 12 +-- .../dashboard/app/components/AgentDetailView.css | 16 +--- .../dashboard/app/components/AgentDetailView.tsx | 102 ++++++++++++++++----- .../dashboard/app/components/CreateRoomModal.css | 19 +++- .../dashboard/app/components/CreateRoomModal.tsx | 57 ++++++++---- .../dashboard/app/components/FloatingWindow.css | 13 ++- .../dashboard/app/components/FloatingWindow.tsx | 15 +++ .../dashboard/app/components/GitHubImportModal.css | 11 +-- .../dashboard/app/components/GitHubImportModal.tsx | 40 ++++++-- .../dashboard/app/components/TaskDetailModal.css | 52 +---------- .../dashboard/app/components/TaskDetailModal.tsx | 58 ++++++------ .../__tests__/AgentDetailView.core.test.tsx | 2 +- .../AgentDetailView.mobile-scroll.test.tsx | 6 +- .../components/__tests__/CreateRoomModal.test.tsx | 62 +++++++++++-- .../components/__tests__/FloatingWindow.test.tsx | 1 + .../__tests__/GitHubImportModal.test.tsx | 8 +- ...etailModal.responsive-and-dependencies.test.tsx | 77 +++++++--------- .../__tests__/modal-presentation-contract.test.tsx | 74 +++++++++++++++ .../dashboard/app/hooks/useEmbeddedPresentation.ts | 2 +- .../dashboard/app/hooks/useModalResizePersist.ts | 5 + 23 files changed, 441 insertions(+), 221 deletions(-) Fusion-Task-Id: FN-8621 Fusion-Task-Lineage: 04b6f3fe-d527-4a21-a0cb-489eb20f5e91 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
7715a83e6f |
FN-8624: fix task detail activity right padding
Keep Task Detail activity insets symmetric while reserving overlay clearance only for first-row content. - Move Live/Feed overlay clearance from the activity container to first-row elements. - Preserve responsive overlay spacing and the full-width Interventions timeline. - Cover modal, pop-out, embedded, and responsive activity layouts with updated tests. - Add a patch changeset for the Task Detail padding fix. Files changed: .changeset/fn-8624-task-detail-inset.md | 7 ++++ .../dashboard/app/components/TaskDetailModal.css | 41 ++++++++++------------ .../TaskDetailModal.attachments-and-tabs.test.tsx | 6 ++-- .../__tests__/TaskDetailModal.css.test.ts | 21 ++++++----- ...etailModal.responsive-and-dependencies.test.tsx | 25 +++++++------ 5 files changed, 54 insertions(+), 46 deletions(-) Fusion-Task-Id: FN-8624 Fusion-Task-Lineage: 578cfe86-3021-421d-841b-2670efc10a5d Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
d3c1955866 |
FN-8625: remove heartbeat controls from agent org charts
Keep org charts read-only for heartbeat configuration while preserving controls on board and list surfaces. - Remove heartbeat toggle props, markup, and styling from org chart nodes - Cover both org chart layouts and board heartbeat availability with regression tests - Add a patch changeset for the dashboard behavior fix Files changed: .../fn-8625-remove-org-chart-heartbeat-toggle.md | 7 +++++++ packages/dashboard/app/components/AgentsView.css | 7 ------- packages/dashboard/app/components/AgentsView.tsx | 14 +++++--------- .../__tests__/AgentsView.orgchart.test.tsx | 20 ++++++++++++++++++++ .../app/components/__tests__/AgentsView.test.tsx | 20 +++++++++++--------- 5 files changed, 43 insertions(+), 25 deletions(-) Fusion-Task-Id: FN-8625 Fusion-Task-Lineage: 454c05e6-fe31-486b-975a-80ba5e8c518c Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
89b4621a93 |
FN-8607: migrate shared modals to FloatingWindow
Standardize agent, onboarding, and utility modal behavior on the shared FloatingWindow contract. - Migrate modal hosts to shared geometry, sheet, dismissal, and focus behavior. - Make FloatingWindow the sole owner of modal ARIA semantics and protect portal-safe dismissal surfaces. - Cover migrated modal contracts and document the responsive sheet requirements. Files changed: docs/dashboard-guide.md | 6 +- packages/dashboard/app/components/AgentGenerationModal.tsx | 8 +- packages/dashboard/app/components/AgentImportModal.tsx | 4 +- packages/dashboard/app/components/AgentListModal.tsx | 4 +- packages/dashboard/app/components/AgentOnboardingModal.tsx | 4 +- packages/dashboard/app/components/DockerNodeOnboardingModal.tsx | 4 +- packages/dashboard/app/components/ExperimentalAgentOnboardingModal.tsx | 4 +- packages/dashboard/app/components/FloatingWindow.css | 36 ++++-- packages/dashboard/app/components/FloatingWindow.tsx | 12 ++ packages/dashboard/app/components/MilestoneSliceInterviewModal.tsx | 2 +- packages/dashboard/app/components/NativeShellOnboardingModal.tsx | 2 +- packages/dashboard/app/components/SetupWizardModal.tsx | 3 +- packages/dashboard/app/components/SubtaskBreakdownModal.tsx | 2 +- packages/dashboard/app/components/__tests__/AgentModals.floatingWindow.test.tsx | 134 ++++++++++++++++++--- packages/dashboard/app/components/__tests__/OnboardingModals.floatingWindow.test.tsx | 128 +++++++++++++++++--- packages/dashboard/app/components/__tests__/UtilityModals.floatingWindow.test.tsx | 124 +++++++++++++++++-- packages/dashboard/app/components/__tests__/migratedModalFixtures.tsx | 59 ++++++--- packages/dashboard/app/components/__tests__/modalFloatingWindowContract.test.tsx | 20 ++- 18 files changed, 458 insertions(+), 98 deletions(-) Fusion-Task-Id: FN-8607 Fusion-Task-Lineage: 11ba6a9c-ce89-4358-83c4-a15ef15b6128 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
bdfa5186c4 |
FN-8622: capture Chromium CDP modal screenshots
Add assertion-guarded CDP evidence for migrated Agent List and Setup Wizard modal touch geometry. - Mount production modal surfaces in the resize browser fixture - Verify tablet resize and drag behavior plus true-phone sheet behavior - Store the captured phone and tablet screenshots as regression evidence - Extend mobile sheet styling to the migrated modal hosts Files changed: .../dashboard/app/components/FloatingWindow.css | 8 ++ .../app/task-modal-touch-resize-e2e-fixture.tsx | 17 +++- .../fn-8607/phone-fullscreen-sheet.png | Bin 0 -> 17823 bytes .../fn-8607/tablet-agent-list-after.png | Bin 0 -> 21489 bytes .../fn-8607/tablet-setup-wizard-after.png | Bin 0 -> 81964 bytes .../task-modal-touch-resize-browser.test.ts | 99 +++++++++++++++++++++ 6 files changed, 120 insertions(+), 4 deletions(-) Fusion-Task-Id: FN-8622 Fusion-Task-Lineage: 3fabd950-bac0-47f4-9649-08709db31e02 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
ba24a530ef |
FN-8620: migrate dashboard modals to FloatingWindow
Standardize dashboard modal geometry and interaction behavior through the shared FloatingWindow contract. - Migrate New Task, right-dock expansion, terminal, onboarding, and utility modals to FloatingWindow. - Expand shared window resizing, positioning, accessibility, and contract coverage. - Document the modal migration inventory and publish changesets. Files changed: .changeset/fn-8607-floating-modal-contract.md | 7 + .changeset/fn-8620-bespoke-geometry-modals.md | 7 + docs/dashboard-guide.md | 47 ++ docs/dashboard-modal-inventory.md | 6 +- .../app/components/AgentGenerationModal.tsx | 14 +- .../dashboard/app/components/AgentImportModal.tsx | 7 +- .../dashboard/app/components/AgentListModal.tsx | 8 +- .../app/components/AgentOnboardingModal.tsx | 6 +- .../app/components/DockerNodeOnboardingModal.tsx | 14 +- .../ExperimentalAgentOnboardingModal.tsx | 6 +- .../dashboard/app/components/FloatingWindow.css | 21 + .../dashboard/app/components/FloatingWindow.tsx | 62 ++- packages/dashboard/app/components/MailboxModal.tsx | 14 +- .../components/MilestoneSliceInterviewModal.tsx | 12 +- .../app/components/NativeShellOnboardingModal.tsx | 6 +- packages/dashboard/app/components/NewTaskModal.css | 196 +------ packages/dashboard/app/components/NewTaskModal.tsx | 593 +++++++-------------- packages/dashboard/app/components/RightDock.css | 84 +-- .../app/components/RightDockExpandModal.tsx | 333 ++---------- .../dashboard/app/components/SetupWizardModal.tsx | 20 +- .../app/components/SubtaskBreakdownModal.tsx | 6 +- .../dashboard/app/components/TerminalModal.css | 120 +---- .../dashboard/app/components/TerminalModal.tsx | 321 ++--------- .../__tests__/AgentModals.floatingWindow.test.tsx | 26 + .../components/__tests__/FloatingWindow.test.tsx | 27 +- .../app/components/__tests__/NewTaskModal.test.tsx | 66 +-- .../OnboardingModals.floatingWindow.test.tsx | 20 + .../app/components/__tests__/RightDock.test.tsx | 18 +- .../components/__tests__/TerminalModal.test.tsx | 61 +-- .../UtilityModals.floatingWindow.test.tsx | 18 + .../components/__tests__/migratedModalFixtures.tsx | 25 + .../__tests__/modalFloatingWindowContract.test.tsx | 30 ++ 32 files changed, 726 insertions(+), 1475 deletions(-) Fusion-Task-Id: FN-8620 Fusion-Task-Lineage: 2a912260-3292-4b13-bcf0-9de5a3df8ccd Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
256c64a7bd |
chore(release): v0.74.0-beta.5
Version bump via changesets. |
||
|
|
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> |
||
|
|
73b2a32e2b |
test: backfill dashboard test mocks for new api and viewport exports
Concurrent dashboard work added runtime exports that hardcoded module mocks did not expose, so any suite rendering the affected component threw "No <export> is defined on the mock". Adds the missing `../api` exports (system-info probe, update install/restart, cloudflared, provider key and login helpers, git remotes/branches) and the `isTabletTouchViewport` viewport helper across the 26 suites that mock those modules. Verified: all 26 files pass (1012 tests). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
beebd270bd |
fix: make Queued to plan / Ready badges agree with the planning lane
TaskCard inferred "unplanned" from steps.length === 0 while triage's todo-discovery and the scheduler's dispatch filter both decide from PROMPT.md seed-ness, so the badges disagreed with the engine in both directions: a real spec that parsed to zero steps read as "Queued to plan" while the scheduler already treated it as a WIP-slot candidate, and a re-seeded card still carrying old steps read as "Ready" while triage was about to plan it. Either way the badge sent operators to the wrong cap. Adds the shared isTaskAwaitingPlanning predicate (replan park, missing spec, seed-vs-real content) used by both triage's discovery and a new best-effort `awaitingPlanning` enrichment on GET /api/tasks. TaskCard derives both badges from that one value — strict complements — and keeps the step count only as a fallback for SSE payloads and older servers. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
01b27b13f1 |
test(dashboard): add per-character typing coverage to uncovered field surfaces
Sweeping the other views for the FN-8606 typing bug found no further breakage, but it did expose why the bug shipped: almost all field coverage uses fireEvent.change, which sets a value in one shot on a node it already holds and never needs the input to stay mounted. A remount is invisible to it. Adds expectStableTyping (types character by character via userEvent, then asserts DOM node identity, accumulated value, and retained focus) and applies it to the uncovered surfaces: the FN-8606-migrated AddNode, ConnectNode, NodeDetail, Scripts, and WorkflowAddStep modals, plus the board's QuickEntryBox composer and SubtaskBreakdownModal title editing. All pass — this is a detection floor, not a fix. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
d193dcdbb0 |
chore(lint): ban React components declared inside another component
Adds fusion-react/no-nested-component-definitions, a custom rule in the house style of the existing detached-spawn guard. A component declared in render is a new element type every render, so React remounts its subtree on each parent update and destroys focus, scroll, and local state. This pattern shipped three times without review or tests catching it: FN-8606's ModalShell left Planning Mode and Settings untypable, and MailboxModal's ReplyContextExpandable collapsed expanded reply rows. Tests missed it because fireEvent.change sets a value without needing the node to stay mounted. The rule reports PascalCase functions (including memo()/forwardRef()-wrapped) that return JSX and are declared inside another JSX-returning function. Lowercase render helpers are deliberately allowed — they are the sanctioned fix. Escape hatch: // nested-component-allowlist: <reason>. Scoped to production .tsx, with a vitest guard for the rule itself. Hoists the two pre-existing violations (ProviderStatusBadge, GitHubStatusBadge in ModelOnboardingModal) to module scope so the rule lands clean at "error". Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
5ea98f7d4b |
fix: release admission claims when triage evicts a hung planner
evictStaleProcessing cleared `processing` but left the task in `coordinatorAdmittedTaskIds`, which is only cleared by specifyTask's finally — the path a hung promise never reaches. The card stayed eligible (so the throttle branch never logged or emitted `task:plan-admission-throttled`) while admitOldest's refresh filtered it out, leaving it on the "Queued to plan" badge with free slots and no diagnostic until engine restart. Also drop an untransferred pre-held host slot, which otherwise waits out the 600s stale-excess valve. Regression tests assert the invariant on the real production candidate source: an evicted card is re-offered and its host slot returned, while a still-live stale task keeps both claims. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
c21fb0d1d0 |
fix(dashboard): stop Mailbox reply-context rows collapsing on unrelated re-renders
ReplyContextExpandable was declared inside MailboxModal's render, making it a new element type on every render. Any parent update remounted the whole recursive reply thread, so expanding one reply row collapsed the others and discarded their DOM identity, focus, and scroll position. Hoist it to module scope and pass the parent's reply state and handlers through an explicit env prop so the element type stays stable. Adds a regression test that expands one row, expands a second, and asserts the first keeps both its node identity and aria-expanded state — same defect class as the FN-8606 ModalShell fix. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
62e13f484b |
docs: index dashboard-modal-inventory.md in Audit Reports
FN-8617 committed docs/dashboard-modal-inventory.md as the canonical classification of all 45 dashboard modal surfaces (classes A-D) with file:line evidence and FloatingWindow migration targets, but the docs index was not updated. Add the Audit Reports entry so the doc is discoverable from the docs hub. Verified: orphan scan clean (only known intentional orphans remain); pnpm --filter @runfusion/fusion test:docs-index passes (2/2). |
||
|
|
7065d03895 |
fix(dashboard): keep Planning Mode and Settings typable after floating-window migration
FN-8606 declared the window shell as a component inside PlanningModeModal and SettingsModal render. A component declared in render is a new element type on every render, so React remounted the whole subtree on each keystroke, destroying the focused input: Planning Mode dropped everything after the first character and Settings text fields did the same. Replace ModalShell with a plain renderModalShell(children) call so the returned element types stay stable, and add a Planning regression test that types per-character across both the modal and embedded surfaces (fireEvent.change cannot observe this class of bug, which is why it shipped). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
0022621d22 |
chore(release): v0.74.0-beta.4
Version bump via changesets. |
||
|
|
892e50b810 | Update roadmap for GPT and Opus support | ||
|
|
2bb8537352 |
FN-8616: make agent tool-output limits configurable
Expose the shared agent tool-output budget as a scoped operator setting with an explicit no-limit option. - Resolve global and project output caps with a safe finite default and zero sentinel. - Propagate configured budgets through PI and plugin runtime tool wrappers. - Add settings controls, localized labels, documentation, and regression coverage. Files changed: .changeset/fn-8616-tool-output-budget-setting.md | 7 ++++ docs/agents.md | 4 +- docs/settings-reference.md | 1 + .../core/src/__tests__/tool-output-budget.test.ts | 23 ++++++++--- packages/core/src/index.gate.ts | 2 + packages/core/src/index.ts | 2 + packages/core/src/settings-schema.ts | 12 ++++++ packages/core/src/tool-output-budget.ts | 31 +++++++++++++-- packages/core/src/types/settings-scope.ts | 8 ++++ .../app/components/settings/save-split.ts | 1 + .../sections/GlobalGeneralSection.search.ts | 20 ++++++++++ .../settings/sections/GlobalGeneralSection.tsx | 26 ++++++++++++ ...lobalGeneralSection.tool-output-budget.test.tsx | 46 ++++++++++++++++++++++ .../settings-default-descriptions.test.tsx | 1 + .../src/__tests__/agent-session-helpers.test.ts | 20 ++++++++++ .../src/__tests__/runtime-resolution.test.ts | 15 +++++++ .../__tests__/tool-output-budget-wrapper.test.ts | 45 ++++++++++++++++----- packages/engine/src/agent-runtime.ts | 2 + packages/engine/src/agent-session-helpers.ts | 18 +++++++-- packages/engine/src/pi.ts | 29 ++++++++++---- packages/engine/src/runtime-resolution.ts | 10 ++++- packages/i18n/locales/en/app.json | 4 ++ packages/i18n/locales/es/app.json | 6 ++- packages/i18n/locales/fr/app.json | 6 ++- packages/i18n/locales/ko/app.json | 6 ++- packages/i18n/locales/zh-CN/app.json | 6 ++- packages/i18n/locales/zh-TW/app.json | 6 ++- packages/i18n/src/resources.d.ts | 4 ++ 28 files changed, 323 insertions(+), 38 deletions(-) Fusion-Task-Id: FN-8616 Fusion-Task-Lineage: 3ca99a61-d6ae-48ff-98d2-f14a153aa2b7 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
d3002d1453 |
FN-8617: restore authoritative dashboard modal inventory
Restore the committed source of truth for dashboard modal migration coverage. - Add the evidence-backed inventory of dashboard modal classifications and migration ownership. - Link the dashboard guide to the canonical modal inventory. Files changed: docs/dashboard-guide.md | 4 ++ docs/dashboard-modal-inventory.md | 103 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) Fusion-Task-Id: FN-8617 Fusion-Task-Lineage: 87159726-d574-4f71-bd6f-66cf9f2f9a9e Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
743dc5f46e |
FN-8612: remove tablet task modal padding
Keep task modals dense on tablets without reducing their touch resize targets. - Move the Task Detail drag target out of layout flow while preserving its 44px hit area. - Restore desktop-density New Task header and body padding on tablet resize surfaces. - Add CSS, unit, and browser coverage for tablet geometry and generic floating windows. Files changed: .changeset/fn-8612-tablet-modal-padding.md | 7 + docs/dashboard-guide.md | 8 +- .../task-detail-modal-tablet-width.test.ts | 8 + .../dashboard/app/components/FloatingWindow.css | 40 ++++- packages/dashboard/app/components/NewTaskModal.css | 14 ++ .../FloatingWindow.touch-geometry.test.tsx | 14 ++ .../app/components/__tests__/NewTaskModal.test.tsx | 8 + .../app/task-modal-touch-resize-e2e-fixture.tsx | 54 ++++++- .../task-modal-touch-resize-browser.test.ts | 177 ++++++++++++++++++++- packages/dashboard/vitest.config.ts | 6 + 10 files changed, 322 insertions(+), 14 deletions(-) Fusion-Task-Id: FN-8612 Fusion-Task-Lineage: fecd7c48-7b6c-434e-9002-f8f21241120c Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
a9b30013bb |
fix(core): approval dedupe lookup matches on PostgreSQL instead of minting duplicates
`findLatestByDedupeKey` read `targetContext` through the string-only `fromJson`. In backend (PostgreSQL) mode that column is jsonb and Drizzle returns it ALREADY PARSED, so the dedupe scan never matched: every gate retry minted a duplicate approval request, and an approved grant could never be redeemed. The live database shows the signature plainly — 17 approved requests, 0 completed. Normalize both shapes in one place (`normalizeTargetContext`), applied at `rowToRequest` and both dedupe scan sites, so a row resolves whether it arrives as a JSON string (SQLite) or a parsed object (Postgres). The regression test asserts shape-independence rather than the single reported case: the same stored key must resolve in BOTH shapes, and must not match a different key or an absent context in either. Mutation-checked — reverting the scan sites fails exactly the parsed-object case. Cherry-picked ahead of #2457, which carries the wider approval/permission hardening pass, because this one is an active production defect on its own. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |
||
|
|
30f81ac0cd |
fix(engine): compact verification failure output
Keep successful verification responses quiet and return bounded, high-signal diagnostics for failures without hiding zero-work or green-while-red warnings. |
||
|
|
65f6748e5b |
FN-8613: theme mailbox markdown links
Theme mailbox message anchors with dashboard tokens and verify link coverage. - Style markdown anchor default, visited, hover, and focus-visible states with design tokens - Cover inline, autolink, list, and table links while preserving file-path controls - Add a patch changeset for themed mailbox links Files changed: .changeset/theme-mailbox-markdown-links.md | 7 ++++ packages/dashboard/app/components/MailboxModal.css | 29 +++++++++++++ .../__tests__/MailboxMessageContent.test.tsx | 49 ++++++++++++++++++---- 3 files changed, 77 insertions(+), 8 deletions(-) Fusion-Task-Id: FN-8613 Fusion-Task-Lineage: a8c7e8bb-8238-4018-bf95-38193f908eb4 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
07c8c95b10 |
FN-8614: cap agent tool output
Bound every engine-injected tool result to preserve agent context capacity. - Add shared 16,000-character total text budgets with deterministic truncation markers and validated overrides. - Apply outermost output clamps to Pi and non-Pi plugin tool paths, with semantic caps for high-volume reads. - Cover budget behavior and document the operator-facing configuration contract. Files changed: .changeset/fn-8614-tool-output-budget.md | 7 ++ docs/agents.md | 8 ++ .../core/src/__tests__/tool-output-budget.test.ts | 58 +++++++++++++ packages/core/src/index.gate.ts | 7 ++ packages/core/src/index.ts | 7 ++ packages/core/src/tool-output-budget.ts | 97 ++++++++++++++++++++++ .../src/__tests__/agent-artifact-tools.test.ts | 10 +++ .../src/__tests__/agent-document-tools.test.ts | 10 +++ .../__tests__/agent-task-logs-read-tools.test.ts | 8 ++ .../__tests__/tool-output-budget-wrapper.test.ts | 67 +++++++++++++++ packages/engine/src/agent-session-helpers.ts | 7 +- packages/engine/src/agent-tools.ts | 43 ++++++++-- packages/engine/src/pi.ts | 54 +++++++++++- 13 files changed, 374 insertions(+), 9 deletions(-) Fusion-Task-Id: FN-8614 Fusion-Task-Lineage: b6a76ccd-d7b4-4b43-af7e-cfd16ffb7fc8 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
a6885b73f2 |
FN-8606: migrate core workflow modals to shared floating windows
Migrate dashboard dialogs to the shared movable and resizable FloatingWindow contract. - Move core, workflow, Git, planning, and automation modal surfaces to stable floating-window identities with persisted geometry. - Suspend geometry and floating controls for phone and short-viewport sheets, including Quick Chat. - Add accessibility wiring, tablet touch targets, migration tests, and operator documentation. Files changed: .changeset/fn-8606-floating-window-core-modals.md | 7 + docs/dashboard-guide.md | 4 + packages/dashboard/app/App.tsx | 8 +- .../dashboard/app/components/ActivityLogModal.tsx | 30 ++-- packages/dashboard/app/components/AddNodeModal.tsx | 8 +- .../dashboard/app/components/ChangesDiffModal.tsx | 35 +++-- .../dashboard/app/components/ConnectNodeModal.tsx | 9 +- .../dashboard/app/components/FloatingWindow.css | 71 ++++++++- .../dashboard/app/components/FloatingWindow.tsx | 27 +++- .../dashboard/app/components/GitManagerModal.tsx | 30 +++- .../dashboard/app/components/GroupTaskModal.tsx | 8 +- .../app/components/ModelOnboardingModal.tsx | 28 ++-- .../dashboard/app/components/NodeDetailModal.tsx | 9 +- .../dashboard/app/components/PlanningModeModal.css | 1 - .../dashboard/app/components/PlanningModeModal.tsx | 57 +++---- .../app/components/ScheduledTasksModal.tsx | 9 +- packages/dashboard/app/components/ScriptsModal.css | 1 - packages/dashboard/app/components/ScriptsModal.tsx | 32 ++-- .../dashboard/app/components/SettingsModal.css | 1 - .../dashboard/app/components/SettingsModal.tsx | 58 ++++--- .../app/components/WorkflowAddStepModal.css | 15 -- .../app/components/WorkflowAddStepModal.tsx | 46 +++--- .../components/__tests__/ActivityLogModal.test.tsx | 33 ++-- .../app/components/__tests__/AddNodeModal.test.tsx | 12 +- .../components/__tests__/ChangesDiffModal.test.tsx | 78 +++++----- .../components/__tests__/ConnectNodeModal.test.tsx | 7 + .../components/__tests__/FloatingWindow.test.tsx | 173 ++++++++++++++++++++- .../components/__tests__/GitManagerModal.test.tsx | 30 ++-- .../components/__tests__/GroupTaskModal.test.tsx | 9 ++ .../__tests__/ModelOnboardingModal.test.tsx | 18 ++- .../components/__tests__/NodeDetailModal.test.tsx | 9 ++ .../__tests__/PlanningModeModal.autosize.test.tsx | 30 ++-- .../__tests__/ScheduledTasksModal.test.tsx | 21 ++- .../app/components/__tests__/ScriptsModal.test.tsx | 15 +- .../__tests__/SettingsModal.mobileClose.test.tsx | 25 ++- .../__tests__/WorkflowAddStepModal.test.tsx | 7 + .../floatingWindowMigration.test-helpers.ts | 126 +++++++++++++++ 37 files changed, 828 insertions(+), 259 deletions(-) Fusion-Task-Id: FN-8606 Fusion-Task-Lineage: dab0df2d-73f4-4b0f-bec3-a45016310c91 Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai> |
||
|
|
cf5575a319 | Add new items to the project roadmap | ||
|
|
4c3b3c14b7 |
Update roadmap with new tasks and workflows
Added new items regarding tasks, workflows, and CEO role. |
||
|
|
82f85ce863 | Update roadmap with new planned and completed items | ||
|
|
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> |
||
|
|
15a2fb18cc |
Merge branch 'fix/incomplete-pg-ports'
Wire incomplete PostgreSQL ports for archive, reconcile, health, settings cache, agent cache, and async prompt overrides. |
||
|
|
ab87d0d803 |
fix(api): return 404 for missing tasks, and make task deletions attributable
Three related fixes, all originating from a `[api:error] Request failed` log line showing a 500 on `GET /api/tasks/FN-8610/runtime-fallback`. 1. Missing/deleted tasks now return 404 instead of 500. `getTaskImpl` signalled a miss with a bare `Error`, and route catches only mapped errno `ENOENT` to 404 — a leftover from the file-backed storage era. In Postgres mode nothing sets an errno code, so every unknown/missing/soft-deleted/wrong-project read returned 500. Adds a typed `TaskNotFoundError` (message byte-identical) plus a shared `task-lookup-error` mapper applied across the task, session-diff, git/GitHub, workflow and file-workspace route registrars. The same bare throw existed on both archive-lifecycle delete paths, so `DELETE /tasks/:id` was affected too. 2. 5xx logs now carry the origin stack. `rethrowAsApiError` constructed a fresh `ApiError` from the message and discarded the original, so the `FNXC:ApiErrorDiagnostics` contract logged the rethrow site rather than the throw site — the reported log entry had no stack at all. Threads `cause` through the error factories and walks the chain (bounded, cycle-guarded). 3. Task deletions are attributable, and non-operator deletes notify. `task:deleted` audit rows recorded `agentId: "system"` for every HTTP delete, making an operator click indistinguishable from a script or an agent; the calling agent's task id was accepted by the store and then never persisted. Adds a `callerKind` union recorded in audit metadata, tags every delete call site, and stamps a self-reported `x-fusion-client` header from the dashboard client. When the caller is `agent-tool` or `api-unattributed`, a best-effort notice is sent to the operator mailbox; operator and engine deletes stay silent. `x-fusion-client` is attribution, not authentication — anything can send it. No delete-blocking, gating or permission logic is added here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> |