Files
crimson_leaf_publishing/templates/kdp_publish.yml

406 lines
13 KiB
YAML

name: kdp_publish
description: "KDP publishing pipeline. Hard prerequisites in order: chapter readiness, manuscript-level slop gate (AI fingerprint + style diversity + human polish log within 7 days), KDP compliance, KDP throttle window. Failing any prerequisite halts upload and routes to a remediation task. No operator override -- the only path past a failed gate is the remediation task succeeding and the pipeline being re-run."
debug: false
model: power
system: agent_prompt
agent_prompt:
- "= identity.md"
sections:
- agent
- project
- deliverables
- rag
- message
- instructions
steps:
# =========================================================================
# STAGE 1: Readiness check -- all chapters polished?
# =========================================================================
- type: tool
action: git_read_file
optional: false
output_key: canonical_manifest
params:
path: "canonical_manifest.json"
- type: tool
action: git_read_file
optional: true
output_key: pipeline_status
params:
path: "pipeline_status.json"
- type: tool
action: git_read_file
optional: false
output_key: book_metadata
params:
path: "publishing/metadata.yml"
- type: think
max_tokens: 600
output_key: readiness_check
hint: |
You are {agent.name} checking if {project.name} is ready for KDP submission.
Canonical manifest: {canonical_manifest}
Pipeline status: {pipeline_status}
Check:
1. Are ALL chapters listed in the manifest in "polished" status?
2. Is the total word count above 20,000 words? (KDP minimum for a full novel)
3. Is there a metadata.yml with title, description, keywords, categories,
author name, and price_usd?
If all checks pass, output:
READINESS: GO
[brief summary of chapter count, word count, and book title]
If any check fails, output:
READINESS: BLOCKED
[specific list of what is missing]
- type: think
max_tokens: 20
output_key: readiness_status
hint: |
Read the READINESS line from the check above.
Output ONLY the word: GO or BLOCKED. Nothing else.
- type: branch
condition: "{readiness_status} == BLOCKED"
target: publish_blocked
# =========================================================================
# STAGE 2: Assemble manuscript and inject AI disclosure into description
# =========================================================================
- type: tool
action: assemble_manuscript
optional: false
output_key: manuscript_result
params:
project_id: "{project.id}"
output_format: "plain_text"
- type: think
max_tokens: 800
output_key: enriched_metadata
hint: |
You are preparing the KDP submission metadata for {project.name}.
Existing metadata YAML:
{book_metadata}
Sprint 84j requirement: the description MUST contain an AI-disclosure
sentence near the end. KDP's content-policy rule R007 requires this and
Tool.SlopDetector.check_kdp_compliance will fail without it.
If the description already contains language matching any of:
"AI-assisted", "AI assisted", "AI-generated", "AI generated",
"artificial intelligence", "written with AI", "created with AI"
then leave it as-is.
Otherwise, append exactly one short paragraph at the END of the description:
"This book was developed with AI assistance under human creative direction.
The story, characters, and creative choices were shaped by the author in
collaboration with an AI writers' room."
Re-emit the FULL metadata as a JSON object with these keys (use real values
from the YAML; do not invent any):
title, author, description, price_usd, keywords (array), categories (array)
Output ONLY the JSON. No preamble, no markdown fence.
# =========================================================================
# STAGE 3: Slop gate -- AI fingerprint + style diversity (manuscript-level)
# Hard prerequisite for KDP upload. Failure spawns human_polish_brief.
# =========================================================================
- type: tool
capability: Tool_SlopDetector
optional: false
output_key: ai_fingerprint
params:
action: "detect_ai_fingerprint"
text: "{manuscript_result.text}"
provider_pool: ["local_heuristic"]
- type: tool
capability: Tool_SlopDetector
optional: false
output_key: style_analysis
params:
action: "analyse_style_diversity"
text: "{manuscript_result.text}"
- type: tool
action: git_read_file
optional: true
output_key: human_polish_log
params:
path: "publishing/human_polish_log.md"
- type: think
max_tokens: 800
output_key: slop_gate_assessment
hint: |
You are {agent.name} acting as the manuscript-level slop gate for
{project.name}. Sprint 84j requires three independent pass conditions
before KDP upload may proceed. Be strict. Do NOT rationalise borderline
results upward.
AI fingerprint (Tool.SlopDetector.detect_ai_fingerprint): {ai_fingerprint}
Style diversity (Tool.SlopDetector.analyse_style_diversity): {style_analysis}
Human polish log (publishing/human_polish_log.md): {human_polish_log}
Today is {task.created_utc}.
DIMENSION 1 -- AI FINGERPRINT (PASS if aggregate_score < 65)
Read aggregate_score from ai_fingerprint. Lower is better.
If aggregate_score < 65: PASS
Otherwise: FAIL with the score and any provider disagreement noted
DIMENSION 2 -- STYLISTIC QUALITY (PASS if all of the below)
- sentence_length_variance > 8.0 (chapter rhythm not flat)
- opening_word_repetition_rate < 0.15 (paragraphs do not all start the same)
- metaphor_family_clusters >= 3 (imagery is not single-register)
- dialogue_tag_diversity >= 6 (or 0 if there is genuinely no dialogue)
Any single failure means the dimension FAILs. List which thresholds missed.
DIMENSION 3 -- HUMAN POLISH (PASS if there is a polish_log entry whose
timestamp is within the last 7 days)
If human_polish_log is empty or its newest entry is older than 7 days:
FAIL.
If a polish entry exists within 7 days: PASS.
OUTPUT EXACTLY this format:
KDP_FINGERPRINT: PASS|FAIL
<one-sentence justification with score>
KDP_STYLE: PASS|FAIL
<one-sentence justification with the specific style metrics that crossed/missed>
KDP_POLISH: PASS|FAIL
<one-sentence justification citing the most recent polish_log timestamp or its absence>
KDP_OVERALL: PASS|FAIL
<PASS only if all three dimensions are PASS; otherwise FAIL>
REMEDIATION_BRIEF:
<if KDP_OVERALL is FAIL: 3-6 sentences describing what the human polish task should
target -- specific chapters, specific style metrics, specific opening passages.
If KDP_OVERALL is PASS: write the literal string "n/a">
- type: think
max_tokens: 20
output_key: slop_gate_status
hint: |
Read the KDP_OVERALL line from the assessment above.
Output ONLY the word: PASS or FAIL. Nothing else.
- type: document
source_step: slop_gate_assessment
filename: "slop-gate-{task.id}"
dest_path: "deliverables/slop-gate"
commit_msg: "slop_gate: manuscript verdict for kdp_publish task {task.id}"
- type: branch
condition: "{slop_gate_status} == FAIL"
target: slop_gate_failed
# =========================================================================
# STAGE 4: KDP compliance check (Tool.SlopDetector check_kdp_compliance)
# =========================================================================
- type: tool
capability: Tool_SlopDetector
optional: false
output_key: compliance_result
params:
action: "check_kdp_compliance"
metadata: "{enriched_metadata}"
manuscript_text: "{manuscript_result.text}"
- type: think
max_tokens: 400
output_key: compliance_evaluation
hint: |
Review the KDP compliance check result: {compliance_result}
If all_pass is true: output GO
If any rule failed: list the failed rules and output BLOCKED with reasons.
Output exactly:
COMPLIANCE: GO
or
COMPLIANCE: BLOCKED
[list of failed rules with rule_id and issue]
- type: think
max_tokens: 20
output_key: compliance_status
hint: |
Read the COMPLIANCE line from the evaluation above.
Output ONLY the word: GO or BLOCKED. Nothing else.
- type: branch
condition: "{compliance_status} == BLOCKED"
target: compliance_blocked
# =========================================================================
# STAGE 5: KDP throttle gate -- daily and weekly upload caps
# =========================================================================
- type: tool
action: kdp_throttle_check
optional: false
output_key: throttle_result
- type: think
max_tokens: 20
output_key: throttle_status
hint: |
Read the throttle_result JSON: {throttle_result}
Output ONLY one of these two words based on the verdict field:
PROCEED (if verdict is "PROCEED")
HALT (if verdict is "HALT")
Nothing else.
- type: branch
condition: "{throttle_status} == HALT"
target: throttle_blocked
# =========================================================================
# STAGE 6: Format manuscript and validate cover (Tool.AmazonKdp)
# =========================================================================
- type: tool
capability: Tool_AmazonKdp
optional: false
output_key: format_result
params:
action: "kdp_format_manuscript"
manuscript_text: "{manuscript_result.text}"
manuscript_result: "{manuscript_result}"
- type: tool
capability: Tool_AmazonKdp
optional: false
output_key: cover_validation
params:
action: "kdp_validate_cover"
image_path: "publishing/cover.jpg"
# =========================================================================
# STAGE 7: Upload (only reached when ALL gates pass)
# =========================================================================
- type: tool
capability: Tool_AmazonKdp
optional: false
output_key: upload_result
params:
action: "kdp_upload_book"
metadata: "{enriched_metadata}"
epub_path: "{format_result.epub_artifact_path}"
cover_path: "publishing/cover.jpg"
is_ai_assisted: true
# Record the upload against the throttle counter so the next run respects the cap.
- type: tool
action: kdp_throttle_record
optional: true
output_key: throttle_record_result
- type: document
source_step: upload_result
filename: "kdp_submission_{task.id}"
dest_path: "publishing/submissions"
commit_msg: "kdp: submission record {task.id} -- ASIN {upload_result.asin}"
- type: reply
target: channel
channel_name: "crimson_leaf_publishing:live-feed"
hint: |
Post: "PUBLISHED: {project.name} live on Amazon.
ASIN: {upload_result.asin}
Status: {upload_result.status}
URL: {upload_result.sales_page_url}"
- type: close
rag_update: true
# =========================================================================
# FAIL PATHS
# =========================================================================
- type: label
name: slop_gate_failed
- type: tool
action: enqueue_strategy
optional: false
params:
company_slug: "crimson_leaf_publishing"
project_slug: "{project.slug}"
task_type: "human_polish_brief"
content: "Slop gate failed for {project.name} during kdp_publish task {task.id}. See deliverables/slop-gate/slop-gate-{task.id}.md for the assessment. The remediation brief in that document defines what the human polish pass must address. Re-run kdp_publish after the polish is committed to the manuscript and a new entry appears in publishing/human_polish_log.md."
- type: reply
target: channel
channel_name: "crimson_leaf_publishing:live-feed"
hint: |
Post: "KDP upload HALTED for {project.name} -- slop gate failed.
Verdict written to deliverables/slop-gate/. Human polish task spawned.
Re-run kdp_publish after human polish is committed."
- type: close
rag_update: false
- type: label
name: publish_blocked
- type: reply
target: channel
channel_name: "crimson_leaf_publishing:live-feed"
hint: |
Post: "KDP publish BLOCKED for {project.name} -- manuscript not ready.
Details: {readiness_check}"
- type: close
rag_update: false
- type: label
name: compliance_blocked
- type: reply
target: channel
channel_name: "crimson_leaf_publishing:live-feed"
hint: |
Post: "KDP publish BLOCKED for {project.name} -- compliance check failed.
Details: {compliance_evaluation}"
- type: close
rag_update: false
- type: label
name: throttle_blocked
- type: reply
target: channel
channel_name: "crimson_leaf_publishing:live-feed"
hint: |
Post: "KDP upload DEFERRED for {project.name} -- throttle window not open.
Throttle response: {throttle_result}.
Retry kdp_publish after the throttle window opens. The slop gate, compliance,
and assembly results all PASSED -- only the rate limit is blocking."
- type: close
rag_update: false
adjudication:
enabled: false