Commit Graph

7967 Commits

Author SHA1 Message Date
gsxdsm
7348e35a11 docs: capture observable-agent-turns architecture pattern and seed CE session vocabulary
ce-compound learning from the live-output/steering work: push-channel-
alongside-pull-contract, void-safe detached turns, inactivity watchdog,
transient liveActivity + persisted trace, replay suppression. Also adds a
"Compound Engineering sessions" cluster to CONCEPTS.md and refreshes the
plugin reference doc's Sessions section with the new transport behaviors.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 15:20:34 -07:00
gsxdsm
0106eee4ff feat(compound-engineering): live agent output, steering, and a real Q&A surface
Users can now watch everything the agent does while a CE stage works, steer
it mid-stage, and read the whole conversation as a proper chat surface.

Live output:
- New host capability: CreateInteractiveAiSessionOptions.onProgress — the
  engine adapter streams thinking/text deltas + tool start/end markers from
  the pi agent hooks (any plugin can use this).
- Orchestrator buffers per-session live activity (merged deltas, discrete
  tool lines, capped), emits throttled progress events over SSE, and
  GET /sessions/:id attaches it as liveActivity for the polling fallback.
- Routes detach turn execution: start/answer/resume return immediately
  (status active) and clients converge via push/poll — the turn is watchable
  instead of hidden inside a blocking POST.
- Turn timeout is now INACTIVITY-based: an actively-working long turn is
  never killed; a quiet one interrupts with its working trace preserved.
- On settle the trace persists into history as a condensed record.

Steering:
- Stage protocol: responses may be a direct answer, {value, comment}
  (answer + guidance), or {feedback} (guidance without answering); the
  system prompt instructs agents to treat steering as first-class input.
- CeFlow: guidance textarea alongside selectable questions — attach to the
  clicked answer, or "Send guidance" on its own.

Q&A UI:
- Transcript no longer hides control records: past questions/answers render
  as chat bubbles (option ids → labels), steering turns marked, working
  traces as collapsible "Agent work" blocks, completion marker.
- Live working pane (pulse + streaming thinking/tool lines) while a turn runs.

Tests: 130 plugin tests green (14 new: live buffer/flush ordering, inactivity
watchdog survives active work, detached convergence, steering payload shapes,
transcript rendering, live pane). Engine seam tests green; plugin/core/
engine/dashboard tsc clean. Core full suite OOMs locally (known orchestrator-
shell issue) — covered by CI shards.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 14:17:40 -07:00
gsxdsm
cff0dee87c Merge branch 'gsxdsm/compound' of https://github.com/Runfusion/Fusion into gsxdsm/compound 2026-06-03 13:47:22 -07:00
gsxdsm
7f8db9f892 feat(compound-engineering): manage and work across multiple CE sessions
The store/orchestrator were already multi-session (independent rows + live
handles per session); this surfaces it end to end:

- Sessions panel in the dashboard view: lists every session with stage,
  status badge ("needs your input" for awaiting_input), and last activity;
  stays visible while a flow is open so switching is one click. Closing a
  flow returns to the overview without stopping the session.
- useCeSession.open(): adopt an existing session (pins its projectId for
  answer/resume/poll); useCeSessions list hook with push-event refresh and
  poll fallback while any session is mid-turn.
- DELETE /sessions/:id + orchestrator.discard(): dispose the live handle
  before deleting the row (pipeline-link rows kept for task provenance);
  Discard affordance on settled sessions.
- Tests: cross-session independence through one orchestrator, store delete,
  route list/delete, hook open/list/remove/push/poll, view panel
  open/switch/discard. 116 tests green; plugin + dashboard tsc clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 13:47:02 -07:00
gsxdsm
fa7da2bdfd Merge branch 'main' into gsxdsm/compound 2026-06-03 13:29:20 -07:00
gsxdsm
3a62b6820f update agents 2026-06-03 13:20:17 -07:00
gsxdsm
1761a7ffd2 FN-5940: stop logging no-op task:moved activity rows
Prevent same-column task move noise from bloating the activity log.

- skip task:moved activity logging and event emission when a task stays in the same column
- add a one-time TaskStore cleanup migration that deletes existing same-column task:moved rows
- cover listener, moveTask, polling replication, and migration behavior with focused core tests
- document the no-op cleanup invariant and manual VACUUM guidance for reclaimed SQLite space

Files changed:
 docs/storage.md                                    |   8 ++
 packages/core/src/__tests__/activity-log-no-op-moved.test.ts | 122 +++++++++++++++++++++
 packages/core/src/__tests__/no-op-moved-cleanup-migration.test.ts          | 108 ++++++++++++++++++
 packages/core/src/store.ts                         |  51 ++++++++-
 4 files changed, 286 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-5940

Fusion-Task-Lineage: f34cf8d0-3639-44d5-8a90-8ba461636eaa
2026-06-03 13:20:17 -07:00
gsxdsm
76c18efa92 FN-5939: expose operational log retention setting
Expose operational log retention as a project setting in the dashboard.

- add an Operational log retention selector to the Project General settings section with supported retention options
- validate operationalLogRetentionDays in the settings API and cover accepted and rejected values in tests
- document the constrained retention values and assert project-scope/default parity for the setting

