Commit Graph

10373 Commits

Author SHA1 Message Date
gsxdsm
4119dc4cf8 fix(ci): remove unused isWithinReplayWindow import in pagerduty signal source
Lint failure (@typescript-eslint/no-unused-vars). The pagerduty replay-window
check itself is tracked as a residual review finding (P1) for follow-up.
2026-06-15 21:15:28 -07:00
gsxdsm
c1b581e018 fix(review): apply autofix feedback
- add missing changesets for the Command Center dashboard and Monitor stage
  (both ship in published @runfusion/fusion; required by AGENTS.md)
- pin the knowledge_pages migration test to literal version 118 (not
  SCHEMA_VERSION-1) so it keeps exercising migration 119 after later bumps
2026-06-15 21:09:14 -07:00
gsxdsm
f5bd86214f feat(monitor): U13 — monitor stage (deployments, incidents, MTTR) closes the loop
Adds deployments + incidents tables (db migration 119→120), real MTTR/deploy/
incident aggregation replacing the U7 seam, an auth-gated SSRF-safe deploy/
incident ingestion route, and a monitor trait that auto-opens a single fix task
on a regression signal. Storm guard groups by the U11 Signal groupingKey with a
threshold gate, cooldown absorption, per-window circuit breaker, and self-loop
guard. Also completes the otel test ActivityAnalytics fixture.
2026-06-15 20:59:57 -07:00
gsxdsm
0a87890bd8 feat(knowledge): U14 — persistent knowledge index
Adds knowledge_pages (db migration 118→119) + a deterministic, model-free
keyword index of task/PR history in packages/dashboard/src, incrementally
refreshed on task completion (task:moved→done listener) and queryable via an
auth-gated, project-scoped API. Complements the LLM-extracted insights/memory
surfaces rather than duplicating them.

Follow-ups: no React view yet; PR-history page population attaches via U18.
2026-06-15 20:34:52 -07:00
gsxdsm
168dc2f796 feat(command-center): U10 — OpenTelemetry (OTLP) metrics export
mapAnalyticsToOtlp maps token/cost/activity aggregates to the OTLP/HTTP JSON
envelope (counters + gauges, model/provider/node/agent attributes); a periodic
dashboard exporter is opt-in via FUSION_OTEL_METRICS_ENDPOINT, https-validated,
header-redacted, backs off on failure, and never blocks startup/shutdown.
Minimal exporter (no SDK dep) — real @opentelemetry SDK is a follow-up.
2026-06-15 20:19:16 -07:00
gsxdsm
5bc8901f06 feat(command-center): U7 — SDLC funnel + throughput
aggregateSdlcFunnel derives per-stage counts, conversion, completion rate, and
throughput/day from activityLog task:moved transitions, mapping columns to stages
by trait (unknown → Other). Rides additively on the /activity payload; SdlcFunnel
renders it via the U4 Funnel primitive in the Overview Throughput section.
2026-06-15 20:15:59 -07:00
gsxdsm
f45dde22e5 feat(triage): U12 — triage trait for issues and pull requests
Registers a built-in 'triage' onEnter trait (via TraitRegistry +
registerTraitHookImpl) that classifies and decomposes incoming signals/issues
into todo tasks, and routes inbound PRs (dependency-bump vs feature) without
minting issues, with a Fusion-opened-PR self-loop guard. Reuses subtask-breakdown
via a new decomposeForTriage seam.

