WeChat Official Account Content Factory
Automate the tedious manual work after writing: formatting, images, compliance, and delivery.
The writing itself is left to the model; this skill ensures a draft can be published, looks good, and avoids pitfalls.
Capabilities
| Level | Capability | Description | Dependencies |
|---|---|---|---|
| L0 Material | ingest.py Material Ingestion | PDF/docx/pptx/web page/long text → structured, referenceable material | pypdf, python-docx, python-pptx |
| L1 Paste-ready | md2wx.py Markdown → Inline-style HTML | 4 themes, output directly pasteable into the editor | Pure standard library |
| L2 Draft-ready | cover.py Cover Images, lint.py Writing Gate, check.py Compliance Check, preview.py Formatting Confirmation | 900×383 / 1080×1080 / 200×200; validation during writing | Pillow, Chrome |
| L3 Direct-publish | Draft API Direct Publishing | Not implemented, interface contract in references/api.md | AppID + AppSecret + Verified Account |
Full creation defaults to L1 + L2 delivery; partial tasks deliver based on the request scope, without forcing a complete set of outputs. L3 requires an account with developer privileges and an AppSecret – unverified subscription accounts lack developer interfaces and can only achieve L2 (manual pasting). Confirm this with the user first, don't assume it's available.
Quick Start
Order is important: preview first, then checks, then build the workspace. The workspace is a snapshot; generating it before editing will produce an outdated version.
Full creation follows this skill's three-tier cover image standards for acceptance. Formatting requiring publish-ready layout also needs cover image checks;
lint --out out --publishmarks missing or incorrectly sized covers as must-fix. Ordinary "formatting only," "compliance only," or "preview only" don't require cover images. These three sizes are this project's delivery specification, not a substitute for WeChat backend requirements or actual image checks.
# 0. When material files exist, ingest first (PDF/docx/pptx/web pages)
python3 scripts/ingest.py material.pdf -o out/ingest
# 1. Full creation generates covers per project specs: 900×383 headline + 1080×1080 square + 200×200 sub-headline
python3 scripts/cover.py --md article.md --all -o out/cover
# 2. First, generate preview page (this doesn't create a workspace); output directory is created automatically if missing
python3 scripts/md2wx.py article.md -o out/article.html
# 3. Formatting confirmation (if browser is unavailable, state it clearly)
python3 scripts/preview.py out/article.html -o out/preview.png --height 4000
# 4. Dual compliance checks (run once first; find issues, edit the draft, then re-run)
python3 scripts/lint.py article.md --cards out/material-cards.md --outline out/outline.md --strict
python3 scripts/check.py article.md --html out/article.body.html --strict
# 5. After all checks pass, finally generate the workspace and create a snapshot (build fingerprint written into artifacts and build.json)
python3 scripts/md2wx.py article.md --sheet --snapshot -o out/article.html
# 6. Final check before delivery: artifacts must match the current source draft, and covers must be complete (--publish)
python3 scripts/lint.py article.md --out out --publish --strict
python3 scripts/check.py article.md --html out/article.body.html --strict
All commands execute from the skill root directory. python3 must be 3.9+; cover.py requires Pillow. Execute steps in order and check exit codes; don't ignore failures. Enable set -e for batch execution. Omit parameters if material cards or outlines are unavailable, and document unchecked scope; if explicitly provided but parsing fails, do not treat as absent. Full snapshots require local images to be in the output directory; formatting-only doesn't require snapshots or covers.
Before Writing: Write the Frontmatter First
Write metadata—title, summary, author, theme—only once, at the top of the Markdown file, shared by three scripts:
---
title: I Wasted 150 Weekly Reports Before Realizing: Leaders Don't Want "What You Did"
title_short: Stop Writing Weekly Reports as To-Do Lists
summary: Weekly reports go through three layers of paraphrasing, each losing information. If your leader can't steal a sentence from it, your week's output equals zero.
author: Cloud in the Maze
tag: Career Growth
theme: growth
---
# Main Title
The article starts here...
| Field | Required | Description |
|---|---|---|
title | Yes | Long title, ≤64 characters; used in the backend |
title_short | Yes | Short title, ≤20 characters; only used for feed display check, not filled in backend |
summary | Yes | Summary, ≤120 characters |
author | No | Backend author field + cover attribution; defaults to "Cloud in the Maze" if not provided |
tag | Recommended | Tag in the top-left corner of the cover, 2-4 characters |
theme | Recommended | tech / growth / minimal / elegant |
cover_title | No | Use when a different title is desired on the cover; defaults to title if omitted |
Once written, subsequent rendering, cover generation, and checks don't need parameters re-specified.
Attribution rules: Default is "Cloud in the Maze"; use user-specified attribution if provided.
| Scenario | Action |
|---|---|
| User didn't specify attribution | Don't write anything; automatically use default "Cloud in the Maze"; workspace notes "from default attribution" |
| User specified attribution | Write into frontmatter author – workspace, cover, and backend author field all read from it |
| User wants temporary cover text test | Use md2wx.py --author / cover.py --author to override, without saving to disk |
Priority: --author command-line > frontmatter author > default "Cloud in the Maze".
Don't only use cover.py --author without modifying frontmatter – that would cause inconsistency between cover attribution and workspace author field.
Workflow
First, select the task branch, then execute corresponding steps. Only "full creation" requires the complete sequence; partial tasks don't apply the full creation questionnaire.
| Task | Typical Request | Confirmation Needed | Execution Route |
|---|---|---|---|
| Full creation | Write an article; turn material into an article | Vertical field, audience, material, theme | Step 0 → 0.5 (if material exists) → 1~7 |
| Formatting only | Draft done, just format; convert to WeChat Official Account HTML | Source file, theme or existing frontmatter; supplement missing metadata only when publishing | Step 4 → Step 6.2 (check hints, don't edit the draft yourself) → Step 7 (partial delivery) |
| Cover only | Just generate WeChat Official Account cover | Cover text, theme/style, required sizes, optional tag and attribution | Step 5 → Manual cover text review → Step 7 (partial delivery) |
| Compliance only | Just check compliance, formatting, or references | File to check; use corresponding parameters only when HTML, material cards, or outlines are available | Related Step 6 checks → Step 7 (only deliver report) |
If the branch is unclear (e.g., "handle this article for me", "see if this can be published"): First follow Step 0 for full creation, but ask only the most critical question; don't ask all four at once. Better to ask one extra question than assume the wrong branch and force seven steps.
Partial tasks only supplement necessary information for the current task; reuse existing information directly. Don't rewrite finalized body text or existing titles. Don't reconfirm audience, topic selection, or outline. Don't force offering five title candidates. Only enter corresponding creation steps when the user explicitly requests editing.
- Formatting-only doesn't call
cover.py, unless the user also requests covers. Prefer existing themes; if no preference, usetechand explain, don't block. - Cover-only doesn't require a summary, body text, material cards, or outline. Don't fabricate an article to run full checks. Follow
references/compliance.mdto only review actual cover text and explain the scope. - Compliance-only doesn't modify files being checked. Don't pass
--htmlif only Markdown is available; if only HTML and no Markdown source exists, perform only HTML compatibility manual checks and explain the scope, don't fabricate body text. If material cards are missing, explain that references and numbers can't be fully verified. - Don't install Pillow or a browser if missing; don't pretend a step is complete. Deliver what's completed and list missing items. Partial completion does not mean the entire article is publishable.
Step 0 · Confirm Input (Full Creation Only)
For full creation, confirm four things; reuse existing answers; ask only when necessary information is missing, don't fabricate:
- Vertical field: Tech/product, or career/growth (determines theme and writing style)
- Audience: Who they are, their pain points, what they can do after reading
- Material: Real cases, data, code, screenshots
- Theme preference: Defaults based on vertical field (see "Theme Selection")
Also determine the starting point, leading to different paths:
| Starting Point | Typical Phrase | Path |
|---|---|---|
| Material provided | "Turn this PDF/report/webpage into a WeChat Official Account article" | Step 0.5 → Step 1 |
| Topic provided | "Write an article about X" | Skip 0.5, go directly to Step 1 |
| Both | "Based on this report, write an article about Y" | Step 0.5 → Step 1 |
Step 0.5 · Ingest Material (Only if User Provided Files or Links)
Read references/ingest.md and execute accordingly. Don't skip this step and start writing directly – reading the original text may lead to misreading, missing conclusions, or misremembering numbers.
python3 scripts/ingest.py material.pdf meeting-notes.docx -o out/ingest
Generates three-layer files (cleaned body / structural outline / candidate quotable sentences). Then, following ingest.md §2, extract material cards:
| Prefix | Type |
|---|---|
F | Fact (objective statement) |
D | Data (number + unit + scope) |
O | Opinion (author's claim, not fact) |
? | Questionable (contradictory / unsourced / needs verification) |
Deliverable: material card table + gap list. Confirm with user before proceeding.
Three red lines (ingest.md §3): don't change numbers, don't change scope, don't write speculation as fact. If multiple values for the same indicator are found, create a ? card and ask; never silently pick one.
Step 1 · Topic Expansion and Outline
- User provided material: Infer possible angles from material cards (
references/topic-expand.md§3) - User provided only a topic: Use
topic-expand.md§1–§3 to expand a sentence into an argument tree
Then, combine references/writing-playbook.md §1 (vertical baseline) and §4 (5 structural templates) to select a skeleton and produce an outline with word count allocation for user confirmation.
Each argument in the outline must reference a material card ID ([F1] [D2]). Arguments that can't be linked are deleted; don't fabricate structural completeness (topic-expand.md §4).
Step 2 · Write Title and Summary
Read references/writing-playbook.md §2 and §6:
- Generate long title (≤64 characters, for backend) + short title (≤20 characters, for feed display)
- Offer 5 candidates at once, labeling the formula used for each, and let the user choose
- Summary ≤120 characters, provide 1–2 versions
Step 3 · Write Body
Write Markdown following the outline. Note:
- Opening hook per §3: grab attention in the first 3 lines
- One idea per paragraph, ≤5 lines (≈260 characters)
- Closing per §5: use "question-ending / series preview / value summary"; don't write clickbait
- After writing, run through the 24-point "AI-voice" checklist in §7; delete all transition words that don't affect understanding
Step 4 · Formatting and Rendering
Use the theme from frontmatter or a user-specified theme. If no preference, choose based on vertical field; formatting-only defaults to tech:
python3 scripts/md2wx.py article.md -o out/article.html
The parent output directory is created automatically. Two files are generated:
out/article.html– Preview page (with white background container, like mobile reading view) → for viewingout/article.body.html– Pure body fragment → backup pasting option
This step does not generate a workspace; the final out/sheet.html is created in Step 7 to avoid saving premature snapshots before cover and draft finalization.
After rendering, use preview.py to take a screenshot. Check it yourself before handing to the user (check for ugly title line breaks, table width issues, code block truncation). If the browser is unavailable, open the HTML and manually inspect; clearly state that no screenshot was taken, and don't require rewriting the article as a result.
Step 5 · Generate Cover Images (Required for Publishing)
A WeChat Official Account article cannot be published without a cover image. This step is not optional in "full creation" or "formatting for publishing."
python3 scripts/cover.py --md article.md --all -o out/cover
Generates three sizes at once: cover.png 900×383 (headline 2.35:1), cover-square.png 1080×1080 (square), and cover-thumb.png 200×200 (sub-headline). Incorrect sizes will be cropped by the platform; lint --publish verifies them.
Parameters are read from frontmatter by default (title, tag, author, theme); usually no need to pass them again:
--style:gradient(default, dark background) /minimal(white background, opinion pieces) /band(color band, brand articles)--allgenerates three sizes: headline 900×383, square 1080×1080, sub-headline 200×200- Cover title defaults to
title(long title has a stronger hook); to change text, addcover_titleto frontmatter
Step 6 · Dual Compliance Checks (Two Gates, Each Handles a Section)
Full creation executes both gates; formatting-only and compliance-only follow the entry table to select corresponding checks, without forcing the creation of missing materials or editing the original draft. When metadata, material cards, or screenshots are missing, document the limitations; partial delivery is not marked as publish-ready full verification.
6.1 Writing Gate – Checks "are claims supported, and where do numbers come from?"
python3 scripts/lint.py article.md --cards out/material-cards.md --outline out/outline.md
This is a hard gate, not just a suggestion:
| Check | Rule | Consequence of Failure |
|---|---|---|
| Empty reference | [F1] in body must exist in material cards | Mark as "must fix" |
| Questionable card | [?N] must not appear in body | Mark as "must fix" – verify or delete |
| Number without source | Every number+unit in body must be in F/D cards | Mark as "must fix" |
| Argument without support | Each supporting argument in outline must reference ≥1 [F]/[D] | Mark as "must fix" |
| Main argument quality | Cannot be a phrase (e.g., "caching is important") | Mark as "must fix" |
| Opinion card | [O] referenced as primary evidence | Mark as "should confirm" |
| Gap list | Outline must have P0/P1/P2 gaps | Mark as "hint" |
If material cards are absent, downgrade automatically: only hint that "numbers can't be verified," and list all numbers with units for manual review.
Artifact version verification: When --out <artifact directory> is added, it compares the build fingerprint in the deliverables against the fingerprint computed from the current source draft.
python3 scripts/lint.py article.md --out out --publish --strict
--publish indicates acceptance according to publish-ready scope; --out specifying the artifact directory is required. Without the directory parameter, an error is raised. It checks file existence and PNG header dimensions according to this project's three-tier specification, without fully decoding images or verifying cover text, uploads, or WeChat backend requirements.
| Situation | Verdict |
|---|---|
| Artifact fingerprint == current source draft fingerprint | Pass |
| Draft was edited but not re-rendered | "Must fix": preview page/workspace is an old version |
Source draft digest in build.json doesn't match | "Must fix": source draft was modified after generation |
article.body.html was replaced or manually edited | "Must fix": bypassed by build.json body digest cross-validation |
| Artifact has no fingerprint | "Should confirm": generated by old script or manually modified |
Missing cover / incorrect size (--publish) | "Must fix": does not meet project's publish-ready cover specifications |
This step is the only mechanical safeguard against "edited the draft, forgot to re-run, and published the old version." Must run before delivery.
6.2 Publishing Compliance Check – Checks "can it be published?"
python3 scripts/check.py article.md --html out/article.body.html --strict
Title length and summary length are automatically read from frontmatter; no need to pass them again.
Hard pass criteria:
| Metric | Requirement |
|---|---|
| lint "must fix" | Must be 0 |
| High-risk items | 0 unresolved high-risk items; manually confirmed false positives must leave evidence and review record |
| Metadata | title, title_short, summary required and non-empty; only single-line key: value fields supported |
| Title length | Long title ≤64, short title ≤20; actual published title's key opening information still needs manual check |
| Summary length | ≤120 |
| External images | Upload or replace with WeChat-compatible images before publishing, and confirm in editor preview |
| Professional or confidential content | Must undergo manual/legal final review; keyword deletion, rewriting, or anonymization cannot substitute for review and authorization |
Both --strict flags are CI-friendly: exit code 1 when "must fix" or high-risk items exist. check.py treats missing/oversized metadata, unsupported multi-line field values, and explicitly specified but nonexistent HTML as high-risk. Without --strict, it still reports issues but exit code is 0.
Publishing compliance scanning covers title, title_short, summary, cover_title, author, tag, and body text; body code blocks are skipped, but backticks in metadata cannot bypass checks. JSON findings include field for source; body line remains relative to body text. Command-line overrides for title/summary are the final check objects.
Passing scanning does not mean publishing is allowed. High-risk items are recorded per references/compliance.md §0 as "pending review / confirmed false positive / revision completed / publication denied"; scripts cannot read or replace manual review records; confirmed false positives don't automatically pass --strict. If professional, authorization, or confidentiality issues are unresolved, pause and don't deliver as publishable draft. Medium/low-risk retained items, manually confirmed items, and their basis are explained together.
If material usage rights or sources are unclear, first obtain authorization/source or exclude the material; don't change the magnitude, and don't rewrite external opinions as the author's personal experience. After material ingestion, retain a separate licensing-and-restrictions.md file, documenting source, attribution, scope of use, applicable boundaries, and authorization status.
Step 7 · Delivery
For tasks requiring HTML/workspace, regenerate the final workspace before delivery. After confirming the finalized draft, metadata, theme, and requested covers are complete, run with the same source draft and same theme/output parameters:
python3 scripts/md2wx.py article.md --sheet -o out/article.html
This simultaneously updates the preview page, body fragment, and sheet.html. The workspace reads the final cover.png, cover-square.png, and cover-thumb.png from the same directory. It is a static file snapshot; refreshing the browser won't regenerate the workspace. If the body, metadata, theme, or images are subsequently modified, regenerate the relevant artifacts and re-run corresponding checks and previews; don't deliver old snapshots.
Build fingerprint and rollback:
- Fingerprints include rendering code, source draft, merged theme, actual title/attribution/theme overrides, output options, local images, and cover content; metadata and local asset changes invalidate old builds.
build.jsonuses schema 2, declaring actually requested files and listing complete SHA256 for each; the checker validates based on actual rendering parameters, so explicit-ttheme overrides shouldn't cause false positives. Missing files, content replacement, or structural damage will block.article.body.htmlstays clean, without any markings; it, along with preview/workspace, is verified via manifest digest separately, not just trusting the fingerprint tag in HTML. If the old manifest can't fully verify, prompt for re-rendering.- Full creation uses
--snapshoton the final render, saving source draft, requested HTML, local images, and covers toout/.builds/<fingerprint>/. Snapshots with the same fingerprint cannot be overwritten; missing local images cannot qualify as a full snapshot. Images must be relative paths within the output directory; snapshots don't fetch remote images. md2wx.py --list-builds --out-dir outshows history;md2wx.py --rollback <fingerprint> --out-dir outrestores the source draft to its original path, plus artifacts, local images, and covers, and cleans up outputs from the previous manifest that this version doesn't need. Confirm the rollback intention before proceeding, as it will overwrite the current source draft and declared assets; only use trusted local snapshots.- Rollback verifies all files and digests first; damaged or dangerous paths won't cause partial recovery. Snapshots don't restore rendering scripts or global theme configurations; these changes still require re-rendering and re-checking after the rollback. For stdin snapshots, the source draft is restored as
article.mdin the output directory. - Formatting-only uses the above command without
--snapshot; full creation uses:
python3 scripts/md2wx.py article.md --sheet --snapshot -o out/article.html
Pre-delivery self-check checklist (check each item manually; don't use "command ran successfully" as a substitute for "file was inspected"):
- Full creation:
lint.py article.md --out out --publish --strictpasses – artifacts match the current source draft and covers meet project specifications -
check.py article.md --html out/article.body.html --strictpasses – no high-risk items - Visually reviewed
article.htmlorpreview.png(title line breaks, table widths, code block truncation) - Title/short title/summary/author in
sheet.htmlmatch what will be entered in the backend - Three cover images exist with correct header dimensions (
--publishalready checked); additional manual opening to confirm they are decodable and text isn't cropped - Local images in the body are listed as "need manual upload"
- Delivery note specifies: which medium/low-risk items were retained, what wasn't completed
Inspect actual output files item by item. List missing covers or screenshots; don't substitute file confirmation with command execution. For full creation, unresolved missing items mean delivery is not labeled as complete. Provide source Markdown at its actual path; don't move or overwrite the user's original.
Self-check by task scope (self-check items follow the request scope, don't apply full creation checklist to all):
- Full creation: Full item-by-item checklist
- Formatting-only: Source draft, HTML, body fragment, and workspace usable; formatting-only doesn't require three cover sizes
- Cover-only: Only review cover text and dimensions; no body or compliance checks required
- Compliance-only: Only deliver the report; no draft editing required
Partial tasks only deliver requested artifacts: Formatting-only delivers source draft, HTML, body fragment, and workspace; cover-only delivers images of requested size and text review conclusion; compliance-only delivers the inspection report. Don't require filling in covers, material cards, or outlines; don't treat partial checks as full publishing acceptance.
The following checklist applies only to full creation; source file location is based on actual path:
out/
├── article.md Finalized draft Markdown (source file, with frontmatter)
├── article.html Preview page (for viewing)
├── article.body.html Pure body fragment (backup)
├── sheet.html Publishing workspace (for publishing)
├── cover.png Headline cover 900×383
├── cover-square.png Square 1080×1080
├── cover-thumb.png Sub-headline 200×200
└── preview.png Formatting screenshot
Full creation also provides: long title / short title / summary / compliance conclusion (which medium/low-risk items were retained). Partial tasks only list existing metadata, requested artifacts, actual inspection scope, and unfinished items; don't write a title, summary, or body just to complete the checklist.
Publishing to WeChat Official Account (Key Steps)
Open out/sheet.html, a single page handles all copying:
- ① Title → Click "Copy" → Paste into backend title field
- ③ Summary → Click "Copy" → Paste into backend summary field
- ④ Author → Click "Copy" → Paste into author field
- Body → Click "Copy Body" in the top right → Paste into editor area
- Body images → Process each in the "Body Images" card on the left (see below)
- Cover image → Upload
cover.png - Follow the "Pre-publish Checklist" item by item
Why Images Are Lost
The WeChat editor's paste function only receives text and styles; it won't upload local images for you. An <img src="fig.png"> in the body is a local relative path; after pasting into the editor, the image slot will be empty – this isn't a formatting issue, but a limitation of the host environment: images must first be uploaded to WeChat's server (mmbiz.qpic.cn) to display.
Without API permissions, this step is manual. The workspace condenses it into two paths:
| Method | Action |
|---|---|
| Copy image | Click "Copy Image" → Cmd+V at the corresponding position in the editor; WeChat will upload automatically |
| Right-click copy | If "Copy Image" fails, click "Open Original Image" → Right-click "Copy Image" → Paste in editor |
| Fallback | Right-click "Save Image As..." → Use editor's "Image" button to upload |
Order follows appearance in the body (1st image, 2nd image...); match positions while pasting.
Don't copy the
.mdsource: md is plain text; pasting it will result in a mess of#and**, with no images or formatting. You must copy the workspace's rich text or the rendered result ofarticle.body.html.
Check for missing images: Before publishing, scroll through the entire mobile preview to ensure every image is in place.
Fallback: Open article.body.html in a browser → Cmd+A → Copy → Paste. (Don't use article.html; that's the preview page and will include the outer container.)
Theme Selection
| Theme | When to Use | Visual Style |
|---|---|---|
tech Tech Blue | Technical breakdowns, product analysis, engineering practice | Blue accent, H2 vertical bar, dark code blocks |
growth Growth Orange | Career experience, growth retrospectives, methodology | Warm orange accent, H2 color block, looser line spacing |
minimal Minimal Black & White | Opinion pieces, deep thinking | Black & white, H2 underline |
elegant Business Navy | Brand articles, formal publications, industry analysis | Serif font, navy accent, centered H1 |
Principle: The harder the content, the simpler the theme. When in doubt, use tech.
To add a new theme, just add a JSON file in scripts/themes/. Field descriptions are in references/layout-spec.md §13.
Command Quick Reference
| Command | Purpose | Key Parameters |
|---|---|---|
ingest.py <files...> | Material → structured text + candidate quotable sentences | -o output directory, --json |
md2wx.py <md> | Markdown → WeChat Official Account HTML | --sheet generate workspace, --snapshot create snapshot, -t theme, -o output, --no-body, --check |
md2wx.py --list-builds | View historical builds | --out-dir |
md2wx.py --rollback <fingerprint> | Restore a specific version's artifacts | --out-dir |
cover.py | Cover images | --md automatically reads frontmatter, --style, --all; --title/--tag/--author/--theme override |
lint.py <md> | Writing gate + artifact version verification | --cards, --outline, --out, --json, --strict |
check.py <md> | Pre-publishing compliance check | --html, --json, --strict; --title/--summary override frontmatter |
preview.py <html> | Screenshot for formatting confirmation | -o, --width, --height |
Title, summary, author, and theme are by default read from frontmatter; command-line parameters are only for temporary overrides.
--strict is for CI/automation: exit code 1 when high-risk items exist.
Common Pitfalls (Must Know)
| Pitfall | Phenomenon | Treatment |
|---|---|---|
| External links unclickable | https://... in body don't respond when tapped | Change to text description, or put in "Read Original" |
| Image blank | External images display as placeholder/gray block | Manually upload in editor, or use L3 material interface |
| Unstable line breaks | Using blank lines for paragraph spacing, inconsistent client behavior | Use margin for spacing; md2wx.py handles this |
| Code line wrapping | Long code automatically wraps, unreadable | Each block ≤30 lines; split overly long blocks into fragments |
| Table overflow | Tables with 5+ columns scroll horizontally | Columns ≤4; split into two tables if exceeded |
| Title truncated | Feed only displays about 20 characters | Must have a short title version |
| Can't publish without a cover | Backend headline cover is mandatory; skipping it means delivery is impossible | Full creation must run cover.py --all; verify with lint --out --publish before delivery |
| Delivered an outdated version | Edited the draft but didn't re-render, published the old version | Run lint --out out --strict before delivery; mismatched fingerprints will block it |
Reference Documentation (Load on Demand, Don't Read All at Once)
| Document | When to Read |
|---|---|
references/ingest.md | Step 0.5: Material ingestion, extracting material cards, fidelity rules, conflicting scope, gap list |
references/topic-expand.md | Step 1: Topic expansion, argument tree, anti-watering discipline |
references/writing-playbook.md | Steps 2~3: Title formulas, opening hooks, structural templates, anti-AI-voice |
references/compliance.md | Step 6: Compliance vocabulary list, violation types, alternative phrasing |
references/layout-spec.md | When adjusting formatting, adding themes, or judging visual issues |
references/api.md | When the user wants L3 automatic publishing |
Dependencies
| Dependency | Used For | When Missing |
|---|---|---|
| Python 3.9+ | All scripts | Required |
| Pillow | cover.py | Cover generation will fail; everything else works |
| pypdf | ingest.py PDF parsing | Vendored to scripts/vendor, no separate installation needed |
| python-docx | ingest.py docx parsing | Vendored to scripts/vendor, no separate installation needed |
| python-pptx | ingest.py pptx parsing | Vendored to scripts/vendor, no separate installation needed |
| Chrome/Chromium | preview.py screenshot | Screenshot step will fail but won't block other steps |
Pillow installation: pip install Pillow
All scripts are vendored to avoid network dependencies and version conflicts. No pip install pypdf, python-docx, or python-pptx needed – installed versions are ignored in favor of vendored copies. Uninstalling global versions won't break anything.
