Add explicit visibility for active missions that remain intentionally unlinked to goals.
- document the no-backfill decision with an engine-emitted unlinked mission advisory
- add a scheduler reporter that emits one deduped workflow insight for active missions without goal links and falls back to task logs when insight storage is unavailable
- cover the advisory reporter and scheduler integration with focused tests
- clear PR remediation errors when changing the Create Pull Request base branch
Files changed:
docs/missions.md | 2 +
.../dashboard/app/components/PrCreateModal.tsx | 2 +
packages/engine/src/__tests__/scheduler.test.ts | 8 +
.../unlinked-missions-advisory-reporter.test.ts | 170 +++++++++++++++++++++
packages/engine/src/scheduler.ts | 18 +++
.../src/unlinked-missions-advisory-reporter.ts | 117 ++++++++++++++
6 files changed, 317 insertions(+)
Fusion-Task-Id: FN-5960
Fusion-Task-Lineage: efdbb4f5-fbd5-4ed7-9b9e-58706041d993
- Add dirPicker.createFolderError to all locale files (en, es, fr, ko, zh-CN, zh-TW)
- Use t() for the folder name validation error in DirectoryPicker
- Add missing dirPicker keys: cancel, createFolder, createFolderAria,
createFolderConfirm, createFolderTitle, newFolderPlaceholder
- routes.ts: use isAbsolute() before resolve() for proper path validation
- routes.ts: wrap mkdir() in try/catch to map EEXIST/ENOENT/ENOTDIR to 4xx
- DirectoryPicker.tsx: use !browser.currentPath guard to prevent re-fetch loop
- DirectoryPicker.tsx: disable Create button during in-flight requests
- DirectoryPicker.tsx: add fetchEntries to useEffect dependency array
- DirectoryPicker.tsx: client-side validation for folder names
- Add changeset for the new create-folder feature
Fix bug where navigating into an empty folder in the DirectoryPicker
would automatically revert to the previous folder. The useEffect that
auto-fetches on open was using the stale 'value' prop instead of
'browser.currentPath' after navigation.
Also adds a 'New folder' button to the DirectoryPicker toolbar so users
can create folders directly when setting up a project.
- DirectoryPicker.tsx: fix useEffect to use browser.currentPath || value
- DirectoryPicker.tsx: add create folder UI state and handlers
- DirectoryPicker.css: styles for create folder input and actions
- routes.ts: add POST /api/create-directory endpoint
- legacy.ts: add createDirectory API client
- DirectoryPicker.test.tsx: add tests for empty folder nav and create folder
Run auto-layout automatically when a workflow is loaded so nodes are
tidily positioned instead of scattered at persisted positions. Position
the viewport at (0,0) with zoom 1 so the laid-out nodes are visible in
the top-left corner.
- workflow-auto-layout.ts: change ORIGIN_X/Y from 40 to 0
- WorkflowNodeEditor.tsx: apply autoLayout on load, setViewport to top-left
- WorkflowNodeEditor.test.tsx: update test to verify layout runs on load
Security hardening + cleanups from code review: parseAgentVerdicts now
ignores out-of-batch thread ids and fails safe (disagree) on conflicting
duplicate verdicts for one thread; drop the unused store param from
makePrResponseAgentRunner; correct the rework-bound doc (to-node, not
from-node) and the migration idempotency comment (PK is the re-run guard).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds the fn pr noun — create/show/list/respond/approve/retry/merge/close/
automerge — routing to the same store/engine/release paths as the U7
dashboard routes (surface-parity pinned by a consistency test). Retires
fn task pr-create (dispatch removed; deprecated re-export kept for
importers). Changeset: @runfusion/fusion minor. 22 command tests.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds /api/pull-requests routes (list, detail, merge/approve/retry/close/
automerge — all re-fetch authoritative state before acting), a
PullRequestView rendering every entity state distinctly (creating/failed/
unverified/responding/await-review/conflict) with the action bar, live
auto-merge gate reason, and conflict CTA; TaskCard PR node-state badge +
link; and the R16 column-move-backward guard. User actions route through
the existing releaseHeldTaskByEvent primitives. Maps the new PR node kinds
in the workflow editor's kind resolver. 13 route tests + lazy-view guard
green; component test runs in CI.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Generalizes the foreach-only bounded-rework mechanism to the top-level
graph walk so the PR review loop (await-review -> pr-respond -> rework
back) is a legal bounded cycle: a kind:rework back-edge to a stacked node
returns a ReworkSignal the loop-head re-runs up to maxReworkCycles, then
routes outcome:rework-exhausted. Non-rework cycles still throw 'Cycle
detected' (safety preserved); foreach rework unchanged (shared core
constants). Adds createAutoMergeGateHandler (live entity re-fetch +
isPrEntityAutoMergeReady -> auto-on/auto-off). Pins R14: graph-executed
PR tasks merge through pr-merge, never the legacy queue. 122 graph tests
green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implements the fix-or-disagree agent loop behind pr-respond: batched
one-run-per-cycle over actionable threads (filtering resolved/outdated/
self/bot), with prompt-injection delimiting of untrusted comment bodies,
viewer-authenticated anti-spoof markers, a pre-push secret scan, fast-
forward-only push (no force-push path) with non-ff abort+re-batch, reply+
resolve, commit-last thread-state persistence with marker+SHA crash
recovery (R15), and an iteration cap on responseRounds (R8). GitHub/git/
agent ops injected; engine stays dashboard-import-free. Adds GraphQL
getPrReviewThreadsDetailed + getViewerLogin to the client. 23 tests.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds PrReconciler — a per-repo, self-owned polling loop (started from the
runtime layer in project-engine.ts, NOT the scheduler) that ETag-probes
GitHub, deep-fetches on change, persists mirror state, clears unverified
on first reconcile, and fires releaseHeldTaskByEvent(github:pr-<event>)
for transitions (changes-requested/approved/conflict/conflict-cleared/
merged/closed). Drops terminal entities; persists an audit event on error.
GitHub ops injected via PrReconcileGithubOps at the 3 CLI sites; engine
never imports the dashboard client. scheduler.ts stays PR-free (R20),
pinned by a regression test. 8 tests.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds the three first-class PR workflow node kinds and their handlers via
createPrNodeHandlers(deps), registered in createDefaultNodeHandlers
(fail-closed pr-nodes-unwired when absent). GitHub ops are injected as
callbacks (PrNodeGithubOps) at all three CLI sites (daemon/serve/dashboard)
so the engine never imports the dashboard client (FN-3049). pr-create
routes open/failed as outcomes; pr-merge passes expectedHeadOid and never
writes 'merged' (reconcile corroborates); pr-respond delegates to an
injected respond callback (U5 fills the body). 10 tests.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds the net-new GitHub primitives the PR nodes need: replyToReviewThread
and resolveReviewThread (GraphQL mutations, dual gh/API), an ETag-conditional
probePrChanged (304 is rate-limit-free, gates the reconcile deep-fetch), and
expectedHeadOid on mergePr (--match-head-commit / REST sha) raising a typed
PrStaleHeadError on a head-moved race so pr-merge can re-evaluate.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- boot-smoke: shutdown verdict now requires SIGTERM actually delivered and a
clean exit (code 0 or SIGTERM); EADDRINUSE port race retries with a fresh
port (3 attempts)
- test-changed: rename shouldForceFullSuite -> isSharedInfraChange (it routes
to gate mode, not full); run the changed-mode gate under the isolation guard
- workflows: least-privilege permissions (contents: read) on pr-checks and
full-suite
- decideExecutionPlan: implicit wide-blast reasons (missing base, diff failed,
no changes, shared infra, unmapped package) route to new gate mode instead of full
- CI===true force-full branch removed (CI no longer calls test-changed.mjs)
- changed mode runs pnpm test:gate before the affected set
- full suite reachable only via explicit --full / FUSION_TEST_FULL=1
- characterization tests updated + new only-explicit-full invariant test
- pr-checks.yml: gate job = boot smoke + pnpm test:gate; shards/slow/inventory removed
- full-suite.yml (new): 4-way shards, engine slow tier, inventory guard on push to main
- ci.yml deleted (trigger-disabled since FN-1541; was dead config)
- ci-workflow.test.ts rewritten to pin the new gate shape; release/signing blocks preserved
- docs/contributing.md: pnpm test:gate is the merge gate; verify:workspace repositioned as deep opt-in
BRANCH-PROTECTION CUTOVER: set required checks to exactly [Lint, Typecheck, Build, Gate] after merging; open PRs must rebase.
- TaskFieldsSection.css: restore the toggle knob fill to the themed
var(--card) token (was hardcoded to #fff on this branch), which the
AgentListModal theme-token guard scans all app CSS for and rejects.
- ListView.test.tsx: add fetchBoardWorkflows + api to the ../../api mock;
TaskDetailModal (rendered via the embedded detail) now calls both at mount
for board workflows and the cli-sessions lookup, so the object-literal mock
must provide them ("No X export is defined on the ../../api mock").
- auto-merge-toggle-blank.mobile.test.tsx / board-mobile-initial-render.test.tsx:
revert the runOnlyPendingTimers→runAllTimers change; with the installed rAF
shim that re-schedules itself, runAllTimers loops forever and trips vitest's
10000-timer infinite-loop abort.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>