Files changed:
 docs/settings-reference.md                         |  2 +-
 packages/core/src/__tests__/settings-parity.test.ts |  7 ++++
 packages/dashboard/app/components/SettingsModal.tsx | 47 ++++++++++------------
 packages/dashboard/app/components/__tests__/SettingsModal.test.tsx |  8 ++++
 packages/dashboard/src/__tests__/routes-settings.test.ts | 21 ++++++++++
 packages/dashboard/src/routes/register-settings-memory-routes.ts | 10 +++++
 6 files changed, 69 insertions(+), 26 deletions(-)

Fusion-Task-Id: FN-5939

Fusion-Task-Lineage: 2148dd88-1cef-4c6d-9696-31148fce97d3
2026-06-03 13:20:17 -07:00
gsxdsm
ac92174cba FN-5907: harden planning task creation side effects
Keep Planning Mode task creation responses successful when follow-up work fails.

- catch and log planning create-task/create-tasks side-effect failures so the API can still return 201 after task creation succeeds
- safely handle async task lifecycle listener failures in the core store to avoid leaking unhandled rejections during follow-up updates
- add regression coverage for single-task and multi-task Planning Mode creation across live/persisted sessions, branch selection surfaces, and GitHub tracking failures

Files changed:
 .changeset/fn-5907-planning-create-fetch.md        |   5 +
 .../core/src/__tests__/task-creation-hook.test.ts  |  25 ++
 packages/core/src/store.ts                         |  38 ++-
 .../src/__tests__/routes-planning-tracking.test.ts | 108 ++++++++-
 .../src/__tests__/routes-planning.test.ts          | 267 +++++++++++++++++++++
 .../src/routes/register-planning-subtask-routes.ts |  69 +++++-
 6 files changed, 496 insertions(+), 16 deletions(-)

Fusion-Task-Id: FN-5907

Fusion-Task-Lineage: d9f6574b-e19b-4459-a612-7a3d2510836f
2026-06-03 13:20:17 -07:00
gsxdsm
419f688afb FN-5936: fix auto-merge board stabilization on mobile
Keep the dashboard board visible when auto-merge toggles across viewport changes.

- keep board stabilization subscribed to visualViewport resize events instead of removing the listener after the first resize
- add regression coverage for Android, iOS, tablet, desktop, empty-column, rollback, and error-boundary auto-merge toggle paths
- relax settings hydration assertions and expand app-settings tests for auto-merge rollback and coercion behavior

Files changed:
 .changeset/fn-5936-auto-merge-mobile-fix.md        |   7 +
 packages/dashboard/app/components/Board.tsx        |  19 +-
 packages/dashboard/app/components/__tests__/App.test.tsx          |   8 +-
 packages/dashboard/app/components/__tests__/auto-merge-toggle-blank.mobile.test.tsx        | 418 +++++++++++++++++++++
 packages/dashboard/app/hooks/__tests__/useAppSettings.test.ts     |  53 ++-
 5 files changed, 489 insertions(+), 16 deletions(-)

Fusion-Task-Id: FN-5936