Follow-up: auto-firing the built-in async onEnter from store.moveTaskInternal
(currently fires plugin: hooks only) — invoked via the registry seam meanwhile.
2026-06-15 20:08:38 -07:00
gsxdsm
29acf14884 feat(command-center): U8 — CSV export for analytics endpoints
?format=csv branch on tokens/tools/activity/productivity serializes the same
scoped aggregator output (RFC-4180 quoting, attachment headers, header-only on
empty). Scoping applied before aggregation — no cross-project leak via export.
2026-06-15 20:05:14 -07:00
gsxdsm
070ed98ca2 feat(command-center): U6b — live Mission-Control panel
MissionControlPanel renders the U6a /live snapshot with push+poll convergence
(SSE-triggered refetch + 5s interval armed only while sessions are in-flight,
cleared when idle), stale-node marking, and the live SDLC funnel. Wired into the
shell's Mission Control tab.
2026-06-15 20:05:14 -07:00
gsxdsm
ed3c572a81 feat(command-center): U5 — historical analytics areas + date-range filtering
Tokens/Tools/Activity/Productivity/Ecosystem/Signals area components fetch the
U9 endpoints and render via the U4 chart primitives, wired into the shell tabs.
SWR reset effects key on a derived signature (not array identity) to survive
revalidation. LOC/plugin gaps show unavailable sentinels; Signals degrades to
empty until U11/U13 data lands.
2026-06-15 19:57:20 -07:00
gsxdsm
cf46859335 feat(router): U17 — Fusion Model Router (session-level selection layer)
routeModel + conservative v0 allowlist (dependabot/lint → cheap tier) wired
into execution/planning/validation lanes in model-resolution.ts; governance
(isPermitted) and column-agent override are absolute, OFF by default. Routing
decisions (with counterfactual) emit via the U1 usage_events seam.
2026-06-15 19:57:20 -07:00
gsxdsm
e617ce65d9 feat(pr): U18 — surface + gate auto-resolution of PR review comments
Adds autoResolveReviewComments project setting (default on) gating the existing
Review-response loop, a single-sourced summarizePrThreadActivity counter, and
fixed/acted thread counts in the dashboard PR summary. Resolution stays
independent of the auto-merge gate (disabled merge still resolves threads).
2026-06-15 19:44:17 -07:00
gsxdsm
113263f362 feat(command-center): U9+U6a — analytics API endpoints + live snapshot composer
composeLiveSnapshot (core, U6a) feeds GET /api/command-center/live; register-
command-center-routes exposes tokens/tools/activity/productivity/live as thin
adapters over the U2 aggregators + U3 cost. All endpoints inherit session auth
(401 unauth) and apply getScopedStore (no cross-project leak). Vite proxy verified.
2026-06-15 19:44:10 -07:00
gsxdsm
4519732b20 feat(analytics): U3 — model pricing map + cost derivation
costFor() derives USD from token counts via a hand-maintained provider:model
rate map with pricingAsOf + staleness flag; unknown models report unavailable
rather than guessing. Cost wired additively into token-analytics per-task so it
is correct for any groupBy.
2026-06-15 19:31:54 -07:00
gsxdsm
53bb1d8f37 feat(analytics): U2 — core date-range aggregators (tokens/tools/activity/productivity)
Reusable aggregate() over tasks + usage_events with model/provider/node/agent
grouping. Autonomy ratio sources interventions from approval audit events +
user-authored steers (agent steers excluded); fully-autonomous sessions report
tool-calls-per-session, never divide-by-zero. LOC/MTTR seams flagged unavailable.
2026-06-15 19:27:45 -07:00
gsxdsm
951c6ef5cd feat(signals): U11 — external signal ingestion (Sentry/Datadog/PagerDuty/webhook)
SignalSource adapter seam with mandatory HMAC verification, replay window +
nonce dedup, SSRF-safe URL handling, body-size/rate-limit/field caps, and a
groupingKey on every normalized Signal for U13's storm guard. Inbound webhooks
create triage tasks via the existing store (no schema change).
2026-06-15 19:23:23 -07:00
gsxdsm
90cfbfb4fc feat(dashboard): U4 — Command Center view shell, nav, and chart primitives
New command-center built-in view (lazy-loaded, ARIA-tabbed) with hand-rolled
CSS-bar chart primitives (Bar/StackedBar/Sparkline/Funnel), DateRangePicker,
and Overview tab. Animations use --duration-* tokens (IACVT-safe).
2026-06-15 19:23:17 -07:00
gsxdsm
ab9fdc4136 feat(telemetry): U1 — queryable usage_events table + emitUsageEvent capture
Schema migration 117→118 adds usage_events; events captured via a dedicated
emitUsageEvent seam wired through AgentLogger tool hooks + executor session
context (model/provider/nodeId), not by widening log signatures. meta is
size-capped and carries only non-sensitive descriptors.
2026-06-15 19:20:38 -07:00
gsxdsm
8051e89e74 docs(plan): Command Center dashboard + SDLC gap-fill plan 2026-06-15 19:05:15 -07:00
gsxdsm
65c49585d1 fix(review): address PR #1682 re-review (reuse concurrency + auth hardening)
- 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>
2026-06-15 14:52:58 -07:00
gsxdsm
b0bb39aa39 feat(acp): opt-in warm connection reuse across turns (OQ2)
Keep a warm bridge connection + ACP session across turns of one
conversation (gated by FUSION_CLAUDE_ACP_REUSE=1, default OFF), so
multi-turn lanes skip the cold bridge/claude spawn and session/new
round-trip and send only the latest-turn delta (buildResumePrompt).
A stable router indirection serves each turn's handlers.

