Commit Graph

13864 Commits

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


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

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

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

---

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

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


</details>

---------

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

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


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

## Summary by CodeRabbit

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

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

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

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

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

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

## Why

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

## Testing

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


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

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

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

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

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

## Summary by CodeRabbit

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

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

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

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

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

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

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 18:34:39 -07:00
gsxdsm
5378bca7f6 test: fix the dashboard quality runner's self-spawning tests
Running the dashboard's REAL test command (`run-quality-tests.mjs`, which shards
into 15 lanes) surfaced two failures that a plain `vitest run` never shows —
worth noting on its own, since measuring around a package's own command is how
a suite gets called green on a number the project does not produce.

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

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

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

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

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

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

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

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

Fusion-Task-Id: FN-9204

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

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

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

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

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

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

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

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

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

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

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

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

## Why

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

## How

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

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

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

## Verification

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

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

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

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

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

---------

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

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

## Test plan

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


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

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

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

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

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

## Test plan

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

## Local gate notes

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


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

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

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

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

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

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

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

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

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

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

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

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

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

## What's included

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

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

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

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

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

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

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

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


## Rebase Note (2026-08-23)

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

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

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

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

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

---------

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

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

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

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

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


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

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

Co-authored-by: gsxdsm <gsxdsm@users.noreply.github.com>
2026-08-23 16:45:30 -07:00
Phil Larson
38edc2366b fix(core): restore executor workflow creation guidance (#3513)
## Summary
- restore explicit executor guidance for assigning workflows to tasks
the agent creates
- keep the existing prohibition on rerouting the task currently being
executed
- restore parity between both built-in executor prompt variants and
their regression test

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

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

* **Improvements**
* Executor workflow guidance now appears only when task creation or
delegation capabilities are available.
* Built-in executor prompts provide clearer task-assignment instructions
based on available capabilities.
  * Custom executor prompts remain unchanged.
* Removed outdated workflow-setting guidance when task-management
capabilities are unavailable.

* **Tests**
* Added coverage for task creation, delegation, and capability-specific
workflow guidance scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-23 16:45:03 -07:00
Phil Larson
6c2a461816 test(core): refresh lane-wiring baseline after merge readiness (#3515)
## Summary
- Re-record the lane-wiring baseline after #3514 removed the final
unwired merge-readiness call site.
- Normalize the duplicate `self-healing.ts` key while regenerating the
canonical JSON baseline.

## Test Plan
- `node scripts/check-lane-wiring.mjs`
- `git diff --check`


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

## Summary by CodeRabbit

* **Chores**
* Updated internal baseline tracking to remove an obsolete merge-task
entry.
  * No user-facing functionality or behavior changed.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-23 16:44:42 -07:00
gsxdsm
9838f42076 fix: repair core and CLI suites, plus a PG table-registry omission
Core 32 failures -> 0 (5,981 passing); CLI 46 -> 0 (2,021 passing). Three
agents per package, root-cause fixes only.

One product defect, same class as FN-9059 and found the same way — by a test
that leaked state between runs:

  `projectTableNames` was missing SEVENTEEN tables the schema declares
  (current_plan_evidence, spec_locks, spec_drift_reports, symbol_locks,
  configuration_revisions, chat_tags, chat_session_tags, mission_lineage_stops,
  task_verification_requests, unplanned_execution_blocks,
  workflow_agent_capacity_leases and the six task_lifecycle_* tables). That list
  drives BOTH the PG test-harness per-test reset and production health
  compaction, so those tables were never truncated between tests (a plan-evidence
  version counter carried forward, making whole-file runs disagree with isolated
  ones) and never VACUUM/ANALYZEd in production. Registered, with
  project-table-registry.test.ts as a ratchet — verified it fails on an
  unregistered new table naming the offender.

Everything else was drift behind deliberate changes: branch-write provenance,
FN-073 dependency validation, the FN-9191 pre-merge merge gate, U11's triage/
planning lane merge, refinement workflow coming from the ORIGIN selection,
async-converted provider registration, a barrel mock missing exports a guard
added, and several source-pinned inventories broken by module moves. Tests for
removed features were deleted with their removing commit cited.

Also fixes a vitest config gap where @fusion/core/mcp-builtin-servers resolved
only to dist/, which was breaking test COLLECTION in unrelated CLI files and had
been misread as transient cross-agent noise.

Quarantines mission-store.pg's concurrent-claim race (second sighting): it holds
a transaction open, sleeps 250ms and asserts the rival has not settled, which
fails under parallel load. An A/B against the registry change above looked
causal on one run and did not reproduce on three — that coincidence is the flake
itself, and rescue needs a real lock-wait probe rather than a longer sleep.
Core's config now inlines its exclude array, because check-quarantine-ledger.mjs
cannot resolve a variable reference and silently reported the ledger unpaired.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 16:31:25 -07:00
gsxdsm
9d1bd393d8 FN-9202: Unify dashboard banner styling
Standardize dashboard notices on a shared, token-driven banner shell.

- Add a reusable Banner primitive with consistent tones, layouts, actions, and dismissal behavior.
- Migrate dashboard notification banners away from bespoke shells and left accent borders.
- Document and test banner styling invariants, including token-only CSS lengths and colors.
- Add a patch changeset for the published dashboard bundle.

Files changed:
 .changeset/fn-9202-banner-style-unification.md     |   7 ++
 docs/dashboard-guide.md                            |   4 +
 .../app/__tests__/banner-style-consistency.test.ts |  25 ++++
 .../app/components/ApprovalNotificationBanner.css  |  10 --
 .../app/components/ApprovalNotificationBanner.tsx  |   5 +-
 packages/dashboard/app/components/Banner.css       |  81 ++++++++++++
 packages/dashboard/app/components/Banner.tsx       |  78 ++++++++++++
 .../app/components/CapacityRiskBanner.css          |  50 +-------
 .../app/components/CapacityRiskBanner.tsx          |  39 +++---
 .../app/components/CliBinaryInstallBanner.css      | 126 ++-----------------
 .../app/components/CliBinaryInstallBanner.tsx      |  14 +--
 .../app/components/DbCorruptionBanner.css          |  18 +--
 .../app/components/DbCorruptionBanner.tsx          |   5 +-
 .../app/components/EngineStatusBanner.css          |  94 ++------------
 .../app/components/EngineStatusBanner.tsx          |  48 +++----
 .../app/components/EngineUnavailableBanner.css     |  42 +------
 .../app/components/EngineUnavailableBanner.tsx     |  21 ++--
 .../app/components/MergeAdvanceNotice.css          | 129 +++----------------
 .../app/components/MergeAdvanceNotice.tsx          |  36 +++---
 .../app/components/MigrationInProgressBanner.css   |  25 ----
 .../app/components/MigrationInProgressBanner.tsx   |  19 +--
 .../app/components/OAuthReloginBanner.css          |  53 +-------
 .../app/components/OAuthReloginBanner.tsx          |  26 +---
 .../app/components/SessionNotificationBanner.css   |  16 +--
 .../app/components/SessionNotificationBanner.tsx   |   5 +-
 .../app/components/SetupWarningBanner.css          | 106 +---------------
 .../app/components/SetupWarningBanner.tsx          |  31 +----
 .../app/components/SqliteMigrationBanner.css       |  40 +-----
 .../app/components/SqliteMigrationBanner.tsx       |  33 ++---
 .../app/components/TaskIdIntegrityBanner.css       |  18 +--
 .../app/components/TaskIdIntegrityBanner.tsx       |   5 +-
 .../dashboard/app/components/TestModeBanner.css    |  18 ---
 .../dashboard/app/components/TestModeBanner.tsx    |  12 +-
 .../app/components/UpdateAvailableBanner.css       | 139 +++------------------
 .../app/components/UpdateAvailableBanner.tsx       |  22 ++--
 .../app/components/__tests__/Banner.test.tsx       |  48 +++++++
 36 files changed, 450 insertions(+), 998 deletions(-)

Fusion-Task-Id: FN-9202

Fusion-Task-Lineage: 14762201-55e5-4124-a897-9667c3a1ab84

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-23 16:00:53 -07:00
gsxdsm
4475342145 docs: record a first-sighting PG setup-hook flake in the observed register
`handoff-to-review-atomicity.pg.test.ts` aborted its `beforeAll` at the 15s
budget on the first `pnpm test:gate` of a session; not reproduced in 8 later
runs across three shapes (gate x2, pg-gate x3, isolated x3).

Same mode as entries 6 and 7, but narrower: it happened under the capped
four-fork lane with two selected files, so fork oversubscription does not
explain it. Recorded the cold-cluster correlation as a hypothesis rather than a
finding — reproducing it means stopping the embedded cluster, and this host runs
a live Fusion instance.

Discloses that the failing run's full output was lost to a tail pipe, and that
inline quarantine was unavailable regardless (quarantinedCoreTests must stay
empty); eviction of a transactional-invariant gate file is owner-escalated.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 15:45:31 -07:00
gsxdsm
08f8c26ec1 fix: honor the workflow-principal hold cooldown on the dispatch path
The U4 executor peel (#3317) rewrote executor.ts from a pre-change base and
dropped `isPrincipalHoldCoolingDown`, re-inlining the read inside
executeWorkflowGraph behind `!opts?.alreadyClaimed` — a flag its only caller,
executeCore, always sets. The ladder kept recording and clearing correctly, so
it read as working while never once deferring a dispatch.

Without it, an unroutable role pool re-enters the graph on every dispatch only
to re-fence and re-park: one graph run, two work-item writes and two audit rows
per pass, for a condition that clears only when an operator enables or adds an
agent. The `!repeated` log suppression keeps that flood invisible after the
first line.

Restore the guard in executeCore, ahead of the graphRouting claim. Position is
load-bearing in both directions: returning after the claim would strand it
(graphRunnerOwnsClaim stops the finally from cleaning up), which is also why
the inner check must keep its alreadyClaimed gate.

Make the ladder a primitive with one exported writer and one exported reader so
a lost reader is a lost reference the compiler can see, rather than a .get()
that quietly moved somewhere its guard could never be true. Its test-mode zero
is now read at record time; bound at module load it collapsed the cooldown to
until === now under VITEST, so no test could have caught this.

Regression test asserts the invariant on both entry surfaces plus the negatives
that keep the guard from becoming a permanent block. Mutation-checked: with the
guard disabled the two dispatch-deferral cases fail.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 15:45:20 -07:00
gsxdsm
39812f4898 test: quarantine one suite-only flake, record another, fix the lockstep guard
Full engine suite at a97aa84a20: 3 failures out of 12,414. All three diagnosed:

- self-healing-pending-wedge-notification's marker-selection case fails ONLY in
  a full-suite run (expects 1 elapsed marker, sees 2) and passes deterministically
  alone. This is its SECOND sighting, so per AGENTS.md it is an on-sight
  quarantine with no further discretion: ledger entry + matching vitest exclude,
  same commit, 2026-09-06 deletion deadline.
- spec-drift-reconciler's exponential-backoff case shows the same shape on a
  FIRST sighting, so it is recorded in the observed register instead of evicting
  that file's other passing coverage. Both are timer-driven reconciler tests that
  only fail alongside other suites, pointing at cross-file fake-timer state.
- merge-orphan-durable-write-inventory drift was pure lineHint movement (19
  changed, zero newly unclassified entries) after product edits shifted lines.
  Regenerated.

Also fixes check-quarantine-ledger.mjs, which could not see the exclude I added:
its comment stripper treated the `/**` inside glob literals like "node_modules/**"
and "src/**/*.slow.test.ts" as a block-comment opener and deleted through to the
next "*/", swallowing whole array literals and every entry after them. It now
scans string-aware, so the lockstep check actually holds. Nothing was appeased:
no timeout widened, no retry added, no assertion relaxed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 15:43:00 -07:00
gsxdsm
e259b1a290 fix: retighten lane-wiring baseline after merge-readiness wiring
#3514 removed the last unwired task-merge review-lane call site but left
the ratchet allowance at 1, so every PR against main failed
check:lane-wiring on a drop.
2026-08-23 15:40:48 -07:00
Phil Larson
bc82d8e0e1 fix(core): thread review lanes through merge readiness (#3514)
## Summary
- thread resolved review lanes through `isTaskReadyForMerge`
- preserve required pre-merge step filtering
- add coverage for a renamed review lane

## Test plan
- `pnpm --filter @fusion/core exec vitest run --silent=passed-only
--reporter=dot src/__tests__/task-merge.test.ts`
- `pnpm --filter @fusion/core typecheck`
- `pnpm check:lane-wiring`
- `pnpm check:changesets`
- `pnpm exec eslint packages/core/src/merge/task-merge.ts
packages/core/src/__tests__/task-merge.test.ts`

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

* **Bug Fixes**
* Custom review lanes are now honored during merge-readiness checks and
auto-merge processing.
  * Renamed workflow lanes correctly determine whether tasks can merge.
* Tasks resumed from a paused state are routed and evaluated using the
appropriate review lane.
* The default `in-review` lane remains supported when no custom review
lanes are configured.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: gsxdsm <gsxdsm@users.noreply.github.com>
2026-08-23 15:31:17 -07:00
Phil Larson
febe375b14 fix(core): preserve merge finalization review lanes (#3508)
## Summary
- Forward project review lanes and required pre-merge steps through
merge-confirmed finalization.
- Cover custom review-lane and required-step blockers in the merge
finalization tests.
- Correct future-dated FNXC stamps that were blocking the shared lint
gate.

## Test Plan
- `corepack pnpm --filter @fusion/core exec vitest run
src/__tests__/task-merge.test.ts --silent=passed-only --reporter=dot`
- `corepack pnpm --filter @fusion/core typecheck`
- `corepack pnpm check:lifecycle-columns`
- `corepack pnpm check:lane-wiring`
- `corepack pnpm check:fnxc-future-dates`
- `corepack pnpm check:changesets --strict`
- `git diff --check`


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

## Summary by CodeRabbit

- **Bug Fixes**
- Confirmed merge finalization now preserves the selected review lane
and applies its resolved review requirements.
- Required pre-merge steps are correctly enforced for both durable and
non-durable merges.

- **Tests**
- Added coverage for review-lane handling and pre-merge blockers across
merge paths.

- **Documentation**
  - Added release notes documenting the merge finalization fix.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-23 15:24:08 -07:00
gsxdsm
a97aa84a20 fix: remove debug probes swept into ab9789f0a8 by mistake
ab9789f0a8 was committed with `git add -A` while an agent was mid-investigation
in this same checkout, so it captured that agent's temporary instrumentation:
eight `process.stderr.write('[F] …')` probe lines inside product code
(executor/mark-stuck-aborted.ts) and a 359-line scratch copy of a test file.
Both were pushed. Reverting both; no product behavior was ever intended to
change in those files.

Also lands the executor-stuck-requeue fix that investigation produced: the
grace-timeout assertion ran before the product finished, because the callback
continues past its timer into resetStepsIfWorkLost -> loadWorkspaceConfig, real
async fs I/O that `vi.advanceTimersByTimeAsync` does not await. The test now
awaits a completion barrier resolved by the requeue's own final moveTask rather
than a timeout or retry. The product was correct.

Lesson for this checkout: stage by explicit path while agents are running.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 15:05:27 -07:00
gsxdsm
ab9789f0a8 fix: correct workspace review fingerprint range and land-intent resolve gating
Two product defects surfaced by workspace-e2e's remaining failures.

1. A merge-boundary fence silently did not apply. captureWorkspaceReviewEvidence
   computes a repository's file list over baseCommitSha..<resolved task branch>,
   but computeReviewDiffFingerprint hardcoded baseRef..HEAD. For a workspace
   entry whose checkout sits on the integration branch those are different
   ranges, so the fingerprint did not describe the files captured beside it: a
   diverged checkout hard-failed an approved repository as content-changed,
   and a checkout at the base produced an empty diff -> undefined fingerprint ->
   the repo dropped out of mergeBoundaryFingerprints, so BOTH the
   approval-missing and content-changed fences stopped applying to it at all.
   computeReviewDiffFingerprint now takes an optional headRef; workspace
   evidence passes the resolved task branch. The singular-review caller, whose
   worktree IS the branch, keeps the ambient HEAD default.

2. Land intents were recorded and resolved under different conditions.
   landOneRepo records an intent only when ctx.workspaceLand is set, which
   landWorkspaceTask passes only for remote targets, but the resolve side was
   gated on durableLandLease alone. A local-only land therefore resolved an
   intent that was never recorded, got "missing", and failed a fully-landed
   repo as a partial land AFTER its integration ref had advanced. Resolve now
   uses the same condition as record.

The approveWorkspaceReview helper's "reviewStep called exactly once" constant
only held because defect 1 suppressed a repository; it now derives the expected
count from the same production capture the review loop uses.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 15:01:39 -07:00
gsxdsm
3533fc8a47 docs: pin the hybrid step-storage contract (the "steps: [] no-op" is not a bug)
An investigation reported that under PostgreSQL `updateTask(id, { steps: [] })`
silently no-ops while a non-empty array writes fine, and worked around it in
fixtures. Reproduced and traced: the write is literal and correct — the row and
task.json both hold `[]`. What actually happens is that an empty array means
"plan not parsed yet", not "this task has no steps", so all four read paths
re-derive steps from PROMPT.md when the stored array is empty: getTaskImpl, the
two list hydrations (reads.ts), and updateStep's auto-init, whose range error
already says outright that "its steps are defined in PROMPT.md".

No product change: removing the re-derivation would strand every task whose plan
lives only in PROMPT.md. Instead both halves of the contract are now pinned by a
PG test and documented at the write site, so the next reader sees the mechanism
instead of re-diagnosing it as a lost write. To make a task genuinely stepless,
remove the step headings from PROMPT.md.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 14:58:49 -07:00
gsxdsm
e37ebd5af9 chore(release): v0.77.0-beta.8
Version bump via changesets.
2026-08-23 14:49:26 -07:00
gsxdsm
455bdbc007 fix: repair the engine suite and the product regressions it was pointing at
Six parallel agents worked the 150 remaining failures. Engine suite: 297 failing
tests at baseline 3f448f7292 -> 8. 12,391 passing.

The failures were mostly pointing at live regressions, not stale tests. Eleven
product defects found and fixed:

- Operator approval mail dropped from BOTH executor gate closures: a gate paused
  a task for approval and no mailbox row was ever written.
- FN-8840 title-duplicate handling reverted in triage.ts, self-healing.ts, and
  scheduler.ts: a title-only "DUPLICATE: <id>" card consumed a full planner
  session, an operator-authored PROMPT.md could be erased, and a title-only
  redirect became dispatchable again.
- A failed plan-admission audit write set its dedupe marker anyway, silencing
  the stall permanently (FN-8600 regression); engine now has an outcome-reporting
  bounded-audit seam mirroring core's FN-9182.
- A best-effort plan mirror could abort a whole planning attempt after the
  authoritative PROMPT.md had already been written.
- AI-merge cleanup lost its alreadyAbsent/idempotent signal on the real-git path.
- Workspace merge-boundary file comparison ran without its review-evidence fence,
  hard-failing every file for callers with no review episode.
- After a file-scope violation the retry re-selected the rejected squash and
  never re-merged.
- Parallel step branches leaked: a name-based classifier read executor-created
  fusion/step-* branches as operator-owned and skipped cleanup.
- workspace_coordination_leases / workspace_land_intents were missing from
  projectTableNames, so the PG harness never truncated them and leases leaked
  across tests.

Four of those are silent reversions from ONE commit, 1cf86baa1c, labeled a
behavior-preserving "executor pure peels" refactor. It passed its own targeted
verification; only a full-suite audit found them.

Test-side repairs are root-cause fixes at shared factories: required pre-merge
gate declarations, branch-write provenance, fake stores missing production write
seams, dead vi.mock specifiers that silently mocked nothing (allowlist ratcheted
11 -> 8), and stale expectations after deliberate IR/tool/error-class changes.
Tests for deleted features were deleted with their removing commit cited.

Left red deliberately (4): executor-worktree-liveness's unrouted-graph-run
assertion and three workspace-e2e landing-stack layers, each needing a design
ruling rather than a test edit. Two durable-write call sites remain flagged
unresolved rather than given invented fencing verdicts.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 12:31:25 -07:00
gsxdsm
3d37cfa7db FN-9201: Prevent mobile nav lift when the iOS keyboard opens
Keep mobile bottom chrome pinned or hidden during keyboard focus transitions, including landscape phone layouts.

- track keyboard-focus intent before visual viewport metrics settle
- clamp focused iOS viewport offsets so fixed bars remain behind the keyboard
- cover runtime bootstrap, landscape integration, nav, focus, and offset behavior
- document the mobile keyboard layout contract and add a patch changeset

Files changed:
 .changeset/fn-9201-mobile-nav-keyboard-lift.md     |  7 ++
 docs/dashboard-guide.md                            |  4 +-
 packages/dashboard/app/App.tsx                     | 43 ++++++++--
 ...ile-nav-keyboard-landscape.integration.test.tsx | 91 ++++++++++++++++++++
 .../__tests__/icb-inline-script.runtime.test.ts    | 74 ++++++++++++++++
 .../mobile-bottom-bars-keyboard-layout.test.ts     | 15 +++-
 .../viewport-compensation-keyboard.test.ts         |  5 +-
 .../__tests__/MobileNavBar.keyboard-lift.test.tsx  | 65 ++++++++++++++
 .../__tests__/useKeyboardFocusPending.test.tsx     | 99 ++++++++++++++++++++++
 .../dashboard/app/hooks/useKeyboardFocusPending.ts | 43 ++++++++++
 packages/dashboard/app/index.html                  | 12 ++-
 .../utils/__tests__/mobileBarKeyboardFlags.test.ts | 22 +++++
 .../app/utils/__tests__/viewportOffset.test.ts     | 32 +++++++
 .../dashboard/app/utils/mobileBarKeyboardFlags.ts  | 10 ++-
 packages/dashboard/app/utils/viewportOffset.ts     |  8 ++
 15 files changed, 510 insertions(+), 20 deletions(-)

Fusion-Task-Id: FN-9201

Fusion-Task-Lineage: 4b3b01d3-8968-432b-9537-a63ee6bbde31

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-23 11:40:06 -07:00
gsxdsm
29f9edf153 test: declare branch-write provenance in reliability fixtures
Three more fixtures wrote a task branch without an origin, so the
`updateTaskUnlockedImpl` provenance boundary threw before any scenario ran —
the same guard, and the same missed-fixture class, as the shared reliability
helper fixed earlier. Each fixture binds a task to its worktree branch on the
engine's behalf, so each now says so.

worktree-lifecycle-certification 0/4 -> 4/4, audit-and-recovery 1/3 -> 3/3,
self-healing-interactions 6/7 -> 7/7.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:11:18 -07:00
gsxdsm
f2eda4819d docs: make a behavior change own the tests that assert the old behavior
Fusion agents keep shipping behavior changes that leave stale tests behind, and
targeted verification structurally cannot catch it: it runs the tests for the
files the agent TOUCHED, while the assertions encoding the old behavior live in
files it did not. Measured on one full engine suite run (2026-08-24): 297 failing
tests, ~135 of them from exactly five such changes — the FN-158 pre-merge-gate
guard (~70 fixtures across 13 files), the branch-write provenance guard (18 from
ONE shared fixture), a workflow-IR reorder (10 stale topology assertions), an
updateTaskAtomic seam missing from fake stores (~9), and FN-074's splitting
removal leaving 4 reviewer-prompt tests asserting a deleted contract. Every one
passed its own targeted verification.

- AGENTS.md: new standing rule with the four search triggers (guard added,
  feature removed, order/default/constant/prompt changed, public method added),
  a fix-at-the-shared-factory preference, and an explicit ban on weakening a
  stale test or restoring removed behavior to satisfy one.
- Executor prompt: the same searches, stated as a finish condition.
- Full triage prompt: specs for behavior-changing tasks must include a step that
  NAMES the search, so it is planned rather than left to chance.

The fast triage prompt is deliberately excluded: it carries a hard size budget
(agent-prompts.test.ts caps it at 7500 chars) and adding this pushed it over —
an instance of the very rule being documented, now cited in it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 11:02:02 -07:00
gsxdsm
339d849938 fix: classify legacy adoption review-lane literals
Mark isAtOrPastReviewLane as DELIBERATE-LITERAL so the lifecycle-column
census ratchet stops treating FN-158's physical pre-cutover lane IDs as
new unexamined guards. Refresh the pinned baseline to match.
2026-08-23 11:01:13 -07:00
gsxdsm
eade82f55d FN-9200: preserve docked chat sidebar width
Preserve docked chat behavior across tablet layouts and excluded one-pane hosts.

- Let the inline docked width remain authoritative in the tablet cascade.
- Expand behavioral coverage for viewport eligibility, host exclusions, persistence, resizing, rooms, and header controls.
- Add computed-style coverage for tablet and mobile sidebar widths.

Files changed:
 packages/dashboard/app/components/ChatView.css     |   5 +-
 .../__tests__/ChatView.docked-sidebar-css.test.tsx |  52 +++++
 .../__tests__/ChatView.docked-sidebar.test.tsx     | 212 ++++++++++++++++-----
 3 files changed, 220 insertions(+), 49 deletions(-)

Fusion-Task-Id: FN-9200

Fusion-Task-Lineage: 5e8100ea-1a60-42b5-a64a-5e33b7d4b2c7

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-23 10:35:53 -07:00
gsxdsm
4f40c91b38 test: drop reviewer-prompt tests for the deliberately removed splitting feature
Four tests asserted DEFAULT_REVIEWER_PROMPT still carried the task-SPLITTING
contract: "Subtask breakdown", "12+ implementation steps", "The bar for
splitting is high", and a REVISE directing the planner to fn_task_create 2-5
child tasks. FN-074 removed task splitting across core, dashboard, and engine,
and FN-125 removed the reviewer's ability to create tasks at all. FN-074's
message says it updated affected tests; these were missed and sat red asserting
a contract the product deliberately dropped.

Removed rather than repaired: restoring that prompt text to make them pass would
re-add removed behaviour. The two tests in this block covering the prompt
contract that still exists are untouched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 10:28:33 -07:00
gsxdsm
324145c1e1 test: repair engine fixtures that predate shipped product guards
The engine suite's failures are not independent bugs; they are a handful of
systemic drifts where a guard shipped and its fixtures were never updated.

- Required pre-merge gates (FN-158): the door refuses a card whose enabled
  optional groups produced no result, and the built-in workflow enables Plan and
  Code Review by default. Merge-mechanics fixtures now declare an explicit empty
  list, stating the intent they always had. group-merge-coordinator's
  "post-Code-Review member" instead gets real PASSING workflowStepResults,
  because recording the pass is what that fixture actually means.
- Branch-write provenance: the shared reliability fixture creates a task with a
  branch, which now requires an explicit origin. It stands in for an
  engine-created branch, so it says so.
- updateTaskAtomic: a production write seam missing from several fake stores,
  copied from the faithful fake in merger-ai.test.ts.
- Durable-write inventory: eight unclassified TaskStore surfaces classified,
  including the two batched reads this branch added.
- workflow-graph-merge-region-collapse asserted completion-summary AFTER
  code-review; the IR wires it before, and production logs agree.

merger-ai.test.ts alone goes 37 -> 0. Engine failures 288 -> ~200.

Also records a first-sighting suite-only flake in the observed register per the
standing rule, rather than quarantining a file with substantial coverage.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 10:18:50 -07:00
gsxdsm
323d55a43b FN-9196: Move archived chat toggle into filter row
Restyle the chat archive control as a compact, responsive filter-line toggle.

- Place the Archived toggle beside the tag filter with stable pressed-state semantics.
- Add token-based responsive styling for desktop, narrow, and mobile sidebars.
- Cover toggle behavior, selected-tag coexistence, and filter-row layout.
- Add a patch changeset for the published Fusion package.

Files changed:
 .changeset/chat-archived-filter-row.md             |  7 ++
 packages/dashboard/app/components/ChatView.css     | 17 +++-
 packages/dashboard/app/components/ChatView.tsx     | 44 +++++++---
 .../ChatView.archived-toggle-row.test.tsx          | 99 ++++++++++++++++++++++
 4 files changed, 151 insertions(+), 16 deletions(-)

Fusion-Task-Id: FN-9196

Fusion-Task-Lineage: 2bd3d000-84be-4798-9b73-de1feac40536

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-23 10:03:46 -07:00
gsxdsm
52d124bde2 FN-9195: Keep the chat composer visible above iOS keyboards
Keep Chat input reachable across software-keyboard viewport changes.

- Track visual viewport changes across phones, tablets, compact docks, and narrow floating Chat hosts.
- Clamp thread height using the measured host offset while preserving iOS focus behavior.
- Add regression coverage, shared viewport test helpers, operator documentation, and a patch changeset.

Files changed:
 .changeset/fn-9195-chat-ios-keyboard-composer.md   |   7 +
 docs/dashboard-guide.md                            |   2 +-
 packages/dashboard/app/components/ChatView.css     |  44 +--
 packages/dashboard/app/components/ChatView.tsx     |  43 ++-
 .../__tests__/ChatView.ios-keyboard.test.tsx       | 335 +++++++++++++++++++++
 .../components/__tests__/ChatView.test-harness.tsx | 103 ++++++-
 6 files changed, 506 insertions(+), 28 deletions(-)

Fusion-Task-Id: FN-9195

Fusion-Task-Lineage: cdada0cc-af6c-4cf8-8ffd-0940d280b07a

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-23 09:55:53 -07:00
gsxdsm
ea48af7ab5 fix: require a durable merge record for the step-finalization exemption
Full-suite set-diff against 3f448f7292 caught three regressions the raw counts
hid (that suite is chronically red: 297 failures at baseline, 294 with the
change).

The step exemption was too broad. It also applied to
recoverAlreadyMergedReviewTasks, the content-scan recovery where mergeDetails is
ABSENT and landing is inferred by finding matching content on the base branch.
That heuristic can match a cherry-pick, so exempting incomplete steps there
would launder a genuinely unfinished task to done on a guess — which is exactly
what landed-content-soft-blocker.real-git.test.ts exists to prevent. The
exemption now requires mergeConfirmed AND a commitSha: FN-9193's actual state,
and nothing weaker. Content-scan recovery and no-op merges keep the blocker.

Also seeds mergeSweepHoldReasons in the shared merge-lane fixture, which the
fixture-drift guard requires of every auto-merge state field.

Verified by set-diff: zero test files now fail that did not fail at baseline.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 09:45:10 -07:00
gsxdsm
a879ead0fc fix: let a proven merge finalize even with unfinished steps
FN-9193's branch landed on main as eaa1d47c, but a Code Review revision request
had reset its steps while the approved merge was in flight. The card was left
mergeConfirmed WITH incomplete steps, and every finalization site refused with
"task has incomplete steps" — so it sat failed, re-reading its own contradiction.
Restarting it made things worse: replanning issued seven fresh pending steps, so
the retry re-created the exact condition blocking it. A loop with no exit.

Holding a landed card out of done un-merges nothing; the code is on the target
branch either way. All four finalization sites now use
getMergeConfirmedFinalizationBlocker, which exempts incomplete steps once
landing is proven and records the unfinished ones on the task instead of
dropping them. A no-op merge that landed no content still blocks — that is the
protective half of the guard being replaced, and the executor's no-op branch
depends on it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-23 09:26:16 -07:00
gsxdsm
3857e0dc14 FN-9198: Fix narrow chat switcher dropdown rendering
Anchor the direct-conversation switcher to the visible thread header across narrow Chat surfaces.

- position narrow-host switcher menus relative to the thread header
- cover mobile, compact dock, floating, desktop, and empty-menu states
- add the shared 2px spacing token and document the corrected behavior
- add a patch changeset for the published Fusion package

Files changed:
 .../fn-9198-chat-title-switcher-menu-anchor.md     |   7 +
 docs/dashboard-guide.md                            |   2 +-
 .../app/components/ChatThreadTitleSwitcher.css     |  11 +-
 .../__tests__/ChatView.title-switcher.test.tsx     | 144 ++++++++++++++++++++-
 packages/dashboard/app/styles.css                  |   2 +
 5 files changed, 160 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-9198

Fusion-Task-Lineage: 9a1132d2-9b1a-4150-918a-085b42b22e02

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-23 09:21:10 -07:00
gsxdsm
46b329fed9 FN-9199: Replace chat text back marker with arrow icon
Use a consistent icon-and-label back affordance across direct and room chat threads.

- Render the lucide ArrowLeft icon with localized Back text and preserved accessible naming.
- Cover mobile direct and room thread back buttons with icon, text, and accessibility assertions.
- Add a patch changeset for the published Fusion package.

Files changed:
 .changeset/fix-chat-back-arrow.md                          |  6 ++++++
 packages/dashboard/app/components/ChatView.css             |  2 +-
 packages/dashboard/app/components/ChatView.tsx             | 14 ++++++++++++--
 .../app/components/__tests__/ChatView.mobile.test.tsx      |  4 +++-
 .../app/components/__tests__/ChatView.rooms.test.tsx       |  7 ++++++-
 5 files changed, 28 insertions(+), 5 deletions(-)

Fusion-Task-Id: FN-9199

Fusion-Task-Lineage: aab2a300-cc2a-4768-b60b-81d7477b8fab

Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-08-23 09:13:23 -07:00