Skip to content

feat(ai): AutoPublishCrew — in-process SEO generation crew (AI-042)#337

Merged
mrviduus merged 1 commit into
mainfrom
ai-042-autopublish-crew
Jun 16, 2026
Merged

feat(ai): AutoPublishCrew — in-process SEO generation crew (AI-042)#337
mrviduus merged 1 commit into
mainfrom
ai-042-autopublish-crew

Conversation

@mrviduus

Copy link
Copy Markdown
Owner

AI-042 — AutoPublishCrew integration (Phase 7)

Admin-triggered, in-process crew that runs the AI-041 specialists (researcher→drafter→critic→editor) over ILlmService to generate an Edition's SEO prose (Description + SeoRelevanceText). Per-field 4-stage CrewPlan, persists each run as a crew.autopublish agent_run, applies a fail-closed review gate, and writes the Edition only when both fields pass clean. Edition stays Draft — no auto-publish.

Why a new path, not a swap

Legacy AutoPublish gen is out-of-process (systemd bash poller → Claude CLI, Max sub, effectively $0). The crew is in-process metered nano. So "replace the single call" isn't a one-liner — this adds a parallel, observable path; the bash poller stays intact and default. A/B (AI-046) decides any cutover.

Endpoint

POST /admin/autopublish/editions/{id}/crew-generate (admin auth, autopublish.crew rate limit 4/min). Loads source material mirroring seo-generate.sh (title, authors, language, first-chapter excerpt), runs the crew twice, gates, writes back. Returns both runIds + per-field critique summaries + needsReview/manualProtected so AI-045's transcript UI can fetch later.

Fail-closed gate + data-loss guards (hardened per adversarial QA)

  • NeedsReview = true unless status completed AND critic parsed AND no blocker issue.
  • Empty/short output floor: empty/whitespace OR below-MinLength editor text → flagged, never blanks a real field.
  • Manual-source protection: a hand-written Description/Relevance on a SeoSource.Manual Edition is never overwritten (manualProtected: true) — matches the legacy backfill contract.
  • Both fields evaluated after both runs → no half-write. Rejected runs still persist their transcript (audit).

Cost

CostCapUsd = 0.02/field (4 nano calls). ~$0.04/edition worst case.

Tests — 22 unit (full suite 377 green)

Fake ILlmService routed per FeatureTag + recording IAgentRunWriter, no DB/network: clean→write, blocker→flag, ParseFailed→flag, empty/whitespace/below-MinLength→flag, cost-cap halt→flag, persistence (crew.autopublish, editionId, nested sub-agent steps), manual-protection battery. StudyBuddy tool set-equality still green (no ITool leaked).

Verify

  • dotnet test tests/TextStack.UnitTests → 377 pass
  • dotnet test tests/TextStack.AiEvals → 24 pass / 5 skip (no-key floor)
  • dotnet format --verify-no-changes → clean

Legacy seo-publish-poll.sh / seo-generate.sh unmodified. No DB migration.

🤖 Generated with Claude Code

Admin-triggered crew path that runs the AI-041 specialists (researcher→
drafter→critic→editor) over ILlmService to generate Edition SEO prose
(Description + SeoRelevanceText). Per-field 4-stage CrewPlan, persists
each as crew.autopublish agent_run, fail-closed review gate, writes the
Edition only when BOTH fields pass clean. Edition stays Draft (no
auto-publish). Legacy bash+Claude-CLI poller untouched and default.

New in-process path rather than swapping the poller: legacy gen is
out-of-process (Claude CLI, Max sub, $0) while the crew is metered nano
— keep both, A/B in AI-046 before any cutover.

Data-loss guards (per QA):
- gate flags NeedsReview on empty/whitespace OR below-MinLength editor
  output — never blanks a real field
- honors SeoSource.Manual: a hand-written Description/Relevance is never
  overwritten (returns manualProtected), matching legacy backfill contract

CostCapUsd 0.02/field; autopublish.crew rate limit (4/min). 22 unit tests
(fake ILlmService + recording IAgentRunWriter), no DB/network.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@mrviduus mrviduus merged commit 7bcafea into main Jun 16, 2026
13 of 21 checks passed
@mrviduus mrviduus deleted the ai-042-autopublish-crew branch June 16, 2026 00:22
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