Addresses the adversarial review of the reuse path:
- P0: a warm-child death routes failure to the CURRENT owner turn via
  router.fail, so a reuse turn fails fast instead of hanging until the
  30-min inactivity timeout.
- P1: eviction is cache-identity-aware (evictCachedAcpConn only deletes
  the map key when it still points at the entry), so a concurrent cold
  turn / stale close handler / idle timer can't evict or kill a newer
  live entry's child.
- P1: an empty resume delta cold-starts instead of issuing an empty
  prompt that could hang.
- P2: a per-turn token drops cross-turn stray updates on the shared
  warm connection.
- The idle reaper is unref'd so it never pins the process.

Default OFF → the cold path is functionally unchanged (reviewer-verified).
Adds multi-turn tests: reuse skips spawn+session/new, flag-off spawns
fresh, fail-fast on warm-child death, empty-resume cold fallback.
346/346 pass, tsc clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 14:38:19 -07:00
gsxdsm
031a5470bb fix(review): address PR #1682 security review (usage validation + cache tokens)
- P2: event-bridge handleMessageDelta now consumes cache_read/cache_creation
  tokens (parity with handleMessageStart) — the OQ3 usage path carried them but
  they were silently dropped, understating cost for cached turns.
- P2: validate the untrusted bridge usage payload — coerce each field to a
  finite, non-negative number before forwarding, so a malformed value
  (string/NaN/negative) can't corrupt totalTokens/cost.
- Tests: usage now asserts cache tokens + totalTokens; new cases for malformed
  usage, tool-use turns reporting zero usage, the ANTHROPIC_AUTH_TOKEN middle
  precedence, and that the auth token is read from process.env (never a
  caller-supplied value — no token substitution).
- Doc: state the auth-forwarding exposure trade-off in the code comment.

acp-driver 13/13; event-bridge tests green; typecheck clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 14:19:17 -07:00
gsxdsm
799e590e3e Merge pull request #1580 from Runfusion/feature/workflow-owned-merge-s07-completion-handoff-merge-work
refactor(workflow): S07 completion handoff creates merge work
2026-06-16 04:30:22 +08:00
gsxdsm
4e2a887422 fix(acp): import afterEach in acp-driver test (typecheck)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 13:28:43 -07:00
gsxdsm
1b5b8708a6 Merge pull request #1579 from Runfusion/feature/workflow-owned-merge-s06-git-merge-capabilities
refactor(workflow): S06 git and merge capability extraction
2026-06-16 04:28:26 +08:00
gsxdsm
d217125a90 feat(acp): wire ACP token usage (OQ3) + opt-in headless auth (R17)
- Item 2 (OQ3): capture PromptResponse.usage from conn.prompt and feed it into
  the bridge before finish(), so ACP-path turns report token usage/cost instead
  of always zero. Zero-when-absent is safe; tool-use (break-early) turns
  inherently report zero (the prompt result never resolves).
- Item 3 (R17): opt-in headless credential delivery. When
  FUSION_CLAUDE_ACP_FORWARD_AUTH=1, buildBridgeEnv forwards a SINGLE Claude auth
  token (CLAUDE_CODE_OAUTH_TOKEN > ANTHROPIC_AUTH_TOKEN > ANTHROPIC_API_KEY) from
  the operator's launch env so a detached daemon (no login Keychain) can
  authenticate. Default OFF — the secure no-secrets posture is unchanged.

acp-driver tests 9/9 (usage + the three auth-opt-in cases); typecheck clean.
Remaining: item 1 (connection reuse / resume latency).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 13:26:15 -07:00
gsxdsm
b83210b471 test(acp): cover the claude-cli status acp block + auth-failure signal (U12)
GET /providers/claude-cli/status: asserts acp.{enabled,bridgeAvailable,active,
authFailed,authReason} reflect the FUSION_CLAUDE_ACP env + the bridge auth-failure
signal file, and that acp is inactive/clean when no bridge path is published.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 13:19:10 -07:00
gsxdsm
ffef0aad6a docs(solutions): ACP bridge 'Not logged in' — thin spawn env + keychain session isolation
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>
2026-06-15 13:15:38 -07:00
gsxdsm
f816598107 Merge pull request #1681 from Runfusion/feature/acp-route-a-enable
feat(acp): enable Claude CLI via ACP bridge by default (experimental switch) + status
2026-06-16 03:51:49 +08:00
gsxdsm
dc8510447f fix(review): address PR #1681 round-2 comments
- CodeRabbit: spinner class `spin` -> `animate-spin` (matches the card's other
  Loader2 usages).
