Automates the PR delivery workflow: uploads .docx to Google Drive as Google Docs,
creates Gmail drafts with template-based emails and Ref: CU-<task_id> tracking tags,
and polls for client replies to update ClickUp tasks. Includes contact directory
with alias support, email template system, and manual CLI scripts for retries.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add add_dependency() to ClickUpClient and clickup_add_dependency chat tool
for setting "blocked by" relationships between tasks. New create-task-set
skill enables bundled task creation (LINKS, PR, NEW, OPT) with correct
fields, time estimates, due date offsets, and automatic dependencies.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
LLM plural check was firing for every non-exact keyword pair (e.g. "insert molding"
vs "cement plant lubrication"), causing timeouts and wasted API calls. Now requires
keywords to share all but one word before escalating to the LLM.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New lightweight web UI with dark theme, SSE-streamed chat, and live
dashboard. Gradio moved to /old for transition. Adds jinja2,
python-multipart, sse-starlette deps.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Execution brain timeout bumped from 15 min to 45 min default to avoid
content writing timeouts. BLM stays at 30 min. Both configurable via
CHEDDAH_TIMEOUT_EXECUTION_BRAIN / CHEDDAH_TIMEOUT_BLM env vars or
config.yaml timeouts section.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Server-side filter tasks by _CORA_ELIGIBLE_STATUSES in _match_xlsx_to_clickup,
_match_xlsx_to_content_task, and _distribute_cora_file instead of fetching all
tasks and filtering client-side. Reduce watcher interval from 40m to 10m.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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>