Commit Graph

8006 Commits

Author SHA1 Message Date
gsxdsm
39bbe48c8a test(FN-branch-group): update routes-tasks subtask expectations to real-groupId semantics
Two stale assertions still encoded the synthetic planning:<sessionId> groupId:
shared mode without a group-capable store now stamps no groupId, and
per-task-derived members never carry one.
2026-06-03 18:12:59 -07:00
gsxdsm
1557fc5a47 fix(FN-branch-group): repair CI failures — execFile mock compatibility, TaskCard narrowing, e2e memo race
- resolve execFile lazily via namespace import in coordinator/merger/
  task-lifecycle so the repo's exec-only child_process test mocks load again
  (10+ engine suites failed at import); dashboard.test.ts mock gains execFile
  so the argv-based git probes hit the mock instead of spawning real git
- TaskCard: capture optional branchContext.groupId into a const (narrowing
  doesn't survive into the onClick closure; app tsconfig caught it in CI)
- planning e2e: bounded poll past the 2.5s listTasks startup memo that served
  a pre-landing snapshot on fast CI runs
2026-06-03 17:57:00 -07:00
gsxdsm
0be074f8c2 fix(FN-branch-group): address fourth-round PR review feedback (#1357)
- needsPrRepair no longer short-circuited by the open-state guard: legacy
  fallback rows (finalized + prState open + prNumber null) now repair by
  creating the real PR on re-promotion; regression test added
- no-PR abandon route test asserts last persisted call + response body
- goal-provenance fallback test clears missionId on its own in-memory store
  so the feature-linkage path is genuinely exercised
2026-06-03 17:42:43 -07:00
gsxdsm
64d02b5108 fix(FN-branch-group): address third-round PR review feedback (#1357)
- abandon (route + CLI) preserves prState 'none' for groups that never had a
  PR instead of falsely persisting 'closed'; regression tests both sides
- stale-snapshot write guard extracted to syncGroupPrOnLanding and covered by
  a fast in-memory unit test (FN-5048); the slow real-git duplicate removed
2026-06-03 17:22:11 -07:00
gsxdsm
d1cd8b6ed8 merge main: unify CONCEPTS.md vocabularies and reconcile core exports
Both sides bootstrapped CONCEPTS.md — kept main's broader structure (Missions,
Merge lifecycle, CE sessions) and folded the branch-group vocabulary into its
Merge-lifecycle cluster (enriched Shared branch group + Self-healing sweep;
added Branch assignment mode, Landed, Group promotion). Union-merged core
index/store imports; took main's AGENTS.md discoverability wording. Also adds
execFile to the two child_process test mocks that only stubbed exec (the
coordinator's argv-based git calls now require it).
2026-06-03 15:57:41 -07:00
gsxdsm
3e927bc5fc fix(FN-branch-group): address second-round PR review feedback (#1357)
- syncGroupPrCallback forwards owner/repo to updatePr (multi-project daemons
  could 404 or edit an unrelated same-numbered PR via process-cwd fallback)
- merger background reconcile re-reads the group before persisting and skips
  the write when the PR snapshot changed (stale-write race vs newer open PR)
- branchContext.groupId trimmed on metadata emit/parse round-trip
- triageSlice non-shared invariant assertions (no groupId, no group row)
2026-06-03 15:46:23 -07:00
gsxdsm
866d01f532 FN-5959: bridge task goal provenance from mission links
Bridge mission-linked task provenance into goal diagnostics.

- derive task goal ids and goal records from the linked mission hierarchy with a task mission fallback
- record provenanceGoalIds in goal-injection diagnostics, run-audit metadata, and executor task logs
- add regression coverage and mission/diagnostics docs for derived task-to-goal provenance

Files changed:
 docs/diagnostics.md                                |   5 +-
 docs/missions.md                                   |  19 ++++
 packages/core/src/__tests__/mission-store.test.ts  | 123 +++++++++++++++++++++
 packages/core/src/mission-store.ts                 |  55 ++++++++-
 packages/engine/src/__tests__/goal-injection-diagnostics-wiring.test.ts      |  35 +++++-
 packages/engine/src/goal-injection-diagnostics.ts  |  21 +++-
 6 files changed, 247 insertions(+), 11 deletions(-)

Fusion-Task-Id: FN-5959

Fusion-Task-Lineage: 7c76ae98-37b1-421c-b477-a0147d034a4c
2026-06-03 15:32:29 -07:00
gsxdsm
1853459def FN-5961: document goals refinement evidence gate
Add the governance doc and regression coverage for the conditional post-v1 goals refinement gate.

- add docs/goals-refinement-gate.md defining accepted trigger evidence, activation requirements, and the no-automatic-refinement rule for Slice 4
- link the new goals refinement gate doc from docs/README.md
- add a vitest doc guard that asserts the required trigger categories and activation constraints remain documented

Files changed:
 docs/README.md                                     |   1 +
 docs/goals-refinement-gate.md                      | 104 +++++++++++++++++++++
 packages/dashboard/app/__tests__/goals-refinement-gate-docs.test.ts   |  51 ++++++++++
 3 files changed, 156 insertions(+)

Fusion-Task-Id: FN-5961

Fusion-Task-Lineage: 8e641782-93bb-470e-8bc3-14379dbd6cf6
2026-06-03 15:32:29 -07:00
gsxdsm
8aed4da764 FN-5949: add AI PR conflict resolution to Create PR flow
Add dashboard support for resolving task-branch PR conflicts with AI before PR creation.

- add a dashboard PR conflict resolver that merges the selected base into the task branch, invokes an AI merge session on conflicted files, verifies markers are removed, then commits and pushes the updated branch
- expose a POST /tasks/:id/pr/resolve-conflicts route plus client API/export wiring, docs updates, and a changeset for the published CLI package
- update the Create PR modal UI, styling, and tests to surface preflight conflicts, trigger AI resolution, and refresh preflight state after success
- add API coverage for successful and unresolved conflict-resolution paths and include the new route test in the dashboard API quality shard

Files changed:
 .changeset/fn-5949-pr-conflict-resolution.md       |   5 +
 docs/dashboard-guide.md                            |   1 +
 docs/task-management.md                            |   1 +
 packages/dashboard/README.md                       |   1 +
 packages/dashboard/app/api/legacy.ts               |  20 ++
 .../dashboard/app/components/PrCreateModal.css     |  32 ++-
 .../dashboard/app/components/PrCreateModal.tsx     |  46 ++++
 .../components/__tests__/PrCreateModal.test.tsx    |  33 +++
 ...egister-git-github.pr-resolve-conflicts.test.ts | 186 +++++++++++++++
 packages/dashboard/src/index.ts                    |   5 +
 packages/dashboard/src/pr-conflict-resolver.ts     | 258 +++++++++++++++++++++
 .../dashboard/src/routes/register-git-github.ts    | 225 ++++++++++++------
 packages/dashboard/vitest.config.ts                |   2 +-
 13 files changed, 739 insertions(+), 76 deletions(-)

Fusion-Task-Id: FN-5949

Fusion-Task-Lineage: fea35fbf-6254-415c-83cc-0bc24abc911e
2026-06-03 15:32:29 -07:00
gsxdsm
de3273eba3 FN-5937: clear deadlock auto-pause on retry
Clear deadlock auto-pauses when users retry failed in-review tasks.

- add a shared core helper to clear only the in-review stall deadlock auto-pause without overriding manual or unrelated pauses
- apply the auto-pause clear patch across dashboard, CLI, and extension retry flows while preserving existing merge retry reset behavior
- add regression coverage for core, CLI, extension, and dashboard retry paths plus a patch changeset and architecture note

Files changed:
 .changeset/fn-5937-clear-auto-pause-retry.md       |   5 +
 docs/architecture.md                               |   2 +-
 packages/cli/src/__tests__/extension.test.ts       | 126 ++++++++++++++++++
 packages/cli/src/__tests__/task-retry.test.ts      |  59 +++++++++
 packages/cli/src/commands/task.ts                  |  12 +-
 packages/cli/src/extension.ts                      |  12 +-
 .../core/src/__tests__/manual-retry-reset.test.ts  |  44 ++++++-
 packages/core/src/index.ts                         |   7 +-
 packages/core/src/manual-retry-reset.ts            |  19 +++
 packages/core/src/store.ts                         |   8 +-
 .../src/__tests__/routes-tasks-ops.test.ts         | 141 +++++++++++++++++++++
 .../src/routes/register-task-workflow-routes.ts    |  12 +-
 12 files changed, 436 insertions(+), 11 deletions(-)

Fusion-Task-Id: FN-5937

Fusion-Task-Lineage: 8a15e01b-7b05-4126-ac6b-895467801f02
2026-06-03 15:32:29 -07:00
gsxdsm
da7c82ebea FN-5947: fix mobile task review header spacing
Tighten the Task Review tab layout on mobile and lock in the responsive header contract.

- override the mobile .task-review-tab__summary-wrap flex rule so the summary block stops reserving excessive blank space
- extend TaskReviewTab coverage to assert the mobile summary-wrap override and prevent regressions between empty and populated review states across reviewer-agent and pull-request sources
- keep the review header structure stable across both review sources and empty/populated states

Files changed:
 .../dashboard/app/components/TaskReviewTab.css     |  4 +
 .../components/__tests__/TaskReviewTab.test.tsx    | 98 ++++++++++++++++++++++
 2 files changed, 102 insertions(+)

Fusion-Task-Id: FN-5947
Fusion-Task-Lineage: 813e1142-bf28-4687-8510-2f93ec40e582
2026-06-03 15:32:29 -07:00
gsxdsm
f1572a3b62 FN-5946: render PR create modal through a portal
Ensure the PR creation dialog escapes transformed ancestor layout traps.

- render `PrCreateModal` with `createPortal(..., document.body)` so the overlay stays fixed to the viewport
- add regression coverage for container-type and nested-overlay portal behavior plus close interactions
- document the modal overlay portal requirement in the dashboard guide

Files changed:
 docs/dashboard-guide.md                            |  2 +-
 .../dashboard/app/components/PrCreateModal.tsx     |  6 ++-
 .../components/__tests__/PrCreateModal.test.tsx    | 63 +++++++++++++++++++++-
 3 files changed, 66 insertions(+), 5 deletions(-)

Fusion-Task-Id: FN-5946

Fusion-Task-Lineage: eb22590e-1776-49f3-82d7-ac87c5138f0b
2026-06-03 15:32:28 -07:00
gsxdsm
acc7456a5e Merge pull request #1343 from Runfusion/gsxdsm/compound
feat: Compound Engineering plugin with interactive sessions, work bridge, and bidirectional sync
2026-06-03 15:31:40 -07:00
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
1b83317cfe docs(solutions): document branch-group single-PR silent breakage; seed CONCEPTS.md
First docs/solutions/ learning: synthetic groupIds, mock-masked engine wiring,
and side-effect-free state flips (PR #1357 post-mortem). Seeds CONCEPTS.md with
the branch-group domain vocabulary and surfaces both knowledge stores in
AGENTS.md reference docs.
2026-06-03 15:11:19 -07:00
gsxdsm
4aa9048909 Merge pull request #1345 from Runfusion/gsxdsm/missonsdebug
fix(engine): recover missions wedged by stranded done features
2026-06-03 15:00:08 -07:00
gsxdsm
7bfdd97f22 Merge pull request #1361 from Runfusion/gsxdsm/vitest-killguard
fix(tui): stop vitest auto-kill firing on garbage memory metric and killing non-vitest processes
2026-06-03 14:42:54 -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
f3bc757d22 fix(FN-branch-group): address PR review feedback (#1357)
- abandon route: guard already-abandoned groups (matches CLI)
- CLI branch-group list: single task fetch via filterTasksByBranchGroup (N+1)
- branch-name validator: git check-ref-format parity (//, dot-segments, .lock, @, @{, trailing /.)
- updateBranchGroup: validate renamed branchName too
- already-merged-detector: escape regex metachars in git log --grep; non-vacuous prose-mention assertion
- group PR callbacks: thread per-project cwd through SyncGroupPrFn/reconcile/github helpers (multi-project correctness)
- merger: group-PR sync is fire-and-forget (never blocks merge completion); deterministic test handle
- coordinator: sibling PR reuse only when open; reconcile skips member fetch on read-only path; argv-based git calls (no shell)
- task-lifecycle: legacy group-PR path links open PRs only; branch probes via execFile argv (injection hardening)
- mission/planning: branchContext.groupId only stamped for actual shared-mode members (groupId now optional)
- UI: Abandon reachable whenever PR is open (decoupled from completion); promote stays completion-gated
- tests: deterministic concurrency gate, real reconcile path in e2e, Surface Enumeration sections
2026-06-03 13:51:13 -07:00
gsxdsm
a9e16cedf8 Merge pull request #1348 from Runfusion/gsxdsm/fix-branch-group-collision
fix(core): reuse same-name branch group instead of colliding on mission triage
2026-06-03 13:49:38 -07:00
gsxdsm
580c9005cc Update packages/core/src/vitest-processes.ts
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-06-03 13:48:02 -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
60c307320d Merge main: adopt FN-5902 lazy assertion linkage in shared runFeatureValidation
- runFeatureValidation now lazy-ensures a linked assertion (FN-5902) instead
  of the removed zero-assertion auto-pass, for both task-completion and the
  stranded-feature recovery path
- CONCEPTS.md: union of main's Merge-lifecycle cluster and this branch's
  Missions clusters; Contract Assertion entry updated for FN-5902 semantics
- AGENTS.md: take main's docs/solutions + CONCEPTS.md pointer wording

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 13:45:11 -07:00
gsxdsm
614bec2126 fix(tui): stop vitest auto-kill firing on garbage memory metric and killing non-vitest processes
Two compounding bugs made the memory-pressure vitest auto-kill a
30-second SIGKILL sweep of anything mentioning vitest:

1. False pressure: getAvailableMemory probed os.availableMemory, which
   does not exist, and silently fell back to os.freemem() — on macOS
   that reads ~99% used on an idle 256GB machine, permanently above the
   90% threshold. Now reads process.availableMemory() (Node 22+) and
   refuses to auto-kill when only the unreliable freemem fallback is
   available.

2. Overbroad targeting: pgrep -f vitest matches full command lines, so
   the sweep also killed wrapper shells (zsh -c '... npx vitest run'),
   monitor loops, and anything else whose argv mentions vitest —
   stranding exit handlers and taking out unrelated process trees.
   New shared findVitestProcessIds (@fusion/core) filters matches to
   actual node executables.

Surface enumeration (all vitest-process kill/count surfaces):
- TUI memory-pressure auto-kill (controller.killVitestProcesses)
- TUI manual kill-vitest command (same method)
- dashboard POST /api/kill-vitest
- dashboard GET /api/system-stats vitestProcessCount (display)
All four now route through findVitestProcessIds.
2026-06-03 13:33:38 -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
e926cac038 docs(plan): mark branch-group single-PR plan completed 2026-06-03 12:43:59 -07:00
gsxdsm
e54417c987 fix(FN-branch-group): security, parity, reconcile-on-read, N+1 review residuals
Review residuals #5/#7/#8/#11/#12 + #3 wiring: forward the configured GitHub
token to the abandon route's client; guard abandon against finalized/merged
groups; reconcile an open group PR's state from GitHub on single-group reads
(merged out-of-band now flips prState); add fn branch-group abandon for
agent-native parity; block branchName shell injection (execFile argv push +
core-side branch-name validation at group creation); and collapse the
branch-groups list N+1 to a single task fetch via a shared
filterTasksByBranchGroup helper.
2026-06-03 12:43:25 -07:00
gsxdsm
d9272abd0f fix(FN-branch-group): promotion lock, PR repair, audit on failure, typed sync block
Review residuals #3/#4/#6/#10: per-group in-process promotion lock (concurrent
route+auto promotion could double-create PRs), finalized-but-PR-less groups can
be repaired by re-promotion without re-merging, auto-promotion failures emit
merge:branch-group-promotion-failed instead of silent swallow, exported
reconcileBranchGroupPr for out-of-band merged reconciliation, and the merger
sync block drops its (store as any) casts (TaskStore already carries the
methods).
2026-06-03 12:25:11 -07:00
gsxdsm
bde7bdf766 fix(FN-branch-group): review fixes — fast-path mergeTargetSource + open-PR reuse only
Code review (Tier 2) found two P1s: (1) the early no-op fast-path persisted
mergeConfirmed/mergeTargetBranch without mergeTargetSource, so a shared-group
member landing via it could never satisfy the strict completion predicate —
promotion permanently blocked; thread mergeTarget.source through like the
standard landing sites. (2) createGroupPrCallback's findPrForBranch used
state:'all' and could reuse a closed/merged PR from a prior group, persisting
a terminal prState onto a fresh promotion; create path now matches open PRs
only.
2026-06-03 11:23:14 -07:00
gsxdsm
928b14ae1b refactor(FN-branch-group): remove dead cross-unit group-PR helpers
Simplicity pass over the 8-unit diff: delete caller-less closeGroupPrCallback
(CLI), dead dashboard createGroupPullRequest/syncGroupPullRequest (+ their
builders/types/tests — production uses the CLI callbacks), and merge the two
CLI PR-body builders into one parameterized function. ~140 LOC of
parallel-but-unused code from isolated unit implementation.
2026-06-03 11:00:16 -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
3bea12f5d8 test(FN-branch-group): end-to-end planning + mission single-PR flows (U8)
Engine half: real-git E2E covering planning- and mission-sourced groups —
members land on the group branch (never main/sibling), completion-gated single
PR via injected callback, re-promote idempotency, sync on later landing,
abandon→closed, and a self-healing finalize mid-flow staying group-anchored.
Core half: real triageFeature stamps the BG- id, member enumeration, and the
canonical completion gate flipping on landing.
2026-06-03 10:48:23 -07:00
gsxdsm
9512e98330 feat(FN-branch-group): surface group PR controls in dashboard + CLI (U7)
Extend BranchGroupCard/GroupTaskModal with an Abandon action (open PRs) and
terminal merged/closed badges; promote stays completion-gated. New
fn branch-group list|show|promote (alias fn bg) reaching the same coordinator
path with createGroupPrCallback wired — agent-native parity with the dashboard
promote flow, same completion-gate rejection.
2026-06-03 10:31:18 -07:00
gsxdsm
415470c7bd feat(FN-branch-group): sync group PR as members land + terminal lifecycle (U6)
Push the single group PR's body (member checklist, x/N landed) on each member
landing via an injected SyncGroupPrFn — new updatePr/closePr GitHubClient
helpers (gh CLI + API parity); refreshPrInBackground is task-scoped/wrong
direction and intentionally not reused. Sync failures are non-fatal+retryable;
out-of-band closed/merged PRs reconcile prState instead of erroring. New
POST /branch-groups/:id/abandon closes the PR best-effort and marks the group
abandoned. Also fixes the U5-introduced stub-context regression in the U4
dashboard bridge test (missing options).
2026-06-03 10:20:30 -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
b1454c198e feat(FN-branch-group): create single real GitHub PR on group promotion (U5)
Group promotion in PR mode previously flipped prState to 'open' without ever
calling GitHub — prNumber/prUrl were never populated. Add an injected
CreateGroupPrFn (mirrors the processPullRequestMerge seam, no engine→dashboard
import): coordinator creates-or-reuses exactly one PR per group, persists
prNumber/prUrl/prState, and leaves state untouched on GitHub failure so
re-promotion retries. Idempotent via persisted prNumber +
getBranchGroupByBranchName. Wired at all three CLI engine-construction sites
(daemon/dashboard/serve).
2026-06-03 10:01:53 -07:00
gsxdsm
508b9c44d0 fix(FN-branch-group): add engine.promoteBranchGroup bridge method (U4)
The dashboard promote route called engine.promoteBranchGroup(groupId) as a
method that never existed — only a standalone coordinator function did — so
the route was dead, masked by a vi.fn mock in the test. Add the real method on
ProjectEngine delegating to the coordinator (resolving store/cwd/settings like
attemptBranchGroupPromotion), and de-mock the test so it now fails if the
method goes missing. No PR-creation behavior yet (U5).
2026-06-03 09:46:54 -07:00
gsxdsm
cad44b1f56 fix(FN-5846): commit-ownership-anchor already-merged attribution (U3)
Audit of all shared-member merge + self-healing finalize paths: routing,
merger finalize-success, and the 6 self-healing recovery paths were already
group-branch-safe (FN-5846). Found a residual of the 2026-05-23 lost-work
incident bug #2: already-merged-detector's ancestry strategy used bare
git log --grep first-hit, and the ownership regex made the conventional scope
optional (bare 'feat:' matched). Anchor attribution on trailers or task-scoped
subject; scan candidates instead of accepting the first grep hit. Adds real-git
characterization tests.
2026-06-03 09:40:30 -07:00
gsxdsm
88b4b0d5b3 fix(FN-branch-group): unify landed/completion predicate in core (U2)
Route and coordinator disagreed on landed/complete: the route required
mergeConfirmed + matching mergeTargetBranch, the coordinator accepted bare
column===done/in-review and never checked the branch. Extract canonical
isBranchGroupMemberLanded/isBranchGroupComplete in @fusion/core (stricter
route semantics win — load-bearing for merge-target safety) and consume from
both sides. Tightens promotion gating to fire only when all members are
merge-confirmed onto the group branch.
2026-06-03 09:23:44 -07:00
gsxdsm
66ca583ece fix(FN-branch-group): stamp real BG- id into branchContext.groupId (U1)
Planning and mission entry points discarded the BranchGroup returned by
ensureBranchGroupForSource and stamped a synthetic planning:/mission: string
that never resolved against getBranchGroup, breaking member enumeration.
Capture and stamp the real BG- id; stop setTaskBranchGroup hardcoding
assignmentMode; add a removable legacy read-side shim. Export TaskBranchContext.
2026-06-03 09:17:51 -07:00
gsxdsm
36218876a3 docs(plan): branch-group single managed PR flow plan 2026-06-03 08:58:06 -07:00
gsxdsm
56a0001c45 docs: capture learning for branch-group-collision triage stall
Document the UNIQUE(branch_groups.branchName) collision that silently
stranded mission triage, in docs/solutions/logic-errors/, cross-linked to
the sibling PR #1345 mission-stall learning.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-03 08:51:57 -07:00