Commit Graph

42 Commits (d6f9620d5fe9c944f2ad44f5adf549ac6b6f26cd)

Author SHA1 Message Date
PeninsulaInd f4e642240c Add direct BLM handler for Link Building build stage
Replace Claude-based link building with direct subprocess calls to
Big-Link-Man CLI. The build stage now runs ingest-cora + generate-batch
deterministically without LLM involvement.

- New clickup_runner/blm.py: BLM subprocess runner (ported from old linkbuilding.py)
- New handler="blm" in skill_map for Link Building build stage
- Add BLMConfig to config.py (blm_dir, cora_inbox, timeout)
- Add task-specific fields (Keyword, CLIFlags, etc.) to build_prompt
- Strip YAML frontmatter from skill files in read_skill_file
- Skip orphaned AutoCora results with no state DB entry

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 15:22:55 -05:00
PeninsulaInd 19f6ee94c6 Skip orphaned AutoCora results that have no matching state DB entry
Previously, results from prior runs (or the old CheddahBot system) would
be processed without context, causing "unknown" keyword in comments and
cascading errors. Now they are archived silently.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 11:00:27 -05:00
PeninsulaInd e0388b1f6f Fix --tier1-count CLI flag + set Stage on task creation + update docs
- Fix --tier-1 -> --tier1-count in create_task_set.py and create-task-set.md skill
- Set initial Stage field when creating tasks (run_cora for most, draft for PR)
- Add Quick Reference section to clickup_runner README with stage tables
- Add Stage field docs to clickup-task-creation.md
- Remove stale xlsx_urls tests from test_claude_runner.py

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 10:17:52 -05:00
PeninsulaInd b287d759a1 Fix ClickUp field name: Customer -> Client
The ClickUp dropdown is named "Client", not "Customer". Updated field
lookups, prompt labels, README docs, and all tests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 10:26:32 -05:00
PeninsulaInd 645b9cfbef Add AutoCora job submission + result polling -- Phase 3
Submits Cora SEO jobs as JSON files to the NAS queue, polls for .result
files each cycle, and updates ClickUp on success/failure. Async design:
submission and result processing happen on separate poll cycles so the
runner never blocks. Full README rewrite with troubleshooting section.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 10:17:42 -05:00
PeninsulaInd b19e221b8f Add Claude Code runner -- Phase 2: claude -p subprocess + ClickUp integration
Implements _dispatch_claude: reads skill files, builds prompts with task
context, runs claude -p as subprocess, uploads output files to ClickUp,
copies to NAS, advances stage/status, and posts structured error comments
on failure. Includes ntfy.sh notifications and generous max_turns defaults.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 09:34:54 -05:00
PeninsulaInd 74c1971f70 Add clickup_runner module -- Phase 1: skeleton + ClickUp polling
New headless automation runner that replaces CheddahBot's multi-agent
system with a simpler design: poll ClickUp for tasks with "Delegate to
Claude" checkbox checked + due date <= today, route by task type + stage
through a skill map, and dispatch to Claude Code headless or AutoCora.

Module structure:
- config.py: env vars > YAML > defaults configuration
- clickup_client.py: ClickUp API client (adapted from cheddahbot/clickup.py)
  with checkbox, stage dropdown, and attachment operations
- skill_map.py: task_type + stage -> SkillRoute routing dictionary
  (Content Creation, On Page Optimization, Press Release, Link Building)
- state.py: minimal SQLite KV store + run log
- __main__.py: poll loop with graceful shutdown
- README.md: setup, config reference, skill map docs

Dispatch functions are stubs (Phase 2: Claude runner, Phase 3: AutoCora).
Includes system-design-spec.md that drives this rewrite.