- CodeRabbit (major): tighten auth-failure detection so it only fires when the
  WHOLE turn is the short "Not logged in" message (<=80 chars), not when a long
  legitimate answer merely mentions the phrase — avoids false positives.
- CodeRabbit (major): expand the auth-signal test to assert the full invariant —
  set on a not-logged-in turn, clear (unlink) on a real response, and NOT flag a
  long answer that mentions the phrase.

pi-claude-cli acp-driver 5/5; typecheck clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 12:43:08 -07:00
gsxdsm
5696d4497f fix(review): address PR #1681 feedback (acp.active accuracy + FNXC comments)
- Greptile P2: `acp.active` now reflects the ACTUAL dispatch determinant
  (FUSION_CLAUDE_ACP, which includes the operator force-override), not the
  experimental flag alone — so the status isn't misleading when forced on/off.
- CodeRabbit/Greptile P2: add FNXC:ClaudeAcp comments to the new code blocks
  per the AGENTS.md greppable-comment convention.

Already fixed in the prior commit (daa37d08c): the P1 "sticky env" / latch
(applyClaudeAcpEnable now recomputes each call + FUSION_CLAUDE_ACP_FORCE
override) and the enable->disable-on-same-env regression test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 12:34:44 -07:00
gsxdsm
daa37d08c5 feat(acp): surface bridge auth failure in the UI with fallback / fix-auth (R17)
When the bridged `claude` can't authenticate (detached daemon / no keychain),
the turn returns "Not logged in" instead of a real answer. Rather than silently
relay that, detect it and let the user choose.

- Driver: detect a "Not logged in"-only turn and write a cross-process signal
  (fusion-acp-bridge-auth.json); a real response clears it (acp-driver test).
- Dashboard status: GET /providers/claude-cli/status reports
  acp.authFailed + authReason from the signal.
- UI: the Claude CLI provider card shows an auth-failure banner with
  "Use claude -p" (sets experimentalFeatures.claudeCliAcp=false) and
  "I fixed auth — re-test", plus a fix hint (run `claude` to log in).
- Enable resolution now recomputes each call with an operator force-override
  (FUSION_CLAUDE_ACP_FORCE), so the "Use -p" fallback takes effect on the next
  turn — no restart. claude-acp-enable tests updated.

pi-claude-cli + engine tests green; dashboard typecheck clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 12:32:00 -07:00
gsxdsm
9314d1c329 Merge pull request #1669 from Runfusion/fix/test-timeout-failures
fix(test-infra): bound test invocations with a fail-fast watchdog + CI timeouts
2026-06-16 03:23:17 +08:00
gsxdsm
2e0bcd75c4 feat(acp): U12 — surface ACP transport state in claude-cli status
GET /providers/claude-cli/status now returns an `acp` block:
{ enabled (experimental flag), bridgeAvailable (KTD10 published path), active
(enabled && acpEnabled && bridgeAvailable) } so operators can see whether Claude
CLI is routing through the ACP bridge vs `claude -p` — important for the
default-on rollout. Additive; typechecks clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 12:16:30 -07:00
gsxdsm
45184aef7e feat(acp): enable Route A via experimental flag (claudeCliAcp), default ON
Replace the manual FUSION_CLAUDE_ACP env enable with an experimental feature
switch. `experimentalFeatures.claudeCliAcp` is ON by default (off only when
explicitly set false); the engine translates it into the FUSION_CLAUDE_ACP
dispatch the pi-claude-cli provider reads, at registerExtensionProviders time.

- Still fail-closed: with no bridge path published (acp-runtime plugin absent),
  the provider falls back to `claude -p`.
- Explicit FUSION_CLAUDE_ACP env always wins (operator / test override).
- New testable helper claude-acp-enable.ts (6/6 tests); flag documented in the
  core experimentalFeatures doc.

