> For the complete documentation index, see [llms.txt](https://faction-os.gitbook.io/faction-os-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://faction-os.gitbook.io/faction-os-docs/.spec_system/archive/sessions/phase19-session04-campaign-workbench/code-review.md).

# Code Review and Repair Report

**Session ID**: `phase19-session04-campaign-workbench` **Package**: cross-cutting (`apps/server`, `apps/web`) **Reviewed**: 2026-06-26 **Scope**: All uncommitted changes in the working tree **Result**: RESOLVED

## Review Surface

**Files reviewed** (all uncommitted changes):

* `.spec_system/state.json` - tracked-modified
* `.spec_system/specs/phase19-session04-campaign-workbench/spec.md` - untracked
* `.spec_system/specs/phase19-session04-campaign-workbench/tasks.md` - untracked
* `.spec_system/specs/phase19-session04-campaign-workbench/implementation-notes.md` - untracked
* `.spec_system/specs/phase19-session04-campaign-workbench/code-review.md` - untracked generated report
* `apps/server/src/lib/commandCenterValidation.ts` - tracked-modified
* `apps/server/src/managers/orchestrationCommandCenter.ts` - tracked-modified
* `apps/server/src/managers/taskQueue.ts` - tracked-modified
* `apps/server/src/managers/planCampaignManager.ts` - untracked
* `apps/server/src/routes/commandCenter.ts` - tracked-modified
* `apps/server/src/routes/orchestration.ts` - tracked-modified
* `apps/server/src/server.ts` - tracked-modified
* `apps/server/tests/commandCenterRoutes.test.ts` - tracked-modified
* `apps/server/tests/planCampaignManager.test.ts` - untracked
* `apps/web/src/components/orchestration/CampaignWorkbench.tsx` - untracked
* `apps/web/src/components/orchestration/QueueWorkbench.tsx` - untracked
* `apps/web/src/components/orchestration/CommandCenterPanes.tsx` - tracked-modified
* `apps/web/src/components/orchestration/OrchestrationShell.tsx` - tracked-modified
* `apps/web/src/components/orchestration/OrchestrationTabs.tsx` - tracked-modified
* `apps/web/src/components/orchestration/index.ts` - tracked-modified
* `apps/web/src/lib/commandCenterUi.ts` - tracked-modified
* `apps/web/src/lib/orchestrationApi.ts` - tracked-modified
* `apps/web/src/store/useGameStore.ts` - tracked-modified
* `apps/web/tests/OrchestrationPanel.test.tsx` - tracked-modified
* `apps/web/tests/commandCenterStore.test.ts` - tracked-modified
* `apps/web/tests/commandCenterUi.test.ts` - tracked-modified
* `apps/web/tests/orchestrationApi.test.ts` - tracked-modified

**Inventory commands**: `git status`, `git diff HEAD`, `git diff --cached`, `git ls-files --others --exclude-standard`

## Findings by Severity

### Critical

* No findings.

### High

* `apps/server/src/managers/planCampaignManager.ts:129` - Campaign create saved user-provided task ids through an upsert path without preflighting global task-id collisions or collection capacity, so a second campaign could overwrite an existing task or leave partial orphan state if later saves failed. | Fix: Added create preflight for campaign/task capacity, duplicate ids within the draft, and existing task ids before any write. Added regression coverage for duplicate task ids. | Status: FIXED
* `apps/server/src/managers/planCampaignManager.ts:313` - Re-dispatching an already queued `in_progress` campaign with no dispatchable tasks marked the campaign `failed`, even though no queue bridge failure occurred. | Fix: Dispatch now returns a duplicate no-op response when there are no pending/failed/blocked tasks to dispatch. Added regression coverage for repeated dispatch. | Status: FIXED

### Medium

* `apps/server/src/managers/planCampaignManager.ts:214` - Refining an unknown task id was silently ignored while the campaign could still mutate, and unchanged tasks could receive revision bumps during refinement. | Fix: Unknown refinement ids now return `404`, and unchanged tasks are skipped unless direct fields or recalculated dependency metadata changed. Added regression coverage. | Status: FIXED
* `apps/server/src/managers/planCampaignManager.ts:175` - Transition reasons could persist as `blockedReason` on approved or in-progress campaigns after approve/resume, creating contradictory state. | Fix: Reasons are stored only for paused or cancelled states. Added transition reason regression coverage. | Status: FIXED
* `apps/server/src/managers/taskQueue.ts:294` - A reused queue transition idempotency key could mutate the same entry again after the entry moved to a later state. | Fix: Transition idempotency replay now returns duplicate only while the entry is still in the duplicate target state; otherwise it returns compact `duplicate_trigger`. Added regression coverage. | Status: FIXED

### Low

* `apps/web/src/components/orchestration/CampaignWorkbench.tsx:62` - The campaign draft form kept `taskSummary` state but exposed no control to edit it, and task refine controls did not disable while a refine mutation was in flight. | Fix: Added a visible task summary field, included it in preview/create payloads, and disabled refine buttons during scoped refine mutations. Added component coverage for task summary payload flow. | Status: FIXED

## Assumptions and Deliberate Non-Fixes

* The campaign create preflight mirrors the existing command-center manager collection cap of 200 because that cap is private to `OrchestrationCommandCenterManager`; using the same value keeps behavior aligned without broadening the manager API in this review pass.
* No deliberate non-fixes remain.

## Behavior Changes

* Campaign create now rejects duplicate task ids before writing any campaign or task state.
* Campaign refine now rejects unknown task ids instead of silently ignoring them.
* Campaign approve/resume no longer carry blocked reasons into active states.
* Repeated campaign dispatch with no remaining dispatchable tasks is a no-op duplicate response instead of a failure transition.
* Reused queue transition idempotency keys fail after later state changes instead of remutating the entry.
* The web campaign workbench exposes task summary editing and disables refine while the scoped refine action is in flight.

## Verification

* Tests: `npm test -- apps/server/tests/planCampaignManager.test.ts` - PASS - 7/7 tests passed.
* Tests: `npm test -- apps/server/tests/planCampaignManager.test.ts apps/server/tests/commandCenterRoutes.test.ts apps/web/tests/orchestrationApi.test.ts apps/web/tests/commandCenterUi.test.ts apps/web/tests/commandCenterStore.test.ts apps/web/tests/OrchestrationPanel.test.tsx` - PASS - 42/42 focused tests passed.
* Tests: `npm test` - PASS - 2721/2722 tests passed, 1 skipped.
* Type checker: `npm --workspace apps/server run typecheck` - PASS.
* Type checker: `npm --workspace apps/web run typecheck` - PASS.
* Type checker: `npm run typecheck --workspaces --if-present` - PASS - adapters, server, warroom, web, protocol, and public-website typechecks passed.
* Linter: `npm run lint` - PASS - Biome checked 668 files with no fixes.
* Formatter: `npm run format:check` - PASS - Biome checked 666 files with no fixes.
* Formatter: `npx biome format --write apps/server/src/managers/planCampaignManager.ts apps/server/src/managers/taskQueue.ts apps/server/tests/planCampaignManager.test.ts apps/web/src/components/orchestration/CampaignWorkbench.tsx apps/web/tests/OrchestrationPanel.test.tsx` - PASS - formatted touched repair files.
* Whitespace: `git diff --check` - PASS - no whitespace errors.
* ASCII/LF: `while ... git diff --name-only HEAD ... git ls-files --others --exclude-standard ...` - PASS - printed `ASCII_LF_OK`.
* Final diff re-read: no remaining issues found.

## Summary

1. Reviewed 27 uncommitted files across the active spec session, server campaign/queue behavior, route validation, web API helpers, Zustand cleanup, workbench UI, and tests.
2. Findings: 0 critical, 2 high, 3 medium, 1 low; all resolved with focused regression coverage.
3. No deliberate non-fixes remain.
4. Verification passed across focused tests, full tests, workspace typechecks, lint, format check, whitespace, and ASCII/LF checks.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://faction-os.gitbook.io/faction-os-docs/.spec_system/archive/sessions/phase19-session04-campaign-workbench/code-review.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