Fusion-Task-Lineage: 6e937d0e-dc60-4863-a884-001228dd0cd1
2026-06-03 13:20:17 -07:00
gsxdsm
ad740775b3 Merge pull request #1356 from Runfusion/gsxdsm/automerge
fix(engine): honor per-task auto-merge override when global auto-merge is off
2026-06-03 13:19:03 -07:00
gsxdsm
e00bc0235b Address PR review feedback (#1356)
- Add behavior-level tests for the shared merge-enqueue funnel
  (enqueueEligibleInReviewTasks) with a Surface Enumeration of all
  in-review entry surfaces, per review
- Seed real stale in-review fixtures in the FN-5147 no-mutation
  regression block so sweeps enumerate candidates and the assertions
  are non-vacuous
- Keep per-task auto-merge gating uniform across reclaim/contamination
  candidate columns: the suggested in-review-only scoping broke the
  FN-5704 regression contract (reclaim short-circuits when autoMerge
  is off); documented the tension in code comments and the learning doc
- Drop hardcoded commit hash from the learning doc
2026-06-03 13:08:06 -07:00
gsxdsm
ff1bb20b8f docs: capture per-task auto-merge override learning and seed CONCEPTS.md
Document the trigger-layer gating bug fixed in this PR under
docs/solutions/logic-errors/, seed CONCEPTS.md with the merge-lifecycle
vocabulary, and surface both knowledge stores in AGENTS.md's reference
docs index.
2026-06-03 10:55:26 -07:00
gsxdsm
ad468813d5 fix(engine): honor per-task auto-merge override when global auto-merge is off
Tasks with autoMerge explicitly enabled never auto-merged when the
project-level setting was disabled: the merge enqueue gate
(allowInReviewMergeProcessing) and all 19 in-review self-healing sweeps
checked only settings.autoMerge, and the board stall-signal hydration
passed the raw global into the diagnostic gates.

Introduce allowsAutoMergeProcessing(task, settings) in core — additive
relative to the global setting so configs with global auto-merge ON are
unchanged (explicit autoMerge:false tasks still flow to the merger's
manual-required parking) — and use it at the enqueue gate, every
self-healing sweep, and the store's stall/stalled signal contexts.
2026-06-03 10:18:24 -07:00
gsxdsm
04a5cd196c Merge pull request #1347 from Runfusion/gsxdsm/activitydebug
fix(dashboard): show missing Minimax usage rows and weekly windows
2026-06-03 08:09:32 -07:00
gsxdsm
e37c57305d fix(dashboard): load CE plugin view via @vite-ignore so tsc doesn't compile plugin source
With @fusion/dashboard removed from the CE plugin's deps (cycle fix), a literal
import() of its dashboard-view made the dashboard typecheck the plugin source and
fail to resolve the plugin's type-only @fusion/dashboard import. Use the
moduleId-variable + @vite-ignore pattern (as cli-printing-press does) so tsc
treats it as dynamic; Vite still resolves it at runtime.
2026-06-03 08:02:03 -07:00
gsxdsm
8c170480dd fix(compound-engineering): break dashboard dependency cycle
A new workspace-acyclicity invariant on main (run via the PR merge) flagged
compound-engineering -> @fusion/dashboard -> compound-engineering: the plugin is
listed in @fusion/dashboard's deps (for view loading) AND declared @fusion/dashboard
as a runtime dependency, which the cycle check (deps+devDeps) and the
'bundled plugins must not depend on host packages' check both reject.

The plugin's only @fusion/dashboard use is the type-only PluginDashboardViewContext
import. Drop the @fusion/dashboard dependency and resolve that type via an ambient
dashboard-interop.d.ts + tsconfig paths mapping (the fusion-plugin-dependency-graph
interop pattern). Breaks the cycle; the host passes the real context at runtime.
2026-06-03 07:59:20 -07:00
gsxdsm
6f378067f4 fix(dashboard): show missing Minimax usage rows and weekly windows
The Minimax usage panel only rendered one model row. The primary `general`
model meters quota purely via `current_interval_remaining_percent` (its
`current_interval_total_count` is 0), so the count-based `total > 0` visibility
filter dropped it entirely. The percent was also derived from count fields
rather than the authoritative `*_remaining_percent` field.

fetchMinimaxUsage now builds windows via a helper that prefers
`*_remaining_percent` (count-based fallback when absent) and skips a window only
when no quota signal exists. Each model's separate weekly quota window is now
surfaced as its own indicator alongside the interval window.

Verified against the live coding_plan/remains endpoint: 2 models (general,
video) now produce 4 windows (interval + weekly each) instead of 1.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 07:51:38 -07:00
gsxdsm
db0cf7d415 docs(solutions): capture plugin bundled-skill loading learning
Document why PluginSkillContribution.skillFiles silently fails to load bundled
skills in live sessions (resolver only filters disk-discovered skills) and the
physical-install + additionalSkillPaths-forwarding fix, as a searchable
docs/solutions/ learning. Surface docs/solutions/ in AGENTS.md so agents
discover it.
2026-06-03 07:26:15 -07:00
gsxdsm
1cf0521a0a fix(compound-engineering): validate parsed JSON shape in rowToSession
safeParse() previously only caught JSON syntax errors, so a semantically-wrong
but valid column ('null', '{}', a string) would rehydrate a non-array
conversationHistory that later crashed appendHistory's spread (and a bogus
currentQuestion). safeParse now takes a shape validator and falls back to []/null
on invalid shapes too. + regression test covering 'null'/'{}'.
2026-06-03 07:10:10 -07:00
gsxdsm
59cd9ea66c Planning fixes 2026-06-03 07:10:02 -07:00
gsxdsm
d72cb2ab2b FN-5911: move agent logs to per-task JSONL storage
Store agent logs in per-task JSONL files instead of the legacy SQLite table.

- add a file-backed agent log store with JSONL append/read/prune helpers and task-scoped source refs
- migrate legacy SQLite agentLogEntries data into task files, rewrite goal citation references, and preserve soft-deleted logs for forensics
- update task store, settings, docs, dashboard route coverage, and add regression tests for migration, retention, and log access

Files changed:
 .changeset/fn-5911-agent-log-jsonl.md              |   5 +
 AGENTS.md                                          |   2 +-
 docs/diagnostics.md                                |   2 +-
 docs/settings-reference.md                         |   2 +
 docs/soft-delete-verification-matrix.md            |   7 +-
 docs/storage.md                                    |   8 +-
 .../src/__tests__/agent-log-file-store.test.ts     | 123 ++++++
 .../core/src/__tests__/agent-log-migration.test.ts | 186 +++++++++
 .../core/src/__tests__/agent-log-retention.test.ts | 208 ++++++++++
 packages/core/src/__tests__/db-migrate.test.ts     |  14 +-
 packages/core/src/__tests__/db.test.ts             |  39 +-
 .../src/__tests__/goal-citations-store.test.ts     |  38 +-
 packages/core/src/__tests__/goals-schema.test.ts   |   2 +-
 packages/core/src/__tests__/insight-store.test.ts  |  10 +-
 .../src/__tests__/merge-request-record.test.ts     |   2 +-
 packages/core/src/__tests__/mission-store.test.ts  |   2 +-
 packages/core/src/__tests__/run-audit.test.ts      |   2 +-
 packages/core/src/__tests__/secrets-schema.test.ts |   6 +-
 .../src/__tests__/soft-delete-agent-logs.test.ts   |  71 ++--
 .../src/__tests__/store-agent-log-file.test.ts     |  91 +++++
 .../core/src/__tests__/store-merge-queue.test.ts   |   2 +-
 packages/core/src/__tests__/store-test-helpers.ts  |  43 +-
 packages/core/src/__tests__/store-upsert.test.ts   |  37 +-
 packages/core/src/__tests__/task-documents.test.ts |   2 +-
 packages/core/src/agent-log-constants.ts           |  25 ++
 packages/core/src/agent-log-file-store.ts          | 267 ++++++++++++
 packages/core/src/db.ts                            |  51 ++-
 packages/core/src/settings-schema.ts               |   1 +
 packages/core/src/store.ts                         | 453 ++++++++++++---------
 packages/core/src/types.ts                         |  10 +-
 .../__tests__/agent-log-routes.integration.test.ts |  48 +++
 .../src/__tests__/evaluator-evidence.test.ts       |  47 ++-
 packages/engine/src/self-healing.ts                |  12 +
 .../src/store/__tests__/roadmap-store.test.ts      |   4 +-
 34 files changed, 1477 insertions(+), 345 deletions(-)