68 new tests, all passing. Existing 347 tests unaffected.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 09:14:22 -05:00
PeninsulaInd 48d2e47835 Replace fuzzy keyword matching with exact match + LLM plural check
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>
2026-03-18 18:53:24 -05:00
PeninsulaInd e8df7a9750 Add get_active_tasks tool to show what's running before restart
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>
2026-03-18 17:04:19 -05:00
PeninsulaInd 5cb15756fc Filter Cora distribution to eligible statuses and reduce poll interval to 40m
- 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>
2026-03-18 12:29:02 -05:00
PeninsulaInd ad7094e8a5 Separate PR Topic (angle) from Keyword (anchor text) in press release pipeline
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>
2026-03-17 10:51:10 -05:00
PeninsulaInd fb4498b978 Enhance ClickUp task creation, smart field setting, and Cora distribution comments
- 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>
2026-03-11 18:06:03 -05:00
PeninsulaInd 0d5450fb65 Add ClickUp task creation via chat tool, skill, and CLI script
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>
2026-03-11 12:19:54 -05:00
PeninsulaInd 6250918e5e Migrate ClickUp Customer field to space-level Client field
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>
2026-03-09 12:23:14 -05:00
PeninsulaInd 85d9fc7a1f Route create_content by content_type instead of URL presence
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>
2026-03-08 20:58:07 -05:00
PeninsulaInd af67ae166d Fix ntfy dedup: make duplicate suppression permanent for process lifetime
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>
2026-03-08 14:22:27 -05:00
PeninsulaInd 9102657c15 Add dedup, daily cap, and 429 backoff to ntfy notifier
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>
2026-03-07 17:32:52 -06:00
PeninsulaInd 1e26969ff8 Add explicit poll_task_types allowlist to filter ClickUp polling
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>
2026-03-05 19:28:42 -06:00
PeninsulaInd 45ab4c1b33 Fix task looping: increase stale recovery to 6h, add file logging, use UNC paths
- 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>
2026-03-04 21:41:46 -06:00
PeninsulaInd 83c7c378e5 Add ntfy.sh push notifications for alerts and errors
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>
2026-03-04 11:07:51 -06:00
PeninsulaInd 813dd4cb01 Wire Phase 3 test block pipeline into automated optimization flow
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>
2026-03-03 15:49:49 -06:00
PeninsulaInd 236b64c11c Add Cora report distribution watcher to route xlsx to pipeline inboxes
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>
2026-03-03 13:07:03 -06:00
PeninsulaInd 917445ade4 Steps 7-8: Eliminate KV store from task pipelines and update tests
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>
2026-02-27 16:26:44 -06:00
PeninsulaInd 5ddeb93033 Fix 1: AutoCora prioritized sweep and KV-free result polling
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>
2026-02-27 15:57:09 -06:00
PeninsulaInd 41487c8d6b Add file-first content creation pipeline with Cora inbox watcher
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>
2026-02-25 17:29:04 -06:00
PeninsulaInd 2ef7ae2607 Merge branch 'content-creation' 2026-02-25 15:13:57 -06:00
PeninsulaInd a3b8457afe Add two-phase content creation tool with human-in-the-loop outline review
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>
2026-02-25 15:10:09 -06:00
PeninsulaInd bc64fae6f1 Add AutoCora job submission and result polling automation
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>
2026-02-25 07:52:53 -06:00
PeninsulaInd 3f2798d338 Add "automation underway" and "error" ClickUp statuses for bot visibility
Tasks now show "automation underway" when the bot picks them up and "error"
on failure, replacing the old "in progress" / "to do" fallbacks that were
invisible on Bryan's ClickUp board. Folder watcher also syncs ClickUp status
on match, missing IMSURL, pipeline failure, success, and exceptions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 20:36:58 -06:00
PeninsulaInd 3b4a8e47be Require IMSURL for Cora pipeline, fail early if missing
Remove placeholder URL fallback from ingest-cora args. Add early
validation in run_cora_backlinks and folder watcher — if IMSURL is
empty, block the task with a notification instead of running with a
fake URL. Update tests to pass money_site_url and add missing-URL test.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 12:11:11 -06:00
PeninsulaInd f67f1b9124 Rename Client field to Customer and refine Overview sections
ClickUp "Client" custom field was deleted; switch all references to
"Customer" across config, tools, tests, and docs. Refine Overview tab:
rename Due Soon to Up Next (today/tomorrow, fallback next 5), expand
This Month to include both month tag and due-date-in-month matches.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 11:20:19 -06:00
PeninsulaInd 916bec8c0e Reformat code and update ClickUp tools to reset pattern
- Ruff format: consistent dict/call wrapping in agent.py, db.py,
  skills.py, delegate.py
- Replace clickup_approve_task/clickup_decline_task with
  clickup_reset_task/clickup_reset_all (simpler state machine)
