Conversation
…ter registry Drop OAuth 1.0a for X entirely. All X API calls now use OAuth 2.0 Bearer tokens. This fixes media uploads (OAuth 1.0a media IDs rejected by v2) and prepares the adapter layer for the targets feature. - New oauth_tokens DB table for per-account user tokens - New adapters/auth.py: shared token refresh with SQLite serialization - XAdapter rewrite: Bearer auth, 401 retry with injected refresher - AdapterRegistry: process-scoped adapter cache in scheduler - Factory reads tokens from DB, env vars reduced from 4 to 2 - Setup wizard updated for OAuth 2.0 (client ID + secret, PKCE flow) - Section U E2E overhaul: post-media, thread, quote scenarios, capability exercise registry, --pause on all live posts, platform discovery from config instead of hardcoded list - Test PNG replaced with 100x100 (X rejects tiny images) - Remove requests-oauthlib dependency Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Matches the X Developer Portal callback URL configuration. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The E2E harness creates an isolated temp environment with a fresh DB. Tokens from oauth2_setup.py are in the user's real ~/.social-hook/social-hook.db. Copy them into the harness DB when running --live so adapters can authenticate. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…in Section U The audience_introduced column was removed in a prior migration, replaced by the platform_introduced table. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Config model: platform_credentials, accounts, targets, strategies expansion in config.yaml. New config/targets.py with AccountConfig, TargetConfig, PlatformCredentialConfig, PlatformSettingsConfig, and validation. Backward compat auto-migration from legacy platforms config. commit_analysis_interval and pending_drafts_cap added to ContextConfig. DB schema: content_topics, content_suggestions, evaluation_cycles, draft_patterns, system_errors tables. New columns on drafts (target_id, evaluation_cycle_id, topic_id, suggestion_id, pattern_id), posts (target_id, topic_tags, feature_tags, is_thread_head), projects (brief_section_metadata). Adapter registry: extended with get_for_account() for multi-account keying. Factory gains create_adapter_from_account() and resolve_platform_creds(). auth.py gains on_error callback. LinkedInAdapter gains token_refresher + 401 retry. System error feed: DB-backed ErrorFeed with severity routing, in-memory cache fallback, module-level singleton. Wired into scheduler via _ensure_error_feed(). Integration: target_id branching in _post_draft(), error feed wiring in scheduler_tick(), target_id propagation to Post records. Quality: _tick_single_draft uses record_post_success (no duplication), redundant arc query eliminated, dead constants removed, consistent sqlite3 timeout=5 across auth.py and error_feed.py. 2495 tests pass, 0 failures. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ief) Two-stage evaluation: StrategyDecisionInput replaces TargetDecisionInput. Evaluator reasons per-strategy. ContextSourceSpec tells routing layer what context to assemble for drafter. Freeform tags: EpisodeTypeSchema enum removed. Content filter gate removed. Strategy post_when/avoid replaces filter as gating mechanism. Project brief: llm/brief.py with structured sections, incremental updates, operator-edit preservation via per-section metadata. ContentSource registry: 4 built-in resolvers (brief, commits, topic, operator_suggestion). Evaluator specifies sources, routing assembles. Target routing: routing.py with route_to_targets(). Primary first, dependents last. Draft sharing via groups. Pipeline rewiring: trigger.py iterates strategies when targets config exists. Evaluation cycles, tag-to-topic matching, brief updates. Full backward compat for legacy config. Quality cleanup: dead skip_content_filter chain removed, dead episode_type extraction removed, lint fixes applied. 2597 tests pass, 0 failures. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Arcs rework: strategy-scoped with PROPOSED lifecycle. Added strategy and reasoning fields. propose_arc(), activate_arc(), abandon_arc(). Max arcs per-strategy configurable via max_arcs_per_strategy. Topic queue: topics.py with seed_topics_from_brief(), match_tags_to_ topics(), get_evaluable_topics(), force_draft_topic(). Discovery seeds product-level topics after brief generation. Operator suggestions: suggestions.py with create_suggestion(), evaluate_suggestion(), dismiss_suggestion(). run_suggestion_trigger() in trigger.py. Quality: unused imports removed, dead variable cleaned, lint fixes. 2670 tests pass, 0 failures. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Brand-primary template: new strategy template for high-level marketing content. get_template_defaults() for strategy reset support. Brand-primary candidate operations: combine_candidates() merges 2+ held topics into single draft. trigger_hero_launch() assembles full project context for hero-level content. Cross-account scheduling: _check_cross_account_gap() with ~33% fixed jitter. Integrated into both normal and post-now scheduler paths. Notification grouping: notify_evaluation_cycle() groups per cycle. Interactive buttons: Expand All, Approve All, per-draft View, arc Approve/Dismiss. Backward compat with legacy notifications. LinkedIn entity: personal profile vs organization page posting via entity parameter. Org admin validation, factory pass-through. 2753 tests pass, 0 failures. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CLI: 9 new command groups — credentials, account, target, strategy, topics, brief, content, cycles, system. 85 tests. Web API: ~30 new endpoints matching all CLI commands. LLM ops via background tasks + 202. check_unknown_keys(strict=True). 74 tests. Web UI: 11 new components — evaluation cycles, topic queue, brief editor, content suggestions, error feed, settings pages. Uses AsyncButton, useBackgroundTasks, useDataEvents. 2912 tests pass, 0 failures. tsc clean. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Wire evaluate_suggestion() and force_draft_topic() with full LLM evaluation pipeline. Wire 3 web API endpoints (draft-now, combine, hero-launch) to actual backend functions. Add __post_init__ validation to ContentTopic/ContentSuggestion. Add ARC_STATUSES. Remove dead EpisodeType enum. Add Approve All button to evaluation cycles UI. 2912 tests pass, 0 failures. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Fix /api/projects/{id}/targets returning dict-of-dicts instead of
array. Auto-generate target name. Fix UI destination options.
2912 tests pass, 0 failures.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
## X Adapter Migration
- Drop OAuth 1.0a, all X API calls use OAuth 2.0 Bearer tokens
- New oauth_tokens DB table for per-account user tokens
- New adapters/auth.py: shared token refresh with SQLite serialization
- XAdapter: Bearer auth, 401 retry with injected refresher callback
- AdapterRegistry: process-scoped adapter cache in scheduler
- Factory reads tokens from DB, env vars reduced from 4 to 2
- Remove requests-oauthlib dependency
## Generic OAuth Web Flow
- OAuthPlatformConfig registry in setup/oauth.py (X + LinkedIn)
- Server endpoints: /api/oauth/{platform}/authorize, callback, status, disconnect
- Frontend: Connect/Disconnect/Re-authorize for any OAuth platform
- Reusable <Note> component (ui/note.tsx) with warning/info/success/error variants
- Callback URL derived from server (not frontend port)
- postMessage notification from callback popup to opener
## CLI & Setup
- Inline PKCE flow in setup wizard (no separate script needed)
- Setup wizard prompts for 2 fields (Client ID + Secret), not 4
- social_hook/terminal.py: shared getch(), copy_to_clipboard(), pause_with_url()
- TUI select uses physical line tracking (fixes wrapping bug)
- Auto npm install on social-hook web if node_modules missing
## E2E Testing
- Section U overhaul: post-media, thread, quote, reply exercises
- Capability exercise registry for future extensibility
- --pause on all live-posting scenarios with [c] copy URL
- Per-scenario selection: --only U-x-post-media,U-x-quote
- Platform discovery from config (not hardcoded list)
- Token copy from real DB for --live mode
- VCR record mode: always re-record on --live
- Test PNG replaced with 100x100 (X rejects tiny images)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- test_oauth.py: run_pkce_flow happy path + error cases, _exchange_code, _save_tokens - test_terminal.py: copy_to_clipboard, getch, pause_with_url - test_adapters_platform_factory.py: create_adapter for X (DB tokens), LinkedIn, errors - test_adapters_x.py: validate/delete/upload 401 refresh retry Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
feat: OAuth 2.0 migration, generic web OAuth, E2E overhaul
First docs maintenance loop run. Enriched help text for under-documented commands so both --help and the auto-generated CLI reference explain what each command actually does, when to use it, and include examples. Commands improved: - quickstart, trigger, scheduler-tick, consolidation-tick - discover, web, test - draft approve/cancel/retry/schedule/quick-approve Also adds site-docs/DOC_STATUS.md for tracking doc coverage. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Generic maintenance loop agent (.claude/agents/maintenance-loop.md) that diffs a branch from last run, performs autonomous work, flags new work for approval, and creates PRs. Works in both local and remote environments (detects gh availability). Includes docs-maintenance config (.claude/loops/docs-maintenance.yml) as the first concrete use case. Un-ignores .claude/agents/ and .claude/loops/ so remote agents can read them from the repo. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New helper: scripts/e2e/helpers/time_travel.py with backdate_recent_records() and capture_timestamp() for simulating time passage in E2E scenarios without waiting. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New helper: scripts/e2e/helpers/decisions.py with get_latest_evaluation(), format_evaluation_summary(), and assert_strategy_actions() for structured evaluator output inspection. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… drafting Replace the synthetic "preview" platform with preview mode on real platforms. Targets can now omit account (setting platform directly) to draft with real constraints without a connected OAuth account. Key changes: - TargetConfig.account optional, new platform field + resolve helpers - Strategies wired to evaluator at all 5 call sites - preview_mode DB column replaces draft.platform=="preview" checks - draft connect command links an account to enable posting - Single drafter call per strategy group (shared_group mode) - Wizard/quickstart use real X platform, no more preview option - Legacy platform-based drafting path gets deprecation warning Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
# Conflicts: # scripts/e2e/sections/platform_posting.py # scripts/oauth2_setup.py # src/social_hook/adapters/auth.py # src/social_hook/adapters/platform/factory.py # src/social_hook/adapters/platform/registry.py # src/social_hook/config/yaml.py # src/social_hook/db/schema.py # src/social_hook/scheduler.py # src/social_hook/setup/wizard.py # tests/test_adapter_registry.py # tests/test_adapters_auth.py # tests/test_adapters_x.py # tests/test_db.py # tests/test_setup_wizard.py # web/src/components/ui/note.tsx # web/src/components/wizard/step-credentials.tsx # web/src/lib/api.ts
…e OAuth test - Settings sections (credentials, accounts, strategies, targets, platform-settings) now convert API dict responses to arrays - Fix React rendering 0 from integer && JSX pattern (!!coerce) - Filter legacy "preview" platform from settings grid - Add preview-mode / connected badge to platform cards - Remove stale /api/accounts/oauth-callback test (replaced by generic OAuth) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Fix 12 mypy errors: TargetAction enum usage in routing, str|None annotations, exception variable scoping, Any return types - Regenerate site-docs/cli/ for new draft connect command and targets command groups (account, brief, content, etc.) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- credentials.py: rename shadowed variable 'missing' - registry.py: type _adapters dict as dict[str, PlatformAdapter] - test_targets_db.py: use relative path for migrations dir (was hardcoded to worktree path, fails in CI) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New test files: - test_cli_target.py (22) — list, add, disable, enable - test_cli_account.py (27) — list, add, validate, remove - test_cli_credentials.py (26) — list, add, validate, remove - test_cli_content.py (22) — suggest, list, dismiss, combine, hero-launch - test_api_connect.py (13) — draft connect + promote endpoints - test_drafting_shared_group.py (16) — lead selection, unthread, shared group - test_drafting_adapt.py (10) — cross-platform adaptation - test_trigger_coverage.py (6) — strategy wiring, legacy path - test_topics_coverage.py (15) — resolve_default_platform, force_draft - test_suggestions_coverage.py (11) — create, dismiss, evaluate Updated: - test_draft_cli.py (+12) — draft connect command - server.py — fix connect endpoint check_unknown_keys error handling Total: 2963 → 3139 tests (+180) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
docs: enrich CLI docstrings and add DOC_STATUS tracking
- /api/projects/{id}/cycles now returns trigger (human-readable),
strategies (per-strategy decision/reasoning/draft), and status
(derived from draft statuses) — previously only raw DB fields
- Evaluate button uses AsyncButton with spinner + elapsed time counter
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>
Also moves "Agent-first CLI equivalents" from backlog to recurring checks in DOC_STATUS.md and regenerates CLI docs. https://claude.ai/code/session_01VPEn1WCxtvWPtcjAd5wphk
Ensures every CLI command that has a --yes flag also documents it in the docstring examples, so agents and CI can discover the non-interactive bypass from --help output. https://claude.ai/code/session_01VPEn1WCxtvWPtcjAd5wphk
…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>
chore(docs-maintenance): maintenance run 2026-03-31
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>
- 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>
feat: ✨ targets system — full implementation with two-stage evaluation, topic queue, and UI
|
Codecov Report❌ Patch coverage is 📢 Thoughts on this report? Let us know! |
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.
What's New
This release introduces the targets system — multi-account, multi-destination content flows with per-target content strategies. 215 commits, 339 files changed, +52K/-7K lines.
Targets: Multi-Account Content Flows
Configure multiple accounts across platforms, each with its own strategy, audience, and posting schedule. A single commit can produce different content for different audiences simultaneously.
Two-Stage Evaluation Architecture
Replaces the single-stage evaluator with a commit analyzer (stage 1) + strategy evaluator (stage 2) pipeline.
commit_analysis_intervalsetting batches commits. Deferred commits skip the expensive LLM pipeline until the threshold is crossed.Content Topic Queue
A persistent, prioritized queue of topics worth covering. The evaluator works through topics by priority rather than reactively posting about whatever commit landed.
OAuth 2.0 & Preview Mode
Unified Logging & Diagnostics
social-hook logs) and web UI (System > Event Log).Codebase Decomposition
models/__init__.pysplit into 7 submodules (enums, core, narrative, content, infra, context, _helpers). Direct imports only, no re-exports.trigger.pydecomposed into 6 sibling modules (trigger_git, trigger_context, trigger_decisions, trigger_side_effects, trigger_batch, trigger_secondary).enum_value(),AdapterRegistry, OAuth PKCE, migration runner, scheduling algorithm all extracted for reuse.Web UI
CLI
credentials,account,target,strategy,topics,brief,content,cycles,logstopics dismiss,topics list --include-dismissed,topics draft-nowon uncovereddecision batch-evaluatefor manual batch evaluationcredentials add --setfor non-interactive CI use--json,--yes,--project, help text with examplesBot Integration
Test Plan
Migration Notes
content_topics,content_suggestions,evaluation_cycles,draft_patterns,system_errors,oauth_tokensdrafts(target_id, evaluation_cycle_id, topic_id, arc_id, preview_mode) andposts(target_id, topic_tags, feature_tags, is_thread_head)models/__init__.pyis now empty — update imports tomodels.enums,models.core,models.content, etc.trigger.pyfunctions moved to submodules — backward-compatible re-exports in trigger.py🤖 Generated with Claude Code