So with the acp-runtime plugin installed, Claude CLI now routes through the ACP
bridge by default; set experimentalFeatures.claudeCliAcp=false to force `-p`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 12:14:20 -07:00
gsxdsm
2bffad1784 Merge remote-tracking branch 'origin/main' into fix/test-timeout-failures
# Conflicts:
#	scripts/test-changed.mjs
2026-06-15 12:13:40 -07:00
gsxdsm
e409f2d437 Merge pull request #1680 from Runfusion/feature/acp-route-a
feat: migrate Claude off `claude -p` to ACP runtime + bridge (Route B + U10; Route A in progress)
2026-06-16 03:08:00 +08:00
gsxdsm
642780220e chore(acp): apply subagent-review follow-ups (changeset, KTD10 tests, docs)
Two-reviewer pass (security + architecture) on KTD10 + the full Route A
increment: no code defects, no P0, merge-ready as a dormant increment. Applying
the P1 follow-ups:

- Add the feature changeset (@runfusion/fusion minor) — the one convention gap.
- KTD10 tests: fail-closed (bridge not resolved -> env stays unset -> -p) and
  idempotency (second onLoad keeps the first published path).
- Document the two intentional, parallel MCP-forwarding paths (U10 engine-adapter
  vs U11 provider-driver) so nobody double-forwards, and the known
  ACP-path-token-usage=0 residual so U12 doesn't treat it as a bug.

Reviewers confirmed: dormancy invariant holds end-to-end (nothing sets
FUSION_CLAUDE_ACP=1; both flag+path required; -p is the default); OAuth pi path
untouched. 206/206 plugin tests, 333/333 pi-claude-cli tests, typecheck clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 11:40:06 -07:00
gsxdsm
022bee5842 feat(acp): U11/KTD10 — publish bundled bridge path on plugin load
The acp-runtime plugin's onLoad now publishes the identity-pinned bundled
claude-code-cli-acp path to FUSION_CLAUDE_ACP_BRIDGE (when unset), so the
pi-claude-cli kill-switch resolves the bridge WITHOUT a manual env var — no
engine->plugin static coupling. Publishes the path only; the ACP transport stays
OFF until an operator sets FUSION_CLAUDE_ACP=1 (rollout gate). Explicit env
override wins; resolver is pinned to the plugin's node_modules/.bin shim.

204/204 plugin tests green (3 new KTD10 tests); typecheck clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 11:34:36 -07:00
gsxdsm
239bec74c4 docs(acp): record U11 tool-flow verification PASS — enablement gate cleared
Live run: forwarded MCP tools and native Bash both refuse to execute when we
return cancelled to session/request_permission (no TOCTOU). streamViaAcp's
deny-by-default + break-early is verified safe. Env allow-list (incl. XDG/USER)
validated as required for the bridged claude to authenticate.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 11:21:43 -07:00
gsxdsm
71a6c5a05f test(acp): verify kill-switch dispatch routing (U11/R9/R14)
streamSimple routes to streamViaAcp ONLY when FUSION_CLAUDE_ACP=1 AND a bridge
path is provided; otherwise stays on the -p streamViaCli path. Covers the three
cases (off / flag-without-path / flag+path) and asserts the bridge path + env
are forwarded. 333/333 pi-claude-cli tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 10:55:27 -07:00
gsxdsm
0d6b3f6660 fix(acp): apply review findings to streamViaAcp (U11)
Three-reviewer pass (correctness/security/reliability) on the highest-risk file.

P0:
- Break-early now gates on isPiKnownClaudeTool: Claude's internal ToolSearch
  (used to load deferred MCP tools) no longer aborts the turn before the real
  fn_* call. Surface+break works from both tool_call updates and
  request_permission. New test replays the U9 [ToolSearch, fn_task_list] sequence.
- Downgrade a tool_use turn that surfaced zero pi tool calls -> stop (mirrors
  provider.ts), so pi never dispatches non-existent tools.
- register the bridge child in the process registry (no orphan on teardown).
- inactivity timeout (30 min, re-armed per chunk) + per-RPC timeouts on
  newSession (a hung bridge now ends the stream and dies).

P1:
- capture bridge stderr + child 'close' handler -> surface exit code/stderr
  (no more silent, undebuggable failures).
- sanitize untrusted agent output: strip ANSI/control chars, per-chunk +
  per-turn caps, bound tool ids/names (no terminal-escape injection / DoS).