Fusion-Task-Id: FN-5911

Fusion-Task-Lineage: 07c42f3a-87cf-4558-8f01-ac8460b5558b
2026-06-03 01:10:18 -07:00
gsxdsm
1962bea0fc FN-5934: replace undefined dashboard spacing token
Replace dashboard CSS uses of the undefined --space-2xs token with supported spacing values.

- swap var(--space-2xs) for var(--space-xs) in confirm dialog, merge advance notice, and PR checks styles
- add a dashboard test that scans component stylesheets for undefined --space-2xs references
- assert shared token sources continue to omit an intentional --space-2xs definition

Files changed:
 .../app/__tests__/space-token-defined.test.ts      | 45 ++++++++++++++++++++++
 .../dashboard/app/components/ConfirmDialog.css     |  2 +-
 .../app/components/MergeAdvanceNotice.css          |  8 ++--
 packages/dashboard/app/components/PrChecksList.css |  2 +-
 4 files changed, 51 insertions(+), 6 deletions(-)

Fusion-Task-Id: FN-5934

Fusion-Task-Lineage: aa77df19-3f76-4ede-aa42-0396230edde5
2026-06-03 01:08:09 -07:00
gsxdsm
5336ad1071 FN-5923: remove duplicate merger fixture key
Remove the duplicate merger override from the SettingsModal test fixture.

- delete the earlier legacy merger object from the mocked settings payload
- keep the deterministic merger override as the single effective fixture value

Files changed:
 packages/dashboard/app/components/__tests__/SettingsModal.test.tsx | 1 -
 1 file changed, 1 deletion(-)

Fusion-Task-Id: FN-5923

Fusion-Task-Lineage: 206239b0-af4a-4e45-93b8-2940a42d431a
2026-06-03 01:04:04 -07:00
gsxdsm
43c3fa9edc FN-5935: fix dashboard interop plugin context types
Align the dependency graph plugin's dashboard interop declarations with the current dashboard contract.

- import ReactNode for plugin task card rendering support
- add DetailTaskTab, PluginToastType, and PluginTaskView type exports
- update PluginDashboardViewContext to require workflowSteps and the expanded openTaskDetail signature
- add optional renderTaskCard and addToast hooks to match dashboard expectations

Files changed:
 .../src/dashboard-interop.d.ts                            | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-5935

Fusion-Task-Lineage: 32313a96-1008-4de6-a7cb-e6bfbc385534
2026-06-03 00:53:24 -07:00
gsxdsm
38ff2ef86d FN-5932: fix research settings containment layout
Keep research settings controls inside their containment wrappers so inputs stay onscreen across breakpoints.

- wrap advanced provider controls in a dedicated research settings body container
- tighten research grid and field min-width behavior in desktop and mobile styles
- add regression coverage for global and project research sections on desktop and mobile

Files changed:
 packages/dashboard/app/components/SettingsModal.css                  |  37 +++++++-
 packages/dashboard/app/components/SettingsModal.tsx                  | 104 +++++++++++----------
 packages/dashboard/app/components/__tests__/SettingsModal.test.tsx   |  65 +++++++++++++
 packages/dashboard/app/components/__tests__/settings-mobile.test.tsx |  48 ++++++++++
 4 files changed, 201 insertions(+), 53 deletions(-)

Fusion-Task-Id: FN-5932

Fusion-Task-Lineage: 22dff41f-b563-40d0-97ea-1ca6d1e09466
2026-06-03 00:49:22 -07:00
gsxdsm
de7847c44d FN-5927: categorize pnpm build scripts for install
Document and enforce pnpm build-script review decisions to prevent ignored-script install warnings.

- add reviewed ignoredBuiltDependencies entries to the root pnpm config and mirror the effective policy in pnpm-workspace.yaml
- add a regression test that verifies reviewed dependencies are categorized exactly once and stay aligned across both config files
- document the pnpm build-script approval policy in contributing docs and link plugin authoring guidance from AGENTS.md and PLUGIN_AUTHORING.md

