diff --git a/CHANGELOG.md b/CHANGELOG.md
index a114f3d2..cbe8e9ae 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,6 +11,17 @@ date, grouped by `Added` / `Changed` / `Fixed` / `Removed`.
## [Unreleased]
+## [2026-07-13] — v0.10.1 · Human-action visibility
+
+### Changed
+
+- **Runtime permission pauses are now first-class decisions.** Command Center surfaces them in its priority queue with the requested command and inline approve/reject controls, counts them in the Decisions badge, and no longer mislabels a patient approval wait as a stale run that should be abandoned.
+
+### Fixed
+
+- **Human-action stalls no longer disappear when an issue is unassigned.** Issue detail resolves the real active or waiting run independently of current assignment, prioritizes permission and waiting states, and shows the same actionable permission card in the main issue flow and persistent agent rail.
+- **Approval state now refreshes every related surface reliably.** Connector approval capture and resolution write a deduplicated run event plus an audited activity event carrying the issue context, so Mission Control, Command Center, and issue detail converge over realtime updates. Open issue-bound asks created outside comments are also visible on the issue.
+
## [2026-07-13] — v0.10.0 · Rich issue rendering & delivery-safe goals
### Added
diff --git a/DEVLOG.md b/DEVLOG.md
index d40e7539..84e0edb0 100644
--- a/DEVLOG.md
+++ b/DEVLOG.md
@@ -2,6 +2,33 @@
> Append-only session log. Read at session start. Update at session end.
+## 2026-07-13 — AXI-102 human-action visibility
+
+Traced AXI-102 from production: its intentionally unassigned Backlog issue had
+a valid Victor RESEARCH run in WAITING with a connector permission request,
+but no ActionRequest, notification, or approval-specific activity event. The
+floating agent overlay read the run directly; Command Center's priority queue
+only understood ActionRequests/recovery/gates; and issue detail rejected the
+run because it did not match `Issue.assignedAgentId`.
+
+Made runtime approvals a first-class Command Center decision with inline
+approve/reject controls and badge counts. Issue detail now resolves live runs
+from the issue relationship rather than mutable assignment, prioritizes
+approval/waiting work, renders the approval in the main flow and rail, and
+surfaces open issue-bound asks that were created outside a comment. Approval
+waits are excluded from generic stale recovery instead of recommending an
+incorrect abandon action.
+
+Added an atomic approval lifecycle boundary: poll and subscription producers
+deduplicate capture, late subscription detail enriches poll-first records,
+and capture writes both the run event and audited/realtime BLOCKED event with
+issue context. Provider and operator resolution races similarly produce one
+refresh event.
+
+Verification in progress for v0.10.1. Targeted approval, recovery, Command
+Center, event-rollup, and unassigned-issue coverage is green (**23 passed**);
+lint and typecheck are green with existing repository warnings only.
+
## 2026-07-13 — Rich-rendering recovery + human delivery acceptance
Recovered the six AXI-95–99 rich-rendering commits from the stale Codex bridge
diff --git a/package.json b/package.json
index f377cc0a..5c80ec06 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "forge",
- "version": "0.10.0",
+ "version": "0.10.1",
"private": true,
"description": "Forge — a fast, minimalist, keyboard-driven project management platform with pluggable agents.",
"license": "MIT",
diff --git a/src/app/(app)/w/[slug]/command-center/page.tsx b/src/app/(app)/w/[slug]/command-center/page.tsx
index bbea5352..38d2c6e8 100644
--- a/src/app/(app)/w/[slug]/command-center/page.tsx
+++ b/src/app/(app)/w/[slug]/command-center/page.tsx
@@ -26,6 +26,7 @@ import { Button } from "@/components/ui/button";
import { Picker } from "@/components/ui/modal";
import { EmptyState, SkeletonList } from "@/components/ui";
import { AgentAttentionPanel } from "@/components/agent-attention-panel";
+import { RunApprovalCard } from "@/components/agents/run-approval-card";
import { WorkspaceActivityTimeline } from "@/components/workspace-activity-timeline";
import { trpc } from "@/lib/trpc";
import { useWorkspace } from "@/hooks/use-workspace";
@@ -108,6 +109,16 @@ export default function CommandCenterPage() {
counts: { ...prev.counts, reviewGates: Math.max(0, prev.counts.reviewGates - 1) },
});
};
+ const dropRuntimeApproval = (id: string) => {
+ const prev = utils.commandCenter.summary.getData(summaryInput);
+ if (!prev) return;
+ const runtimeApprovals = prev.runtimeApprovals.filter((run) => run.id !== id);
+ utils.commandCenter.summary.setData(summaryInput, {
+ ...prev,
+ runtimeApprovals,
+ counts: { ...prev.counts, runtimeApprovals: runtimeApprovals.length },
+ });
+ };
const dropRunFailures = (ids: string[]) => {
const prev = utils.commandCenter.summary.getData(summaryInput);
if (!prev) return;
@@ -142,10 +153,14 @@ export default function CommandCenterPage() {
},
});
const attentionCount = data
- ? data.actionRequests.length + data.reviewGates.length + data.stalledRuns.length
+ ? data.actionRequests.length +
+ data.runtimeApprovals.length +
+ data.reviewGates.length +
+ data.stalledRuns.length
: 0;
const activeAttentionGroups = data
? Number(data.actionRequests.length > 0) +
+ Number(data.runtimeApprovals.length > 0) +
Number(data.stalledRuns.length > 0) +
Number(data.reviewGates.length > 0)
: 0;
@@ -156,7 +171,7 @@ export default function CommandCenterPage() {
title="Command Center"
subtitle={
data
- ? `Decisions & live agent ops · ${data.counts.actionRequests} asks · ${data.counts.reviewGates} gates · ${data.counts.activeRuns} active runs`
+ ? `Decisions & live agent ops · ${data.counts.actionRequests} asks · ${data.counts.runtimeApprovals} approvals · ${data.counts.reviewGates} gates · ${data.counts.activeRuns} active runs`
: "Decisions & live agent ops"
}
/>
@@ -208,6 +223,22 @@ export default function CommandCenterPage() {
))}
) : null}
+ {data.runtimeApprovals.length > 0 ? (
+
+ {data.runtimeApprovals.map((run) => (
+ dropRuntimeApproval(run.id)}
+ />
+ ))}
+
+ ) : null}
{data.stalledRuns.length > 0 ? (
- void;
+}) {
+ const utils = trpc.useUtils();
+ const href = `/w/${run.issue.workspace.slug || slug}/i/${run.issue.workspace.key}-${run.issue.number}`;
+ return (
+