- validate bridge path (absolute + exists) before spawn.
- preserve image content blocks in the prompt (flatten-to-text dropped vision).

P2:
- enforce the bridge env allow-list INSIDE the driver (HOME/PATH/terminal only),
  not trusting the caller-supplied object.

Documented residual (kill-switch stays OFF until verified): the bridge's
tool-execution ordering and native-tool (Bash/Read/Write) execution-prevention
need a live behavioral test before any lane enables this path.

pi-claude-cli: 330/330 tests green; typecheck clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 06:17:11 -07:00
gsxdsm
85c180508c feat(acp): U11 — drive pi-claude-cli provider via the ACP bridge (kill-switch OFF)
Adds streamViaAcp: a drop-in alternative to streamViaCli that drives Claude
through the claude-code-cli-acp bridge over ACP instead of `claude -p`. Returns
the same AssistantMessageEventStream, so streamSimple dispatches to either
transport behind a kill-switch (FUSION_CLAUDE_ACP=1 + an injected bridge path),
OFF by default — the live `-p` path is byte-for-byte untouched until soak.

- Full-history prompt every turn (buildPrompt) — the ACP path has no --resume (R13).
- Forwards schema-only MCP servers so Claude emits correct tool calls; breaks
  early on the first tool_call (cancel turn, surface to pi) so the bridge never
  executes Fusion's tools — mirrors the `-p` break-early pattern.
- Translation reuses the tested createEventBridge by synthesizing Claude stream
  events from ACP session/updates, sharing pi sequencing + tool-name mapping.
- Bridge env forwards only HOME/PATH so `claude` authenticates from the login
  session (R17); never inherited process.env or API keys.

Verified: 3/3 translation unit tests; real-bridge session/update shapes confirmed
(agent_message_chunk text + tool_call); 326/326 existing pi-claude-cli tests green;
typecheck clean.

Remaining for Route A: engine injection of the bridge path (KTD10), U12 picker/
auth/status, U13 workflow verification.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 06:08:27 -07:00
gsxdsm
03d12b6289 docs(acp): record U11 implementation design (ready to execute)
Reverse-engineered the streamViaCli contract and locked the U11 build plan:
AssistantMessageEventStream shape to match, the kill-switch branch point in
streamSimple, the KTD10 injection seam (pi-claude-cli adds @agentclientprotocol/sdk;
bridge path injected like mcpConfigPath), MCP-server construction reusing
ensureMcpConfig, full-history prompting (R13), ACP->pi event translation
paralleling event-bridge.ts, and live-bridge verification via the U9 harness.

No transport change yet — the live `claude -p` path is untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 05:56:47 -07:00
gsxdsm
079844e1c1 feat(acp): forward MCP servers on session/new (U10) + record U9 GO / R17
Route A unblock + the first Route A code increment.

- U9 verdict recorded (plan OQ1 + docs/acp-contract.md): in an authenticated
  interactive session the pinned claude-code-cli-acp 0.1.1 bridge forwards
  session/new mcpServers to Claude, Claude invokes the forwarded Fusion tool,
  and the call traverses the ACP permission gate (session/request_permission).
  Both security-critical answers resolve positively — overturns the headless
  NOT-GO chain (FN-6466/6467/6473/6476), whose only blocker was running
  detached from the login keychain session.
- R17 (daemon auth) recorded and closed for the supported setup: creds are
  macOS Keychain-only; the user's login-session fn daemon has keychain access
  (the existing claude -p provider authenticates there), so the bridge does too.
- U10: thread an optional mcpServers list through the ACP runtime contract.
  newAcpSession now forwards it (was hardcoded []); AgentRuntimeOptions (engine
  + plugin-local copy) gains the field; defaults to [] to preserve Route B's
  read-only ask posture. Tool calls still route through the U5 permission floor.

Plugin typechecks clean; provider-session tests 12/12 (incl. 2 new forwarding
tests). U11-U13 (provider transport swap, picker/auth, workflow verify) remain.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 05:56:47 -07:00
gsxdsm
bc6dfd386e FN-6478: surface paused workflow graph failures
Surface stranded paused workflow exits as actionable executor failures.

- Treat paused or aborted graph exits as benign only while the live task remains in-progress.
- Preserve terminal/review lifecycle state while recording operator-actionable failure evidence for advanced columns.
- Cover user-paused, pause-aborted, existing-failure, in-progress, in-review, todo, and done column recovery paths.
- Document the workflow lifecycle invariant and add a patch changeset.