Files changed:
 AGENTS.md                                          |  5 ++
 docs/PLUGIN_AUTHORING.md                           |  3 +-
 docs/contributing.md                               | 14 ++++
 package.json                                       |  9 +++
 pnpm-workspace.yaml                                | 14 ++++
 scripts/__tests__/pnpm-build-scripts-config.test.mjs   | 74 ++++++++++++++++++++++
 6 files changed, 118 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-5927

Fusion-Task-Lineage: 192bbed9-c5ed-45cb-b4bd-fb18514e2783
2026-06-03 00:28:41 -07:00
gsxdsm
7be377da0c FN-5926: break bundled plugin dashboard dependency cycle
Remove direct dashboard package dependencies from bundled plugins while preserving typed dashboard interop.

- add a workspace acyclic dependency regression test for all packages and dashboard-bundled plugins
- expose dashboard app aliases in dashboard TS/Vite/Vitest configs for plugin interop imports
- replace bundled plugin @fusion/dashboard dependencies with local dashboard interop declarations and updated tsconfig path mappings

Files changed:
 .../workspace-dependency-acyclicity.test.ts        | 174 +++++++++++++++++++++
 packages/dashboard/tsconfig.app.json               |   6 +-
 packages/dashboard/tsconfig.test-check.json        |   6 +-
 packages/dashboard/vite.config.ts                  |   4 +
 packages/dashboard/vitest.config.ts                |   4 +
 .../fusion-plugin-cli-printing-press/package.json  |   1 -
 .../src/dashboard-interop.d.ts                     |  19 +++
 .../fusion-plugin-cli-printing-press/tsconfig.json |   7 +-
 .../fusion-plugin-dependency-graph/package.json    |   1 -
 .../src/dashboard-interop.d.ts                     |   6 +
 .../fusion-plugin-dependency-graph/tsconfig.json   |   3 +-
 plugins/fusion-plugin-roadmap/package.json         |   1 -
 .../src/dashboard-interop.d.ts                     |  19 +++
 plugins/fusion-plugin-roadmap/tsconfig.json        |   7 +-
 pnpm-lock.yaml                                     |   9 --
 15 files changed, 248 insertions(+), 19 deletions(-)

Fusion-Task-Id: FN-5926

Fusion-Task-Lineage: 1b39c08a-1415-407d-90cc-b3de89af0316
2026-06-03 00:12:13 -07:00
gsxdsm
0971eced30 FN-5920: prefer mission detail event count for activity tab
Use mission detail event counts as the authoritative pre-load source for mission activity.

- add mission hierarchy eventCount support in core and dashboard mission types
- return mission eventCount from mission detail APIs and document the field
- prefer the detail eventCount over stale list summaries before activity events load
- add coverage for store, API, and MissionManager pre-load count behavior

Files changed:
 docs/missions.md                                   |  2 +-
 packages/core/src/__tests__/mission-store.test.ts  | 18 +++++++++
 packages/core/src/mission-store.ts                 |  6 +++
 packages/core/src/mission-types.ts                 |  2 +
 packages/dashboard/app/api/legacy.ts               |  2 +
 packages/dashboard/app/components/MissionManager.tsx    | 12 +++++-
 packages/dashboard/app/components/__tests__/MissionManager.test.tsx   | 46 +++++++++++++++++++++-
 packages/dashboard/app/components/mission-types.ts |  1 +
 packages/dashboard/src/__tests__/mission-e2e.test.ts    |  2 +
 9 files changed, 86 insertions(+), 5 deletions(-)

Fusion-Task-Id: FN-5920

Fusion-Task-Lineage: a0269499-d34a-495d-89fc-0534bb62a94e
2026-06-02 23:47:32 -07:00
gsxdsm
fb1f726f39 fix(compound-engineering): address code review feedback
- session-store: rowToSession parses JSON columns via a safeParse helper, so a
  corrupted currentQuestion/conversationHistory column degrades to null/[] instead
  of throwing and crashing reads of an otherwise-valid row (+regression test)
- session-routes: validate the ?status= list filter against CE_SESSION_STATUSES
  (asCeSessionStatus) instead of casting an arbitrary query string with 'as never'
- _harness: makeScriptedSession throws on an empty script rather than yielding
  undefined, surfacing test mistakes loudly
- useCeSession tests: use fake timers (advanceTimersByTimeAsync) instead of real
  setTimeout waits for deterministic poll-interval assertions

