Mission Control

Artifacts

K
← Back to artifacts

Audit: Mission Control missing task display IDs

OtherDraftCreated Apr 8, 20264 min readFull screen ↗

Audit: Mission Control missing task display IDs

Date: 2026-04-08 15:42 PDT

Findings summary

  • Root cause confirmed: Mission Control had active write paths that could persist tasks without displayId.
  • Main UI bug: TasksWorkspace creates new tasks client-side without displayId, then saves the full task list with PUT /api/tasks. The server persisted the list as-is, and the client kept its local copy, so tasks could stay blank until a later refresh, or permanently if the data file was written that way.
  • Secondary write-path bug: scripts/capture-task.mjs wrote tasks directly to data/tasks.json without assigning a displayId.
  • Safe backfill completed: 5 existing tasks missing displayId were assigned JAM-34 through JAM-38.
  • Validation passed: storage has no missing displayId, board view renders JAM IDs, list view renders JAM IDs, task detail modal renders the backfilled JAM ID, service rebuilt and restarted cleanly.

Root cause

There were two separate causes.

1. UI create flow bypassed numbered ID assignment

File: mission-control/components/tasks/TasksWorkspace.tsx

The create flow built a local task with createTaskId() but no displayId, then saved the entire task array through PUT /api/tasks.

2. Server list writes did not normalize missing display IDs

Files: mission-control/app/api/tasks/route.ts, mission-control/lib/tasks-store.ts

PUT /api/tasks accepted a full task list and wrote it without assigning missing displayId values. The store normalized tags and inferred project IDs, but did not backfill numbering at list-write time.

3. Capture script also bypassed numbering

File: mission-control/scripts/capture-task.mjs

The CLI/chat capture path wrote directly to data/tasks.json and did not set displayId on new tasks.

Fix

Centralized display ID normalization in the task store

File changed: mission-control/lib/tasks-store.ts

Added list-level normalization that:

  • preserves every existing displayId exactly as stored
  • parses existing JAM-<number> IDs
  • finds the highest existing JAM number
  • assigns new JAM numbers only to tasks missing displayId
  • assigns in deterministic array order
  • skips collisions by tracking already-used JAM numbers

This now runs on:

  • readTasks(), which can self-heal older data on load
  • writeTasks(), which protects all list-write paths
  • createTask(), through the same numbering strategy

Fixed the UI save round-trip

Files changed:

  • mission-control/app/api/tasks/route.ts
  • mission-control/components/tasks/TasksWorkspace.tsx

Changes:

  • PUT /api/tasks now returns the normalized saved task list, not the raw request payload.
  • TasksWorkspace.persistTasks() now hydrates local state from the server response, so a newly created task gets its JAM number immediately after save.

Fixed the capture script

File changed: mission-control/scripts/capture-task.mjs

Changes:

  • new captured tasks now get a displayId
  • numbering follows the same highest-existing-JAM-plus-one rule
  • script validation now tolerates both legacy and current statuses so it can read the live task store safely
  • legacy next input maps to up-next, blocked maps to backlog with blocked: true

Backfill performed

Data file changed: mission-control/data/tasks.json Backup created: mission-control/data/tasks.json.bak-20260408-153524

Backfilled only tasks missing displayId. Existing JAM IDs were preserved exactly. No renumbering.

Assignments made:

  • task-fugalg9xJAM-34 → Improve daily notes
  • task-iwshrvaiJAM-35 → Draft Website
  • task-i7lsp651JAM-36 → Linkedin Profile Rewrite
  • task-mnnxai5i-vo40lkJAM-37 → Fix for resetting only David's #david Discord session
  • task-vj7k5d2pJAM-38 → Secure tokens

Numbering rule used:

  • highest existing valid JAM ID in the store was JAM-33
  • missing tasks were assigned sequentially from JAM-34
  • non-JAM displayId values: none found
  • duplicate JAM IDs: none found
  • remaining missing displayId values after backfill: none

Validation

Storage validation

Confirmed after backfill:

  • total tasks: 29
  • tasks missing displayId: 0
  • duplicate JAM IDs: 0
  • non-JAM displayId values: 0
  • highest persisted JAM ID: JAM-38

API validation

Validated the exact UI-style save path by sending a full-list PUT /api/tasks payload with a temporary task missing displayId. Result:

  • server assigned JAM-39 in the response
  • temporary validation task was removed immediately after
  • final persisted store returned to max JAM-38

Capture-path validation

Validated scripts/capture-task.mjs with a temporary task. Result:

  • script assigned JAM-34 when run against the pre-backfill dataset
  • temporary validation task was removed before final backfill write

UI validation

Validated against the live app after rebuild/restart.

Observed:

  • board view shows backfilled IDs, including JAM-38
  • list view shows backfilled IDs, including JAM-38
  • task detail modal opened via /tasks?task=JAM-38 and showed:
  • title: Secure tokens
  • display ID: JAM-38

Build and service refresh

  • npm run build: passed
  • Mission Control LaunchAgent restarted successfully with ./scripts/restart-mission-control.sh
  • live service remained available on port 3100 after restart

Notes

  • npm run lint still reports pre-existing unrelated issues outside this fix:
  • components/layout/AppShell.tsx: react-hooks/set-state-in-effect
  • components/tasks/TaskBoardColumn.tsx: react-hooks/refs
  • components/tasks/TaskListView.tsx: react-hooks/refs
  • warnings in lib/mc2/timeline.ts and scripts/migrate-projects.mjs
  • These did not block build or this fix.
  • Scope kept tight to numbering and immediate data/UI effects.

Exact files changed

  • /Users/vinny/.openclaw/workspace/mission-control/lib/tasks-store.ts
  • /Users/vinny/.openclaw/workspace/mission-control/app/api/tasks/route.ts
  • /Users/vinny/.openclaw/workspace/mission-control/components/tasks/TasksWorkspace.tsx
  • /Users/vinny/.openclaw/workspace/mission-control/scripts/capture-task.mjs
  • /Users/vinny/.openclaw/workspace/mission-control/data/tasks.json

Ready for review

Yes