Files changed:
 .changeset/fn-6478-paused-workflow-executions.md   |   5 +
 docs/architecture.md                               |   1 +
 .../engine/src/__tests__/executor-recovery.test.ts | 283 +++++++++++++++++++++
 packages/engine/src/executor.ts                    |  30 ++-
 4 files changed, 315 insertions(+), 4 deletions(-)

Fusion-Task-Id: FN-6478

Fusion-Task-Lineage: 219d8612-6604-4dbc-9a3a-a1c7837419c1
2026-06-15 02:30:41 -07:00
gsxdsm
de8f871b4d FN-6479: index upstream ACP MCP forwarding doc
Index the upstream ACP MCP forwarding sponsorship doc so the docs README and CLI index test keep it discoverable.

- Add the upstream ACP MCP passthrough and permission forwarding sponsorship doc link under Audit Reports.
- Add the upstream doc to the required docs README index coverage.
- Guard that CLI Printing Press docs remain indexed in Audit Reports only, not duplicated under Plugins.

Files changed:
 docs/README.md                                      |  5 +++++
 .../cli/src/__tests__/docs-readme-index.test.ts     | 21 +++++++++++++++++++++
 2 files changed, 26 insertions(+)

Fusion-Task-Id: FN-6479

Fusion-Task-Lineage: f23afeba-a989-4552-8857-fe2984df6081
2026-06-15 02:30:41 -07:00
gsxdsm
56d4fd24b3 FN-6476: record ACP auth rerun blockage
Document the authenticated ACP bridge rerun attempt and preserve the Route A blocked verdict.

- Update the ACP contract with FN-6476 readiness proof results showing the pinned bridge still reports an unauthenticated Claude session.
- Keep OQ1 answers unresolved because no forwarded Fusion tool invocation or permission-gate traversal was observed.
- Add FN-6476 status notes to the Claude ACP runtime plan so U9 remains NOT GO without a claude -p fallback.

Files changed:
 docs/acp-contract.md                                      | 11 ++++++++++-
 docs/plans/2026-06-14-001-feat-claude-acp-runtime-plan.md |  3 +++
 2 files changed, 13 insertions(+), 1 deletion(-)

Fusion-Task-Id: FN-6476

Fusion-Task-Lineage: f37dcc62-9758-47af-bb50-169e902211a5
2026-06-15 02:30:41 -07:00
gsxdsm
fcca1366ef FN-6475: document ACP MCP forwarding sponsorship
Record the upstream sponsorship package for ACP MCP passthrough and permission gating while keeping Route A blocked.\n\n- Add a ready-to-file upstream issue for claude-code-cli-acp MCP passthrough and permission-forwarding support.\n- Link the filed upstream issue from the ACP contract and runtime plan.\n- Preserve the OQ1/U9 NOT GO status until authenticated reruns prove forwarded tool invocation and gating.\n\nFiles changed:\n docs/acp-contract.md                               |   5 +\n .../2026-06-14-001-feat-claude-acp-runtime-plan.md |   3 +\n ...laude-code-cli-acp-mcp-permission-forwarding.md | 121 +++++++++++++++++++++\n 3 files changed, 129 insertions(+)

Fusion-Task-Id: FN-6475

Fusion-Task-Lineage: 3cbd14e3-9388-4cf4-b256-3678459eb926
2026-06-15 02:30:41 -07:00
gsxdsm
1d474a1dff FN-6473: document Route A ACP escalation blockage
Record the authenticated Route A ACP escalation rerun and keep U9 blocked.

- Update the ACP contract OQ1 status to FN-6473 with the observed unauthenticated bridge result.
- Capture the explicit request-permission instrumentation outcome: zero forwarded tool calls and zero permission callbacks.
- Extend the Claude ACP runtime plan with the escalation status and upstream bridge/ACP permission-forwarding requirement.

Files changed:
 docs/acp-contract.md                                      | 13 +++++++++++--
 docs/plans/2026-06-14-001-feat-claude-acp-runtime-plan.md |  3 +++
 2 files changed, 14 insertions(+), 2 deletions(-)

Fusion-Task-Id: FN-6473

Fusion-Task-Lineage: 2e6ec23b-a9cd-4fd0-b24e-72ee8bb145ac
2026-06-15 02:30:41 -07:00