feat: ✨ targets system — full implementation with two-stage evaluation, topic queue, and UI#72
Merged
feat: ✨ targets system — full implementation with two-stage evaluation, topic queue, and UI#72
Conversation
Wizard (Change 1):
- CardSelect supports multiSelect prop (toggle cards on/off)
- WizardData.strategyIds is now string[] (was single string)
- Primary strategy (first selected) drives voice/audience customization
- Secondary strategies written with template defaults
- Voice/Audience steps show "(for {strategy name})" label
- Summary lists all with "(primary)" badge
- isSkippable checks all selected, not just first
CLI (Change 2):
- --strategy / -s flag (repeatable) on quickstart. Default: building-public
- --branch / -b flag sets trigger_branch after registration
- Validates strategy IDs against known templates (excludes "custom")
- Writes all strategies to content_strategies with template defaults
- strategies + trigger_branch in JSON output
- Help text with usage examples
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Small dot next to "Social Hook" in nav bar. Activates after 5s of sustained pipeline/task events (avoids flashing on quick ops), fades out 5s after last event or on task completion. CSS transitions for smooth fade-in/fade-out. Links to /system page. Uses existing useGateway().addListener pattern from slow-task-banner. Listens for both pipeline stage events and task lifecycle events. CSS-only animation via Tailwind animate-ping + opacity transitions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Moved from left (next to logo) to center of nav bar. Now fully hidden (opacity-0 + pointer-events-none) when idle — only fades in after a background task runs for 5+ seconds. No idle dot visible. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Use absolute positioning (left-1/2 top-1/2 -translate) on the nav element (now position:relative) so the dot is dead center regardless of logo/link widths. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The cleanup query looked for 'evaluating' which was removed from the enum — decisions stuck in 'processing' were never cleaned up on restart. Now uses DecisionType.PROCESSING.value for all transient decision states. Also fixed response status on suggestion evaluate endpoint (was still returning 'evaluating' instead of 'processing'). Moved DecisionType to top-level import in server.py. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Error feed: Copy button on each error entry copies severity, message, component, source, timestamp, and context to clipboard via useToast - Activity indicator: polls /api/tasks?status=running on mount so the animation shows immediately after page refresh if a task is running (previously only activated via WebSocket events) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ages Pipeline stage events (analyzing, evaluating, drafting) fire multiple times per task without matching completion signals, so the counter incremented but never decremented. Now only tracks task entity started/completed/failed which have a proper 1:1 lifecycle. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wire the full topic-to-drafter pipeline: content source resolution (previously dead code) now flows through to the drafter prompt, topic_id and arc_id are set on Draft objects, and topic status transitions happen at posting time instead of draft creation. - Show topic IDs + descriptions in evaluator prompt (Fix 1) - Wire resolved content source through 6-point drafting chain (Fix 2) - Auto-include topic in context_source when topic_id set (Fix 3) - Thread topic_id, arc_id, cycle_id to Draft constructor (Fix 4, 14) - Move topic status transitions to posting time (Fix 5) - Validate topic_id belongs to strategy (Fix 6) - Store hold_reason on topics with atomic update_topic_hold (Fix 7) - Add batch evaluate endpoint, CLI command, and frontend (Change 1) - Server-side sort/filter on decisions endpoint (Change 2) - Batch grouping visual with indigo headers (Change 4) - CLI parity: batch-evaluate + batch grouping (Change 5) - Extract delete_drafts_for_decision to eliminate 3x duplication Migration: arc_id on drafts, hold_reason on content_topics, idx_drafts_topic_id index. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…-call variants Preview drafts were written as X free-tier threads regardless of config because the drafter received no platform constraints. Shared group drafting used a "lead platform" string-adapt pattern instead of the designed single-call multi-variant approach. - Drafter always includes tier/char-limit in platform description - Generic preview (no platform) gets explicit "no constraints" guidance - User message uses platform_config.name not raw target name - Add PlatformVariant model + variants field to CreateDraftInput - Multi-platform user message with per-platform tier/intro context - Rewrite _draft_shared_group: one LLM call, extract variants per platform - Delete _pick_lead_platform, _adapt_content_for_platform, _unthread_content - Add "Other Platforms / Preview" + "Multi-Platform Variants" to drafter.md Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…e collision
Strategy validation in _parse_targets only checked config.content_strategies,
rejecting built-in templates like 'technical-deep-dive' that are valid
strategies shown in the UI. Now checks both config overrides and
STRATEGY_TEMPLATES.
Auto-generated target names now include strategy to prevent collisions:
{account}-{strategy}-{destination} instead of {account}-{destination}.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…g decision The batch evaluate endpoint passed all selected decisions as deferred AND used the first one as trigger_commit_hash, causing duplicate hashes and a UNIQUE constraint violation. Now the last decision is the trigger (with existing_decision_id set so _run_targets_path reuses the row) and the rest are deferred. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add --limit / -n option to import-commits CLI and limit param to web API (import-preview + import-commits). Returns the N most recent commits when set. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Import history modal now has a Limit field — restricts import to the N most recent commits. Preview updates live as limit changes. Reasoning column truncates in collapsed rows, shows full text in expanded detail section. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The trigger commit in a batch evaluation was not getting batch_id set, so it appeared outside the batch group in the UI. Now all decisions in a batch (deferred + trigger) share the same batch_id. Also fix React crash when content_source is an object (ContextSourceSpec) instead of a string — render the types array as comma-separated text. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Paid tier guidance now explicitly tells the drafter to take advantage of the 25K char limit with rich, detailed content. Prefer single flowing posts over threads. Intro posts emphasize substance and depth. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ation Move batch membership marking from post-hoc (after _run_targets_path) to Phase A (cycle creation) and Phase E (decision creation). Deferred decisions show "Batched" immediately instead of staying as "Processing" until drafting finishes. - Add TargetsPathResult dataclass (exit_code, cycle_id, decision_id) - _run_targets_path returns TargetsPathResult instead of int - Deferred decisions get batch_id in Phase A (cycle creation) - Trigger decision gets batch_id in Phase E (after decision insert) - Remove mark_decisions_processing from evaluate_batch (redundant) - Delete post-hoc batch marking block (get_recent_cycles re-query) - Add error recovery: clear batch_id on pipeline failure - Add DECIDING pipeline stage (decision creation + arc + queue actions) - Replace _val() with enum_value() from parsing.py Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Auto-discovery (brief creation + stale refresh) was inline in run_trigger, missing from batch evaluate, CLI batch-evaluate, and scheduler drain. Extracted as ensure_project_brief() called from all four evaluation paths. Fresh projects now get a brief regardless of evaluation entry point. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Background tasks can now emit named stages via ops.emit_task_stage(). Frontend useBackgroundTasks tracks current_stage/stage_label in-memory from SSE events. Per-row buttons show stage labels with timers during batch evaluation and retrigger. Backend: - emit_task_stage() in operations.py (thin wrapper over emit_data_event) - task_id on TriggerContext + run_trigger for stage tracking - Pipeline stages (ANALYZING, EVALUATING, DECIDING, DRAFTING) emit both pipeline events (toasts) and task stage events (per-task progress) - Mutable holder pattern for passing task_id to blocking closures Frontend: - DataChangeEvent gains stage/stage_label fields - BackgroundTask gains current_stage/stage_label/stage_started_at - useBackgroundTasks handles "stage" action in-memory, preserves during refresh - Per-row buttons use batch task stage for label and timer Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The "N pending" / "N posted" text in the evaluation cycles status column is now a clickable link to the drafts page filtered by project. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rom commit column Reasoning was duplicated in the expanded commit detail section and truncated by max-w-[300px] in the reasoning column. Removed the duplicate box and the width constraint so reasoning displays fully when the row is expanded. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…truncation Reasoning was truncated to 500 chars before DB storage — removed the limit so full per-strategy reasoning is preserved. Added ExpandableText component (ui/) for table cells that clamp to 3 lines collapsed and wrap fully when expanded. Applied to reasoning and angle columns. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Targets with an account but no OAuth tokens (no credentials set up) were not getting preview_mode=True. Now checks oauth_tokens table — if the account has no tokens, the draft is in preview mode. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Preview mode now triggers when a target's account has no OAuth tokens in the DB (per-account check, not per-platform). Diagnostics also report preview mode when account exists but has no credentials. The accounts_with_creds set is built from oauth_tokens at the caller level (trigger.py for diagnostics, drafting.py for preview_targets) to keep diagnostic checks as pure functions per CODING_PRACTICES. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All 4 bot handler LLM calls (Gatekeeper, Expert escalation, angle redraft, media spec) now run via _run_background_task instead of blocking the HTTP/WebSocket response for 5-60s. Backend: - handle_message + handle_callback accept optional task_id - Stage events emitted before each LLM call (routing, thinking, redrafting, generating) using locally-scoped connections - /api/message always returns 202 (all messages go through background) - /api/callback returns 202 for LLM actions (media_gen_spec), sync for non-LLM (approve, reject, schedule) - WebSocket send_message dispatches to background task with deferred ack containing task_id Frontend: - sendMessage/sendCallback return types include optional task_id - button-row.tsx guards against undefined events on 202 responses Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
draft-action-panel.tsx: wires useBackgroundTasks for edit_angle and other text prompts. onTaskCompleted clears pending state and refreshes draft. Failed tasks show error message. chat-panel.tsx: tracks chat background tasks via gateway ack envelope with task_id. Listens for task completion/failure events. Shows toast on failure. Keeps sending=true until task completes (not on send). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…per, reuse conn - Fix critical stale closure: chatTaskId changed from useState to useRef so the gateway listener always reads the current value - Extract _dispatch_chat_message() shared by /api/message and WebSocket - Use db.conn for emit_task_stage in _handle_expert_escalation instead of opening a separate connection - Move generate_id import inside LLM branch of /api/callback Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The Confirm button and text input disappeared immediately after clicking because handleTextSubmit cleared textPrompt/submenu in the finally block. Now the UI stays in loading state until onTaskCompleted fires — the user sees the Confirm button disabled with actionPending while the LLM works. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…iately promoteDraft() always returns a task_id (LLM pipeline work) but the handler was ignoring it and clearing loading state in finally. Now tracks via useBackgroundTasks — loading persists until the promote task completes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
# Conflicts: # src/social_hook/models/__init__.py # src/social_hook/parsing.py # src/social_hook/topics.py # src/social_hook/trigger.py # src/social_hook/web/server.py # tests/test_drafting_adapt.py # tests/test_drafting_shared_group.py # tests/test_phase6_pipeline.py
Develop added 500-char truncation to _combine_strategy_reasoning(). Our branch deliberately keeps full reasoning — truncation loses per-strategy context that operators need for decision review. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Develop's decomposition of trigger.py into submodules lost our emit_task_stage calls in evaluate_batch(). These track "analyzing" and "evaluating" stages for the frontend progress indicator. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
- Regenerate site-docs/cli/ for --strategy and --branch quickstart flags - Fix trigger_batch.py:259 mypy error: annotate exit_code as int Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tests derived from TARGETS_DESIGN.md cross-referenced with coverage gaps. Focus on behaviors that catch real bugs, not trivial plumbing. Interval gating (4 tests): - Deferral when count < threshold - Evaluation at threshold - Minimum clamp (interval=0 → always evaluate) - No config defaults to evaluate Topic queue (7 tests): - Dismissed topics excluded from tag matching - Dismissed topics not recreated by seeding - Strategy-scoped seeding (positioning vs code-driven) - Draft Now accepts uncovered, rejects dismissed - Granularity gating (routine blocked at low, notable passes) Evaluator prompt (3 tests): - Diff excluded when analysis present - Diff included without analysis - Empty strategies raises ConfigError Config validation (3 tests): - Invalid topic_granularity raises ConfigError - Valid values accepted - Default is "low" Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
8 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Complete targets system implementation: multi-account, multi-destination content flows with per-target content strategies. 177 commits, 310 files changed, +47K lines.
Two-Stage Evaluation Architecture
AnalyzerOutcomewithshould_evaluatefield. Commits deferred withprocessed=1(invisible to scheduler drain). Stage 2 only runs when threshold crossed.Topic Queue Overhaul
Core Pipeline (Phases 1-6)
Interfaces
Infrastructure
Merge with develop
Test plan
🤖 Generated with Claude Code