feat: GM Workbench generation scratchpad — GenerationResult (#138) #217

Merged
claude-bot merged 1 commit from feat/138-generation-scratchpad into feat/v3.10-gm-workbench 2026-07-19 14:58:03 +00:00
Contributor

Foundation item 3/3 of v3.10.0 GM Workbench. Targets the integration branch. Builds on #134.

Closes #138.

What

The persistence + async-status layer the whole Workbench polls.

  • GenerationResult model (generation_results, migration f0a1b2c3d4e5): status TEXT + CHECK (pending/ready/failed), JSONB params/output/token_usage (none_as_null=True), campaign_id FK CASCADE, session_id/created_by SET NULL, pinned, indexes on campaign_id + (campaign_id, tool_id). token_usage captured from day one for future metering.
  • Service generation_result_service.py: create_result / mark_ready / mark_failed (the pending→ready/failed lifecycle #136's sync + Celery tools write into), list_results (filter by tool/pinned), set_pinned, delete_result, delete_expired.
  • Endpoints (campaign-scoped, GM-only): GET …/workbench/history?tool_id=&pinned=, POST …/history/{id}/pin + /unpin, DELETE …/history/{id} (404 on cross-campaign).
  • Retention: daily prune_generation_results beat task deletes unpinned rows > 30 days; pinned never swept.
  • Frontend: api/workbench.js + a minimal GenerationHistory list (pin/delete/re-open, tool filter), surfaced in CampaignPlanning — the full right-rail is #153.

Verification (Docker)

  • Backend 674 tests (+15 in test_workbench_history.py); migration f0a1b2c3d4e5 up/down/up clean against real Postgres 16; ruff check/format clean.
  • Frontend 345 tests (+5 GenerationHistory.test.jsx) + build; eslint 0 errors. (Fixed 4 tests where getByText(tool_id) was ambiguous — the id renders in both the row and the filter option; scoped to the row/action button.)
  • No migration-vs-model drift, no bot API change.

🤖 Generated with Claude Code

Foundation item 3/3 of **v3.10.0 GM Workbench**. Targets the integration branch. Builds on #134. Closes #138. ## What The persistence + async-status layer the whole Workbench polls. - **`GenerationResult` model** (`generation_results`, migration `f0a1b2c3d4e5`): `status` TEXT + CHECK (pending/ready/failed), JSONB `params`/`output`/`token_usage` (`none_as_null=True`), `campaign_id` FK CASCADE, `session_id`/`created_by` SET NULL, `pinned`, indexes on `campaign_id` + `(campaign_id, tool_id)`. `token_usage` captured from day one for future metering. - **Service** `generation_result_service.py`: `create_result` / `mark_ready` / `mark_failed` (the `pending→ready/failed` lifecycle #136's sync + Celery tools write into), `list_results` (filter by tool/pinned), `set_pinned`, `delete_result`, `delete_expired`. - **Endpoints** (campaign-scoped, GM-only): `GET …/workbench/history?tool_id=&pinned=`, `POST …/history/{id}/pin` + `/unpin`, `DELETE …/history/{id}` (404 on cross-campaign). - **Retention**: daily `prune_generation_results` beat task deletes unpinned rows > 30 days; pinned never swept. - **Frontend**: `api/workbench.js` + a minimal `GenerationHistory` list (pin/delete/re-open, tool filter), surfaced in `CampaignPlanning` — the full right-rail is #153. ## Verification (Docker) - **Backend 674 tests** (+15 in `test_workbench_history.py`); migration `f0a1b2c3d4e5` up/down/up clean against real Postgres 16; `ruff check`/`format` clean. - **Frontend 345 tests** (+5 `GenerationHistory.test.jsx`) + build; eslint 0 errors. (Fixed 4 tests where `getByText(tool_id)` was ambiguous — the id renders in both the row and the filter option; scoped to the row/action button.) - No migration-vs-model drift, no bot API change. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
The persistence + async-status layer the Workbench polls: a GenerationResult
model (migration f0a1b2c3d4e5) with campaign-scoped, GM-only history/pin/delete
endpoints, lifecycle helpers (create/mark_ready/mark_failed) for #136's sync and
Celery tools, a daily retention beat task that prunes unpinned rows > 30 days
(pinned never swept), and a minimal GenerationHistory list (pin/delete/re-open).

- Model generation_results: status TEXT+CHECK, JSONB params/output/token_usage
  (none_as_null on the nullable JSONB), campaign_id CASCADE, session_id/created_by
  SET NULL. token_usage captured from day one for future metering.
- Service generation_result_service.py owns all DB access.
- Retention task prune_generation_results registered in the Celery beat schedule.
- Frontend: api/workbench.js + a minimal GenerationHistory list (pin/delete/
  re-open), surfaced in CampaignPlanning; #153 does the full right-rail layout.

Foundation for v3.10.0 GM Workbench; #136 wires the tool registry into this.

Verified in Docker: 674 backend tests (+15), 345 frontend tests (+5), build +
ruff + eslint clean; migration up/down/up against real Postgres. No bot API change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
claude-bot merged commit 40b355a8d0 into feat/v3.10-gm-workbench 2026-07-19 14:58:03 +00:00
Sign in to join this conversation.
No description provided.