Address PR review feedback (#1694)
- TaskChatTab: add FNXC:TaskDetailChat prefix/date to the ephemeral active-session comment, matching the file's comment convention. - useModalManager: clear stale planning/subtask resume-session id (and initial plan) when opening a fresh planning/subtask flow, so the modal no longer reopens into a prior session. - boardWorkflowsCache: validate cached workflow item shape (id/name/ columns) and taskWorkflowIds value types so a malformed cache entry can't pass and later crash Board on render. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -177,6 +177,7 @@ function isActiveAgentSession(task: Task | TaskDetail, opts: { sessionLive?: boo
|
||||
const statusAllowsReviewSteering = !task.status || REVIEW_STEERABLE_STATUSES.has(task.status);
|
||||
const columnAllowsSteering = (task.column === "in-progress" && statusAllowsProgressSteering)
|
||||
|| (task.column === "in-review" && statusAllowsReviewSteering);
|
||||
// FNXC:TaskDetailChat 2026-06-20-20:10:
|
||||
// In the default ephemeral-agents mode the scheduler never writes
|
||||
// `assignedAgentId`/`checkedOutBy` — those are only set when
|
||||
// `ephemeralAgentsEnabled === false` (scheduler.ts). An actively-executing
|
||||
|
||||
@@ -234,10 +234,19 @@ export function useModalManager(options: UseModalManagerOptions): ModalManager {
|
||||
}, []);
|
||||
|
||||
const openPlanning = useCallback(() => {
|
||||
// FNXC:PlanningModals 2026-06-20-20:10:
|
||||
// A fresh planning open must clear any resume-session id / initial plan left
|
||||
// by a prior resumePlanning/openPlanningWith* flow; otherwise the modal reopens
|
||||
// into the stale session or pre-fills an old plan instead of starting blank.
|
||||
setPlanningResumeSessionId(undefined);
|
||||
setPlanningInitialPlan(null);
|
||||
setPlanningWorkflowId(undefined);
|
||||
setIsPlanningOpen(true);
|
||||
}, []);
|
||||
const openPlanningWithInitialPlan = useCallback((initialPlan: string, workflowId?: string | null) => {
|
||||
// FNXC:PlanningModals 2026-06-20-20:10: clear a stale resume-session id so the
|
||||
// supplied initial plan is honored rather than being overridden by an old session.
|
||||
setPlanningResumeSessionId(undefined);
|
||||
setPlanningInitialPlan(initialPlan);
|
||||
setPlanningWorkflowId(workflowId);
|
||||
setIsPlanningOpen(true);
|
||||
@@ -262,6 +271,9 @@ export function useModalManager(options: UseModalManagerOptions): ModalManager {
|
||||
}, []);
|
||||
|
||||
const openSubtaskBreakdown = useCallback((description: string, workflowId?: string | null) => {
|
||||
// FNXC:PlanningModals 2026-06-20-20:10: clear a stale subtask resume-session id
|
||||
// so a new breakdown starts fresh rather than reopening a prior session.
|
||||
setSubtaskResumeSessionId(undefined);
|
||||
setSubtaskInitialDescription(description);
|
||||
setSubtaskWorkflowId(workflowId);
|
||||
setIsSubtaskOpen(true);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { BoardWorkflowsPayload } from "../api";
|
||||
import type { BoardWorkflowDefinition, BoardWorkflowsPayload } from "../api";
|
||||
|
||||
const BOARD_WORKFLOWS_CACHE_PREFIX = "fusion:board-workflows:";
|
||||
const DEFAULT_PROJECT_CACHE_KEY = "default";
|
||||
@@ -17,6 +17,20 @@ function isBoardWorkflowsPayload(value: unknown): value is BoardWorkflowsPayload
|
||||
if (!Array.isArray(value.workflows)) return false;
|
||||
if (typeof value.defaultWorkflowId !== "string") return false;
|
||||
if (!isRecord(value.taskWorkflowIds)) return false;
|
||||
// FNXC:BoardWorkflows 2026-06-20-20:10:
|
||||
// Validate each cached workflow's shape and the taskWorkflowIds value types,
|
||||
// not just the container types. A malformed entry (e.g. `[{}]` from a stale or
|
||||
// partially-written cache) would otherwise pass and later throw in Board/ListView
|
||||
// when accessing workflow.name/columns — re-introducing the legacy flash this
|
||||
// cache exists to prevent. Mirrors the BoardWorkflowDefinition contract (id, name,
|
||||
// columns) and the Record<string,string> taskWorkflowIds map.
|
||||
if (!value.workflows.every((workflow): workflow is BoardWorkflowDefinition => (
|
||||
isRecord(workflow)
|
||||
&& typeof workflow.id === "string"
|
||||
&& typeof workflow.name === "string"
|
||||
&& Array.isArray(workflow.columns)
|
||||
))) return false;
|
||||
if (!Object.values(value.taskWorkflowIds).every((workflowId) => typeof workflowId === "string")) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user