- Add kv_delete() method to Database
- Add due_date and field filter tests to test_clickup.py
- Update test_clickup_tools.py for new reset tools

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 20:44:40 -06:00
PeninsulaInd a1fc5a7c0f Fix lint issues across link building files
- Remove f-prefix from strings with no placeholders
- Use list unpacking instead of concatenation
- Fix import sorting in test file
- Remove unused Path import
- Use contextlib.suppress instead of try/except/pass
- Wrap long lines to stay under 100 chars

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 20:13:37 -06:00
PeninsulaInd 40aca81e16 Add create_custom_field to ClickUp client and link building test suite
- ClickUpClient.create_custom_field() for POST /list/{id}/field
- 40+ tests covering output parsers, CLI arg builder, pipeline,
  ClickUp state machine, and folder scanning
- All tests mock subprocess.run, never call Big-Link-Man

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 20:05:54 -06:00
PeninsulaInd 0becf1dd89 Revert "Add link building agent with content generation pipeline"
This reverts commit 8a98b37725.
2026-02-19 18:38:51 -06:00
PeninsulaInd 8a98b37725 Add link building agent with content generation pipeline
New linkbuilder agent that handles ClickUp "Link Building" tasks.
For each keyword/company, generates three content pieces via the
execution brain: a guest article (500-700 words), a directory
listing, and a social media post — each with proper SEO anchor
text and backlinks. Integrates with ClickUp for status updates,
comments, and file attachments.

- cheddahbot/tools/linkbuilding.py: build_links tool with full pipeline
- skills/linkbuilding.md: skill prompt for SEO content generation
- config.yaml: linkbuilder agent config + Link Building skill_map entry
- tests/test_linkbuilding.py: 36 tests covering helpers, prompts,
  pipeline, file output, error handling, and ClickUp sync

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 11:52:06 -06:00
PeninsulaInd 0f2274e6f1 Phase 4: UI — Agent selector, conversation history, chat persistence
Add sidebar layout with agent selector (Radio), conversation history
(gr.render), and BrowserState for localStorage session persistence.
Conversations tagged by agent_name for per-agent history filtering.
Sidebar auto-closes on mobile viewports via JS. 11 new tests (135 total).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 11:23:50 -06:00
PeninsulaInd 0bef1e71b3 1.1: Delete dead code and fix all lint errors
Remove unused modules that were never called at startup:
- cheddahbot/skills/__init__.py (dead @skill decorator system)
- cheddahbot/providers/__init__.py (empty placeholder)
- cheddahbot/tools/build_skill.py (depends on dead skills system)
- cheddahbot/tools/build_tool.py (security risk: generates arbitrary Python)

Also fix all pre-existing ruff lint errors across the codebase:
- Fix import sorting, unused imports, line length violations
- Fix type comparisons (use `is` instead of `==`)
- Fix implicit Optional types (dict -> dict | None)
- Fix unused variables, ambiguous variable names
- Apply ruff format for consistent style

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 09:56:36 -06:00
PeninsulaInd ff3114b515 Add .docx attachment uploads to ClickUp tasks after press release generation
When a press release task completes, docx file paths are extracted from
the tool output and uploaded as attachments to the ClickUp task. The
completion comment now includes an attachment count note.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 18:04:23 -06:00
PeninsulaInd 5e9cef5e39 Add submit_press_release tool with Press Advantage API integration
Adds PressAdvantageClient API wrapper and submit_press_release tool that
posts finished press releases to PA as drafts. Auto-constructs SEO links
(brand+keyword → IMSURL, company name → SocialURL/GBP/homepage) with
fuzzy anchor matching and warnings when phrases can't be found. The PR
writing prompt now requests anchor text phrases and validates them after
generation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 17:37:41 -06:00
PeninsulaInd 8f6e218221 Add document export (.docx) and email delivery feature
Press releases now auto-generate .docx files alongside .txt for native
Google Docs import. New email_file chat tool sends files via Gmail SMTP
with app password auth, auto-converting .txt to .docx before sending.
Also includes Press Advantage API config and submit_press_release tool.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 17:00:54 -06:00
PeninsulaInd fa064be7c9 Add test suite for ClickUp integration APIs
51 tests covering the core API surfaces:
- ClickUpTask parsing (dropdown resolution, status normalization, fallbacks)
- ClickUpClient HTTP layer (mocked with respx, graceful error handling)
- Database kv_scan and notifications methods
- NotificationBus pub/sub (independent cursors, fault isolation)
- Chat tools state machine (approve/decline transitions, guards)

Also adds pyproject.toml with modern Python tooling (uv, pytest, ruff,
respx) and proper test/coverage configuration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 07:34:34 -06:00