Skipped: 3 doc nits in src/skills/ce-*/references/** — those are pinned upstream
ce-* skill copies (KTD5 vendored snapshot), not this repo's content.
2026-06-02 23:38:43 -07:00
gsxdsm
6d3b1c9810 FN-5931: fix board viewport fill on narrow widths
Keep the board stretched between the header and footer across narrow layouts.

- make .project-content and .board flex-aware with min-size guards so board columns fill the remaining viewport space
- keep the board resize stabilization cleanup defensive when visualViewport lacks removeEventListener
- extend board mobile regression coverage and document footer-safe fill layout guidance

Files changed:
 docs/dashboard-guide.md                            |  2 +
 packages/dashboard/app/components/Board.tsx        |  8 ++-
 packages/dashboard/app/components/ProjectSelector.css   |  2 +
 packages/dashboard/app/components/__tests__/board-mobile-initial-render.test.tsx | 81 ++++++++++++++++++++--
 packages/dashboard/app/styles.css                  |  7 +-
 5 files changed, 89 insertions(+), 11 deletions(-)

Fusion-Task-Id: FN-5931

Fusion-Task-Lineage: 0031ad20-82e5-465d-9326-2b6c2d45de69
2026-06-02 23:33:11 -07:00
gsxdsm
8b450506fc FN-5925: polish task review tab layout
Refine the task review tab layout for clearer hierarchy and better mobile behavior.

- group the review summary and decision badge into a stacked header layout
- reorganize review items with dedicated selection, status, and metadata regions
- restyle review cards, status badges, auto-merge controls, and body containers for improved spacing and overflow handling
- extend TaskReviewTab coverage for populated layout hooks and mobile CSS regressions

Files changed:
 packages/dashboard/app/components/TaskReviewTab.css     | 220 +++++++++++++++------
 packages/dashboard/app/components/TaskReviewTab.tsx     |  24 ++-
 packages/dashboard/app/components/__tests__/TaskReviewTab.test.tsx    |  32 ++-
 3 files changed, 206 insertions(+), 70 deletions(-)

Fusion-Task-Id: FN-5925

Fusion-Task-Lineage: fdb9d882-abda-48b0-aed0-a1ff4262af8f
2026-06-02 23:26:59 -07:00
gsxdsm
a1b7556c7b FN-5924: throttle OAuth expiry alerts across restarts
Persist OAuth expiry alert state so repeated provider expiry warnings are suppressed for 12 hours across engine restarts.

- add a persisted OAuth alert state store under ~/.fusion/agent and share it between the expiry monitor and startup validity logger
- throttle repeated oauth-token-expired notifications and startup expiry warnings per provider for 12 hours, while clearing stale state when providers disappear or change
- cover persisted throttling, restart behavior, failure handling, and wiring updates in engine notification tests
- document the persisted 12-hour OAuth alert throttle and add a patch changeset for @runfusion/fusion

Files changed:
 .changeset/fn-5924-oauth-alert-throttle.md         |   5 +
 docs/settings-reference.md                         |   4 +-
 packages/engine/src/__tests__/project-engine-soft-delete-merge-abort.test.ts |   3 +
 packages/engine/src/__tests__/project-engine.test.ts    |  17 ++-
 packages/engine/src/__tests__/reliability-interactions/soft-delete-in-flight-abort.test.ts            |   3 +
 packages/engine/src/auth-storage.ts                |   6 +-
 packages/engine/src/notification/__tests__/oauth-alert-state.test.ts            |  72 ++++++++++
 packages/engine/src/notification/__tests__/oauth-expiry-monitor.test.ts         | 148 ++++++++++++++++---
 packages/engine/src/notification/__tests__/oauth-validity-logger.test.ts        | 159 ++++++++++++++++++---
 packages/engine/src/notification/index.ts          |   3 +
 packages/engine/src/notification/oauth-alert-state.ts   | 144 +++++++++++++++++++
 packages/engine/src/notification/oauth-expiry-monitor.ts       |  12 +-
 packages/engine/src/notification/oauth-validity-logger.ts      |  16 ++-
 packages/engine/src/project-engine.ts              |  13 +-
 14 files changed, 554 insertions(+), 51 deletions(-)

Fusion-Task-Id: FN-5924
Fusion-Task-Lineage: 83255a25-40c7-44d4-8302-b068ae51250e
2026-06-02 23:13:16 -07:00
gsxdsm
669a6ecfdc FN-5929: track hidden usage windows by instance
Store hidden usage windows with per-instance identities while keeping legacy labels restorable.

- persist hidden usage windows with an index-qualified identity instead of label-only keys
- treat legacy label-only entries as matches for restore/show-hidden behavior
- guard hidden-window counts when provider windows are empty or undefined
- add regression coverage for duplicate labels, multiple hidden windows, and legacy persistence

Files changed:
 packages/dashboard/app/components/UsageIndicator.tsx    |  71 +++++++++----
 packages/dashboard/app/components/__tests__/UsageIndicator.test.tsx   | 113 ++++++++++++++++++++-
 2 files changed, 159 insertions(+), 25 deletions(-)

Fusion-Task-Id: FN-5929

Fusion-Task-Lineage: eb48988e-80b8-4d6c-90b9-0d324564f1aa
2026-06-02 22:46:12 -07:00
gsxdsm
fab2377fd1 FN-5921: persist queued chat messages across navigation
Keep queued chat composer state when users move between sessions and only clear it when the session is truly discarded.

- stop clearing persisted pending chat messages during session switches in useChat and useQuickChat
- clear persisted queued messages only when creating a fresh session or archiving/deleting an existing session
- add regression coverage for navigation, reselection, pre-session queueing, and cleanup behavior across chat and quick chat hooks

Files changed:
 .../dashboard/app/hooks/__tests__/useChat.test.ts  | 246 ++++++++++++++++++++-
 .../app/hooks/__tests__/useQuickChat.test.ts       | 150 +++++++++++++
 packages/dashboard/app/hooks/useChat.ts            |   9 +-
 packages/dashboard/app/hooks/useQuickChat.ts       |   5 +-
 4 files changed, 396 insertions(+), 14 deletions(-)

Fusion-Task-Id: FN-5921

Fusion-Task-Lineage: 8916f862-77f5-4d5b-be9a-412e8a71a47d
2026-06-02 22:42:19 -07:00
gsxdsm
941a3297bc FN-5922: fix(FN-5922): use default model fallback in new chat dialog when no model is explicitly selected
Fix NewChatDialog to resolve the model from the dropdown default when the user has not
explicitly picked a model, allowing chat creation with the default model.

- Introduce `resolvedModel` that falls back to `defaultModelValue` when `selectedModel` is empty
- Use `resolvedModel` in submit handler and submit-disabled guard so the default model is accepted
- Add test for creating a session with the default model ("Use default" selected)
- Add test for creating a session with an explicitly chosen non-default model
- Update existing no-default test to verify the submit button stays disabled and no session is created

Files changed:
 packages/dashboard/app/components/ChatView.tsx     | 12 ++--
 packages/dashboard/app/components/__tests__/ChatView.test.tsx | 69 ++++++++++++++++++++--
 2 files changed, 72 insertions(+), 9 deletions(-)

Fusion-Task-Id: FN-5922

Fusion-Task-Lineage: 30b2aecb-af73-4f6d-b697-cc0b5630d5d8
2026-06-02 22:29:21 -07:00
gsxdsm
3a5a3f2035 FN-5919: restore hidden usage toggle counts
Keep the usage indicator's Show hidden action available when persisted hidden rows no longer render.

- count hidden usage rows from both rendered windows and orphaned persisted labels
- preserve Show hidden visibility on mobile modal and desktop popover surfaces
- add regression coverage for orphaned hidden labels across both UI surfaces

Files changed:
 packages/dashboard/app/components/UsageIndicator.tsx  | 22 ++++++-
 packages/dashboard/app/components/__tests__/UsageIndicator.test.tsx | 75 ++++++++++++++++++++++
 2 files changed, 96 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-5919

Fusion-Task-Lineage: 6e4827a6-0d6f-424d-a4df-ec7185adf841
2026-06-02 22:07:32 -07:00
gsxdsm
ee00d9f1b7 FN-5928: enforce surface enumeration for bug-fix invariants
Require bug-fix specs and reviews to enumerate affected surfaces and reject repro-only regression coverage.

- add a required `## Surface Enumeration` section to triage prompt templates and bug-fix planning guidance
- tighten reviewer guidance to block missing surface enumeration and repro-only regression tests
- document the canonical surface checklist in `docs/testing.md` and cover the new wording with prompt/reviewer tests

Files changed:
 AGENTS.md                                         |  6 ++--
 docs/testing.md                                   |  9 +++++
 packages/core/src/__tests__/agent-prompts.test.ts | 22 ++++++++++++
 packages/core/src/agent-prompts.ts                | 16 +++++++++
 packages/engine/src/__tests__/reviewer.test.ts    | 17 ++++++++++
 packages/engine/src/__tests__/triage.test.ts      | 41 ++++++++++++++++++++---
 packages/engine/src/reviewer.ts                   |  3 ++
 packages/engine/src/triage.ts                     | 24 +++++++++++++
 8 files changed, 131 insertions(+), 7 deletions(-)

Fusion-Task-Id: FN-5928
Fusion-Task-Lineage: 717ddcbe-f3a6-4589-ad90-4e640f7a9ff2
2026-06-02 21:57:21 -07:00
gsxdsm
e33dadd77a FN-5916: fix CLI bin targets for pnpm install
Use a committed launcher for published CLI bin links to avoid fresh-install warnings.

- point the published fn and fusion bin entries at a committed bin.mjs launcher
- add a launcher that checks for dist/bin.js and forwards execution to the built CLI
- cover bin target invariants across workspace packages and update CLI package config tests
- add a patch changeset for the published @runfusion/fusion package

Files changed:
 .changeset/fn-5916-cli-bin-launcher.md            |  5 ++
 packages/cli/bin.mjs                              | 20 ++++++
 packages/cli/package.json                         |  5 +-
 packages/cli/src/__tests__/bin-targets.test.ts    | 85 +++++++++++++++++++++++
 packages/cli/src/__tests__/package-config.test.ts |  8 ++-
 5 files changed, 118 insertions(+), 5 deletions(-)

Fusion-Task-Id: FN-5916

Fusion-Task-Lineage: 59d40654-ff77-4655-b9ce-3f3421521b2c
2026-06-02 21:54:14 -07:00
gsxdsm
a8f91e9cc8 fix(FN-5930): remove duplicate const in afterEach cleanup
The FN-5930 squash merge combined two wait-for-exit strategies,
leaving a shadowed 'const exited' and double await. Collapse to
a single register-before-kill pattern.

Fusion-Task-Id: FN-5930
2026-06-02 21:42:38 -07:00
gsxdsm
3ac02ccdd3 FN-5930: stabilize verification spawn supervision test
Reduce flakiness in the real-git verification spawn supervision test.\n\n- write the child PID to stdout with an awaited newline flush before the parent exits\n- collapse the scenario branching so the SIGTERM path is mutually exclusive with crash handling\n- await parent process exit during cleanup and document coverage across normal, signal, and crash teardown paths\n\nFiles changed:\n .../verification-spawn-supervision.real-git.test.ts              | 9 ++++++---\n 1 file changed, 6 insertions(+), 3 deletions(-)

Fusion-Task-Id: FN-5930

Fusion-Task-Lineage: 20c3fe73-a640-4c34-8a07-edf5bdda4b25
2026-06-02 21:38:03 -07:00
gsxdsm
821d724628 Fix tests 2026-06-02 21:37:16 -07:00
gsxdsm
504308422d docs: update CE transport docs for SSE push + projectId session identity 2026-06-02 21:29:59 -07:00
gsxdsm
b3c7601e79 feat(core,dashboard,compound-engineering): real plugin event push over SSE
Replaces polling-only with a true server-push seam (any plugin benefits):
- core: createRouteContext accepts an emitEvent override (default still logs)
- dashboard: emitPluginCustomSseEvent forwards a plugin's ctx.emitEvent calls to
  connected /api/events clients as a project-scoped 'plugin:custom' event; the
  plugin route context's emitEvent is wired to it
- dashboard: PluginDashboardViewContext gains subscribePluginEvents so views
  consume push via a host capability (no raw EventSource, no deep app import)
- CE view subscribes its session to push and refetches on each event; polling
  stays as the fallback when push isn't wired or an event is missed

Also: skill-reachability test installs into a temp dir (no repo-dir writes).
Tests: dashboard sse +2 (plugin:custom relay + project scoping), plugin 99.
2026-06-02 21:28:57 -07:00
gsxdsm
79e66e414f fix(compound-engineering): thread projectId through session answer/resume/poll
The session's owning store (and its live in-process handle) is selected per
request by projectId. start() sent projectId but answer/resume/getSession did
not, so any project-scoped session broke on the first answer (a different store
resolved → session not found / no live handle). The client now captures the
start projectId and reuses it on every subsequent call. Closes the multi-project
session-identity residual.
2026-06-02 21:12:20 -07:00
gsxdsm
bddc876d10 Fix tests 2026-06-02 21:10:00 -07:00
gsxdsm
234a2a7ec5 docs: mark compound-engineering plugin plan completed 2026-06-02 20:57:06 -07:00
gsxdsm
f5be21178f feat(core,engine,compound-engineering): make CE sub-agent sessions load their skills
Closes the U2/U5 skill-discovery carry-forward so the plugin's interactive ce-*
sessions actually load the stage's bundled skill in a live agent (not just in
scripted-fake tests).

Root cause: createFnAgent built its DefaultResourceLoader without forwarding any
skill-discovery path, and the interactive seam options couldn't carry one. The
loader's skillsOverride only *filters* skills already discovered from cwd's
standard roots, so the plugin-local .fusion-ce-skills/<id>/SKILL.md was never
discoverable.

Fix (end-to-end):
- AgentOptions.additionalSkillPaths forwarded into DefaultResourceLoader
- CreateInteractiveAiSessionOptions gains requestedSkillNames + additionalSkillPaths
- the interactive engine adapter forwards them to createFnAgent (skills +
  additionalSkillPaths)
- the orchestrator runs the session with cwd on the real project root and hands
  it [stage.skillId] + the install root

Proven: a real DefaultResourceLoader with additionalSkillPaths discovers ce-plan
and filters out ce-work; the orchestrator passes the right id/path/cwd. Plugin 96,
engine 136, core 99 tests green.
2026-06-02 20:55:01 -07:00
gsxdsm
6d3a077539 FN-5912: separate planning summary button loading states
Keep planning summary actions responsive with operation-specific loading indicators.

- pass separate single-task and breakdown loading flags into the planning summary view
- show the Creating spinner only on Create Single Task and the Breaking down spinner only on Break into Tasks while keeping the sibling action disabled
- add regression coverage for both pending-action paths and normalize the restart integration test temp worktree root under /private/tmp

Files changed:
 .../dashboard/app/components/PlanningModeModal.tsx |  14 ++-
 .../PlanningModeModal.planning-flow.test.tsx       | 138 +++++++++++++++++++++
 .../src/__tests__/restart.integration.test.ts      |   7 +-
 3 files changed, 151 insertions(+), 8 deletions(-)

Fusion-Task-Id: FN-5912

Fusion-Task-Lineage: b93da566-0c2b-4ff8-83ea-b6e009dfd650
2026-06-02 20:47:42 -07:00
gsxdsm
08312bb59d fix(compound-engineering): correctness fixes from code review
- reconciler: a deleted current-stage board task no longer wedges the pipeline
  in 'running' forever (terminality computed over existing tasks only; all-deleted
  is a no-op, not a wedge)
- session-store: a human-slow awaiting_input session is no longer misclassified
  stale (interval rubric applies only to in-flight active/launching turns)
- stage-registry: pipeline progression uses an explicit order ordinal instead of
  registry insertion order, so out-of-order registration can't corrupt advancement
- orchestrator.answer(): validate questionId before mutating state, so a stale id
  can't destroy the persisted currentQuestion recovery anchor
- orchestrator.resume(): rehydrate a live interactive session by replaying
  persisted history (side effects suppressed) so a resumed session is actually
  answerable instead of dead-ending; honest interrupted+error fallback when no
  factory is available

95 tests (6 new regression tests, each confirmed failing pre-fix).
2026-06-02 20:42:44 -07:00