- P1 (Greptile): a tool-use break-early turn released the warm connection
(inUse=false) while conn.prompt() was still pending, letting the next turn
launch a concurrent prompt on the same ACP session (protocol corruption).
keepWarm now requires !sawToolCall, so a tool-use turn tears the connection
down like the non-reuse path; only a clean stop turn (prompt fully resolved
before finish) keeps it warm. + test.
- buildBridgeEnv: treat a whitespace-only auth var as absent (v.trim()), so a
blank higher-preference token can't shadow a real lower-preference one and we
never forward a useless blank token. + test.
- Auth-forwarding tests: clear ambient auth vars in beforeEach so a runner-env
token can't shadow the case under test (CodeRabbit).
- Doc: clarify the allow-list never carries API keys by default; the single
FUSION_CLAUDE_ACP_FORWARD_AUTH opt-in (default OFF) is the only exception.
348/348 pass, tsc clean.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Compound learning: the claude-code-cli-acp bridge returned 'Not logged in'
despite a working claude -p, due to (1) a too-thin spawn env (needs XDG_*/USER/
SHELL beyond HOME/PATH) and (2) macOS login-Keychain session isolation for
detached/headless processes. Six headless tasks misdiagnosed it as an upstream
gap. Cross-linked from the ACP runtime integration pattern doc.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Prevent the terminal symbols font from corrupting ASCII cell measurement on mobile.\n\n- Add unicode-range scoping to the Fusion terminal Nerd Font symbols face.\n- Cover the CSS contract so symbols ranges include Nerd Font blocks and exclude printable ASCII.\n- Document the xterm font-loading regression and required verification path.\n\nFiles changed:\n .../xterm-symbols-nerd-font-unicode-range.md | 63 ++++++++++++++++++++++\n .../dashboard/app/__tests__/terminal-input.test.ts | 49 +++++++++++++++++\n .../dashboard/app/components/TerminalModal.css | 5 ++\n 3 files changed, 117 insertions(+)
Fusion-Task-Id: FN-6424
Fusion-Task-Lineage: 7350c926-1d51-474b-bfc3-a17f922b9322
Document the root cause (offset-less position:absolute sr-only utility
escaping the kanban board's overflow clip and inflating
documentElement.scrollWidth → iOS shrink-to-fit zoom), the top/left:0 fix,
and the CSS-fixture regression guard. Cross-links the sibling mobile
viewport-containment learnings.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Ensure workflow-mode boards fill the mobile viewport while preserving internal column scrolling.
- Reassert the mobile flex fill chain for project content, workflow board wrappers, and workflow columns.
- Extend mobile board regression coverage across empty/populated workflow states with and without the toolbar.
- Document the workflow board collapse root cause and add a transient temp-dir isolation guard test.
Files changed:
docs/dashboard-guide.md | 1 +
.../ui-bugs/mobile-workflow-board-fill-chain.md | 61 +++++++++++++
.../__tests__/board-mobile-initial-render.test.tsx | 101 +++++++++++++++++++++
packages/dashboard/app/styles.css | 52 +++++++++++
scripts/__tests__/check-test-isolation.test.mjs | 23 +++++
scripts/check-test-isolation.mjs | 12 ++-
6 files changed, 249 insertions(+), 1 deletion(-)
Fusion-Task-Id: FN-6397
Fusion-Task-Lineage: ddee773d-6d3a-46d1-b1c7-f601a961365e
Contain the mobile dashboard document viewport while preserving intended inner horizontal scrollers.
- Lock mobile html/body/#root and fullscreen overlay chrome to the viewport inline axis.
- Default mobile touch handling to vertical-only panning and opt board/code/table scrollers back into horizontal gestures.
- Add CSS fixture regression coverage plus a solution note for mobile horizontal pan containment.
Files changed:
docs/solutions/ui-bugs/mobile-horizontal-pan-document-viewport-containment.md | 62 +++++++++++
packages/dashboard/app/__tests__/mobile-horizontal-pan-containment.test.ts | 116 +++++++++++++++++++++
packages/dashboard/app/styles.css | 47 +++++++--
3 files changed, 219 insertions(+), 6 deletions(-)
Fusion-Task-Id: FN-6365
Fusion-Task-Lineage: 4673da28-1438-4ea5-b32c-25bc52285273
Recover stale iOS document scroll after returning to the Fusion dashboard.
- Add an iOS-only restore hook that clears orphaned body offsets and scrolls the document back to the origin when unlocked.
- Wire the restore reset from the dashboard app shell for mobile layouts.
- Cover visible/page-show restores, platform no-ops, active-lock guards, and orphaned style cleanup.
- Document the mobile restore drift solution for future regressions.
Files changed:
.../mobile-ios-restore-document-scroll-drift.md | 59 ++++++++++
packages/dashboard/app/App.tsx | 4 +-
.../hooks/__tests__/useMobileScrollLock.test.ts | 121 ++++++++++++++++++++-
.../dashboard/app/hooks/useMobileScrollLock.ts | 61 +++++++++++
4 files changed, 243 insertions(+), 2 deletions(-)
Fusion-Task-Id: FN-6364
Fusion-Task-Lineage: 9243cab8-5fbb-4332-ac4d-aabefde4161c
Reset mobile keyboard restore sampling so collapsed viewports clear stale keyboard-open metrics.
- Add a restore-specific sampling path for visibilitychange/pageshow that can reset the viewport baseline and bypass the impossible-sample hold once.
- Preserve the existing in-session impossible-sample guard and tail polling behavior for normal focus/resize updates.
- Cover iOS restore, stale offset drift, genuinely open restored keyboards, and Android-style shrink reset cases.
- Document the mobile keyboard restore stale viewport fix for future UI debugging.
Files changed:
.../mobile-keyboard-restore-stale-viewport.md | 59 ++++++++
.../app/hooks/__tests__/useMobileKeyboard.test.ts | 160 +++++++++++++++++++++
packages/dashboard/app/hooks/useMobileKeyboard.ts | 75 +++++++---
3 files changed, 275 insertions(+), 19 deletions(-)
Fusion-Task-Id: FN-6362
Fusion-Task-Lineage: 3919d892-b2d5-419a-abeb-84ac298ca2d5
Keep the mobile board layout stable while Quick Chat owns the keyboard viewport.
- Treat fullscreen mobile overlays as suppressors for App-level footer hiding.
- Pass Quick Chat mobile open state into the shared keyboard flag helper.
- Cover iOS, Android, modal, and non-mobile keyboard flag behavior.
- Document the Quick Chat mobile keyboard board-shift root cause and fix.
Files changed:
.../quick-chat-mobile-keyboard-board-shift.md | 58 ++++++++++++++++++++++
packages/dashboard/app/App.tsx | 4 +-
.../utils/__tests__/mobileBarKeyboardFlags.test.ts | 57 ++++++++++++++++++++-
.../dashboard/app/utils/mobileBarKeyboardFlags.ts | 10 +++-
4 files changed, 126 insertions(+), 3 deletions(-)
Fusion-Task-Id: FN-6329
Fusion-Task-Lineage: f7c37252-c0ea-44f0-b4e3-5aa2022cf7bc
Keep the mobile dashboard pinned while offscreen auto-merge controls are toggled.
- Reset document horizontal scroll during mobile board stabilization and immediately after auto-merge toggles.
- Cover portrait and landscape mobile scroll realignment in the auto-merge integration test.
- Document the real-browser blank-dashboard root cause and add a patch changeset.
Files changed:
.changeset/FN-6243-mobile-auto-merge-blank.md | 5 ++
...bile-auto-merge-toggle-document-scroll-blank.md | 55 ++++++++++++++++++++++
packages/dashboard/app/components/Board.tsx | 47 ++++++++++++++++--
...-merge-toggle-blank.mobile-integration.test.tsx | 49 +++++++++++++++++++
4 files changed, 152 insertions(+), 4 deletions(-)
Fusion-Task-Id: FN-6243
Fusion-Task-Lineage: 91f74de2-667f-4732-a840-47b792288bec
- Expand the directory-path follow-up section: PR #1428, 400 no-entry
branch, heal-on-enable in both routers
- Document the vitest fs-mock vs externalized workspace-dep trap and
the real-fs drift-guard test pattern
- Add Plugin Entry to CONCEPTS.md Plugins cluster
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Plugins installed from Settings → Built-in Plugins registered the
manifest directory as the plugin path, but since FN-4128 the loader
requires a loadable entry FILE (Node ESM cannot import directories),
so enabling failed with "Plugin entry must be a file, got directory".
Only the CLI startup path had been migrated to entry-file resolution,
which is why CLI-auto-installed plugins worked and Settings installs
never did.
- Add resolvePluginEntryPath (bundled.js → dist/index.js →
src/index.ts) to @fusion/core; the CLI keeps its local copy (its
test fs mocks don't reach externalized core) with sync comments
both ways.
- Register the resolved entry file in both dashboard install routes;
400 with a clear message when a package has no loadable entry.
- Heal legacy directory-path registrations on enable, mirroring the
CLI's startup heal, so existing broken rows recover from the UI
without a restart.
- Route tests: assert installs register entry files, cover the
enable-route heal, and update existing install tests to the
entry-file contract.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Capture the 4-list registration requirement for bundled plugins
(Settings catalog, dashboard fallback set, CLI auto-install list,
tsup staging) in docs/solutions/, and add the Bundled Plugin concept
to CONCEPTS.md.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>