Replace emoji prefixes in ClickUp comments and notifications with
plain ASCII tags ([FAILED], [DONE], [WARNING], [STARTED], [OUTLINE]).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Windows cp1252 console encoding can't handle → (U+2192), causing
UnicodeEncodeError in logging. Replaced with -> in all runtime strings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Substring and word-overlap matching caused cross-contamination between
similar keywords (e.g. "shaft manufacturing" matching "custom shaft
manufacturing"). Now only exact matches pass immediately; non-exact
pairs are checked via OpenRouter LLM call with session-level caching.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- File handler now captures DEBUG+ (was WARNING) for full pipeline visibility
- Add ClickUp comments at every error status transition (missing IMSURL, pipeline crash, content crash)
- Content watcher exception now also sets error status (was silently failing)
- Cora distributor resets matched error tasks to "running cora" when new XLSX arrives
- Add dedicated logs/pipeline_errors.log for tool-handled errors (audit trail)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Thread-safe active execution registry in Scheduler tracks which tool
functions are currently blocking. New get_active_tasks chat tool reads
this registry plus loop timestamps to report running tasks, durations,
loop health, and a safe-to-restart verdict.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move repetitive "Skipping task", "ClickUp task skipped", and "AutoCora
result" messages from INFO to DEBUG level
- Update task-pipeline-flows.md: folder watchers now 40m, add cora_distribute loop
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add _CORA_ELIGIBLE_STATUSES filter so only "running cora" and "error" tasks
get matched during xlsx distribution (prevents accidental "to do" matches)
- Reduce watch_interval_minutes from 60 to 40 for faster Cora file pickup
- Add .txt output to test block generator
- Include docs, scripts, and reference files
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
PR Topic now only drives headline angle and awareness/news framing.
Anchor text is derived from Company Name + Keyword (ClickUp Keyword field).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- "pipeline completed" → descriptive messages for link building and content
- "ClickUp task completed" → "{task} done — ran {tool} successfully"
- "Cora report completed" → "Cora report generated — ready for you to look at it"
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add set_custom_field_smart() to auto-resolve dropdown option UUIDs
- Extend create_task with priority, assignees, time_estimate params
- Expand clickup_create_task tool and CLI script with tags, due dates, custom fields
- Add _comment_distributed_tasks to post clear ClickUp comments on Cora distribution
(e.g. "Cora XLSX moved to cora-inbox" / "content-cora-inbox")
- Remove unused _find_all_todo_tasks; simplify AutoCora sibling matching
- Add tests for set_custom_field_smart dropdown and text fields
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New create_task() and find_list_in_folder() methods on ClickUpClient,
clickup_create_task chat tool, create-task skill, and CLI script for
creating tasks in a client's Overall list with Client/Work Category fields.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replaces all "Customer" field lookups with "Client" to match the new
space-wide dropdown, eliminating the 20+ duplicate list-level fields.
Includes migration script that populated 400 active tasks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Content Creation tasks with a URL were incorrectly routed to the
optimization path. Now the scheduler sets content_type from Work
Category, and the tool routes on that. Chat callers fall back to
URL-based detection when content_type is empty.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Compute the final-content.html save path upfront (network share with
local fallback) and pass it in the Phase 2 prompt so the execution
brain writes directly to the share. Summary still saved separately
as final-content.md via _save_content.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The tool registry only forwarded clickup_task_id from args to ctx,
so clickup_task_status was silently filtered out. Phase 2 detection
in create_content never saw the original "outline approved" status.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The scheduler sets status to "automation underway" before the tool runs,
so create_content's API re-fetch never saw "outline approved". Now the
scheduler passes the pre-change status via clickup_task_status arg.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The scheduler's blanket auto_execute check was blocking "outline approved"
Content Creation tasks from reaching Phase 2. Now checks
auto_execute_on_status for status-specific overrides. Also adds
trigger_hint to skip log messages for easier debugging.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Bump Claude Code subprocess timeout from 5 to 15 minutes for longer content tasks
- Fix scheduler result file loop: unlink source if already exists in processed/ dir
- Pass outline save path to execution brain so it writes directly to network share
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The time-based 1-hour dedup window wasn't preventing repeated skip
notifications for tasks with missing fields every poll cycle. Replaced
with a permanent sent-set so each unique message only fires once per
process run. Dedup log bumped to INFO for visibility.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevents notification spam from repeated ClickUp poll cycles finding the
same tasks with missing fields. Dedup suppresses identical messages within
a 60-min window, daily cap stops at 200 sends (under ntfy.sh 250 free
tier), and 429 responses suppress all sends for the rest of the day.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Only tasks with Work Category in poll_task_types are fetched and
processed. Prevents unrecognized types (SEO Audit, AEO, etc.) from
being evaluated every poll cycle. Falls back to skill_map keys if
the list is empty.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sends a summary at 6:30 AM weekdays / 8:00 AM weekends (Central) with
Cora reports needing action, outlines to approve, PRs to review, and
errors — grouped by customer. Cora tasks cross-reference network share
folders to show file pipeline status. No LLM API credits burned.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Stale task recovery threshold 2h → 6h to prevent resetting tasks while Cora is still running
- Add rotating file logger (WARNING+) to logs/cheddahbot.log for debugging
- Silence httpx/httpcore INFO spam from terminal
- Switch watch folder paths from Z: drive letters to UNC paths to avoid intermittent mount drops
- Fix test_db tests to add messages so list_conversations includes them
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New NtfyNotifier subscribes to NotificationBus and routes notifications
to ntfy.sh topics based on category + message pattern matching. Two
channels configured: human_action (task completed, Cora ready, etc.)
and errors (failures, missing fields). HTTP posts fire in daemon threads
to avoid blocking the notification bus lock.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a ClickUp task with a URL arrives at create_content, route it to the
new optimization pipeline instead of the outline-gate Phase 1/Phase 2 flow.
The pipeline runs 8 steps via the execution brain (scrape, deficit analysis,
entity filtering, template writing, test block generation, readability
rewrite, validation, surgical instructions doc) and uploads deliverables
(test_block.html, optimization_instructions.md, validation_report.json)
directly to ClickUp as attachments.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New watcher thread scans Z:/Cora-For-Human for post-macro Cora xlsx files,
matches them to ClickUp tasks by keyword, and copies to the appropriate
pipeline inbox (Z:/cora-inbox for Link Building, Z:/content-cora-inbox for
Content/OPO). Fixes issue where shared Cora reports left one pipeline's
tasks stuck in automation underway forever.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Changed Press Release topic source from task_name to "PR Topic" custom field
- Added required_fields config to skill_map so scheduler validates before
setting task to "automation underway"
- Tasks missing PR Topic, Customer, or IMSURL are silently skipped with
a notification and re-checked on next poll
- Updated docs and CLAUDE.md with new field mapping
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove all KV store reads/writes from task pipeline code. ClickUp is now
the single source of truth for task state. File location (processed/
subfolder) tracks file processing state. Loop timestamps use in-memory
dict on Scheduler.
Source changes:
- scheduler.py: Remove KV dedup, fallback sync path, docx extraction;
tools own their ClickUp sync; in-memory timestamps
- press_release.py: Remove KV state writes, log-only _set_status
- linkbuilding.py: Remove KV state writes, processed/ subfolder check
- content_creation.py: Phase detection via ClickUp API status, remove
KV phase/state tracking, _update_kv_state removed
- clickup_tool.py: Rewrite to query ClickUp API directly
- ui.py: Pipeline status polling is now a no-op
Test changes:
- test_scheduler.py: Remove KV dedup tests, remove fallback path test,
verify ClickUp API calls instead of KV state
- test_content_creation.py: Mock _get_clickup_client for phase detection,
verify ClickUp sync calls instead of KV assertions
- test_linkbuilding.py: Remove KV status test, verify ClickUp API calls
- test_clickup_tools.py: Rewrite for API-backed tools
- test_scheduler_helpers.py: Test in-memory timestamps
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When Phase 2 cannot find the outline file at any of the searched
locations, the task is now reset to its initial poll status in ClickUp
with a comment explaining the issue and suggesting a Phase 1 re-run.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When upload_attachment() returns False, the ClickUp comment now includes
a warning listing which files failed to upload and their local paths,
so Bryan can retrieve them manually.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix 4: Content watcher now sets ClickUp task to "automation underway" after
matching, matching the behavior of the link building watcher.
Fix 5: Content watcher now moves .xlsx files to a processed/ subfolder on
success, preventing re-processing on subsequent scans.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 1 now writes OutlinePath to a ClickUp custom field via
set_custom_field_by_name(). Phase 2 reads it back with
get_custom_field_by_name(), falling back to convention path
({outline_dir}/{slug}/outline.md) if the field is empty.
Added get_task(), set_custom_field_by_name(), and
get_custom_field_by_name() helpers to ClickUpClient.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace single-day task filter with multi-pass sweep when no explicit
target_date: (1) due today, (2) overdue + current month tag, (3) last
month tag, (4) look-ahead 2 days. Deduplicate across passes.
Remove KV store from submit (dedup by job file existence) and result
poller (scan results/ folder directly, move to processed/ after handling).
Scheduler auto-submit no longer passes explicit target_date.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add date_updated field to ClickUpTask dataclass. Add _recover_stale_tasks()
to scheduler that resets tasks stuck in "automation underway" for >2 hours
back to "to do" with an explanatory comment. This prevents tasks from being
permanently stuck if CheddahBot crashes mid-execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Content tasks now trigger from Cora xlsx files dropped in Z:/content-cora-inbox/
instead of auto-firing from ClickUp polling. The watcher fuzzy-matches files to
ClickUp tasks and auto-detects content type from URL presence (optimization vs
new content). Adds cli_flags support for service page hints.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 1 researches competitors and generates an outline via the execution brain,
saves it to a network/local path, and pauses for human review. Phase 2 picks up
the approved outline and writes full SEO-optimized content. ClickUp integration
maps "On Page Optimization" and "Content Creation" work categories, with
"outline approved" added to poll_statuses for automatic Phase 2 triggering.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Auto-submit Cora jobs for tasks due today on each autocora loop cycle
- Move ClickUp tasks to "automation underway" at submission time
- Default to blank URL for tasks missing IMSURL (new content)
- Use task Keyword field as project_name in folder watcher (not task name)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Automates Cora SEO report workflow: queries ClickUp for qualifying tasks,
submits jobs to a shared folder queue, polls for results, and updates task
statuses. Includes two tools (submit_autocora_jobs, poll_autocora_results),
a scheduler polling loop, and 30 tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Pass scheduler instance to API router and UI for loop timestamps
and force-run endpoints
- Add interruptible waits and force_heartbeat/force_poll methods
- Record last_run timestamps for all scheduler loops in KV store
- Update press release headline examples with real client headlines
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New /api/tasks/need-cora endpoint pulls tasks needing Cora reports
across Link Building, On Page Optimization, and Content Creation work
categories, deduplicates by Keyword field, and filters to a 30-day
window. Dashboard overview now shows Cora Reports as the first section
with color-coded type badges (LB, OPO, Content).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Track per-call token usage and estimated costs across all OpenRouter models.
Switch planner agent from Claude Sonnet 4.6 ($3/$15 per M) to Grok 4.1 Fast
($0.20/$0.50 per M) for ~25x cost reduction. Add budget alerts, a dashboard
card, and a check_api_usage tool for visibility into spending.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New report_issue tool logs bugs/improvements to memory/improvement_requests.md
- Planner agent (Sonnet via OpenRouter) for architecture and debugging tasks
- Heartbeat checks for pending improvement requests to surface to Bryan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- _maybe_set_title sets a quick truncated fallback immediately
- Then fires a background thread to ask the LLM for a 5-8 word summary
- Background thread doesn't block the streaming response
- Title appears in sidebar on first chunk, then upgrades when LLM responds
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- agent.new_conversation() now just resets conv_id to None; DB row is
created lazily by ensure_conversation() when user sends first message
- on_app_load no longer eagerly creates a conversation on page load
- list_conversations filters out conversations with no messages so
orphaned empty rows don't appear in the sidebar
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Move _maybe_set_title() to run at start of respond() generator (before streaming)
so titles are set even if the generator is closed mid-stream by Gradio
- Refresh sidebar conv list on first streaming chunk for immediate title display
- Backfilled 34 existing conversation titles from their first user messages
- Add scheduler loop status cards (heartbeat, poll, clickup, folder_watch) to
both System Health and Notifications tabs in the HTML dashboard
- Loop cards show relative time (e.g. "3m ago") with color-coded status
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Link building runs that finish successfully are already deployed,
so they go straight to complete. PRs still go to internal review.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>