Skip to content

feat: add generate-briefs and audit-articles agents#2

Merged
dspv merged 2 commits intomasterfrom
feat/generate-briefs-audit-agent
Mar 6, 2026
Merged

feat: add generate-briefs and audit-articles agents#2
dspv merged 2 commits intomasterfrom
feat/generate-briefs-audit-agent

Conversation

@dspv
Copy link
Copy Markdown
Contributor

@dspv dspv commented Mar 6, 2026

Summary

Two new agents + supporting docs, developed and battle-tested on the VAMI client blog.

generate-briefs agent

Keeps the content queue full automatically — no more manually writing briefs.

  • Runs daily at 08:00 UTC (1 hour before article generation)
  • Counts ready topics in CONTENT_PLAN.md
  • If below MIN_READY (default: 5) — calls Claude Haiku to generate new briefs
  • Reads docs/KEYWORD_RESEARCH.md for keyword clusters (if present)
  • Reads existing briefs to avoid duplicates
  • Writes files to docs/briefs/, updates CONTENT_PLAN.md
  • Commits and pushes directly to the default branch
  • Telegram notification when briefs are added

Reusable workflow inputs: config_path, min_ready, force_count, dry_run

Client setup:

jobs:
  generate-briefs:
    uses: cybrixcc/leadhunter-engine/.github/workflows/generate-briefs.yml@master
    with:
      config_path: ./config.yml
    secrets: inherit

audit-articles agent

Weekly automated QA pass over all published articles.

  • Runs every Sunday at 07:00 UTC
  • Checks every src/app/blog/*/page.tsx for:
    • Required components (ArticleAuthor, FAQJsonLd, ArticleJsonLd, Header, Footer)
    • Broken internal links (/blog/<slug> pointing to non-existent article)
    • Hardcoded absolute URLs in hrefs that should be relative
    • Missing opengraph-image.tsx
    • Missing date prop on ArticleAuthor
    • Emoji violations
    • Stale year references
  • Checks blog-data.ts — all slugs present, no duplicates
  • Checks llms.txt — all articles listed
  • Opens GitHub Issue with label audit on errors/warnings
  • Updates existing open issue instead of creating duplicates
  • Closes issue automatically when re-audit passes
  • Telegram notification with link to issues

Reusable workflow inputs: config_path, blog_glob


docs/gitattributes.template

Template to copy to .gitattributes in the client repo. Prevents merge conflicts in llms.txt and CONTENT_PLAN.md when multiple article PRs are open at the same time.


Documentation

  • README.md — updated What it does section with new agents
  • CLAUDE.md — updated commands reference and workflow table

Note

Medium Risk
Adds new reusable GitHub Actions that can automatically commit to client repos and create/close labeled issues based on script results, so misconfiguration or script bugs could cause unexpected writes/noise. Changes also introduce new Claude API usage and repository-wide content scanning that may fail on edge-case repo layouts.

Overview
Adds two new reusable workflows: generate-briefs.yml to auto-generate new content briefs via Claude when the CONTENT_PLAN.md ready-queue is low (then commit/push updates and optionally notify via Telegram), and audit-articles.yml to scan all published articles and open/update/close a labeled audit GitHub Issue based on an audit-report.md output.

Introduces scripts/generate-briefs.mjs (Claude-driven brief creation + docs/briefs/ + CONTENT_PLAN.md updates) and scripts/audit-articles.mjs (structure/link/sync/style checks with error/warn exit codes and a markdown report), plus updates to README.md/CLAUDE.md and a docs/gitattributes.template to reduce merge conflicts in append-only tracking files.

Written by Cursor Bugbot for commit b63d98f. Configure here.

generate-briefs.mjs + generate-briefs.yml:
- Keeps content queue full — runs daily at 08:00 UTC before article generation
- Reads CONTENT_PLAN.md, counts ready topics
- If < MIN_READY (default 5) — calls Claude Haiku to generate new briefs
- Reads KEYWORD_RESEARCH.md and existing briefs to avoid duplicates
- Writes brief files to docs/briefs/, updates CONTENT_PLAN.md
- Supports --dry-run, --count=N flags
- Sends Telegram notification when briefs added

audit-articles.mjs + audit-articles.yml:
- Weekly audit of all published articles — runs Sundays at 07:00 UTC
- Checks: required components present, broken internal links, missing OG images,
  blog-data.ts / llms.txt sync, duplicate slugs, stale year references, emoji violations
- Opens GitHub Issue (label: audit) with categorized findings
- Updates existing issue with new run instead of creating duplicates
- Closes issue automatically when re-audit passes
- Sends Telegram notification with link to issues on errors
- Supports --blog-glob flag for custom blog directory path

docs/gitattributes.template:
- Template to copy to client repo root as .gitattributes
- merge=union for llms.txt and CONTENT_PLAN.md prevents conflicts
  when multiple article PRs are open simultaneously

README.md + CLAUDE.md:
- Documented all new workflows and scripts
- Updated commands reference
- Updated workflow table
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Comment @cursor review or bugbot run to trigger another review on this PR

updated = updated.replace(
/\n> Status values:/,
"\n" + newTopicLines.join("\n") + "\n\n> Status values:"
);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New topic rows orphaned from table by blank line

High Severity

The replacement of \n> Status values: inserts new topic rows but always places \n\n (a blank line) before > Status values:. If CONTENT_PLAN.md already has a blank line before > Status values: (standard markdown), the new rows end up separated from the existing table by that blank line. The parseArticleIndex regex in content-plan-parser.mjs terminates table capture at the first \n\n, so the newly inserted rows become invisible to generate-article.mjs. Even starting without a blank line, the first run introduces \n\n, causing all subsequent runs to orphan their rows. The readyCount regex in this script still counts orphaned rows, so the queue appears full while no articles can actually be generated from them.

Fix in Cursor Fix in Web

description: 'Minimum number of ready topics to maintain (default: 5)'
required: false
default: 5
type: number
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Workflow min_ready input is silently ignored

Medium Severity

The workflow declares a min_ready input (default 5) but never passes it to the script. The script hardcodes MIN_READY = 5 and doesn't accept a --min-ready CLI argument. Any caller setting min_ready: 10 (or any other value) in workflow inputs will have it silently ignored, always using the hardcoded threshold of 5.

Additional Locations (1)

Fix in Cursor Fix in Web

- Use /\n+> Status values:/ regex to collapse any blank lines before
  the legend, preventing new rows from being orphaned outside the table
- Accept --min-ready=N CLI arg in generate-briefs.mjs
- Pass inputs.min_ready from workflow to script via --min-ready flag
@dspv dspv merged commit 3fc8c0d into master Mar 6, 2026
@dspv dspv deleted the feat/generate-briefs-audit-agent branch March 6, 2026 21:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant